Skip to content

Conversation

@janbrasna
Copy link
Contributor

@janbrasna janbrasna commented Mar 29, 2025

Description

Adds a little more specificity necessary to not inherit own anchor styles for better resilience.

  • I have documented this change in the design system.
  • I have recorded this change in CHANGELOG.md.

Issue

Fixes #842

Testing

Current styles with added "visited" state by converting the buttons to anchors linking the same preview page recursively, to demonstrate the underlying issue more visibly:
https://control--mzp-dev.netlify.app/components/detail/button--using-link

PR preview:
https://cta--mzp-dev.netlify.app/components/detail/button--using-link

Comment on lines 2 to 15
label: Primary Button
default: Primary
variants:
- name: Using link
notes: CTA anchor styled as Button.
context:
link: './button--using-link'
- name: Primary Dark
preview: '@preview-dark'
notes: Add the class `mzp-t-dark` for use on dark backgrounds (the button itself is light).
context:
class: 'mzp-t-dark'
link: './button--primary-dark'
- name: Secondary
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed the examples from buttons to links to better show any link-related woes right in the Fractal preview. Originally it was only for debug purposes, but I'm thinking about keeping it that way to help surface any anchor pseudo issues.

(That meant adding the anchor as another variant to keep the default button — as form-related styling still has to be demonstrated and some states as readonly/disabled example are derived from it. All the other examples were just switched to links without any further impact, didn't want to duplicate these.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense to me, glad we have both elements in preview

Copy link
Collaborator

@maureenlholland maureenlholland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to merge once the changelog is updated r+wc (edit: this can wait until the notification update is merged!)

I also left a comment on the bigger change I'm interested in exploring for links within the design system. Not something to address in this PR, just thinking out loud

/* stylelint-disable-next-line no-duplicate-selectors */
.mzp-c-button,
a.mzp-c-button {
a.mzp-c-button:link,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: mozilla/bedrock#16128 (review)

The bigger simplification I'm hoping we can put in with the M24 colors update is to reduce some of the specificity involved in link styles. The component class styles should always beat the base element styles and right now that requires some extra specificity overrides because we also have pseudo-classes like :link and :visited in play.

The current selectors feel very heavy and nested and hard to reason about.

notification-cta button-link

There are a couple of approaches I have in mind (some overlapping, some mutually exclusive):

  1. scope the base anchor styles more tightly to elements without an MZP class (similar to the a:not([class]) approach here)
  2. use the anchor element on link base styles instead of the pseudo-classes
  3. wipe out unwanted specificity with :where() (might not have enough support, and I don't think we want to introduce cascade layers + polyfill, but that is another option for better specificity control)
  4. use CSS or Sass color functions to create hover/visited styles automatically
  5. use contextual CSS properties to replace mixins like white-links

My general feeling is, it makes sense that we need to explicitly set link styles to override browser defaults. But we shouldn't have to work so hard to override our own default link styles.

Big caveat: this is not something we've discussed team-wide, so the "reduce specificity" approach might just be a personal preference of mine we don't end up pursuing

As someone who has spent a good amount of time with these codebases, I'm curious to hear your thoughts on a more foundational change (in future) for link styles

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, the specificity of link styles is a constant problem 😭

Copy link
Contributor Author

@janbrasna janbrasna Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll bring the specificity conversation back to the tracking issue to follow up, but just for the context of this PR:

There was this issue back in the day #655 that got resolved, but later disappeared in #864 — while investigating the referenced #842 issues, I actually only ran into tightly scoped regressions, or implementation bugs — like #758 where light-links or white-links are part of the component, but the consumer never changed that etc. — so the only real issue, before having the M24 base in bedrock (that does indeed cause a lot of headache redefining both MZP themes with higher specificity…) was the actual bug addressed here in the PR, i.e. the "primary" and "primary-dark" button themes not having the necessary color explicitly.

Not that a more modern approach to allowing greater flexibility wouldn't be great today, esp. with moving to CSS vars fully, just thought that it might be worth mentioning all the individual occurrences documented never really shown a systemic issue, but always ended up being very concrete bugs instead. NB: From my investigations, yea, color math, :where() and finding a way to replace link color mixins wholesale all sound like a great improvement to the next person fighting this from the short experience I had with some of the surprises like dark-themed-only-with-forced-light-links components etc.!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Changelog updated from release to head again, conflicts resolved.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe you didn't push the rebase? This note is from today but the last update is 5 days ago and I still see a conflict 🙃

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephaniehobson This is weird. Was the same on previous PR with Alex — no idea why it's all green from my side but the last push doesn't appear for a maintainer… I do not rebase unless strictly needed (not to rewrite anything that's been already reviewed, and also to allow reviewing just the conflict resolution merge by itself if needed); for mere changelog conflicts I keep using the PR UI to edit and mark as resolved, i.e. adding in merge commits to update. At the point of the comment, a 5 days old change would be outdated, there was a newer merge 3 days old (I even added extra time to update any caches or stuck state) and there are CI run logs matching that; it's just weird. I pushed another update right now, so, YMMV, but, again updated on last changelog update there;)

label: Primary Button
default: Primary
variants:
- name: Using link
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines 2 to 15
label: Primary Button
default: Primary
variants:
- name: Using link
notes: CTA anchor styled as Button.
context:
link: './button--using-link'
- name: Primary Dark
preview: '@preview-dark'
notes: Add the class `mzp-t-dark` for use on dark backgrounds (the button itself is light).
context:
class: 'mzp-t-dark'
link: './button--primary-dark'
- name: Secondary
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense to me, glad we have both elements in preview

@janbrasna janbrasna force-pushed the fix/button-link-contrast branch 2 times, most recently from 803d724 to 2d77aa1 Compare May 14, 2025 01:22
@janbrasna janbrasna force-pushed the fix/button-link-contrast branch from 237f8d9 to 2d77aa1 Compare May 16, 2025 21:42
@stephaniehobson stephaniehobson merged commit 1e4442b into mozilla:main May 20, 2025
1 check passed
@stephaniehobson
Copy link
Contributor

Finally green and merged 🙂

@janbrasna janbrasna deleted the fix/button-link-contrast branch May 20, 2025 19:54
Comment on lines -72 to 73

@mixin product-states-dark {
@include product-states;
}

// * -------------------------------------------------------------------------- */
// Button shape and size
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking of this now… I haven't really brought up whether it's okay to just drop this mixin without any breaking notice or migration hints — from what I understand it was only ever used internally to style the individual classes of themes of buttons, and never really exposed to consumers per se… but who knows in times of everything being available in the global namespace, right? 😇

So, if anyone could help me judge this… does it look like an internal shim from way back, and is safe to drop silently, or should be noted for consumers to be on the safe side?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick GitHub search suggests it's not used anywhere. I'd still note it in the CHANGELOG to be on the safe side though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I actually have a draft backfilling some missing entries overall, so I'll expedite that work and add this as well.

(Or, this can just be reverted and kept for posterity; now I see that when it was added in #562/files it was merely for consistency anyways?…)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Button link focus styling doesn't override inherited visited link styling

3 participants