@moontra/moonui 6.12.0 → 6.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/index.global.js +29 -0
- package/dist/hooks/index.global.js.map +1 -1
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/__tests__/progress-accessible-name.test.tsx +65 -0
- package/src/components/ui/progress.tsx +14 -0
package/package.json
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #343 — `role="progressbar"` erişilebilir ad taşır.
|
|
3
|
+
*
|
|
4
|
+
* Ölçüm component düzeyinde olduğunu kendi başına söylüyordu: `/docs/components/progress`
|
|
5
|
+
* sayfasındaki 39 ihlal, o sayfadaki progressbar'ların TAMAMIYDI. Kusur tek tek
|
|
6
|
+
* örneklerde değil component'in kendisindeydi.
|
|
7
|
+
*
|
|
8
|
+
* WAI-ARIA `progressbar`ın adlandırılmış olmasını ister; adsız kalırsa ekran okuyucu
|
|
9
|
+
* yalnız yüzdeyi duyurur — "67%" — neyin %67'si olduğu söylenmez.
|
|
10
|
+
*
|
|
11
|
+
* Tasarım kararı (#334'ün dersi): varsayılan ad COMPONENT'ten gelir. Erişilebilirliği
|
|
12
|
+
* "tüketici hatırlarsa" koşuluna bağlamak, `floating-action-button`da olduğu gibi
|
|
13
|
+
* sessizce ihlale dönüşür.
|
|
14
|
+
*/
|
|
15
|
+
import * as React from 'react'
|
|
16
|
+
import { render, screen } from '@testing-library/react'
|
|
17
|
+
import '@testing-library/jest-dom'
|
|
18
|
+
|
|
19
|
+
import { Progress } from '../progress'
|
|
20
|
+
|
|
21
|
+
describe('#343 Progress erişilebilir ad', () => {
|
|
22
|
+
it('ad verilmezse component KENDİ varsayılanını basar', () => {
|
|
23
|
+
render(<Progress value={67} />)
|
|
24
|
+
expect(screen.getByRole('progressbar')).toHaveAccessibleName('Progress')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('tüketicinin `aria-label`i varsayılanı EZER', () => {
|
|
28
|
+
render(<Progress value={67} aria-label="Upload progress" />)
|
|
29
|
+
expect(screen.getByRole('progressbar')).toHaveAccessibleName('Upload progress')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('`aria-labelledby` verildiğinde varsayılan `aria-label` HİÇ basılmaz', () => {
|
|
33
|
+
// İkisi birden basılsaydı accname yine labelledby'ı seçerdi ama DOM kirlenirdi;
|
|
34
|
+
// daha önemlisi, "ad zaten var" durumunun component tarafından anlaşılması gerekir.
|
|
35
|
+
render(
|
|
36
|
+
<>
|
|
37
|
+
<span id="etiket">Sync status</span>
|
|
38
|
+
<Progress value={30} aria-labelledby="etiket" />
|
|
39
|
+
</>
|
|
40
|
+
)
|
|
41
|
+
const bar = screen.getByRole('progressbar')
|
|
42
|
+
expect(bar).not.toHaveAttribute('aria-label')
|
|
43
|
+
expect(bar).toHaveAccessibleName('Sync status')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('değer bilgisi korunur (ad eklemek onu bozmadı)', () => {
|
|
47
|
+
render(<Progress value={45} max={90} />)
|
|
48
|
+
const bar = screen.getByRole('progressbar')
|
|
49
|
+
expect(bar).toHaveAttribute('aria-valuenow', '45')
|
|
50
|
+
expect(bar).toHaveAttribute('aria-valuemax', '90')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('`valueLabel` sayısal olmayan bir değeri `aria-valuetext` ile duyurur', () => {
|
|
54
|
+
// Görsel etiket "3/10" iken ekran okuyucunun ham "30" okuması kopukluk yaratır.
|
|
55
|
+
render(<Progress value={30} valueLabel="3/10 steps" />)
|
|
56
|
+
expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuetext', '3/10 steps')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('indeterminate durumda `aria-valuenow` YOK ama ad hâlâ var', () => {
|
|
60
|
+
render(<Progress indeterminate />)
|
|
61
|
+
const bar = screen.getByRole('progressbar')
|
|
62
|
+
expect(bar).not.toHaveAttribute('aria-valuenow')
|
|
63
|
+
expect(bar).toHaveAccessibleName('Progress')
|
|
64
|
+
})
|
|
65
|
+
})
|
|
@@ -145,6 +145,11 @@ const Progress = React.forwardRef<
|
|
|
145
145
|
|
|
146
146
|
// Etiket içeriği
|
|
147
147
|
const label = valueLabel || `${Math.round(percentage)}%`;
|
|
148
|
+
|
|
149
|
+
// Tüketici kendi adını verdiyse varsayılanı basma. `aria-labelledby` accname
|
|
150
|
+
// algoritmasında `aria-label`i zaten ezer; yine de ikisini birden basmamak daha temiz.
|
|
151
|
+
const hasExplicitName =
|
|
152
|
+
props["aria-label"] != null || props["aria-labelledby"] != null;
|
|
148
153
|
|
|
149
154
|
return (
|
|
150
155
|
<>
|
|
@@ -167,6 +172,15 @@ const Progress = React.forwardRef<
|
|
|
167
172
|
aria-valuemin={0}
|
|
168
173
|
aria-valuemax={max}
|
|
169
174
|
aria-valuenow={indeterminate ? undefined : normalizedValue}
|
|
175
|
+
// #343: WAI-ARIA `progressbar`ın adlandırılmış olmasını ister. Adsız kalırsa
|
|
176
|
+
// ekran okuyucu yalnız yüzdeyi duyurur: "67%" — neyin %67'si belli olmaz.
|
|
177
|
+
// Varsayılan ad component'ten gelir; "tüketici hatırlarsa" bir a11y stratejisi
|
|
178
|
+
// değildir (#334'ün dersi). `{...props}` bu satırlardan SONRA yayıldığı için
|
|
179
|
+
// tüketicinin verdiği `aria-label` her zaman kazanır.
|
|
180
|
+
aria-label={hasExplicitName ? undefined : "Progress"}
|
|
181
|
+
// Sayısal olmayan bir etiket verildiğinde ("3/10", "Uploading") ekran okuyucu
|
|
182
|
+
// ham sayı yerine bunu okumalı.
|
|
183
|
+
aria-valuetext={valueLabel}
|
|
170
184
|
{...props}
|
|
171
185
|
>
|
|
172
186
|
<div
|