Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
id: task-007
title: Create design tokens for Radio component
status: Done
assignee:
- '@agent-designer'
created_date: '2025-10-09 18:27'
updated_date: '2025-10-09 18:34'
labels:
- component
- tokens
- radio
dependencies: []
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Design and implement design tokens for the Radio component following the 4-tier token architecture. The Radio component consists of three parts: Radio Group, Radio button, and Radio button Indicator. Tokens must support 'default' and 'error' variants with one size. This task focuses on defining the design system tokens that will be consumed by the component implementation.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 Design tokens created for Radio Group (spacing, layout),Design tokens created for Radio button (colors, borders, spacing, states),Design tokens created for Radio button Indicator (size, colors, positioning),Both 'default' and 'error' variants are supported,Tokens follow the 4-tier architecture (primitives → semantic → component → variant),Token files are properly structured in the tokens directory,Style-dictionary build generates expected CSS variables
<!-- AC:END -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
id: task-008
title: Implement Radio component with Base UI integration
status: Done
assignee:
- '@agent-developer'
created_date: '2025-10-09 18:27'
updated_date: '2025-10-09 18:41'
labels:
- component
- implementation
- radio
dependencies: []
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Implement the Radio component using Base UI as the foundation. The component consists of three parts: Radio Group (to group radio buttons), Radio button (the interactive element), and Radio button Indicator (visual feedback element). The implementation must integrate with the design tokens created in the previous task and use Vanilla-Extract for styling with recipes for prop-to-style mapping. Support label association with Radio button for accessibility.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 Radio Group component implemented with Base UI integration,Radio button component implemented with Base UI Radio as foundation,Radio button Indicator component implemented,Label association properly configured with Radio button,Vanilla-Extract styling implemented using recipes for prop-to-style mapping,Design tokens from style-dictionary properly integrated,Both 'default' and 'error' variants functional,Component is properly typed with TypeScript,Accessibility features implemented (ARIA attributes, keyboard navigation),Component follows existing codebase patterns,Generated styles from design tokens are properly applied
<!-- AC:END -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
id: task-009
title: Create Storybook story for Radio component
status: Done
assignee: []
created_date: '2025-10-09 18:27'
updated_date: '2025-10-09 18:42'
labels:
- storybook
- documentation
- radio
dependencies: []
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Create a comprehensive Storybook story that showcases the Radio component and all its parts (Radio Group, Radio button, Radio button Indicator). The story should demonstrate both 'default' and 'error' variants, label association, different grouping scenarios, and interactive states. This serves as both documentation and a testing playground for the component.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 Single comprehensive Storybook story created for Radio component,Story showcases Radio Group with multiple Radio buttons,Both 'default' and 'error' variants are demonstrated,Label association examples included,Interactive states are visible (hover, focus, checked, disabled),Different grouping scenarios shown (vertical, horizontal if applicable),Story includes controls for testing variants and states,Component documentation is clear and helpful,Story file follows existing Storybook patterns in codebase
<!-- AC:END -->

## Implementation Notes

<!-- SECTION:NOTES:BEGIN -->
Task completed as part of Task 008. Radio.stories.tsx was created with 6 comprehensive stories covering all acceptance criteria: Default, Variants (default & error), Orientation (vertical & horizontal), States (unchecked, checked, disabled), Controlled example, and FormIntegration example. All stories demonstrate proper label association, interactive states, and follow existing Storybook patterns.
<!-- SECTION:NOTES:END -->
117 changes: 117 additions & 0 deletions src/components/Radio/Radio.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { recipe } from '@vanilla-extract/recipes';

import {
radioBaseStyles,
radioGroupBaseStyles,
radioIndicatorBaseStyles,
radioIndicatorVariants,
radioVariants,
} from '../../tokens/generated/components/radio.generated.css';

/**
* Radio Root Recipe
* Composed from radio tokens
*/
export const radioRoot = recipe({
base: {
// CSS reset
all: 'unset',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
userSelect: 'none',
boxSizing: 'border-box',
flexShrink: 0,
position: 'relative',

// From radio tokens
width: radioBaseStyles.size,
height: radioBaseStyles.size,
borderRadius: radioBaseStyles.borderRadius,
borderWidth: radioBaseStyles.borderWidth,
borderStyle: 'solid',

// Direct pseudo-selectors in base block
':disabled': {
cursor: 'not-allowed',
},

':focus-visible': {
outline: '2px solid',
outlineOffset: '2px',
},
},

variants: radioVariants,

defaultVariants: {
variant: 'default',
},
});

/**
* RadioGroup Recipe
* Composed from radio-group tokens
*/
export const radioGroup = recipe({
base: {
// CSS reset
all: 'unset',
display: 'flex',
boxSizing: 'border-box',

// From radio-group tokens
gap: radioGroupBaseStyles.gap,
},

variants: {
orientation: {
vertical: {
flexDirection: 'column' as const,
},
horizontal: {
flexDirection: 'row' as const,
},
},
},

defaultVariants: {
orientation: 'vertical',
},
});

/**
* RadioIndicator Recipe
* Composed from radio-indicator tokens
*/
export const radioIndicator = recipe({
base: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: radioIndicatorBaseStyles.width,
height: radioIndicatorBaseStyles.height,
borderRadius: radioIndicatorBaseStyles.borderRadius,
pointerEvents: 'none',

// Hide indicator when not checked
opacity: 0,
transform: 'scale(0)',
transition: 'all 0.15s ease',

// Show indicator when checked
selectors: {
'[data-checked] &': {
opacity: 1,
transform: 'scale(1)',
},
},
},

variants: radioIndicatorVariants,

defaultVariants: {
variant: 'default',
},
});
Loading
Loading