Skip to content

CORE-2000: Migrate Checkbox and Radio components to plain CSS - #120

Merged
RoyEJohnson merged 10 commits into
mainfrom
CORE-2000-migrate-checkbox-radio
Jul 23, 2026
Merged

CORE-2000: Migrate Checkbox and Radio components to plain CSS#120
RoyEJohnson merged 10 commits into
mainfrom
CORE-2000-migrate-checkbox-radio

Conversation

@OpenStaxClaude

@OpenStaxClaude OpenStaxClaude commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR migrates the Checkbox and Radio form components from styled-components to plain CSS, following the same patterns established in #115 and #119.

Changes Made

Checkbox Component

  • Created Checkbox.css with CSS variable-based styling
  • Updated Checkbox.tsx to:
    • Remove styled-components imports (StyledLabel, StyledInput)
    • Use plain HTML elements with className
    • Use classnames library for conditional disabled state
    • Bind theme colors as CSS variables in style prop
    • Preserve all existing props: children, disabled, variant, bold, size, labelProps
  • Updated sharedCheckboxStyles.ts to:
    • Keep checkboxVariants export for runtime theme lookups
    • Remove css template literal functions
    • Remove styled-components dependency

Radio Component

  • Created Radio.css with CSS variable-based styling
  • Updated Radio.tsx to:
    • Remove styled-components imports (StyledLabel, StyledInput)
    • Use plain HTML elements with className
    • Use classnames library for conditional disabled state
    • Bind theme colors as CSS variables in style prop
    • Preserve all existing props including tooltip functionality

Infrastructure

  • Added CSS module declaration to react.d.ts
  • Updated package.json sideEffects to ["**/*.css"] to prevent tree-shaking of CSS imports

CSS Variable Bindings

Checkbox (variant-dependent):

  • --checkbox-bg: variant background color
  • --checkbox-color: variant text color
  • --checkbox-border-unchecked: variant unchecked border
  • --checkbox-border-checked: variant checked border
  • --checkbox-checkmark: variant checkmark SVG
  • --checkbox-size: size prop value
  • --checkbox-disabled-color: colors.palette.neutralLight

Radio (static):

  • --radio-border: colors.palette.neutralThin
  • --radio-checked: colors.palette.mediumBlue
  • --radio-bg: colors.palette.white
  • --radio-disabled-color: colors.palette.pale

Testing

  • Run unit tests and update snapshots
  • Verify Ladle stories render correctly
  • Test all Checkbox variants (primary, light, error)
  • Test disabled state for both components
  • Test different sizes for Checkbox
  • Test tooltip functionality for Radio

Related

This comment was marked as resolved.

RoyEJohnson

This comment was marked as resolved.

RoyEJohnson

This comment was marked as resolved.

@OpenStaxClaude

Copy link
Copy Markdown
Contributor Author

Review Comments Addressed

I've addressed all the review comments:

1. Fixed labelAs prop in Radio.tsx (Copilot's unresolved comment)

Issue: The labelAs prop was spreading { as: labelAs } onto a native element, which doesn't work without styled-components. This broke existing usages like labelAs="div" and caused React unknown-prop warnings.

Solution: Refactored to use React.createElement() to properly render different element types based on the labelAs prop. Also extracted tooltipText from props to avoid spreading it to the DOM.

const labelElement = labelAs || 'label';
return React.createElement(labelElement, { className, style, ... }, children);

2. Fixed TypeScript CSS custom property errors in TreeCheckbox.tsx

Issue: TypeScript complained that --checkbox-font-weight and other CSS custom properties are not recognized as valid React.CSSProperties.

Solution: Updated all components (TreeCheckbox, Checkbox, Radio) to use the proper type casting pattern: as unknown as React.CSSProperties. This is necessary because TypeScript's CSSProperties type doesn't include support for CSS custom properties (variables starting with --).

Applied to:

  • src/components/Tree/TreeCheckbox.tsx
  • src/components/Checkbox/Checkbox.tsx
  • src/components/Radio.tsx

Test Results

✅ All 214 tests passing
✅ Updated 7 snapshots to reflect the changes
✅ No TypeScript compilation errors
✅ No React prop warnings

The PR is now ready for another review.

This comment was marked as resolved.

This comment was marked as resolved.

RoyEJohnson

This comment was marked as resolved.

This comment was marked as resolved.

RoyEJohnson

This comment was marked as resolved.

@OpenStaxClaude

This comment was marked as resolved.

RoyEJohnson

This comment was marked as low quality.

@OpenStaxClaude

This comment was marked as resolved.

OpenStaxClaude and others added 10 commits July 22, 2026 19:13
- Created Checkbox.css with CSS variable-based styling
- Updated Checkbox.tsx to use classnames and CSS variables
- Updated sharedCheckboxStyles.ts to remove styled-components dependencies
- Created Radio.css with CSS variable-based styling
- Updated Radio.tsx to use classnames and CSS variables
- Added CSS module declaration to react.d.ts
- Updated package.json sideEffects to preserve CSS imports

Related to CORE-2000
- Updated TreeCheckbox.tsx to use classnames and CSS variables
- Added TreeCheckbox-specific styles to Checkbox.css for data-slot and indeterminate state
- Removed styled-components dependency from TreeCheckbox
- Fixed CSS properties type assertion in TreeCheckbox
- Updated all test snapshots for Checkbox, Radio, and TreeCheckbox
- All 214 tests passing
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Fix Radio.tsx labelAs prop to properly render different element types using React.createElement
- Remove tooltipText from DOM props spreading to avoid React warnings
- Fix TypeScript CSS custom property type errors by casting to unknown first
- Update test snapshots for all affected components

Fixes:
- Radio labelAs prop now works correctly instead of setting invalid DOM attribute
- TreeCheckbox, Checkbox, and Radio now use proper TypeScript type casting for CSS variables
- All 214 tests passing

revert lock files

Update TreeCheckbox.tsx

Update index.spec.tsx.snap
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Replace generic 'disabled' class with BEM-style modifier classes to avoid
  CSS collisions with consumer code:
  - checkbox-label--disabled / checkbox-input--disabled
  - radio-label--disabled / radio-input--disabled
- Add explicit HTMLElement type to ref in Radio.tsx for better type safety
- Update all component implementations to use new BEM class names
- Update test snapshots

All 214 tests passing.

Addresses review comments from Copilot about:
- Generic class names causing potential conflicts in published component library
- Untyped ref leading to potential type errors

revert lock files

Update index.spec.tsx.snap
The selection slot div in TreeCheckbox was using both className="checkbox-input"
and data-slot="selection", causing duplicate styling. The CSS already has
comprehensive [data-slot="selection"] rules that cover all the necessary
styling, making the checkbox-input class redundant and confusing.

Changes:
- Removed className="checkbox-input" from TreeCheckbox selection slot
- CSS [data-slot="selection"] rules already include all necessary styling
- Updated 5 test snapshots to reflect the cleaner markup

This addresses the Copilot review comment about duplicate/conflicting
styling between .checkbox-input class and [data-slot="selection"] attribute.

revert lock files
@RoyEJohnson
RoyEJohnson merged commit e2c6a1b into main Jul 23, 2026
3 checks passed
@RoyEJohnson
RoyEJohnson deleted the CORE-2000-migrate-checkbox-radio branch July 23, 2026 00:26
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.

4 participants