Skip to content

feat(controls): add check and inline-check control types - #972

Merged
dannyhw merged 7 commits into
storybookjs:nextfrom
officialasishkumar:feat/check-control
Nov 14, 2026
Merged

dannyhw merged 7 commits into
storybookjs:nextfrom
officialasishkumar:feat/check-control

Conversation

@officialasishkumar

Copy link
Copy Markdown
Contributor

Issue: #541

What I did

Storybook's web Controls panel has check and inline-check controls for args that take any number of options, but the on-device controls addon had no mapping for them, so those argTypes showed "Invalid type: check" on device. This adds both, so the same argTypes work on web and on device.

  • types/Check.tsx (new): the check / inline-check control. It follows the web check control:
    • options can be an array or a label → value object (also read from control.options), and control.labels maps values to the text shown.
    • The arg is set to an array of the checked values. They're kept in the order of options, so the result doesn't depend on tap order.
    • A missing value means nothing is checked, a single value (e.g. 'bold' instead of ['bold']) checks that option, and values that aren't options are dropped.
    • Like the web control, the selection is kept locally and resynced when the arg changes from outside (reset, another client). That way several quick taps aren't lost while the previous update is still going through an async websocket channel.
  • components/CheckboxSelect.tsx (new): the checkbox list, styled like RadioSelect (same row height, hit slop, label and colours, a wrapping row for inline-check). Each row has accessibilityRole="checkbox" and its checked state.
  • types/index.ts / sharedTypes.ts: map check and inline-check to the new control.
  • Example: ControlExamples/Check stories (Basic, Inline, WithLabels) plus a CSF factories story.
  • Docs: check and inline-check sections in the controls addon docs and the stories skill reference.
  • Changeset: minor for @storybook/addon-ondevice-controls.

Tests (Check.test.tsx, Check.factories.test.tsx) render the stories, and render the control through PropField with the argTypes from getControlArgTypes. They cover:

  • the checked state
  • checking and unchecking
  • several taps before the arg comes back
  • resyncing when the arg changes
  • labels
  • missing, single and unknown values
  • inline-check

Without the mapping, all the control tests fail. To wrap the control in a ThemeProvider, the example now lists @storybook/react-native-theming as a dev dependency. That's the one-line pnpm-lock.yaml change.

I didn't add the new stories to the WebCompatibility stories or the maestro screenshot flow, since that would change the committed baselines.

If #960 lands first, this moves over as-is: the control is two new files plus two lines in the type map.

Screenshots

These are from the expo example's web export at a phone-sized viewport. The control is built only from React Native views, with no web-specific branch.

check after tapping "Mushrooms" inline-check with labels
check (dark) inline-check (dark)

How to test

pnpm build
pnpm --filter expo-example test -- components/ControlExamples/Check

I ran pnpm build, pnpm lint, pnpm format:check, pnpm --filter expo-example check, check:types for the controls addon and the full pnpm test, and all passed. I also exported the example for web and used the Controls panel of the new stories in a headless browser: tapping a checkbox updated the story.

To try it on device, run pnpm example and open ControlExamples / Check. The Basic, Inline and With Labels stories show the controls in the Controls panel.

  • Does this need a new example in examples/expo-example? Yes, included in this PR
  • Does this need an update to the documentation? Yes, included in this PR

Storybook's web Controls panel supports `control: 'check'` and
`control: 'inline-check'` for args that take any number of options, but
the on-device controls addon had no mapping for them, so those argTypes
rendered "Invalid type: check" on device.

Add a `Check` control backed by a new `CheckboxSelect` component, styled
like the existing radio control (vertical list, or a wrapping row for
`inline-check`), with `accessibilityRole="checkbox"` and the checked
state for screen readers.

It follows the web check control:

- `options` can be an array or a label -> value object, also read from
  `control.options`, and `control.labels` maps values to the text shown.
- The arg is set to an array of the checked values. Values are kept in
  the order of `options`, so the result doesn't depend on tap order.
- A missing value means nothing is checked, a single value checks that
  option, and values that aren't options are dropped.
- The selection is kept locally and resynced when the arg changes from
  outside, so several quick taps aren't lost while the previous update
  is still going through an async (websocket) channel.

The expo example gets `ControlExamples/Check` stories (CSF and CSF
factories) and tests that render the control through `PropField` and
cover checking, unchecking, quick consecutive taps, resyncing, labels,
missing and single values and `inline-check`. The example now lists
`@storybook/react-native-theming` as a dev dependency so the tests can
wrap the control in a ThemeProvider.

Docs and the stories skill reference describe the new control types.

Closes storybookjs#541
@changeset-bot

changeset-bot Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf4d295

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@storybook/addon-ondevice-controls Minor
@storybook/react-native Minor
@storybook/react-native-ui-common Minor
@storybook/react-native-ui-lite Minor
@storybook/addon-ondevice-actions Minor
@storybook/addon-ondevice-backgrounds Minor
@storybook/addon-ondevice-notes Minor
@storybook/react-native-theming Minor
@storybook/react-native-ui Minor

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

@chatgpt-codex-connector

Copy link
Copy Markdown
Codex Review Summary: ❌ Failed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ❌ Failed 2026-11-13T15:02:07.748681Z
We couldn’t complete this review. Comment @codex review to try again.
4e8b574 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

dependabot Bot and others added 6 commits November 14, 2026 00:03
* chore: update to Storybook 11.0.0-beta.3

* chore: restore storybook.requires.ts
…value (storybookjs#965)

Co-authored-by: Daniel Williams <dannyhyunsoowilliams@gmail.com>
- Track the checked option labels, like web's normalizeOptions /
  selectedKeys / selectedValues, so options sharing a label collapse into
  one checkbox (last value wins) and options sharing a value are toggled
  independently.
- Emit values in the order they were checked instead of re-sorting them
  into options order.
- Warn and render "-" when the argType has no options, and stop falling
  back to control.options, which web never reads.
- Disable and dim every checkbox when argType.table.readonly is set.

A single non-array value still checks only the option equal to it, not
options it contains as a substring.

@dannyhw dannyhw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed one commit on top to bring the control closer to the web check control:

  • checking an option appends its value to the array instead of sorting the array into options order
  • options come from argType.options only, without the control.options fallback, which web doesn't read
  • an argType with no options renders - and logs a warning
  • table: { readonly: true } disables the checkboxes

Checked on iOS and Android.

@dannyhw
dannyhw merged commit 0cb0a55 into storybookjs:next Nov 14, 2026
1 check passed
dannyhw added a commit that referenced this pull request Nov 14, 2026
Port the check/inline-check control (#972) and the number control fix (#965)
to the built-in controls in packages/react-native/src/controls. Move the
check control's PropField tests into @storybook/react-native, since
PropField is no longer reachable from the addon-ondevice-controls stub, and
retarget the check-control and number-control changesets to
@storybook/react-native.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants