Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(v2)/radio group components #706

Merged
merged 7 commits into from
Oct 27, 2024
Merged
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
15 changes: 15 additions & 0 deletions packages/ui/src/components/radio-group/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { RadioGroup as RadioGroupPrimitive } from 'bits-ui'

import Root from './radio-group.svelte'
import Item from './radio-group-item.svelte'
const Input = RadioGroupPrimitive.Input

export {
Input,
Item,
//
Root as RadioGroup,
Input as RadioGroupInput,
Item as RadioGroupItem,
Root,
}
42 changes: 42 additions & 0 deletions packages/ui/src/components/radio-group/radio-group-item.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script lang="ts">
import { Label, RadioGroup as RadioGroupPrimitive } from 'bits-ui'
import { Circle } from 'lucide-svelte'

import { cn } from '../../utils'

type $$Props = RadioGroupPrimitive.ItemProps & {
id: string
label: string
}
type $$Events = RadioGroupPrimitive.ItemEvents

let className: $$Props['class'] = undefined
export let value: $$Props['value']
export let id: $$Props['id']
export let label: $$Props['label'] = 'label'
export { className as class }
</script>

<div class="flex items-center space-x-2">
<RadioGroupPrimitive.Item
{value}
class="{cn(
'peer border-on-surface-placeholder data-[state=checked]:border-primary text-primary ring-offset-background focus-visible:ring-ring aspect-square h-5 w-5 rounded-full border-2 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className,
)}"
{...$$restProps}
on:click
>
<div class="flex items-center justify-center">
<RadioGroupPrimitive.ItemIndicator>
<Circle class="h-2.5 w-2.5 fill-primary text-current" />
</RadioGroupPrimitive.ItemIndicator>
</div>
</RadioGroupPrimitive.Item>
<Label.Root
for="{id}"
class="text-button2 font-normal leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
{label}
</Label.Root>
</div>
96 changes: 96 additions & 0 deletions packages/ui/src/components/radio-group/radio-group.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script context="module" lang="ts">
import type { Meta } from '@storybook/svelte'

import * as RadioGroup from './index.js'

export const meta = {
title: 'Atom/RadioGroup',
component: RadioGroup,
tags: ['autodocs'],
argTypes: {
'aria-label': {
control: 'text',
description: 'string value that labels an interactive element',
},
value: {
description: 'The selected value in the radio group.',
control: {
type: 'select',
},
options: ['option-one', 'option-two'],
defaultValue: 'option-one',
},
className: {
control: false,
},
itemValue1: {
control: 'text',
description: 'Value for the first RadioGroup.Item',
defaultValue: 'option-one',
},
'item1-label': {
control: 'text',
description: 'Label for the first RadioGroup.Item',
defaultValue: 'option 1',
},
itemValue2: {
control: 'text',
description: 'Value for the second RadioGroup.Item',
defaultValue: 'option-two',
},
'item2-label': {
control: 'text',
description: 'Label for the second RadioGroup.Item',
defaultValue: 'option 2',
},
onClick: {
action: 'onClick',
},
},
} satisfies Meta<RadioGroup>
</script>

<script lang="ts">
import { Story, Template } from '@storybook/addon-svelte-csf'
</script>

<Template let:args>
<RadioGroup.Root {...args}>
<RadioGroup.Item
value="{args.itemValue1}"
id="{args.itemValue1}"
label="{args['item1-label']}"
aria-label="{args['aria-label']}"
/>
<RadioGroup.Item
value="{args.itemValue2}"
id="{args.itemValue2}"
label="{args['item2-label']}"
aria-label="{args['aria-label']}"
/>
</RadioGroup.Root>
</Template>

<Story
name="Default"
args="{{
value: 'option-one',
itemValue1: 'option-one',
'item1-label': 'option 1',
itemValue2: 'option-two',
'item2-label': 'option 2',
'aria-label': 'for example of enable radio group',
}}"
/>

<Story
name="Disabled"
args="{{
itemValue1: 'option-one',
'item1-label': 'option 1',
itemValue2: 'option-two',
'item2-label': 'option 2',
disabled: true,
'aria-label': 'for example of disabled radio group',
}}"
/>
19 changes: 19 additions & 0 deletions packages/ui/src/components/radio-group/radio-group.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import { RadioGroup as RadioGroupPrimitive } from 'bits-ui'

import { cn } from '../../utils'

type $$Props = RadioGroupPrimitive.Props

let className: $$Props['class'] = undefined
export let value: $$Props['value'] = undefined
export { className as class }
</script>

<RadioGroupPrimitive.Root
bind:value
class="{cn('grid gap-2 p-1', className)}"
{...$$restProps}
>
<slot />
</RadioGroupPrimitive.Root>
Loading