Refactor(web-react): Standalone Label, HelperText & ValidationText #DS-2398#2547
Conversation
✅ Deploy Preview for spirit-design-system canceled.
|
|
Here is the URL of the uploaded artifact: https://github.com/alma-oss/spirit-design-system/actions/runs/23202889982/artifacts/5968123307 |
|
Here is the URL of the uploaded artifact: https://github.com/alma-oss/spirit-design-system/actions/runs/23202890306/artifacts/5968128753 |
|
when #2548 is merged, the e2e should be ok |
96bc3fb to
a8484cf
Compare
|
Here is the URL of the uploaded artifact: https://github.com/alma-oss/spirit-design-system/actions/runs/23204858220/artifacts/5969035406 |
There was a problem hiding this comment.
Pull request overview
This PR refactors form-field subcomponents in web-react by extracting Label, HelperText, and ValidationText into standalone components (instead of being bundled under Field), and updates the web (vanilla) docs/demos to use the new “default Label” styling (no Label--box).
Changes:
- Introduces standalone
Label,HelperText, andValidationTextcomponents inpackages/web-reactand wires them into existing form controls viaPropsProvider. - Updates multiple vanilla
packages/webcomponent demos/READMEs to useclass="Label"(and related modifiers) consistently. - Removes the
Fieldsubpath export and related types/tests, and adds supporting hooks/types (useAriaIds,FormFieldVariants, shared form-field context types).
Reviewed changes
Copilot reviewed 135 out of 143 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/web/src/scss/components/** | Updates HTML demos/READMEs to use Label base class instead of Label--box and adjusts related markup formatting. |
| packages/web/src/scss/components/Label/_Label.scss | Removes the explicit “box variant” selector and makes “box” the default (non-inline, non-item). |
| packages/web-react/src/components/** | Replaces Field/* usage with standalone Label, HelperText, ValidationText and introduces styling hooks for these components. |
| packages/web-react/src/context/PropsContext.ts | Filters undefined from provider values to avoid unintentionally overwriting parent context. |
| packages/web-react/package.json | Removes ./components/Field export from the package export map. |
Comments suppressed due to low confidence (1)
packages/web-react/package.json:328
- The package export map removes the
./components/Fieldsubpath export, but there are no new subpath exports for the new standalone components (./components/Label,./components/HelperText,./components/ValidationText). Given the pattern used for other components, this likely makes the new standalone components unavailable via subpath imports and introduces a breaking change for existing.../components/Fieldconsumers. Consider adding explicit exports for the new component subpaths (and/or a compatibility re-export forField) and ensuring this is handled as a documented breaking change.
"require": "./dist/components/EmptyState/index.cjs",
"default": "./dist/components/EmptyState/index.js"
},
"./components/FieldGroup": {
"types": "./dist/components/FieldGroup/index.d.ts",
"development": "./src/components/FieldGroup/index.ts",
"production": "./dist/components/FieldGroup/index.js",
"import": "./dist/components/FieldGroup/index.js",
"require": "./dist/components/FieldGroup/index.cjs",
"default": "./dist/components/FieldGroup/index.js"
},
packages/web-react/src/components/HelperText/__tests__/HelperText.test.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/HelperText/__tests__/HelperText.test.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/Checkbox/__tests__/Checkbox.test.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/HelperText/__tests__/HelperText.test.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/HelperText/__tests__/HelperText.test.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/HelperText/__tests__/HelperText.test.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/UNSTABLE_FileUpload/__tests__/UNSTABLE_FileUpload.test.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/UNSTABLE_FileUpload/__tests__/UNSTABLE_FileUpload.test.tsx
Show resolved
Hide resolved
packages/web-react/src/components/ValidationText/demo/index.tsx
Outdated
Show resolved
Hide resolved
✅ Deploy Preview for spirit-design-system-storybook canceled.
|
|
Here is the URL of the uploaded artifact: https://github.com/alma-oss/spirit-design-system/actions/runs/23301127719/artifacts/6008408670 |
|
I updated the PR and tried to resolve all your comments; hopefully, I didn't miss anything or resolve any unresolved issues. If it happened, I'm sorry, and let me know. |
…ared hooks #DS-2398
packages/web-react/src/components/UNSTABLE_FileUpload/UNSTABLE_FileUpload.tsx
Show resolved
Hide resolved
dlouhak
left a comment
There was a problem hiding this comment.
Significant: Could you please add stories for Label and ValidationText?
Nitpicking: A few comments about query selectors. Looks like we should write down the rules for writing unit tests for coding agents. 🙈
packages/web-react/src/components/Label/__tests__/Label.test.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/UNSTABLE_FileUpload/UNSTABLE_FileUpload.tsx
Outdated
Show resolved
Hide resolved
packages/web-react/src/components/Label/__tests__/useLabelStyleProps.test.ts
Outdated
Show resolved
Hide resolved
|
Here is the URL of the uploaded artifact: https://github.com/alma-oss/spirit-design-system/actions/runs/23482434335/artifacts/6076851956 |
|
Here is the URL of the uploaded artifact: https://github.com/alma-oss/spirit-design-system/actions/runs/23485099826/artifacts/6077992458 |
|
Here is the URL of the uploaded artifact: https://github.com/alma-oss/spirit-design-system/actions/runs/23497208260/artifacts/6083340977 |
There was a problem hiding this comment.
Security review update: I re-validated the current diff and checked prior unresolved review threads; no unresolved security findings remain applicable.
I reviewed only modified code paths and traced attacker-controlled inputs to sinks in the new standalone Label, HelperText, and ValidationText integrations (PropsProvider propagation, aria registration, and rendering in form components). I did not find any medium/high/critical vulnerability introduced by this PR:
- No new HTML/JS injection sink (
dangerouslySetInnerHTML,eval, dynamic script construction) was introduced. - User-provided label/helper/validation content remains rendered through React nodes (framework escaping applies for string content).
- No auth/authz boundary changes, request-forgery surfaces, SSRF/path traversal/file-system sinks, or secret logging paths were introduced in changed runtime code.
- No dependency/supply-chain risk was introduced by this diff.
Inline finding comments: none (no high-confidence security vulnerability).
Slack summary: PR #2547 security review complete — no medium/high/critical vulnerabilities found in modified code paths; no active security findings to address.
Sent by Cursor Automation: Find vulnerabilities
packages/web-react/src/components/Checkbox/__tests__/Checkbox.test.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Stale comment
Code Review:
refactor/DS-2398-react-standalone-form-fieldsScope: 12 commits, 165 files (+7410 / −2723)
Overview
- Splits
Label,HelperText, andValidationTextout of the removedFieldpackage into first-class components with their ownpackage.jsonsubpath exports and barrel exports.- Moves
useAriaIdsintohooks, adds focused tests, and wires form controls (TextFieldBase,Checkbox,Select,Slider,Toggle,FieldGroup, file uploaders, etc.) to the standalone pieces plusPropsProviderfor shared field context.- Tightens
PropsProvidermerging so explicitnull/undefinedvalues remove keys from inherited context (documented in JSDoc).- Carries related SCSS demo/README updates, dropdown placement default handling, and refreshed visual snapshots.
1.
packages/web-react/package.json— Subpath exportssuggestion (non-blocking): Document removal of
@alma-oss/spirit-web-react/components/Fieldand map consumers to@alma-oss/spirit-web-react/components/Label,HelperText, andValidationText(or the main package barrel).Fix: Add a short entry to the next release notes / migration doc (e.g.
docs/migrations/web-react/orCHANGELOG.md) with before/after import examples.Why: The
./components/Fieldexport entry was removed; anyone using that deep import will get a resolution failure on upgrade. Calling it out avoids silent breakage during version bumps.
Summary
Finding type Count issue 0 suggestion 1 question 0 note 0 Verdict: APPROVE
No blocking issues; the refactor is coherent, tests and snapshots were updated, and accessibility registration for helper/validation text is preserved (with a small improvement: cleanup no longer calls
removewhenidis missing).
praise: Solid extraction: shared
FormFieldContextValuetyping,PropsProvider+useContextPropsprecedence documented, dedicated stories/demos for the new components, and broad test updates across inputs and provider tests—good regression safety for a structural change like this.Sent by Cursor Automation: Spirit Cursor Code Review
|
Here is the URL of the uploaded artifact: https://github.com/alma-oss/spirit-design-system/actions/runs/23584370096/artifacts/6118857987 |
There was a problem hiding this comment.
Stale comment
Code Review:
refactor/DS-2398-react-standalone-form-fieldsScope: 15 commits, 168 files (+7376 / −2731)
Overview
- Extracts Label, HelperText, and ValidationText as standalone components with dedicated style hooks, demos, stories, and tests.
- Removes the old Field subcomponents and wires form controls (TextFieldBase, Checkbox, Radio, Select, Slider, Toggle, FieldGroup, FileUploader, UNSTABLE_FileUpload, etc.) to compose these pieces with PropsProvider and
useAriaIdsforaria-describedby.- Moves
useAriaIdsto shared hooks and expands formFieldContextPropsTest for consistent context vs. direct-prop behavior.- Updates Dropdown so
useDropdownContextalways yields a definedplacement, and stops settingdata-spirit-placementfromuseDropdownAriaProps(placement still drives classes viauseDropdownStyleProps).- Refreshes web SCSS demos/docs and visual snapshots for the new composition patterns.
Summary
Category Count Blocking 0 Non-blocking 2 Questions 1 Praise 1 Findings by file
1.
packages/web-react/src/components/ValidationText/ValidationText.tsx— List renderingissue (non-blocking): Array
validationTextitems usekey={\validationText_${item}`}`, which collides when two entries share the same string.File:
Fix: Use the index (or a stable id if messages can be reordered) as part of the key, e.g.
key={\validationText_${index}_${String(item)}`}`.Why: Duplicate messages produce duplicate React keys, which can cause incorrect reconciliation and confusing updates.
2.
packages/web-react/src/hooks/useAriaIds.ts— Externalaria-describedbysuggestion (non-blocking):
otherAriaIdsis only read on the initial render; if a parent passes a newaria-describedbystring later, internal state does not resync.File:
Fix: Consider syncing when
otherAriaIdschanges, e.g.useEffect(() => { setIds(otherAriaIds ? otherAriaIds.split(' ') : []); }, [otherAriaIds]);— only if controlled updates toaria-describedbyare in scope; otherwise document that the hook treats the initial string as static.Why: Avoids stale
aria-describedbywhen the prop is driven by parent state.
3.
packages/web-react/src/components/Dropdown/useDropdownAriaProps.ts—data-spirit-placementquestion (non-blocking):
data-spirit-placementwas removed from popovercontentProps; placement classes still come fromuseDropdownStyleProps.File:
Why: Confirm this matches product/docs expectations for scripts or tests that read
data-spirit-placementon the React-rendered popover.
Verdict
COMMENT — One non-blocking issue (list keys); no blocking findings.
praise: Strong refactor: clear separation of Label / HelperText / ValidationText, consistent PropsProvider +
useAriaIdswiring across inputs, thorough formFieldContextPropsTest coverage, and good README/demo alignment for consumers building custom fields.Sent by Cursor Automation: Spirit Cursor Code Review
There was a problem hiding this comment.
Code Review: refactor/DS-2398-react-standalone-form-fields
Scope: 16 commits, 168 files (+7519 / −2731)
Overview
- Extracts Label, HelperText, and ValidationText into standalone components with style hooks, demos, stories, and package exports; removes the Field barrel and
./components/Fieldexport map entry. - Moves
useAriaIdstohooks/, wiresregisterAriafrom form controls into helper/validation text foraria-describedby, and adds sharedformFieldContextPropsTestcoverage. - Updates
PropsProvidermerge semantics so nested providers can clear inherited keys (e.g.null), with JSDoc aligned to direct-prop precedence. - Adjusts Dropdown so
useDropdownContextalways exposesplacement(with default) and stops duplicating placement on the popover viadata-spirit-placement(placement remains on the styled popover path).
Summary
| Severity | Count |
|---|---|
| Blocking | 0 |
| Non-blocking | 2 |
| Questions | 0 |
| Notes | 1 |
Verdict: APPROVE
No blocking findings. One suggestion on list item keys in ValidationText (duplicate string messages) and a note on documenting the Field removal for consumers. Nice work on tests and context precedence coverage.
Full review (Conventional Comments, file-grouped)
See automation output / thread for grouped findings with permalinks.
Sent by Cursor Automation: Spirit Cursor Code Review
… all components #DS-2398 Drop Field components as they are all already split into standalone components.
…lacement demo - web-react: resolve placement in useDropdownContext; stop setting data-spirit-placement on popover - web: add placement-bottom-start on modal dropdown popover demo
971a82b to
9c34369
Compare


Description
Additional context
Issue reference