@ahmetilhn/hanui 1.2.0 → 2.0.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/README.md +110 -12
- package/build/index.cjs +18 -14
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +1600 -160
- package/build/index.js +3906 -1962
- package/build/index.js.map +1 -1
- package/build/styles.css +1 -1
- package/package.json +18 -5
package/README.md
CHANGED
|
@@ -83,6 +83,9 @@ const THEME = {
|
|
|
83
83
|
light: { blue: '#0d6efd', 'blue-text': '#0a58ca' },
|
|
84
84
|
dark: { blue: '#6ea8fe' },
|
|
85
85
|
fonts: { heading: 'Archivo, sans-serif', body: 'Inter, sans-serif' },
|
|
86
|
+
// Ölçüler tema başına DEĞİL: bir markanın yuvarlaklığı açık temada
|
|
87
|
+
// 12 px, koyu temada 8 px olmaz.
|
|
88
|
+
metrics: { 'radius-md': '2px', 'radius-lg': '4px', 'duration-normal': '120ms' },
|
|
86
89
|
};
|
|
87
90
|
|
|
88
91
|
<HanuiProvider theme={THEME} linkComponent={NextLink}>
|
|
@@ -97,16 +100,65 @@ React'in dışından (bir `<head>` betiğinden, Storybook'tan) aynı işi
|
|
|
97
100
|
(`next/font`, `@font-face`, CDN) siz yaparsınız. Bir UI paketinin ağdan font
|
|
98
101
|
çekmesi, sizin ölçemediğiniz bir istek demek.
|
|
99
102
|
|
|
103
|
+
#### Ezilebilen ölçüler
|
|
104
|
+
|
|
105
|
+
`radius-*` · `space-0…9` · `font-size-2xs…4xl` · `leading-*` · `icon-xs…xl` ·
|
|
106
|
+
`duration-*` · `ease-*` — tam liste `METRIC_TOKENS` içinde ve dışa veriliyor.
|
|
107
|
+
|
|
108
|
+
Ezilemeyenler ve nedenleri: **kırılma noktaları** (`@media (max-width: var(--x))`
|
|
109
|
+
geçersiz CSS), **katman (`z-*`)** (yığılma sırası, marka kararı değil) ve
|
|
110
|
+
**dokunma hedefi** (44 px; yoğun kipte de küçülmemeli — WCAG 2.5.8).
|
|
111
|
+
|
|
112
|
+
### Bilgi yoğunluğu
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<html data-hanui-density="compact"></html>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Satır yüksekliği, dolgu ve punto bir kademe iner. Vitrin bir ekranda 8 satır,
|
|
119
|
+
operasyon paneli 80 satır gösteriyor; ikisini tek ölçekle karşılamanın yolu yok.
|
|
120
|
+
Kararı `initHanui({ density: 'compact' })` da verebilir.
|
|
121
|
+
|
|
122
|
+
**Yarıçap değişmez** (yuvarlaklık yoğunluğun değil markanın işi) ve **dokunma
|
|
123
|
+
hedefi küçülmez**: görsel kutu daralır, `tap-target` örtüsü 44 px kalır.
|
|
124
|
+
|
|
125
|
+
### CSS'imizi ezmek — `@layer hanui`
|
|
126
|
+
|
|
127
|
+
Kütüphane CSS'inin tamamı `@layer hanui` içinde. Katmanlı bir kural, katmansız
|
|
128
|
+
bir kurala **her zaman yenilir** — özgüllüğe ve sıraya bakılmaksızın:
|
|
129
|
+
|
|
130
|
+
```css
|
|
131
|
+
/* Bu kadarı yeter; `!important` ya da `.app .card .card` gerekmez. */
|
|
132
|
+
.my-card {
|
|
133
|
+
padding: 0;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Katman olmadan sizin sınıfınız ile bizimki aynı özgüllükte (0,1,0) yarışıyordu
|
|
138
|
+
ve kazananı **kaynak sırası** belirliyordu; o sıra da bundler'ınızın elinde —
|
|
139
|
+
geliştirme ile üretim aynı olmak zorunda değil.
|
|
140
|
+
|
|
100
141
|
### Temayı değiştirmek
|
|
101
142
|
|
|
102
143
|
```tsx
|
|
103
|
-
const { scheme, toggle, isReady } = useHanuiTheme();
|
|
144
|
+
const { scheme, preference, setScheme, toggle, isReady } = useHanuiTheme();
|
|
104
145
|
|
|
105
146
|
useEffect(() => {
|
|
106
|
-
if (isReady) localStorage.setItem('theme',
|
|
107
|
-
}, [
|
|
147
|
+
if (isReady) localStorage.setItem('theme', preference);
|
|
148
|
+
}, [preference, isReady]);
|
|
108
149
|
```
|
|
109
150
|
|
|
151
|
+
| Alan | |
|
|
152
|
+
| --- | --- |
|
|
153
|
+
| `scheme` | **ÇÖZÜLMÜŞ** tema — ekranda çizili olan (`light` \| `dark`) |
|
|
154
|
+
| `preference` | kullanıcının **SEÇİMİ** (`light` \| `dark` \| `system`) |
|
|
155
|
+
| `setScheme` | `'system'` verildiğinde açık seçim SİLİNİR |
|
|
156
|
+
|
|
157
|
+
Üç durumlu bir anahtar (Açık / Koyu / Sistem) `preference` okur; `scheme`
|
|
158
|
+
okusaydı "Sistem" seçiliyken düğme "Koyu"yu işaretli gösterirdi. `system` bir
|
|
159
|
+
değer değil **değerin yokluğu**: öznitelik silinir ve
|
|
160
|
+
`:not([data-hanui-theme])` sorgusu devreye girer.
|
|
161
|
+
|
|
110
162
|
Kalıcılık **kancanın işi değil**: seçimi `localStorage`a mı, sunucuda
|
|
111
163
|
okunabilsin diye bir çereze mi, kullanıcı profiline mi yazacağınız sizin
|
|
112
164
|
kararınız. Kütüphane `localStorage`a yazsaydı sunucu tarafı onu okuyamayacağı
|
|
@@ -121,13 +173,27 @@ uyuşmazlık üretiyordu.
|
|
|
121
173
|
|
|
122
174
|
```
|
|
123
175
|
theme/palette.ts → ham hex (TEK hex kaynağı)
|
|
124
|
-
theme/tokens.ts → anlamsal token →
|
|
176
|
+
theme/tokens.ts → anlamsal token → değer
|
|
177
|
+
LIGHT_THEME / DARK_THEME (renk, temaya bağlı)
|
|
178
|
+
METRIC_TOKENS (ölçü, temadan bağımsız)
|
|
179
|
+
COMPACT_DENSITY (yoğun kipin ezdikleri)
|
|
125
180
|
styles/*.generated → yukarıdakinden ÜRETİLİR (npm run tokens)
|
|
126
181
|
```
|
|
127
182
|
|
|
128
183
|
SCSS ve TypeScript tarafı elle tutulsaydı bir tarafta var olup diğerinde
|
|
129
184
|
olmayan bir token çıkardı — ve ayrışma sessiz: bileşen `var(--hanui-yok)`
|
|
130
|
-
okuyup rengini kaybediyor, derleme yeşil dönüyor.
|
|
185
|
+
okuyup rengini kaybediyor, derleme yeşil dönüyor. Nöbetçi
|
|
186
|
+
`theme/__tests__/tokens.contract.test.ts`.
|
|
187
|
+
|
|
188
|
+
**Ölçüler CSS değişkeni olduğu için SCSS aritmetiği çalışmaz.**
|
|
189
|
+
`$space-8 - $space-2` derlenmez — ve Sass hata da vermez: ifadeyi olduğu gibi
|
|
190
|
+
geçirip tarayıcıya `var(--a)-var(--b)` yazar, tarayıcı bütün bildirimi atar.
|
|
191
|
+
Hesap `calc()` içinde yazılır, negatif değer dahil:
|
|
192
|
+
|
|
193
|
+
```scss
|
|
194
|
+
padding-inline-start: calc(#{$space-8} - #{$space-2});
|
|
195
|
+
margin-inline: calc(-1 * #{$space-2});
|
|
196
|
+
```
|
|
131
197
|
|
|
132
198
|
---
|
|
133
199
|
|
|
@@ -350,15 +416,47 @@ import NextLink from 'next/link';
|
|
|
350
416
|
```bash
|
|
351
417
|
nvm use # .nvmrc → 24
|
|
352
418
|
npm install
|
|
353
|
-
npm run verify # tokens → typecheck → lint →
|
|
419
|
+
npm run verify # tokens → kontrast → typecheck → lint → kapsam → build → boyut
|
|
420
|
+
npm run playground # bileşen galerisi → http://localhost:5273
|
|
354
421
|
```
|
|
355
422
|
|
|
356
|
-
| Komut
|
|
357
|
-
|
|
|
358
|
-
| `npm run tokens`
|
|
359
|
-
| `npm run build`
|
|
360
|
-
| `npm run test`
|
|
361
|
-
| `npm run
|
|
423
|
+
| Komut | |
|
|
424
|
+
| ------------------------- | --------------------------------------------------------------- |
|
|
425
|
+
| `npm run tokens` | SCSS token dosyalarını `theme/tokens.ts`ten üretir |
|
|
426
|
+
| `npm run build` | `build/` (ESM + CJS + `.d.ts` + `styles.css`) |
|
|
427
|
+
| `npm run test` | Jest + Testing Library + `jest-axe` |
|
|
428
|
+
| `npm run test:coverage` | kapsam kapısı — `helpers`/`hooks`/`theme` satır ≥ %80 |
|
|
429
|
+
| `npm run test:visual` | görsel regresyon (Playwright); `verify` İÇİNDE DEĞİL, aşağı bkz. |
|
|
430
|
+
| `npm run check:contrast` | WCAG kontrast ölçümü, iki temada 118 çift |
|
|
431
|
+
| `npm run size` | paket boyutu bütçesi (`size-limit`) |
|
|
432
|
+
| `npm run playground` | bileşen galerisi (tema · RTL · yoğunluk anahtarı) |
|
|
433
|
+
| `npm run lint` | ESLint (TS) + stylelint (SCSS) |
|
|
434
|
+
| `npm run typecheck` | `tsc --noEmit` |
|
|
435
|
+
|
|
436
|
+
### Nöbetçiler ne koruyor
|
|
437
|
+
|
|
438
|
+
- **Eksen taraması** — dışa verilen her bileşen, her anlamlı durumunda
|
|
439
|
+
(`components/__tests__/a11y.test.tsx`). Deftere girmeyen yeni bir bileşen
|
|
440
|
+
testi kırar.
|
|
441
|
+
- **Klavye sözleşmesi** — tuş matrisleri her bileşenin JSDoc'unda, nöbetçisi
|
|
442
|
+
`components/__tests__/keyboard.test.tsx`.
|
|
443
|
+
- **Kontrast** — metin ≥ 4,5:1, ikon ve odak halkası ≥ 3:1. Eşiği tutmayan bir
|
|
444
|
+
token derlemeyi kırar; düzeltme daima `palette.ts` düzeyinde yapılır.
|
|
445
|
+
- **Token sözleşmesi** — açık/koyu anahtar kümeleri ve üretilmiş SCSS kaynakla
|
|
446
|
+
eşleşir. Ayrışma bugüne kadar sessizdi.
|
|
447
|
+
- **Paket boyutu** — tek bileşen import eden bir uygulamanın ne indirdiği
|
|
448
|
+
ölçülür (`Badge` 2,7 kB, `Button` 3,4 kB, tüm paket 22,2 kB gzip).
|
|
449
|
+
- **Odak halkası ve hareket ölçeği** — stylelint, `focus-ring` mixin'i dışında
|
|
450
|
+
`outline` ve bileşen SCSS'inde ham süre değeri (`0.7s`) yazılmasını
|
|
451
|
+
engelliyor. Üç bileşen kendi halkasını, iki bileşen kendi süresini
|
|
452
|
+
yazıyordu.
|
|
453
|
+
|
|
454
|
+
**Görsel regresyon `verify` içinde değil**: ekran görüntüsü platforma bağlı
|
|
455
|
+
(yazı tipi tarama, alt piksel yumuşatma) ve macOS'te üretilmiş bir referans
|
|
456
|
+
ubuntu üzerinde koşan CI'da her dosyada kırmızı döner. Referanslar platform
|
|
457
|
+
başına saklanıyor (`e2e/__screenshots__/{platform}/`); CI'da açılacağı gün doğru
|
|
458
|
+
yol, Playwright'ın resmi konteynerinde koşup `linux` referanslarını orada
|
|
459
|
+
üretmek.
|
|
362
460
|
|
|
363
461
|
`master`a her push `npm publish` çalıştırır — **`package.json` sürümünü
|
|
364
462
|
yükseltmeyi unutmayın**, aynı sürüm ikinci kez yayımlanamaz ve iş akışı kırmızı
|