refactor(core): lean out SpectrumElement - #6523
Conversation
Trim SpectrumElement to only what every 2nd-gen component needs: - Extract `hasVisibleFocusInTree` into the `isFocusVisibleInTree(root)` utility (mirrors the existing `getActiveElement` util it wraps); add a unit test and export from `@adobe/spectrum-wc-core/utils`. No 2nd-gen component consumed the method. - Remove the `get dir()` override. 2nd-gen resolves direction via `getComputedStyle(...).direction` at each call site; nothing read `element.dir`. - Remove the now-empty `SpectrumMixin` / `SpectrumInterface`. Their only remaining job was a non-null `shadowRoot` retype nothing relied on (all reads use `?.`). `SpectrumElement` now extends `LitElement` directly. - Drop the stale `hasVisibleFocusInTree` / `dir` entries from the Storybook argTypes hide-list. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 79bc21d The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| /** | ||
| * @internal | ||
| */ | ||
| public override get dir(): CSSStyleDeclaration['direction'] { |
There was a problem hiding this comment.
I'm ok with removing this... but it made me think... which should be the source of truth for directionality in our components? probably worth creating a helper that is reused everywhere we access it. I opened a Slack thread in our team channel!
There was a problem hiding this comment.
Thanks — leaving the removal in. Today 2nd-gen already resolves directionality via getComputedStyle(...).direction at each call site (Tabs, Tooltip, focusgroup + placement controllers), so nothing reads element.dir. Happy to consolidate that into one shared helper as a follow-up from your Slack thread; leaving this thread open for that discussion.
…d API Address review feedback on the SpectrumElement cleanup: - Rewrite the util test to actually exercise every branch: keyboard focus via `userEvent.tab()` proves the true (`:focus-visible`) branch; programmatic focus on a button proves the "active but not focus-visible" false branch; and an empty attached shadow root proves the `root` argument scopes the query. Drops the meaningless detached-shadow-root check and the redundant fixture null-guard. - Update the focus-management contributor guide to document the `isFocusVisibleInTree(root)` utility instead of the removed `SpectrumElement.hasVisibleFocusInTree()` method; regenerate nav. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Pushed Test quality (@rubencarvalho, @Rajdeepc) — rewrote
Docs (@Rajdeepc) — updated Directionality (@rubencarvalho) — left the Note: the three red checks on the previous commit were transient infra failures, not this PR — Lint hit |
Coverage Report for CI Build 30121125834Warning Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes. Coverage remained the same at 96.243%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats💛 - Coveralls |
…leInTree
Chromium and WebKit paint :focus-visible on a programmatic .focus() when no
mouse-down preceded it, so the "active but not :focus-visible" case was not
deterministic. Remove it; the nothing-focused (false) and keyboard-focus (true)
cases already exercise both branches of `active?.matches(':focus-visible') ?? false`,
and the attached-shadow-root scoping case remains.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📚 Branch Preview Links🔍 Gen1 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 |
|
@Rajdeepc the two blocking items are resolved and CI is green:
The directionality ( |
cdransf
left a comment
There was a problem hiding this comment.
Looks rad! Just one tiny docs nit ✨
The strategy RFC still described hasVisibleFocusInTree() as a SpectrumMixin method. Update its references (§2, §4.5, §5, §7, §8, Appendix A.7, and the TOC) to reflect that it was extracted to the isFocusVisibleInTree() utility and that SpectrumMixin was removed (SpectrumElement now extends LitElement directly).
Description
Trims
SpectrumElement(2nd-gen@adobe/spectrum-wc-core) down to only what every component actually needs, and moves an unused helper out to a utility.hasVisibleFocusInTree→isFocusVisibleInTree(root)util. It has zero 2nd-gen component callers and is a one-liner over the existinggetActiveElementutil. Now exported from@adobe/spectrum-wc-core/utilswith a unit test. This follows the project rule that a helper used by two or fewer components belongs in utils.get dir()override. It returned the computed direction and was load-bearing in 1st-gen, but 2nd-gen deliberately resolves direction viagetComputedStyle(...).directionat each call site (Tabs, Tooltip, focusgroup-navigation and placement controllers). No 2nd-gen component, controller, test, or Storybook addon readselement.dir.SpectrumMixin/SpectrumInterface. Once the focus helper moved out, the mixin's only remaining job was re-typingshadowRootas non-null, which nothing relied on (every read already uses?.). It was applied exactly once, toLitElement, bySpectrumElementitself.SpectrumElementnowextends LitElementdirectly andshadowRootreverts toShadowRoot | null.dir/hasVisibleFocusInTreeentries from the argTypes hide-list.Why this is low risk
hasVisibleFocusInTreehad 0 2nd-gen callers;.dirhad 0 JS reads in 2nd-gen source;SpectrumMixin/SpectrumInterfacewere imported by no component and re-exported nowhere; no code readsthis.shadowRootwithout optional chaining.get dir()removal aligns with existing 2nd-gen convention, which already prefers per-sitegetComputedStyle(...).direction(with an in-code comment justifying not walkingdir).SpectrumMixin/SpectrumInterfaceexports from@adobe/spectrum-wc-core. No known external consumer uses them; cheap to remove pre-1.0 (0.3.0) and captured in the changeset as aminorbump.Motivation and context
SpectrumElementis the root of 34 2nd-gen component bases. Keeping it minimal reduces surface area, removes 1st-gen carryovers that 2nd-gen has already replaced, and keeps shared helpers where the project conventions expect them.Related issue(s)
Author's checklist
Manual review test cases
Build and lint pass
yarn buildyarn lintFocus utility behaves as before
isFocusVisibleInTreefalsewhen nothing is focused, and a value matching:focus-visiblefor the active elementStorybook renders cleanly
dirorhasVisibleFocusInTreerows and no console errorsDevice review
Accessibility testing checklist
Keyboard
mainScreen reader
main