feat(@fox): FoxSelect에 ariaLabel
라벨을 두지 않는 필터 셀렉트에 이름을 줄 방법이 없었다. FoxSelectText와 같은 규칙으로 label이 있으면 무시하고, 없을 때만 트리거에 aria-label을 붙인다. Co-Authored-By: Claude Opus 5
@3ccae7e99868952a4d20fd34574c4e3b4265a77a
--- @fox/core/components/fox-select/fox-select.tsx
+++ @fox/core/components/fox-select/fox-select.tsx
... | ... | @@ -79,6 +79,11 @@ |
| 79 | 79 |
readOnly?: boolean; |
| 80 | 80 |
/** 필드 위 라벨. 넘기지 않으면 라벨을 렌더링하지 않는다. */ |
| 81 | 81 |
label?: ReactNode; |
| 82 |
+ /** |
|
| 83 |
+ * 라벨을 두지 않는 자리(시안의 필터 셀렉트 등)에서 트리거를 읽어 줄 이름. |
|
| 84 |
+ * `label`이 있으면 그쪽이 이름이라 무시된다(`FoxSelectText`와 같은 규칙). |
|
| 85 |
+ */ |
|
| 86 |
+ ariaLabel?: string; |
|
| 82 | 87 |
/** 라벨 뒤 필수·선택 표시. `label`이 없으면 의미 없다. */ |
| 83 | 88 |
requirement?: FoxFormLabelRequirement; |
| 84 | 89 |
/** select 아래 힌트 메시지. 넘기지 않으면 힌트 영역을 렌더링하지 않는다. */ |
... | ... | @@ -127,6 +132,7 @@ |
| 127 | 132 |
disabled = false, |
| 128 | 133 |
readOnly = false, |
| 129 | 134 |
label, |
| 135 |
+ ariaLabel, |
|
| 130 | 136 |
requirement, |
| 131 | 137 |
hint, |
| 132 | 138 |
hintIcon, |
... | ... | @@ -312,6 +318,7 @@ |
| 312 | 318 |
id={triggerId}
|
| 313 | 319 |
role="combobox" |
| 314 | 320 |
disabled={isDisabled}
|
| 321 |
+ aria-label={label ? undefined : ariaLabel}
|
|
| 315 | 322 |
aria-haspopup="listbox" |
| 316 | 323 |
aria-expanded={open}
|
| 317 | 324 |
// 리스트박스는 열렸을 때만 렌더되므로, 닫힌 동안 없는 id를 가리키지 않게 한다. |
--- @fox/dev-test/component-registry.tsx
+++ @fox/dev-test/component-registry.tsx
... | ... | @@ -1460,10 +1460,10 @@ |
| 1460 | 1460 |
), |
| 1461 | 1461 |
}, |
| 1462 | 1462 |
{
|
| 1463 |
- label: "라벨 없음 · 힌트 없음 — 해당 영역이 렌더되지 않는다", |
|
| 1463 |
+ label: "라벨 없음 · 힌트 없음 — 이름은 ariaLabel로 준다", |
|
| 1464 | 1464 |
node: ( |
| 1465 | 1465 |
<div className={styles.demoFields}>
|
| 1466 |
- <FoxSelect size="md" options={SELECT_ITEMS} />
|
|
| 1466 |
+ <FoxSelect size="md" ariaLabel="등급" options={SELECT_ITEMS} />
|
|
| 1467 | 1467 |
<FoxSelect size="md" label="라벨만" options={SELECT_ITEMS} />
|
| 1468 | 1468 |
</div> |
| 1469 | 1469 |
), |
--- app/(protected)/(basic)/points/accumulated/_components/point-account-list.tsx
+++ app/(protected)/(basic)/points/accumulated/_components/point-account-list.tsx
... | ... | @@ -186,6 +186,7 @@ |
| 186 | 186 |
<div className={styles.select}>
|
| 187 | 187 |
<FoxSelect |
| 188 | 188 |
size="md" |
| 189 |
+ ariaLabel="학년" |
|
| 189 | 190 |
options={numberOptions(GRADE_OPTIONS, '학년')}
|
| 190 | 191 |
value={selectedNumber(query.grade)}
|
| 191 | 192 |
onValueChange={(value) => go({ grade: parseSelected(value) })}
|
... | ... | @@ -194,6 +195,7 @@ |
| 194 | 195 |
<div className={styles.select}>
|
| 195 | 196 |
<FoxSelect |
| 196 | 197 |
size="md" |
| 198 |
+ ariaLabel="반" |
|
| 197 | 199 |
options={numberOptions(CLASS_OPTIONS, '반')}
|
| 198 | 200 |
value={selectedNumber(query.classNo)}
|
| 199 | 201 |
onValueChange={(value) => go({ classNo: parseSelected(value) })}
|
... | ... | @@ -202,6 +204,7 @@ |
| 202 | 204 |
<div className={styles.select}>
|
| 203 | 205 |
<FoxSelect |
| 204 | 206 |
size="md" |
| 207 |
+ ariaLabel="번호" |
|
| 205 | 208 |
options={numberOptions(NUMBER_OPTIONS, '번')}
|
| 206 | 209 |
value={selectedNumber(query.studentNo)}
|
| 207 | 210 |
onValueChange={(value) => go({ studentNo: parseSelected(value) })}
|
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?