Skip to content
This repository has been archived by the owner on Jul 17, 2024. It is now read-only.

Commit

Permalink
Merge pull request #93 from turistikrota/comp/radio-group
Browse files Browse the repository at this point in the history
comp/radio-group: add radio group component
  • Loading branch information
9ssi7 authored Jul 23, 2023
2 parents 30f8f3e + afd2b7f commit c2a89e6
Show file tree
Hide file tree
Showing 9 changed files with 301 additions and 6 deletions.
8 changes: 4 additions & 4 deletions apps/docs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"build-storybook": "storybook build"
},
"dependencies": {
"@turistikrota/ui": "^0.1.2",
"@turistikrota/ui": "^0.1.5",
"boxicons": "^2.1.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
20 changes: 20 additions & 0 deletions apps/docs/src/stories/components/form/radio-group/RadioGroup.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Canvas, Meta, Story, ArgsTable, Controls } from '@storybook/blocks'
import * as RadioGroupStories from './RadioGroup.stories'

<Meta of={RadioGroupStories} />

# Radio Group

```jsx
import RadioGroup from '@turistikrota/ui/form/radio/group'
```

Radio Group is a component that allows you to group radio buttons.

<Canvas of={RadioGroupStories.Playground}>
<div className='bg-second p-4 rounded-md'>
<Story of={RadioGroupStories.Playground} />
</div>
</Canvas>

<Controls of={RadioGroupStories.Playground} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Meta, StoryObj } from '@storybook/react'
import RadioGroup from '@turistikrota/ui/form/radio/group'

const meta = {
title: 'Components/Form/Radio Group',
component: RadioGroup,
tags: [],
argTypes: {
title: {
control: { type: 'text' },
description: 'The title of the radio group',
},
clearable: {
control: { type: 'boolean' },
description: 'If the radio group is clearable',
defaultValue: false,
},
className: {
control: { type: 'text' },
description: 'The className of the radio group',
},
clearText: {
control: { type: 'text' },
description: 'The clear text of the radio group. This for i18n',
},
clearAriaLabel: {
control: { type: 'text' },
description: 'The clear aria label of the radio group. This for i18n and accessibility',
},
children: {
control: { type: 'text' },
description: 'The content of the radio group',
},
onClear: {
action: 'onClear',
description: 'The onClear event of the radio group',
},
},
} satisfies Meta<typeof RadioGroup>

export default meta

type Story = StoryObj<typeof meta>

export const Playground: Story = {
args: {
clearText: 'Clear',
title: 'Radio Group',
clearable: true,
clearAriaLabel: 'Clear the radio group',
},
render: (args) => (
<RadioGroup {...args}>
<RadioGroup.Item checked id='option-1' name='options' reverse>
option 1
</RadioGroup.Item>
<RadioGroup.Item checked id='option-2' name='options' reverse>
option 2
</RadioGroup.Item>
<RadioGroup.Item checked id='option-2' name='options' reverse>
option 2
</RadioGroup.Item>
</RadioGroup>
),
}
20 changes: 20 additions & 0 deletions apps/docs/src/stories/components/form/select-group/SelectGroup.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Canvas, Meta, Story, ArgsTable, Controls } from '@storybook/blocks'
import * as SelectGroupStories from './SelectGroup.stories'

<Meta of={SelectGroupStories} />

# Select Group

```jsx
import SelectGroup from '@turistikrota/ui/form/select/group'
```

Select group is a component that groups multiple select components together.

<Canvas of={SelectGroupStories.Playground}>
<div className='bg-second p-4 rounded-md'>
<Story of={SelectGroupStories.Playground} />
</div>
</Canvas>

<Controls of={SelectGroupStories.Playground} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Meta, StoryObj } from '@storybook/react'
import SelectGroup from '@turistikrota/ui/form/select/group'

const meta = {
title: 'Components/Form/Select Group',
component: SelectGroup,
tags: [],
argTypes: {
className: {
control: { type: 'text' },
description: 'The className of the select group. This is used for tailwindcss',
},
title: {
control: { type: 'text' },
description: 'The title of the select group',
},
filtered: {
control: { type: 'boolean' },
description: 'If the select group is filtered',
defaultValue: false,
},
filter: {
control: { type: 'text' },
description: "The filter of the select group. It's React Node",
},
clearText: {
control: { type: 'text' },
description: 'The clear text of the select group. This for i18n',
},
clearAriaLabel: {
control: { type: 'text' },
description: 'The clear aria label of the select group. This for i18n and accessibility',
},
children: {
control: { type: 'text' },
description: 'The content of the select group',
},
onClear: {
action: 'onClear',
description: 'The onClear event of the select group',
},
},
} satisfies Meta<typeof SelectGroup>

