Repository navigation
feat(Citation): expose the icon wrapper as the citation-icon theme target - #7780
freddymeta wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| Citation · Storybook | 19.9 kB (+12 B) · 4.4 kB CSS (0) | 239 (+5) | — · — · — |
| lab/CommentThread | 227.6 kB (+9 B) · 2.4 kB CSS (0) | — | — · — · — |
| Markdown | 145.3 kB (+5 B) · 18.3 kB CSS (0) | — | — · — · — |
1 more component
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| lab/Comments | 232.9 kB (+5 B) · 2.5 kB CSS (0) | — | — · — · — |
Package size: @astryxdesign/core 6.11 MB packed (+66 B); no new dependencies.
API changes: core +1 · ~0 · −0
Committed API report behind this build: core 51 rows; run pnpm api:report.
1 API change (advisory)
| Package | Where | Signature | Usage | |
|---|---|---|---|---|
| + | core |
Theme targets · target citation-icon (Citation) |
target citation-icon (Citation) |
defineTheme({components: {'citation-icon': {…}}}) |
Wide change (shared styles: packages/themes/probe/src/probeTheme.ts): add ci:run-visual, ci:run-a11y or ci:run-rtl to run them.
Generated by PR Enrichment workflow | View full report
There was a problem hiding this comment.
The citation-icon target is implemented cleanly: the new tests and the theming-targets guard cover it, and unthemed Citation renders identically in light and dark mode. Approval now waits on a maintainer decision, not a code change. component:Citation is still a draft, and its FR6 says Citation exposes no icon target "without an approved theming-contract change", so a maintainer needs to approve or rewrite the proposed FR6, AV1 and ### Theming anatomy map, which settles whether citation-icon becomes a public theme target. Nothing else is needed from you for now.
[Automated review]
…rget The decorative source-icon wrapper paints the icon ring (size, radius, fill, border) but carried no theme class, so a theme had to key on `.astryx-citation > span[aria-hidden='true']`. It now renders `astryx-citation-icon` through the same mergeProps(themeProps, stylex.props) path as the root. No visual prop is reflected: the wrapper renders only in the label variant when a source icon is present and varies by nothing else. Default rendering is unchanged; the probe theme fixture is regenerated so the visual gate covers the new target.
68d9528 to
ba77c5a
Compare
|
Rebased onto @cixzhang — the one open decision is yours: admit |
User need
Theme authors who need to restyle Citation's source-icon ring. The decorative icon wrapper (
styles.iconWrap) paints a 16px circle with a surface fill and a border, and it is the only Citation element without a theme target. A theme that wants a bare icon — or a different ring size, fill or radius — has no selector for it:defineThemeemits one compound selector on one element, so acitationoverride cannot reach a child.--border-width/--color-border, which the label pill also uses, so neutralising them on the root strips the pill's border too.className.The only remaining move is structural CSS keyed on the wrapper being the sole
aria-hiddenchild:.astryx-citation > span[aria-hidden='true']. That selector depends on child order and an ARIA attribute, so an internal restructure or an a11y change breaks a shipped theme silently. This is the Citation row of #5417.Problem and solution fit
The wrapper now renders
astryx-citation-iconthrough the samemergeProps(themeProps(...), stylex.props(...))path the root uses. One class, no new prop, no new API for a consumer to learn; the structural selector above becomes'citation-icon': {base: {...}}.No visual prop is reflected. The wrapper renders only in the label variant when a source icon is present and varies by nothing else, so a
variantreflection would claim variation that does not exist.Current specification
component:Citation(docs/specs/components/Citation/Citation.spec.md, now authoritycurrent, owner @cixzhang). Its FR6 reads "exposes no internal icon or text target without an approved theming-contract change" — this PR is that change, and the spec edit here is the proposed amendment for the owner to accept or rewrite: FR6 admitscitation-iconon the decorative wrapper (and keeps the label text target-less), with matching updates to the contract table, AV1, the design-relationships row and the FR6 verification row, plus the checked### Theming anatomyblock (Container → citation,Icon → citation-icon,Label text/Numberinherit). Same shape as the Banner frame (banner-frame) and FileInput upload-icon (file-input-icon) amendments.Checked against the theming records and the wiki:
component-theming-surfaceINV2/INV3 — anatomy anchors targetscitation-iconmaps to the existingIconanatomy entry; the anatomy block maps all four entries,check:knowledgeenforces it (renaming the entry or the target fails the check — verified).backgroundColor,borderWidth/Style/Color,borderRadius,width/height. It is not a positioning or event wrapper.<img>or a node); an Astryx<Icon>keepsastryx-icon.visualProps.citation-iconfollows<component>-icon(banner-icon,file-input-icon,nav-icon— the last also sits on a wrapper span around a caller-supplied node).citation.citation+icon, kebab-cased.--border-width/--color-border.themingTargets.test.ts, with the negative control below.citationuntouched.Public delta and caller burden
astryx-citation-icon(novisualProps), documented inCitation.doc.mjstheming.targets. Additive;citationunchanged.aria-hidden="true"before the merged props, and its StyleX ring styles are preserved beside the class (tested).main(below).Before (theme CSS a theme ships today):
After, with keys from the guaranteed-property catalog (
architecture:component-theming-surface):width/heighton the wrapper stay best-effort (outside the catalog, INV9); the wrapper isinline-flex, so a bare icon still gets its 16px box from the glyph.Design and alternatives
<img>/ icon node: the ring is what paints and what themes need; the inner node is either the caller's or alreadyastryx-icon(INV5).visualProps: ['variant']: the element never renders in the number variant, so the attribute would never vary.Evidence
Storybook
core-citation--with-node-icon, Chromium (Playwright),main @ 381c0d272avs this PR (re-measured after the rebase; numbers unchanged from the first run on4a2f608f8e), same story loaded under theneutralandprobethemes. The probe theme is the repo's generated fixture that styles every documented target with a distinct colour; regenerated here so it now carriescitation-icon. The same regeneration also picks upcommand-palette-item'shighlighted/selected/disabledstates, whichmaindocuments but never regenerated into the fixture (pnpm visual:probe-theme:checkfails on a cleanmain); the file is generated, so it is committed as the generator emits it rather than hand-trimmed.background-color/border-colorrgb(255,255,255)/rgba(0,0,0,.08)border-width/border-radius/ size1px/9999px/16×16background-colorrgba(0,0,0,0)b72f819e5bf2…background-colorrgb(255,255,255)(no target)rgb(235,152,20)= probecitation-iconborder-colorrgb(0,224,255)(token)rgb(110,34,17)= probecitation-iconbackground-colorrgb(168,224,36)= probecitation variant:label.astryx-citation-iconcountcore-citation--label(no icon): no.astryx-citation-iconon either build, screenshots identical under both themes.EPS-shaped override through the real path (
defineTheme+<Theme>in a scratch story, not committed):'citation-icon': {width:'auto', height:'auto', border:'0', borderRadius:'0', background:'none'}→ wrapper computedborder-width: 0px,border-radius: 0px,background-color: rgba(0,0,0,0). Negative control: the same declarations oncitation-glyph(a class Citation never renders) leave the wrapper at1px/9999px/rgb(255,255,255).Image lives on the asset-only branch
assets/pr-7780; delete it with the PR.Guard negative controls:
Citation.doc.mjstoastryx-citation-glyph→themingTargets.test.tsfails: "core/Citation renders 1 astryx-* class(es) that … does not document: astryx-citation-icon".main'sCitation.tsx→ 4 of the 5 fail (the three icon sources and the StyleX-preserved check); the two placement guards pass on both, as they should.Scope
Testing
pnpm build✓,pnpm lint:strict✓ (0 errors),pnpm -F @astryxdesign/core typecheck✓,pnpm check:knowledge✓,pnpm check:changesets✓,pnpm visual:probe-theme:check✓pnpm exec vitest run packages/core/src/Citation packages/core/src/theme/themingTargets.test.ts→ 462 passed (29 Citation, 433 guard)pnpm testlocally (shared, loaded box): every failure is a|node|CLI subprocess timeout at 30–120 s plus two|ui|files that pass in isolation (DropdownMenuLazySheet.test.tsx,Resizable/utils.test.ts); nothing in Citation, theme, or probe. Relying on CI for the full run.mainand this branch; matrix above.Writing rubric results