diff --git a/package-lock.json b/package-lock.json index 13c0faf..5b55d81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4737,9 +4737,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" diff --git a/src/components/DatePicker/DatePicker.stories.tsx b/src/components/DatePicker/DatePicker.stories.tsx index ea13a1d..f2b44e1 100644 --- a/src/components/DatePicker/DatePicker.stories.tsx +++ b/src/components/DatePicker/DatePicker.stories.tsx @@ -65,16 +65,25 @@ const meta = { type: { summary: 'boolean' }, }, }, + isReadonly: { + description: '編集不可(読み取り専用)状態であるかどうかを指定します。', + control: { type: 'boolean' }, + table: { + defaultValue: { summary: 'false' }, + type: { summary: 'boolean' }, + }, + }, }, args: { size: 'lg', isError: false, isDisabled: false, - children: ({ yearRef, monthRef, dateRef }) => ( + isReadonly: false, + children: ({ yearRef, monthRef, dateRef, ...rest }) => ( <> - - - + + + ), }, @@ -95,11 +104,11 @@ export const WithFieldset: Story = { 例:2025年01月20日 - {({ yearRef, monthRef, dateRef }) => ( + {({ yearRef, monthRef, dateRef, ...rest }) => ( <> - - - + + + )} @@ -125,24 +134,24 @@ export const Errored: Story = { 例:2025年01月20日 - {({ yearRef, monthRef, dateRef }) => ( + {({ yearRef, monthRef, dateRef, ...rest }) => ( <> )} @@ -166,24 +175,71 @@ export const Disabled: Story = { 日付※任意 - 例:2025年01月20日 + + 〜の理由により、この項目は編集できません。 + - {({ yearRef, monthRef, dateRef }) => ( + {({ yearRef, monthRef, dateRef, ...rest }) => ( <> + + )} + + + ); + }, +}; + +/** + * Readonly状態を表示した例 + */ +export const Readonly: Story = { + args: { + isReadonly: true, + }, + render({ ...args }) { + return ( +
+ + 日付※任意 + + + 〜の理由により、この項目は編集できません。 + + + {({ yearRef, monthRef, dateRef, ...rest }) => ( + <> + + + )} @@ -230,25 +286,28 @@ export const WithCalendar: Story = { return ( <> - {({ yearRef, monthRef, dateRef }) => ( + {({ yearRef, monthRef, dateRef, ...rest }) => ( <> setYearInput(e.target.value)} onBlur={updateCalendarDate} + {...rest} /> setMonthInput(e.target.value)} onBlur={updateCalendarDate} + {...rest} /> setDayInput(e.target.value)} onBlur={updateCalendarDate} + {...rest} /> )} diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx index 0005c39..3c1e7b5 100644 --- a/src/components/DatePicker/DatePicker.tsx +++ b/src/components/DatePicker/DatePicker.tsx @@ -7,16 +7,20 @@ export type DatePickerSize = 'lg' | 'md' | 'sm'; export type DatePickerProps = Omit, 'children'> & { size?: DatePickerSize; isError?: boolean; + isReadonly?: boolean; isDisabled?: boolean; children: (props: { yearRef: Ref; monthRef: Ref; dateRef: Ref; + readOnly?: boolean; + 'aria-disabled'?: boolean; + 'aria-invalid'?: boolean; }) => JSX.Element; }; export const DatePicker = (props: DatePickerProps) => { - const { className, size = 'lg', isError, isDisabled, children, ...rest } = props; + const { className, size = 'lg', isError, isReadonly, isDisabled, children, ...rest } = props; const yearRef = useRef(null); const monthRef = useRef(null); @@ -67,14 +71,22 @@ export const DatePicker = (props: DatePickerProps) => { return ( // biome-ignore lint/a11y/noStaticElementInteractions: For date input navigation
- {children({ yearRef, monthRef, dateRef })} + {children({ + yearRef, + monthRef, + dateRef, + readOnly: isReadonly, + 'aria-disabled': isDisabled, + 'aria-invalid': isError, + })}
); }; diff --git a/src/components/DatePicker/parts/DatePickerDate.tsx b/src/components/DatePicker/parts/DatePickerDate.tsx index a27bb9a..8183a55 100644 --- a/src/components/DatePicker/parts/DatePickerDate.tsx +++ b/src/components/DatePicker/parts/DatePickerDate.tsx @@ -3,7 +3,7 @@ import { type ComponentProps, forwardRef } from 'react'; export type DatePickerDateProps = ComponentProps<'input'> & {}; export const DatePickerDate = forwardRef((props, ref) => { - const { className, 'aria-disabled': disabled, readOnly, ...rest } = props; + const { className, 'aria-disabled': ariaDisabled, readOnly, ...rest } = props; return (
); @@ -95,6 +123,9 @@ export const WithFieldset: Story = { * Separatedタイプは個別の入力フィールドがエラー状態になります。 */ export const Errored: Story = { + args: { + isError: true, + }, render({ ...args }) { return (
@@ -103,20 +134,24 @@ export const Errored: Story = { 西暦、半角 - - - + {({ ...rest }) => ( + <> + + + + + )} *正しい日付を入力してください。
@@ -130,26 +165,68 @@ export const Errored: Story = { * 無効化するために`disabled`属性ではなく`aria-disabled`属性を使用します。 */ export const Disabled: Story = { + args: { + isDisabled: true, + }, render({ ...args }) { return (
日付※任意 - 西暦、半角 + + 〜の理由により、この項目は編集できません。 + - - - + {({ ...rest }) => ( + <> + + + + + )} + +
+ ); + }, +}; + +/** + * Readonly状態を表示した例 + */ +export const Readonly: Story = { + args: { + isReadonly: true, + }, + render({ ...args }) { + return ( +
+ + 日付※任意 + + + 〜の理由により、この項目は編集できません。 + + + {({ ...rest }) => ( + <> + + + + + )}
); @@ -191,151 +268,158 @@ export const WithCalendar: Story = { }; return ( - <> - - setYearInput(e.target.value)} - onBlur={updateCalendarDate} - /> - setMonthInput(e.target.value)} - onBlur={updateCalendarDate} - /> - setDayInput(e.target.value)} - onBlur={updateCalendarDate} - /> - - state.setOpen(true)} - /> - - - - {({ state: calendarState }) => ( - <> -
- -
- +

+ {calendarState.focusedDate.month}月 +

+ +
+
+ + + {(day) => ( + + {day} + + )} + + + {(date) => ( + + )} + + +
+ -
- - - - {(day) => ( - - {day} - - )} - - - {(date) => ( - - )} - - -
- - -
- - )} -
-
-
- + 削除 + + + + + )} + + + + + )} + ); }} @@ -349,13 +433,21 @@ export const Partial: Story = { return (
- - + {({ ...rest }) => ( + <> + + + + )} - - + {({ ...rest }) => ( + <> + + + + )}
); diff --git a/src/components/SeparatedDatePicker/SeparatedDatePicker.tsx b/src/components/SeparatedDatePicker/SeparatedDatePicker.tsx index be08a1c..43507f0 100644 --- a/src/components/SeparatedDatePicker/SeparatedDatePicker.tsx +++ b/src/components/SeparatedDatePicker/SeparatedDatePicker.tsx @@ -2,12 +2,20 @@ import type { ComponentProps } from 'react'; export type SeparatedDatePickerSize = 'lg' | 'md' | 'sm'; -export type SeparatedDatePickerProps = ComponentProps<'div'> & { +export type SeparatedDatePickerProps = Omit, 'children'> & { size?: SeparatedDatePickerSize; + isError?: boolean; + isReadonly?: boolean; + isDisabled?: boolean; + children: (props: { + readOnly?: boolean; + 'aria-disabled'?: boolean; + 'aria-invalid'?: boolean; + }) => JSX.Element; }; export const SeparatedDatePicker = (props: SeparatedDatePickerProps) => { - const { className, size = 'lg', children, ...rest } = props; + const { className, size = 'lg', isError, isReadonly, isDisabled, children, ...rest } = props; return (
@@ -16,7 +24,7 @@ export const SeparatedDatePicker = (props: SeparatedDatePickerProps) => { data-size={size} {...rest} > - {children} + {children({ readOnly: isReadonly, 'aria-disabled': isDisabled, 'aria-invalid': isError })}
); diff --git a/src/components/SeparatedDatePicker/parts/SeparatedDatePickerDate.tsx b/src/components/SeparatedDatePicker/parts/SeparatedDatePickerDate.tsx index d85ed5d..785f888 100644 --- a/src/components/SeparatedDatePicker/parts/SeparatedDatePickerDate.tsx +++ b/src/components/SeparatedDatePicker/parts/SeparatedDatePickerDate.tsx @@ -12,7 +12,7 @@ export const SeparatedDatePickerDate = forwardRef { const { children, className, ...rest } = props; return ( -

+

{children}

); diff --git a/src/components/Textarea/Textarea.stories.tsx b/src/components/Textarea/Textarea.stories.tsx index 80e85bb..3d100c3 100644 --- a/src/components/Textarea/Textarea.stories.tsx +++ b/src/components/Textarea/Textarea.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import React from 'react'; -import { ErrorText, Label, RequirementBadge, SupportText } from '../'; +import { ErrorText, Label, RequirementBadge, StatusBadge, SupportText } from '../'; import { Textarea } from './Textarea'; const meta = { @@ -17,159 +17,176 @@ const meta = { type: { summary: 'boolean' }, }, }, - 'aria-disabled': { - description: - '無効化する必要がある場合は `disabled` 属性ではなく `aria-disabled` 属性を使用します。', - control: { type: 'boolean' }, - table: { - defaultValue: { summary: 'false' }, - type: { summary: 'boolean' }, - }, - }, }, } satisfies Meta; export default meta; type Story = StoryObj; -export type TextareaCounterProps = { - count: number; - maxCount: number; - className?: string; - id?: string; -}; - export const Playground: Story = { - decorators: [ - (Story, context) => ( + render: (args) => { + const { isError } = args; + + const formId = React.useId(); + const supportTextId = React.useId(); + const errorTextId = React.useId(); + + const describedBy = isError ? `${errorTextId} ${supportTextId}` : supportTextId; + + return (
-