feat(link): 2nd-gen template, stories, styling#6326
Conversation
|
📚 Branch Preview Links🔍 First Generation Visual Regression Test ResultsWhen a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:
Deployed to Azure Blob Storage: If the changes are expected, update the |
cdransf
left a comment
There was a problem hiding this comment.
Looks good! Just a few minor things. ✨
|
|
||
| @import url("../link.css"); | ||
|
|
||
| @media (forced-colors: active) { |
There was a problem hiding this comment.
Can we move this media query block to the bottom of the file? ✨
| * @cssprop --swc-link-line-height-cjk - CJK standalone link line height | ||
| */ | ||
|
|
||
| @media (forced-colors: active) { |
There was a problem hiding this comment.
Forced color overrides aren't needed, those are the defaults anyway!
5t3ph
left a comment
There was a problem hiding this comment.
Great start here!
The comments I have on link would apply to global-link as well.
| } | ||
| } | ||
|
|
||
| .link-samples { |
There was a problem hiding this comment.
I was originally going to say drop these in favor of the typography ones but see later comment about removing the wrappers entirely, in which case these can also be removed.
| export const StaticWhite: Story = { | ||
| args: { | ||
| context: 'standalone', | ||
| variant: 'staticWhite', | ||
| sampleText: 'white link', | ||
| }, | ||
| tags: ['options'], | ||
| }; | ||
|
|
||
| export const StaticBlack: Story = { | ||
| args: { | ||
| context: 'standalone', | ||
| variant: 'staticBlack', | ||
| sampleText: 'black link', | ||
| }, | ||
| tags: ['options'], | ||
| }; |
There was a problem hiding this comment.
I know documentation is a separate phase but just to note you can use the staticColorsDemo: true to get the background wrapper, and ultimately put these variants in one story (ex. like progress circle) since that decorator expects a child of each type
| }, | ||
| }; | ||
|
|
||
| function cls(...parts: Array<string | false | null | undefined>): string { |
There was a problem hiding this comment.
I see taht I also incorrectly had this in the typography template, but we should use classMap from Lit instead of maintain different versions of our own :)
| * @cssprop --swc-link-text-color - Link text color | ||
| * @cssprop --swc-link-text-color-hover - Link text color on hover | ||
| * @cssprop --swc-link-text-color-down - Link text color on active | ||
| * @cssprop --swc-link-text-color-focus - Link text color on focus-visible | ||
| * @cssprop --swc-link-focus-indicator-color - Focus ring color | ||
| * @cssprop --swc-link-font-family - Standalone link font family | ||
| * @cssprop --swc-link-font-size - Standalone link font size | ||
| * @cssprop --swc-link-font-weight - Standalone link font weight | ||
| * @cssprop --swc-link-inline-font-weight - Inline link font weight override | ||
| * @cssprop --swc-link-line-height - Standalone link line height | ||
| * @cssprop --swc-link-line-height-cjk - CJK standalone link line height |
There was a problem hiding this comment.
These can be removed as they won't be picked up since this isn't a web component.
| } | ||
|
|
||
| .swc-Link { | ||
| --_swc-link-focus-indicator-thickness: token("focus-indicator-thickness"); |
There was a problem hiding this comment.
We have overexposure of custom properties and unnecessary extra private properties. Since these are always light DOM styles, we don't really need to worry about exposing any outside of ones that are useful for the modifiers. Have the agent refer to our custom property guidelines to help resolve.
| /* ========================= | ||
| Links (prose and link lists) | ||
| ========================= */ | ||
| .swc-Typography--prose :where(a), |
There was a problem hiding this comment.
I know these are from the generator, I just marked them up here! :)
[nit] We could simplify this selector:
| .swc-Typography--prose :where(a), | |
| :is(.swc-Typography--prose, .swc-Typography--links) :where(a) |
| }; | ||
|
|
||
| /** Standalone `.swc-Link` sets its own font-size; prose/links inherit from `swc-Body`. */ | ||
| const STANDALONE_SIZE_FONT_VARS: Record<LinkSize, string | undefined> = { |
There was a problem hiding this comment.
I think let's skip "size" as a Playground option and not do this, the complication isn't needed.
| export const Playground: Story = { | ||
| args: { | ||
| variant: 'default', | ||
| context: 'standalone', |
There was a problem hiding this comment.
Across all stories - let's skip standalone unless you're actually demonstrating it in a story since otherwise it makes it seem like you need to have swc-Link swc-Link--standalone for the default appearance, which is incorrect.
| * OF ANY KIND, either express or implied. See the License for the specific language | ||
| * governing permissions and limitations under the License. | ||
| */ | ||
|
|
There was a problem hiding this comment.
I know the patterns from Typography inspired some of this setup, but I think we can simplify and not have the wrappers (like .link-samples / .link-row) at all and just have the bare link, one per demo, plus the use of the static colors decorator I noted in another comment.
| background-color: transparent; | ||
| cursor: pointer; | ||
| outline: none; | ||
| transition: color token("animation-duration-100") ease-in-out; |
There was a problem hiding this comment.
Add this to prevent it stretching in something like a flex context and unexpectedly catching clicks in "blank" space:
| transition: color token("animation-duration-100") ease-in-out; | |
| transition: color token("animation-duration-100") ease-in-out; | |
| inline-size: fit-content; |
Description
Implements Phases 2–5 of the Link 2nd-gen migration (washing-machine workflow): setup, public API direction, accessibility policy documentation, and S2 styling. Phase 6 (testing) and full Phase 7 (documentation) are not in scope — Storybook stories, migration guide, and Typography cross-links are included only as a visual validation scaffold and will be refined in a follow-up PR along with dedicated a11y verification and automated tests.
Link is an atypical migration: there is no
swc-linkcustom element and no core package. Delivery is CSS + native<a href>, aligned with migration plan and PR 6304 packaging review.2nd-gen files added or updated (
2nd-gen/packages/):Stylesheets
swc/stylesheets/link.css— S2 link presentation migrated fromspectrum-cssspectrum-two(components/link/index.css); BEM modifiers (.swc-Link,--secondary,--quiet+--standalone,--staticWhite,--staticBlack,--inline);--swc-*custom properties (no--mod-*)swc/stylesheets/global/global-link.css— opt-in baseline for bare<a>(no cascade layer; importslink.cssfor modifiers)swc/stylesheets/typography.css— regenerated; default anchor rules for.swc-Typography--proseand.swc-Typography--linksvia:where(a)tools/swc-tokens/src/typography.js— generator appends prose/links anchor block (no@importoflink.cssinto typography)Documentation (scaffold — Phase 7 follow-up)
swc/components/link/migration-guide.mdx—sp-link→ native<a>, import paths, attribute→class mapping, a11y policy calloutsswc/components/link/stories/link.stories.ts+link.template.ts— Playground + option stories for standalone / prose / link-list contexts (visual review only)swc/components/typography/migration-guide.mdx— links section; cross-link to Link guideswc/components/typography/stories/typography.stories.ts— inline link in Prose story;LinkListstory (swc-Typography--links)Packaging / Storybook
swc/package.json— exports forlink.cssandglobal-link.cssswc/.storybook/preview.ts— importslink.cssswc/.storybook/preview-head.html—.link-sampleslayout utilitiesMotivation and context
Part of the 1st-gen → 2nd-gen component migration workstream. Epic SWC-1956.
Key architectural decisions in this PR (see migration plan for full rationale):
<a>only — no transitionalsp-link/ CE; prose and link lists use Typography wrapperslink.cssholds explicit BEM modifiers;typography.css(generator) supplies default unclassed anchor appearance inside.swc-Typography--proseand.swc-Typography--linkswith:where(a)so modifier classes can overrideglobal-link.cssis opt-in for app-wide bare<a>baseline — not bundled inswc.css, intentionally outside cascade layers.swc-Link--quiet.swc-Link--standalone(section-scoped pattern; not for undifferentiated body prose)variantlike 1st-gendisabledon navigational links — documented in migration guide (SWC-966)Related issue(s)
Out of scope (follow-up PR)
Manual review test cases
Stylesheets
@adobe/spectrum-wc/link.cssand@adobe/spectrum-wc/typography.css; confirm standalone.swc-Linkmodifiers (default, secondary, static white/black, quiet+standalone) match S2 intent.swc-Typography--prose, unclassed<a href>inherits body typography and shows default link color/underline/focus ring.swc-Typography--links, three list links render with default styling (Typography Link list story and Link Link list story)@adobe/spectrum-wc/global-link.css— bare<a>without classes pick up standalone link presentationGenerator / packaging
yarn workspace @adobe/spectrum-wc stylesheet:typographyregeneratestypography.csswith the prose/links:where(a)block; no@importoflink.cssin typography outputyarn workspace @adobe/spectrum-wc buildemitsdist/link.cssanddist/global-link.cssStorybook scaffold (visual only)
Migration docs
sp-linkattributes to BEM classes and Typography import pathsAccessibility testing checklist
Full keyboard and screen reader testing is deferred to the Phase 6/7 follow-up PR (native
<a>behavior, focus-visible in prose, quiet usage scope). Reviewers can verify policy direction from docs/code:<a href>for navigation; nodisabledon links; quiet scoped to section patterns; icon-only links need accessible names:focus-visibleoutline (not deprecated double-underline-only focus from 1st-gen)sp-link/ shadow-DOM focus delegation — activation target is the author’s native anchor