feat(checkbox): accessibility features, size variants, and custom icons#741
feat(checkbox): accessibility features, size variants, and custom icons#741rohanchkrabrty wants to merge 4 commits intomainfrom
Conversation
…ns, and group orientation Add focus-visible ring (WCAG 2.4.7), readOnly styling, invalid/required state styling, fix disabled+checked hover bug, add indeterminate hover feedback, size variants (small/large), custom icon props (checkedIcon, indeterminateIcon), explicit parent/inputRef prop types, and CheckboxGroup orientation prop (vertical/horizontal). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 58 minutes and 46 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR extends the Checkbox and CheckboxGroup components with new customization options. It introduces a Possibly related issues
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…visible ring
- Remove focus-visible CSS (cross-cutting concern, not checkbox-specific)
- Replace checkedIcon/indeterminateIcon props with children prop that
accepts ReactNode or render function receiving { checked, indeterminate }
- Remove explicit inputRef/parent from CheckboxItemProps (already
exposed via Base UI's CheckboxPrimitive.Root.Props)
- Update tests and docs accordingly
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dicator Extract render from checkbox props and pass it to the Indicator primitive. When no render prop is provided, falls back to default CheckMarkIcon/IndeterminateIcon. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/raystack/components/checkbox/checkbox.tsx (1)
84-94: Explicitly type therenderprop for the indicator component.The
renderprop is inherited fromCheckboxPrimitive.Root.Propsbut is only used forCheckboxPrimitive.Indicator. This creates an implicit type mismatch sinceRoot.renderandIndicator.renderserve different purposes. Explicitly declare the render prop to improve type clarity:♻️ Proposed fix to explicitly type the render prop
interface CheckboxItemProps extends CheckboxPrimitive.Root.Props, - VariantProps<typeof checkboxVariants> {} + VariantProps<typeof checkboxVariants> { + /** Custom render function for the indicator. */ + render?: CheckboxPrimitive.Indicator.Props['render']; +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/raystack/components/checkbox/checkbox.tsx` around lines 84 - 94, Override the inherited ambiguous render type by omitting render from CheckboxPrimitive.Root.Props and explicitly re-declare it using the Indicator's render type: change CheckboxItemProps to extend Omit<CheckboxPrimitive.Root.Props, "render"> and add render?: CheckboxPrimitive.IndicatorProps["render"]; keep the rest of the props (VariantProps<typeof checkboxVariants>) and the CheckboxItem function signature the same so CheckboxPrimitive.Indicator receives the correctly typed render prop.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/www/src/content/docs/components/checkbox/props.ts`:
- Around line 44-50: Update the JSDoc for the render prop so it documents the
full state shape passed to the custom indicator renderer: include
transitionStatus of type TransitionStatus alongside checked and indeterminate.
Specifically, modify the comment on the render?: (props:
React.HTMLAttributes<HTMLSpanElement>, state: { checked: boolean; indeterminate:
boolean }) => React.ReactNode to show state: { checked: boolean; indeterminate:
boolean; transitionStatus: TransitionStatus } and mention it mirrors
Checkbox.Indicator's state.
---
Nitpick comments:
In `@packages/raystack/components/checkbox/checkbox.tsx`:
- Around line 84-94: Override the inherited ambiguous render type by omitting
render from CheckboxPrimitive.Root.Props and explicitly re-declare it using the
Indicator's render type: change CheckboxItemProps to extend
Omit<CheckboxPrimitive.Root.Props, "render"> and add render?:
CheckboxPrimitive.IndicatorProps["render"]; keep the rest of the props
(VariantProps<typeof checkboxVariants>) and the CheckboxItem function signature
the same so CheckboxPrimitive.Indicator receives the correctly typed render
prop.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0fc64279-8568-4794-a23e-501fb4e0e999
📒 Files selected for processing (6)
apps/www/src/content/docs/components/checkbox/demo.tsapps/www/src/content/docs/components/checkbox/props.tspackages/raystack/components/checkbox/__tests__/checkbox-group.test.tsxpackages/raystack/components/checkbox/__tests__/checkbox.test.tsxpackages/raystack/components/checkbox/checkbox.module.csspackages/raystack/components/checkbox/checkbox.tsx
| /** | ||
| * Custom render function for the indicator. Receives `(props, state)` where state includes `checked` and `indeterminate`. | ||
| */ | ||
| render?: ( | ||
| props: React.HTMLAttributes<HTMLSpanElement>, | ||
| state: { checked: boolean; indeterminate: boolean } | ||
| ) => React.ReactNode; |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
@base-ui/react Checkbox.Indicator render prop signature state object
💡 Result:
The render prop signature for Checkbox.Indicator in @base-ui/react is: render?: ReactElement | ((props: HTMLProps, state: Checkbox.Indicator.State) => ReactElement) | undefined The state object (Checkbox.Indicator.State) includes at minimum: - transitionStatus: TransitionStatus From analogous components like Radio.Indicator.State, it likely also includes: - checked: boolean The official Base UI documentation shows this signature explicitly for the render prop, confirming it receives props and state parameters. The exact full shape of Checkbox.Indicator.State is partially documented as having transitionStatus, with checked inferred from patterns in related components (Radio, Checkbox.Root.State).
Citations:
- 1: https://base-ui.com/react/components/checkbox
- 2: https://base-ui.com/react/utils/use-render
- 3: https://base-ui.com/react/components/radio
- 4: https://github.com/mui/base-ui/blob/6583c18f/packages/react/src/checkbox/root/CheckboxRoot.tsx
🏁 Script executed:
# Try to find the Base UI checkbox types in node_modules if available
# or search for any type definitions in the codebase that reference Base UI's Indicator state
find . -type f -name "*.ts" -o -name "*.tsx" | head -20 | xargs grep -l "Checkbox.Indicator.State\|CheckboxPrimitive.Indicator" 2>/dev/null | head -5Repository: raystack/apsara
Length of output: 41
🏁 Script executed:
# Search for actual render prop usage on checkbox indicators
rg "render\s*[=:].*\(props.*state" apps/www/src --type ts --type tsx -A 3Repository: raystack/apsara
Length of output: 86
🏁 Script executed:
# Check the structure of the codebase first
ls -la apps/www/src/content/docs/components/checkbox/
# Search for render prop usage with correct rg syntax
rg "render.*\(.*state" apps/www/src -t ts -A 2
# Also search in the entire repo for any references to Indicator state
rg "Indicator.*State\|CheckboxIndicator" . -t ts -t jsRepository: raystack/apsara
Length of output: 658
🏁 Script executed:
# Check if Base UI types are in node_modules
find . -path ./node_modules/@base-ui -name "*checkbox*" -type f 2>/dev/null | head -10
# Or look for package.json to see the Base UI version
cat package.json 2>/dev/null | grep -A 2 "@base-ui"Repository: raystack/apsara
Length of output: 41
🏁 Script executed:
# Find the actual checkbox component implementation
find apps/www/src -name "*.ts" -o -name "*.tsx" | xargs grep -l "CheckboxPrimitive\|Checkbox.Indicator\|render.*props.*state" 2>/dev/null
# Look at the demo.ts file to see how the component is used
cat -n apps/www/src/content/docs/components/checkbox/demo.tsRepository: raystack/apsara
Length of output: 5324
🏁 Script executed:
# Check what version of Base UI is being used and look for type definitions
find . -name "package.json" -type f | head -3 | xargs grep -l "@base-ui" 2>/dev/nullRepository: raystack/apsara
Length of output: 43
🏁 Script executed:
# Show lines 38-55 of props.ts to see the render prop documentation
sed -n '38,55p' apps/www/src/content/docs/components/checkbox/props.tsRepository: raystack/apsara
Length of output: 499
🏁 Script executed:
# Search for the actual Checkbox component implementation
find apps -name "*.ts" -o -name "*.tsx" | xargs grep -l "Checkbox.*Indicator\|render.*props.*state" 2>/dev/null | grep -v node_modules | head -5Repository: raystack/apsara
Length of output: 113
🏁 Script executed:
# Look for any TypeScript type definitions for Checkbox
find apps -name "*.ts" -type f | xargs grep -l "interface.*Checkbox\|type.*Checkbox" 2>/dev/null | head -10Repository: raystack/apsara
Length of output: 113
Update the render prop state type documentation to include transitionStatus.
The documented state signature { checked: boolean; indeterminate: boolean } is incomplete. Base UI's Checkbox.Indicator state also includes transitionStatus: TransitionStatus, which is not reflected in the current documentation. Update the JSDoc comment to accurately represent the full state shape that the render function receives.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/www/src/content/docs/components/checkbox/props.ts` around lines 44 - 50,
Update the JSDoc for the render prop so it documents the full state shape passed
to the custom indicator renderer: include transitionStatus of type
TransitionStatus alongside checked and indeterminate. Specifically, modify the
comment on the render?: (props: React.HTMLAttributes<HTMLSpanElement>, state: {
checked: boolean; indeterminate: boolean }) => React.ReactNode to show state: {
checked: boolean; indeterminate: boolean; transitionStatus: TransitionStatus }
and mention it mirrors Checkbox.Indicator's state.
…ssibility props The docs were missing sections for size variants and horizontal group orientation that were added in the component. Also documents readOnly, required props and the new CSS-driven accessibility states (disabled, read-only, invalid visual feedback). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
[data-readonly]styling with reduced opacity and default cursorpointer-events: noneand explicit state-preserving rulessizeprop withsmall(12px) andlarge(16px, default) variants via CVA. SVG icons now scale to 100% of containerrenderprop — extracted from checkbox props and passed to the Indicator primitive. Receives(props, state)withcheckedandindeterminateorientationprop toCheckboxGroup('vertical'default,'horizontal')Scoped out
inputRef/parenttyping (already exposed via Base UI'sCheckboxPrimitive.Root.Props)Test plan
small,large, defaultlarge)renderprop (checked state, indeterminate state)requiredprop emittingdata-requiredorientation(vertical,horizontal)🤖 Generated with Claude Code