Add a shared useControllableState hook
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 70
- Forks
- 13
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 8
Description
Summary
Components that support both controlled and uncontrolled usage each re-implement the controlled/uncontrolled merge by hand, with a slightly different shape every time. There's no shared hook for it in packages/raystack/hooks.
Current duplication
sidebar-root.tsx:128-129—const [internalOpen, setInternalOpen] = useState(defaultOpen); const open = providedOpen ?? internalOpen;select-root.tsx:113-122— same??pattern, duplicated again forsearchValuea few lines later.data-view.tsx:73-83— different style again: explicitisViewControlled = view !== undefinedboolean instead of??.
Components built directly on Base UI primitives (Checkbox, Switch, Tabs, Accordion, Dialog) don't have this problem — they get controlled/uncontrolled handling for free from Base UI. This only affects components with custom root logic.
Suggested approach
Add one useControllableState({ value, defaultValue, onChange }) hook to packages/raystack/hooks, modeled on @radix-ui/react-use-controllable-state. Migrate Sidebar, Select, and DataView onto it so all three follow the same merge semantics.
Notes
Found via a components.build practices audit (state management dimension).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/raystack/hooks and compare the controlled/uncontrolled patterns in sidebar-root.tsx, select-root.tsx, and data-view.tsx. Read the referenced @radix-ui/react-use-controllable-state model, then verify that Sidebar, Select, and DataView use the shared semantics consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100