Skip to content

Commit

Permalink
fix: move accessibility warning from SelectBoxRadio to `SelectBoxRa…
Browse files Browse the repository at this point in the history
…dioGroup`
  • Loading branch information
te6-in committed Jan 10, 2025
1 parent 88a53f0 commit ad31322
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 10 deletions.
3 changes: 1 addition & 2 deletions docs/components/example/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,14 @@
"text-field-disabled": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldDisabled() {\n return (\n <div className=\"grid grid-cols-2 gap-4 w-full\">\n <TextField label=\"라벨\" description=\"설명을 써주세요\" disabled>\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField label=\"라벨\" description=\"설명을 써주세요\" disabled defaultValue=\"값\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField\n label=\"라벨\"\n description=\"설명을 써주세요\"\n disabled\n invalid\n errorMessage=\"오류가 발생한 이유를 써주세요\"\n >\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField\n label=\"라벨\"\n description=\"설명을 써주세요\"\n disabled\n invalid\n errorMessage=\"오류가 발생한 이유를 써주세요\"\n defaultValue=\"값\"\n >\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n </div>\n );\n}",
"text-field-enabled": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldEnabled() {\n return (\n <div className=\"grid grid-cols-2 gap-4 w-full\">\n <TextField label=\"라벨\" description=\"설명을 써주세요\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField label=\"라벨\" description=\"설명을 써주세요\" defaultValue=\"값\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField\n label=\"라벨\"\n description=\"설명을 써주세요\"\n invalid\n errorMessage=\"오류가 발생한 이유를 써주세요\"\n >\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField\n label=\"라벨\"\n description=\"설명을 써주세요\"\n invalid\n errorMessage=\"오류가 발생한 이유를 써주세요\"\n defaultValue=\"값\"\n >\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n </div>\n );\n}",
"text-field-grapheme-count": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldGraphemeCount() {\n return (\n <TextField label=\"라벨\" description=\"설명을 써주세요\" maxGraphemeCount={8}>\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n );\n}",
"text-field-indicator": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldIndicator() {\n return (\n <TextField label=\"라벨\" description=\"설명을 써주세요\" indicator=\"(선택)\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n );\n}",
"text-field-large": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldLarge() {\n return (\n <TextField label=\"라벨\" description=\"설명을 써주세요\" size=\"large\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n );\n}",
"text-field-medium": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldMedium() {\n return (\n <TextField label=\"라벨\" description=\"설명을 써주세요\" size=\"medium\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n );\n}",
"text-field-number-formatting": "import { useMemo, useState } from \"react\";\nimport { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldNumberFormatting() {\n const [value, setValue] = useState(\"1000\");\n\n const formattedValue = useMemo(() => {\n if (value === \"\") return value;\n\n const number = Number(value.replace(/,/g, \"\"));\n if (Number.isNaN(number)) return \"\";\n\n return number.toLocaleString();\n }, [value]);\n\n return (\n <TextField\n label=\"금액\"\n description=\"금액을 써주세요\"\n value={formattedValue}\n onValueChange={({ value }) => setValue(value)}\n >\n <TextFieldInput placeholder=\"9,999,999\" />\n </TextField>\n );\n}",
"text-field-optional": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldOptional() {\n return (\n <TextField label=\"라벨\" description=\"설명을 써주세요\" indicator=\"(선택)\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n );\n}",
"text-field-prefix": "import { IconMagnifyingglassLine } from \"@daangn/react-monochrome-icon\";\nimport { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldPrefix() {\n return (\n <div className=\"flex gap-4 w-full\">\n <TextField label=\"라벨\" description=\"설명을 써주세요\" prefix=\"https://\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField\n label=\"라벨\"\n description=\"설명을 써주세요\"\n prefixIcon={<IconMagnifyingglassLine />}\n >\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n </div>\n );\n}",
"text-field-preview": "import { useState } from \"react\";\nimport { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldPreview() {\n const [value, setValue] = useState(\"\");\n\n return (\n <div className=\"flex flex-col items-center w-full\">\n <TextField value={value} onValueChange={({ value }) => setValue(value)}>\n <TextFieldInput autoFocus />\n </TextField>\n <p className=\"text-center\">현재 값: {value}</p>\n </div>\n );\n}",
"text-field-react-hook-form": "import { ActionButton } from \"seed-design/ui/action-button\";\nimport { IconHouseLine } from \"@daangn/react-monochrome-icon\";\nimport { useForm } from \"react-hook-form\";\nimport { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\ninterface FormValues {\n name: string;\n address: string;\n}\n\nexport default function TextFieldReactHookForm() {\n const {\n register,\n handleSubmit,\n clearErrors,\n formState: { errors },\n } = useForm<FormValues>();\n\n const onValid = (data: FormValues) => {\n window.alert(JSON.stringify(data, null, 2));\n };\n\n return (\n <form className=\"grid grid-cols-2 gap-3 w-full\" onSubmit={handleSubmit(onValid)}>\n <TextField\n {...register(\"name\", { required: \"필수 입력 항목입니다\" })}\n label=\"이름\"\n description=\"이름을 써주세요\"\n invalid={!!errors.name}\n errorMessage={errors.name?.message}\n indicator=\"(필수)\"\n required\n >\n <TextFieldInput placeholder=\"홍길동\" />\n </TextField>\n <TextField\n {...register(\"address\", {\n required: \"필수 입력 항목입니다\",\n pattern: {\n value: /^대한민국/,\n message: \"대한민국으로 시작해주세요\",\n },\n })}\n label=\"주소\"\n description=\"주소를 써주세요\"\n invalid={!!errors.address}\n errorMessage={errors.address?.message}\n required\n indicator=\"(필수)\"\n prefixIcon={<IconHouseLine />}\n >\n <TextFieldInput placeholder=\"대한민국 서울특별시 은평구\" />\n </TextField>\n <div className=\"col-span-2 flex gap-2\">\n <ActionButton type=\"submit\" className=\"grow\">\n 제출\n </ActionButton>\n <ActionButton\n type=\"reset\"\n onClick={() => clearErrors([\"name\", \"address\"])}\n variant=\"neutralWeak\"\n >\n 초기화\n </ActionButton>\n </div>\n </form>\n );\n}",
"text-field-read-only": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldReadOnly() {\n return (\n <div className=\"grid grid-cols-2 gap-4 w-full\">\n <TextField label=\"라벨\" description=\"설명을 써주세요\" readOnly>\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField label=\"라벨\" description=\"설명을 써주세요\" readOnly defaultValue=\"값\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField\n label=\"라벨\"\n description=\"설명을 써주세요\"\n readOnly\n invalid\n errorMessage=\"오류가 발생한 이유를 써주세요\"\n >\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField\n label=\"라벨\"\n description=\"설명을 써주세요\"\n readOnly\n invalid\n errorMessage=\"오류가 발생한 이유를 써주세요\"\n defaultValue=\"값\"\n >\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n </div>\n );\n}",
"text-field-required": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldRequired() {\n return (\n <TextField label=\"라벨\" description=\"설명을 써주세요\" required indicator=\"(필수)\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n );\n}",
"text-field-slicing": "import { useState } from \"react\";\nimport { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldSlicing() {\n const [value, setValue] = useState(\"\");\n\n return (\n <TextField\n label=\"라벨\"\n description=\"6글자까지 입력 가능합니다\"\n maxGraphemeCount={6}\n value={value}\n onValueChange={({ slicedValue }) => setValue(slicedValue)}\n >\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n );\n}",
"text-field-suffix": "import { IconWonLine } from \"@daangn/react-monochrome-icon\";\nimport { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldSuffix() {\n return (\n <div className=\"flex gap-4 w-full\">\n <TextField label=\"라벨\" description=\"설명을 써주세요\" suffix=\"cm\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n <TextField label=\"라벨\" description=\"설명을 써주세요\" suffixIcon={<IconWonLine />}>\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n </div>\n );\n}",
"text-field-xlarge": "import { TextField, TextFieldInput } from \"seed-design/ui/text-field\";\n\nexport default function TextFieldXlarge() {\n return (\n <TextField label=\"라벨\" description=\"설명을 써주세요\" size=\"xlarge\">\n <TextFieldInput placeholder=\"플레이스홀더\" />\n </TextField>\n );\n}",
Expand Down
2 changes: 1 addition & 1 deletion docs/public/__registry__/ui/select-box.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{
"name": "select-box.tsx",
"type": "ui",
"content": "\"use client\";\n\nimport { IconCheckmarkFatFill } from \"@daangn/react-monochrome-icon\";\nimport {\n SelectBoxCheck as SeedSelectBoxCheck,\n SelectBoxRadio as SeedSelectBoxRadio,\n} from \"@seed-design/react\";\nimport * as React from \"react\";\n\nimport \"@seed-design/stylesheet/selectBox.css\";\nimport \"@seed-design/stylesheet/selectBoxGroup.css\";\n\nexport interface SelectBoxRadioGroupProps\n extends SeedSelectBoxRadio.GroupProps {}\n\nexport const SelectBoxRadioGroup = SeedSelectBoxRadio.Group;\n\nexport interface SelectBoxRadioProps extends SeedSelectBoxRadio.RootProps {\n label: string;\n\n description?: string;\n\n inputProps?: React.InputHTMLAttributes<HTMLInputElement>;\n\n rootRef?: React.Ref<HTMLLabelElement>;\n}\n\nexport const SelectBoxRadio = React.forwardRef<\n HTMLInputElement,\n SelectBoxRadioProps\n>(({ label, description, inputProps, rootRef, ...otherProps }, ref) => {\n if (!otherProps[\"aria-label\"] && !otherProps[\"aria-labelledby\"]) {\n console.warn(\n \"SelectBoxRadio component requires either an `aria-label` or `aria-labelledby` attribute.\",\n );\n }\n\n return (\n <SeedSelectBoxRadio.Root ref={rootRef} {...otherProps}>\n <SeedSelectBoxRadio.HiddenInput ref={ref} {...inputProps} />\n <SeedSelectBoxRadio.Content>\n <SeedSelectBoxRadio.Label>{label}</SeedSelectBoxRadio.Label>\n {description && (\n <SeedSelectBoxRadio.Description>\n {description}\n </SeedSelectBoxRadio.Description>\n )}\n </SeedSelectBoxRadio.Content>\n <SeedSelectBoxRadio.Control>\n <SeedSelectBoxRadio.Icon\n svg={\n <svg aria-hidden viewBox=\"0 0 24 24\">\n <circle cx=\"12\" cy=\"12\" r=\"12\" fill=\"currentColor\" />\n </svg>\n }\n />\n </SeedSelectBoxRadio.Control>\n </SeedSelectBoxRadio.Root>\n );\n});\nSelectBoxRadio.displayName = \"SelectBoxRadio\";\n\nexport interface SelectBoxCheckGroupProps\n extends SeedSelectBoxCheck.GroupProps {}\n\nexport const SelectBoxCheckGroup = SeedSelectBoxCheck.Group;\n\nexport interface SelectBoxCheckProps extends SeedSelectBoxCheck.RootProps {\n label: string;\n\n description?: string;\n\n inputProps?: React.InputHTMLAttributes<HTMLInputElement>;\n\n rootRef?: React.Ref<HTMLLabelElement>;\n}\n\nexport const SelectBoxCheck = React.forwardRef<\n HTMLInputElement,\n SelectBoxCheckProps\n>(({ label, description, inputProps, rootRef, ...otherProps }, ref) => {\n return (\n <SeedSelectBoxCheck.Root ref={rootRef} {...otherProps}>\n <SeedSelectBoxCheck.HiddenInput ref={ref} {...inputProps} />\n <SeedSelectBoxCheck.Content>\n <SeedSelectBoxCheck.Label>{label}</SeedSelectBoxCheck.Label>\n {description && (\n <SeedSelectBoxCheck.Description>\n {description}\n </SeedSelectBoxCheck.Description>\n )}\n </SeedSelectBoxCheck.Content>\n <SeedSelectBoxCheck.Control>\n <SeedSelectBoxCheck.Icon svg={<IconCheckmarkFatFill />} />\n </SeedSelectBoxCheck.Control>\n </SeedSelectBoxCheck.Root>\n );\n});\nSelectBoxCheck.displayName = \"SelectBoxCheck\";\n"
"content": "\"use client\";\n\nimport { IconCheckmarkFatFill } from \"@daangn/react-monochrome-icon\";\nimport {\n SelectBoxCheck as SeedSelectBoxCheck,\n SelectBoxRadio as SeedSelectBoxRadio,\n} from \"@seed-design/react\";\nimport * as React from \"react\";\n\nimport \"@seed-design/stylesheet/selectBox.css\";\nimport \"@seed-design/stylesheet/selectBoxGroup.css\";\n\nexport interface SelectBoxRadioGroupProps\n extends SeedSelectBoxRadio.GroupProps {}\n\nexport const SelectBoxRadioGroup = React.forwardRef<\n HTMLDivElement,\n SelectBoxRadioGroupProps\n>((props, ref) => {\n if (!props[\"aria-label\"] && !props[\"aria-labelledby\"]) {\n console.warn(\n \"SelectBoxRadioGroup component requires either an `aria-label` or `aria-labelledby` attribute.\",\n );\n }\n\n return <SeedSelectBoxRadio.Group ref={ref} {...props} />;\n});\n\nexport interface SelectBoxRadioProps extends SeedSelectBoxRadio.RootProps {\n label: string;\n\n description?: string;\n\n inputProps?: React.InputHTMLAttributes<HTMLInputElement>;\n\n rootRef?: React.Ref<HTMLLabelElement>;\n}\n\nexport const SelectBoxRadio = React.forwardRef<\n HTMLInputElement,\n SelectBoxRadioProps\n>(({ label, description, inputProps, rootRef, ...otherProps }, ref) => {\n return (\n <SeedSelectBoxRadio.Root ref={rootRef} {...otherProps}>\n <SeedSelectBoxRadio.HiddenInput ref={ref} {...inputProps} />\n <SeedSelectBoxRadio.Content>\n <SeedSelectBoxRadio.Label>{label}</SeedSelectBoxRadio.Label>\n {description && (\n <SeedSelectBoxRadio.Description>\n {description}\n </SeedSelectBoxRadio.Description>\n )}\n </SeedSelectBoxRadio.Content>\n <SeedSelectBoxRadio.Control>\n <SeedSelectBoxRadio.Icon\n svg={\n <svg aria-hidden viewBox=\"0 0 24 24\">\n <circle cx=\"12\" cy=\"12\" r=\"12\" fill=\"currentColor\" />\n </svg>\n }\n />\n </SeedSelectBoxRadio.Control>\n </SeedSelectBoxRadio.Root>\n );\n});\nSelectBoxRadio.displayName = \"SelectBoxRadio\";\n\nexport interface SelectBoxCheckGroupProps\n extends SeedSelectBoxCheck.GroupProps {}\n\nexport const SelectBoxCheckGroup = SeedSelectBoxCheck.Group;\n\nexport interface SelectBoxCheckProps extends SeedSelectBoxCheck.RootProps {\n label: string;\n\n description?: string;\n\n inputProps?: React.InputHTMLAttributes<HTMLInputElement>;\n\n rootRef?: React.Ref<HTMLLabelElement>;\n}\n\nexport const SelectBoxCheck = React.forwardRef<\n HTMLInputElement,\n SelectBoxCheckProps\n>(({ label, description, inputProps, rootRef, ...otherProps }, ref) => {\n return (\n <SeedSelectBoxCheck.Root ref={rootRef} {...otherProps}>\n <SeedSelectBoxCheck.HiddenInput ref={ref} {...inputProps} />\n <SeedSelectBoxCheck.Content>\n <SeedSelectBoxCheck.Label>{label}</SeedSelectBoxCheck.Label>\n {description && (\n <SeedSelectBoxCheck.Description>\n {description}\n </SeedSelectBoxCheck.Description>\n )}\n </SeedSelectBoxCheck.Content>\n <SeedSelectBoxCheck.Control>\n <SeedSelectBoxCheck.Icon svg={<IconCheckmarkFatFill />} />\n </SeedSelectBoxCheck.Control>\n </SeedSelectBoxCheck.Root>\n );\n});\nSelectBoxCheck.displayName = \"SelectBoxCheck\";\n"
}
]
}
19 changes: 12 additions & 7 deletions docs/registry/ui/select-box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,18 @@ import "@seed-design/stylesheet/selectBoxGroup.css";
export interface SelectBoxRadioGroupProps
extends SeedSelectBoxRadio.GroupProps {}

export const SelectBoxRadioGroup = SeedSelectBoxRadio.Group;
export const SelectBoxRadioGroup = React.forwardRef<
HTMLDivElement,
SelectBoxRadioGroupProps
>((props, ref) => {
if (!props["aria-label"] && !props["aria-labelledby"]) {
console.warn(
"SelectBoxRadioGroup component requires either an `aria-label` or `aria-labelledby` attribute.",
);
}

return <SeedSelectBoxRadio.Group ref={ref} {...props} />;
});

export interface SelectBoxRadioProps extends SeedSelectBoxRadio.RootProps {
label: string;
Expand All @@ -29,12 +40,6 @@ export const SelectBoxRadio = React.forwardRef<
HTMLInputElement,
SelectBoxRadioProps
>(({ label, description, inputProps, rootRef, ...otherProps }, ref) => {
if (!otherProps["aria-label"] && !otherProps["aria-labelledby"]) {
console.warn(
"SelectBoxRadio component requires either an `aria-label` or `aria-labelledby` attribute.",
);
}

return (
<SeedSelectBoxRadio.Root ref={rootRef} {...otherProps}>
<SeedSelectBoxRadio.HiddenInput ref={ref} {...inputProps} />
Expand Down

0 comments on commit ad31322

Please sign in to comment.