diff --git a/src/components/CheckboxGroup/CheckboxGroup.module.css b/src/components/CheckboxGroup/CheckboxGroup.module.css index 0cfa49ad..888d4c42 100644 --- a/src/components/CheckboxGroup/CheckboxGroup.module.css +++ b/src/components/CheckboxGroup/CheckboxGroup.module.css @@ -10,4 +10,7 @@ color: var(--color-text-sub); margin-bottom: var(--size-spacing-md); padding: 0; + display: flex; + align-items: center; + gap: var(--size-spacing-xs); } diff --git a/src/components/CheckboxGroup/CheckboxGroup.tsx b/src/components/CheckboxGroup/CheckboxGroup.tsx index 09f6b72f..1a04efe8 100644 --- a/src/components/CheckboxGroup/CheckboxGroup.tsx +++ b/src/components/CheckboxGroup/CheckboxGroup.tsx @@ -1,6 +1,7 @@ 'use client'; import styles from './CheckboxGroup.module.css'; +import { RequiredLabel } from '../../sharedComponents/RequiredLabel/RequiredLabel'; import { Checkbox } from '../Checkbox/Checkbox'; import { Flex } from '../Flex/Flex'; import type { FC, ReactElement } from 'react'; @@ -11,6 +12,11 @@ export type Props = { * チェックボックスグループの見出し(legend要素) */ label: string; + /** + * 必須マークを表示するか + * 注意: trueとしてもinput要素のrequired属性は付与されません + */ + showRequiredLabel?: boolean; /** * チェックボックスの配置方向 * @default column @@ -18,10 +24,13 @@ export type Props = { direction?: 'column' | 'row'; }; -export const CheckboxGroup: FC = ({ children, label, direction = 'column' }) => { +export const CheckboxGroup: FC = ({ children, label, showRequiredLabel, direction = 'column' }) => { return (
- {label} + + {label} + {showRequiredLabel && } + {children} diff --git a/src/components/Label/Label.module.css b/src/components/Label/Label.module.css index dc3b2721..315fe583 100644 --- a/src/components/Label/Label.module.css +++ b/src/components/Label/Label.module.css @@ -1,7 +1,10 @@ .label { + display: flex; font-size: var(--text-body-sm-size); font-weight: bold; color: var(--color-text-sub); + align-items: center; + gap: var(--size-spacing-xs); } legend.label { diff --git a/src/components/Label/Label.tsx b/src/components/Label/Label.tsx index e474af68..617c5c87 100644 --- a/src/components/Label/Label.tsx +++ b/src/components/Label/Label.tsx @@ -1,6 +1,7 @@ 'use client'; import styles from './Label.module.css'; +import { RequiredLabel } from '../../sharedComponents/RequiredLabel/RequiredLabel'; import type { ElementType, FC, ReactNode } from 'react'; type Props = { @@ -14,12 +15,18 @@ type Props = { * ラベルが紐づくフォーム要素のid属性。asにlabelを指定した場合に必用 */ htmlFor?: string; + /** + * 必須マークを表示するか + * 注意: trueとしてもinput要素のrequired属性は付与されません + */ + showRequiredLabel?: boolean; }; -export const Label: FC = ({ children, as: LabelComponent = 'label', htmlFor }) => { +export const Label: FC = ({ children, as: LabelComponent = 'label', htmlFor, showRequiredLabel }) => { return ( {children} + {showRequiredLabel && } ); }; diff --git a/src/components/RadioGroup/RadioGroup.module.css b/src/components/RadioGroup/RadioGroup.module.css index 0cfa49ad..888d4c42 100644 --- a/src/components/RadioGroup/RadioGroup.module.css +++ b/src/components/RadioGroup/RadioGroup.module.css @@ -10,4 +10,7 @@ color: var(--color-text-sub); margin-bottom: var(--size-spacing-md); padding: 0; + display: flex; + align-items: center; + gap: var(--size-spacing-xs); } diff --git a/src/components/RadioGroup/RadioGroup.tsx b/src/components/RadioGroup/RadioGroup.tsx index aa3cc7df..2f6cf639 100644 --- a/src/components/RadioGroup/RadioGroup.tsx +++ b/src/components/RadioGroup/RadioGroup.tsx @@ -1,6 +1,7 @@ 'use client'; import styles from './RadioGroup.module.css'; +import { RequiredLabel } from '../../sharedComponents/RequiredLabel/RequiredLabel'; import { Flex } from '../Flex/Flex'; import { RadioButton } from '../RadioButton/RadioButton'; import { RadioCard } from '../RadioCard/RadioCard'; @@ -14,6 +15,11 @@ export type Props = { * ラジオグループの見出し(legend要素) */ label: string; + /** + * 必須マークを表示するか + * 注意: trueとしてもinput要素のrequired属性は付与されません + */ + showRequiredLabel?: boolean; /** * ラジオボタンの配置方向 * @default column @@ -21,13 +27,16 @@ export type Props = { direction?: 'column' | 'row'; }; -export const RadioGroup: FC = ({ children, label, direction = 'column' }) => { +export const RadioGroup: FC = ({ children, label, showRequiredLabel = false, direction = 'column' }) => { const childrenIsCard = children.some((child) => child.type === RadioCard); const childenIsBlock = direction === 'row' || (childrenIsCard && direction === 'column'); return (
- {label} + + {label} + {showRequiredLabel && } + { + return 必須; +}; diff --git a/src/stories/Checkbox.stories.tsx b/src/stories/Checkbox.stories.tsx index 57524f89..dd09e1b4 100644 --- a/src/stories/Checkbox.stories.tsx +++ b/src/stories/Checkbox.stories.tsx @@ -132,3 +132,36 @@ export const Disabled: Story = { ), }; + +export const ShowRequiredLabel: Story = { + render: () => { + const [selectedItem, setSelectedItem] = useState([options[0]]); + + const onChange: ChangeEventHandler = useCallback( + (event) => { + if (event.target.checked) { + setSelectedItem([...selectedItem, event.target.value]); + } else { + setSelectedItem(selectedItem.filter((item) => item !== event.target.value)); + } + }, + [selectedItem], + ); + + return ( + + {options.map((option) => ( + + {option} + + ))} + + ); + }, +}; diff --git a/src/stories/Form.stories.tsx b/src/stories/Form.stories.tsx index 339b46ee..5f6b0fb6 100644 --- a/src/stories/Form.stories.tsx +++ b/src/stories/Form.stories.tsx @@ -16,7 +16,9 @@ export const Default: StoryObj = { return ( - + 説明文です 説明文です @@ -55,7 +57,7 @@ export const RadioButtons: StoryObj = { return ( - + {options.map((option) => ( ; export const Default: Story = { render: () => , }; + +export const Rqruied: Story = { + render: () => ( + + ), +}; diff --git a/src/stories/RadioButton.stories.tsx b/src/stories/RadioButton.stories.tsx index a054688e..f15c89fd 100644 --- a/src/stories/RadioButton.stories.tsx +++ b/src/stories/RadioButton.stories.tsx @@ -120,3 +120,35 @@ export const Disabled: Story = { name: 'disabled', }, }; + +export const ShowRequiredLabel: Story = { + render: (args) => { + const [selectedItem, setSelectedItem] = useState(options[0]); + + const onChange: ChangeEventHandler = useCallback((event) => { + setSelectedItem(event.target.value); + }, []); + + return ( + + {options.map((option) => ( + + {option} + + ))} + + ); + }, + args: { + ...defaultArgs, + name: 'default', + }, +}; diff --git a/src/stories/RadioCard.stories.tsx b/src/stories/RadioCard.stories.tsx index af69c442..91abc9e5 100644 --- a/src/stories/RadioCard.stories.tsx +++ b/src/stories/RadioCard.stories.tsx @@ -101,3 +101,30 @@ export const Block: Story = { block: true, }, }; + +export const ShowRequiredLabel: Story = { + render: () => { + const [selectedItem, setSelectedItem] = useState(options[0]); + + const onChange: ChangeEventHandler = useCallback((event) => { + setSelectedItem(event.target.value); + }, []); + + return ( + + {options.map((option) => ( + + {option} + + ))} + + ); + }, +};