Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3824470
docs: new form system
TkDodo Mar 3, 2026
93f5a8a
fix: forms category
TkDodo Mar 3, 2026
bee1641
ref: move compactSelect to buttons
TkDodo Mar 3, 2026
02ee265
ref: introduce subgroups
TkDodo Mar 3, 2026
2e8bf50
fix: don't mention fieldset anymore
TkDodo Mar 3, 2026
1ba0072
ref: use a color picker as example
TkDodo Mar 3, 2026
a97459d
fix: extract formDemos to their own file
TkDodo Mar 3, 2026
c38c7f0
fix: z.email()
TkDodo Mar 3, 2026
83cd0c5
remove optional
TkDodo Mar 3, 2026
777e1a6
fix type issues in demo forms
TkDodo Mar 3, 2026
7510b43
fix: don't infer from mutationOptions
TkDodo Mar 3, 2026
23db299
fix: form styling
TkDodo Mar 3, 2026
0c4397c
fix: eslint for story helpers in core
TkDodo Mar 3, 2026
c3387e4
simplify full example
TkDodo Mar 3, 2026
c53f28a
minor docs tweaks
TkDodo Mar 3, 2026
4687d81
intro
TkDodo Mar 3, 2026
80bb004
Merge branch 'master' into tkdodo/ref/form-docs
TkDodo Mar 3, 2026
ad1349f
Merge branch 'master' into tkdodo/ref/form-docs
TkDodo Mar 4, 2026
3c4fb2f
chore: fix knip
TkDodo Mar 4, 2026
2384b42
Update .agents/skills/generate-frontend-forms/SKILL.md
TkDodo Mar 5, 2026
eafa409
Merge branch 'master' into tkdodo/ref/form-docs
TkDodo Mar 5, 2026
d03c544
clarify what fields are built with
TkDodo Mar 5, 2026
65582b7
fix(storyTree): subtree sorting
TkDodo Mar 5, 2026
f5effb5
fix: allow forms to grow in a flex context
TkDodo Mar 5, 2026
94eccd7
explain onDynamic
TkDodo Mar 5, 2026
7a71b79
add t() everywhere
TkDodo Mar 5, 2026
7eb4658
Merge branch 'master' into tkdodo/ref/form-docs
TkDodo Mar 5, 2026
abfa5b9
fix: do not translate initialValue
TkDodo Mar 5, 2026
a6354d1
fix: use inferred component name for StoryTreeNode formatting
TkDodo Mar 5, 2026
a64f3a6
use per-field validation for dynamic field
TkDodo Mar 5, 2026
dde50ea
Merge branch 'master' into tkdodo/ref/form-docs
TkDodo Mar 6, 2026
99a87b9
controls category
TkDodo Mar 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .agents/skills/generate-frontend-forms/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,9 @@ All fields are accessed via the `field` render prop and follow consistent patter

### Radio Field

Radio fields use a composable API with `Radio.Group` and `Radio.Item`. `Radio.Group` renders a `<fieldset>` and provides group context, so the layout's label automatically renders as a `<legend>` for proper accessibility semantics.
Radio fields use a composable API with `Radio.Group` and `Radio.Item`. `Radio.Group` provides group context that changes how the label is rendered for proper accessibility semantics.

> **Important**: The layout (and its label) **must** be rendered _inside_ `Radio.Group`. The group context that makes the label render as a `<legend>` is provided by `Radio.Group`, so placing the layout outside will result in a plain `<label>` instead of the correct `<legend>` element.
> **Important**: The layout (and its label) **must** be rendered _inside_ `Radio.Group`. The group context is provided by `Radio.Group`, so placing the layout outside will result in incorrect accessibility semantics.

```tsx
<form.AppField name="priority">
Expand Down Expand Up @@ -263,17 +263,17 @@ import {Flex} from '@sentry/scraps/layout';
For one-off fields that don't have a built-in component (e.g. a color picker, or any custom input), use `field.Base`. It provides a render prop with all the necessary accessibility and form integration props (`ref`, `disabled`, `aria-invalid`, `aria-describedby`, `onBlur`, `name`, `id`) that you spread onto your native element.

```tsx
<form.AppField name="acceptTerms">
<form.AppField name="color">
{field => (
<field.Layout.Row label="Terms of Service:">
<field.Layout.Row label="Brand Color">
<field.Base<HTMLInputElement>>
{(baseProps, {indicator}) => (
<Flex flexGrow={1}>
<input
{...baseProps}
type="checkbox"
checked={field.state.value}
onChange={e => field.handleChange(e.target.checked)}
type="color"
value={field.state.value}
onChange={e => field.handleChange(e.target.value)}
/>
{indicator}
</Flex>
Expand Down
1 change: 1 addition & 0 deletions eslint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,7 @@ export default typescript.config([
'*.{ts,tsx}', // core/renderToString.tsx at the core root etc.
'*/index.{ts,tsx}', // core/form/index.tsx, core/alert/index.tsx etc.
'**/*.png', // needed for story-files
'**/__stories__/*.{ts,tsx}', // story demo helpers imported by .mdx files
],
},
{
Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@
"@stripe/stripe-js": "^5.10.0",
"@swc/plugin-emotion": "14.3.0",
"@tanstack/query-async-storage-persister": "5.83.1",
"@tanstack/react-devtools": "^0.9.3",
"@tanstack/react-form": "^1.28.0",
"@tanstack/react-form-devtools": "^0.2.13",
"@tanstack/react-pacer": "^0.17.0",
"@tanstack/react-query": "5.85.0",
"@tanstack/react-query-devtools": "5.85.0",
Expand Down
Loading
Loading