export default meta

type Story = StoryObj<typeof meta>

/*
*👇 Render functions are a framework specific feature to allow you control on how the component renders.
* See https://storybook.js.org/docs/react/api/csf
* to learn how to use render functions.
*/
export const Playground: Story = {
args: {
clearText: 'Clear',
title: 'Select Group',
filtered: true,
clearAriaLabel: 'Clear the select group',
},
render: (args) => (
<SelectGroup {...args}>
<SelectGroup.Item name='select-item' id='select-item-1' reversed>
Select 1
</SelectGroup.Item>
<SelectGroup.Item name='select-item' id='select-item-2' value reversed>
Select 2
</SelectGroup.Item>
<SelectGroup.Item name='select-item' id='select-item-3' reversed>
Select 3
</SelectGroup.Item>
</SelectGroup>
),
}
2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@turistikrota/ui",
"version": "0.1.2",
"version": "0.1.5",
"description": "the turistikrota ui library for React",
"main": "./cjs/index.js",
"module": "./index.js",
Expand Down
56 changes: 56 additions & 0 deletions packages/ui/src/form/radio/group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react'
import Radio from '../radio'

type ClearButtonProps = {
onClear?: () => void
clearText: string
clearAriaLabel?: string
}

type Props = ClearButtonProps & {
className?: string
title: string
clearable?: boolean
onClear?: () => void
}

type RadioGroupType = React.FC<React.PropsWithChildren<Props>> & {
Item: typeof Radio
}

const ClearButton: React.FC<ClearButtonProps> = ({ onClear, clearText, clearAriaLabel }) => {
return (
<span
className='text-sm text-primary hover:opacity-90 transition-colors'
onClick={() => onClear && onClear()}
role='button'
title={clearAriaLabel ?? clearText}
aria-label={clearAriaLabel ?? clearText}
>
{clearText}
</span>
)
}

const RadioGroup: RadioGroupType = ({
children,
title,
clearable = false,
onClear,
className,
clearText,
clearAriaLabel,
}) => {
return (
<div className={`${className ? className : ''}`}>
<div className='flex justify-between items-center'>
<div className='text-lg font-bold'>{title}</div>
{clearable && <ClearButton onClear={onClear} clearText={clearText} clearAriaLabel={clearAriaLabel} />}
</div>
<div>{children}</div>
</div>
)
}

RadioGroup.Item = Radio
export default RadioGroup
60 changes: 60 additions & 0 deletions packages/ui/src/form/select/group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react'
import Checkbox from '../checkbox'

type ClearButtonProps = {
onClear?: () => void
clearText: string
clearAriaLabel?: string
}

type Props = ClearButtonProps & {
className?: string
title: string
filtered?: boolean
filter?: React.ReactNode
}

type SelectGroupType = React.FC<React.PropsWithChildren<Props>> & {
Item: typeof Checkbox
}

const ClearButton: React.FC<ClearButtonProps> = ({ onClear, clearText, clearAriaLabel }) => {
return (
<span
className='text-sm text-primary hover:opacity-90 transition-colors'
onClick={() => onClear && onClear()}
role='button'
title={clearAriaLabel ?? clearText}
aria-label={clearAriaLabel ?? clearText}
>
{clearText}
</span>
)
}

const SelectGroup: SelectGroupType = ({
children,
title,
filtered = false,
filter,
onClear,
className,
clearText,
clearAriaLabel,
}) => {
return (
<div className={`${className ? className : ''}`}>
<div className='flex justify-between items-center'>
<div className='font-bold text-lg text-gray-700 dark:text-gray-200'>{title}</div>
{filtered && <ClearButton onClear={onClear} clearText={clearText} clearAriaLabel={clearAriaLabel} />}
</div>
{filter && <div className='my-4 lg:my-2'>{filter}</div>}
<div className={`max-h-60 overflow-y-auto space-y-3 lg:space-y-2 ${!filtered ? 'mt-2 lg:mt-2' : ''}`}>
{children}
</div>
</div>
)
}

SelectGroup.Item = Checkbox
export default SelectGroup

0 comments on commit c2a89e6

Please sign in to comment.