@cahyo-dimas/freeday 3.9.4 → 3.10.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/CHANGELOG.md +49 -0
- package/README.id.md +36 -8
- package/README.md +35 -8
- package/dist/freeday.bundle.css +74 -30
- package/dist/freeday.css +74 -30
- package/docs/getting-started.md +8 -1
- package/package.json +3 -1
- package/src/base.css +0 -3
- package/src/components/avatar.css +1 -1
- package/src/components/breadcrumb.css +1 -1
- package/src/components/cfl.css +72 -25
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,55 @@ benar. Perubahan seperti itu ditulis di bawah `### Changed: BREAKING (types)`
|
|
|
9
9
|
lama → tipe baru, dan cara menyempitkannya — bukan di bawah `### Added`, betapapun aditifnya dari
|
|
10
10
|
sisi kit.
|
|
11
11
|
|
|
12
|
+
## [3.10.0] - 2026-10-26
|
|
13
|
+
|
|
14
|
+
**Lima rilis dalam satu hari, empat di antaranya menambal satu kelas yang sama, dan pemiliknya
|
|
15
|
+
menghentikan polanya.** Setiap cacat Safari hari ini ditemukan oleh sebuah iPhone 7 sesudah
|
|
16
|
+
terkirim, satu per satu, karena suite kit berjalan di Chrome saja: `browser/harness.mjs` berbicara
|
|
17
|
+
CDP ke `chrome-headless-shell` dan tak ada WebKit di ujung kabel itu. Lantai dukungan di README
|
|
18
|
+
adalah prosa yang tak ada yang membacanya. Rilis ini memperbaiki keduanya.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **Gerbang lantai fitur** (`#091`), `test/baseline.test.mjs`. Ia **membaca ketiga angka lantai
|
|
22
|
+
dari README** alih-alih mengetiknya ulang, mengenumerasi 41 fitur CSS di kedua stylesheet yang
|
|
23
|
+
dikirim, dan gagal ketika satu di antaranya menuntut rilis yang lantainya tak capai. Pengecualian
|
|
24
|
+
boleh ada tetapi wajib membawa alasan tertulis minimal 160 karakter, DAN fiturnya harus benar-benar
|
|
25
|
+
masih melampaui lantai; kalau tidak gerbangnya menyuruh menghapus entrinya. Daftar pemaafan yang
|
|
26
|
+
tumbuh tanpa alasan adalah penjaga yang berhenti menjaga, dan itu persis kegagalan yang sudah
|
|
27
|
+
terjadi dua kali di hari yang sama.
|
|
28
|
+
- **Suite WebKit di gerbang** (`#092`), job CI tersendiri dengan Playwright, terpisah penuh dari
|
|
29
|
+
harness CDP yang menjalankan 206 uji dan tidak menyentuhnya. Sebelas uji menutup apa yang hanya
|
|
30
|
+
WebKit dapat perlihatkan: backdrop dan centang checkbox dan thumb switch harus MENCAPAI keadaan
|
|
31
|
+
akhirnya di bawah Reduce Motion, tap pada backdrop menutup drawer (sintesis klik `#057`), dan
|
|
32
|
+
asap tata letak telepon. Ia menolak lulus diam-diam lewat lima jalur yang semuanya diuji terhadap
|
|
33
|
+
laporan JSON nyata: laporan hilang, nol uji, ada yang dilewati, ada yang goyah, atau uji identitas
|
|
34
|
+
mesin hilang.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
- **Tiga fitur melampaui lantai yang kit nyatakan sendiri** (`#091`). `@container` di CFL dipagari
|
|
38
|
+
`@supports` dengan cadangan `@media (max-width:32rem)`, dan angka itu diturunkan dari lebar
|
|
39
|
+
dialognya sendiri bukan dipilih; absennya bukan kosmetik, sebab di Safari 15.4 sampai 15.8 seluruh
|
|
40
|
+
bloknya dibuang dan dialog 372px memakai tabel tiga kolom yang digulir dua arah.
|
|
41
|
+
`overscroll-behavior` dan `text-wrap:balance` jadi pengecualian beralasan. **Lantainya tidak
|
|
42
|
+
dinaikkan:** iPhone 7 yang menemukan empat cacat hari ini berhenti di iOS 15.
|
|
43
|
+
- **`user-select` dikirim tanpa pasangan `-webkit-`** di `.fdy-avatar` dan `.fdy-breadcrumb__sep`
|
|
44
|
+
(`#091`). WebKit menuntut prefiks itu sampai Safari 17.
|
|
45
|
+
- **Blok durasi-mungil lama di `src/base.css` mengalahkan perlakuan reduced-motion kit sendiri**
|
|
46
|
+
(`#093`). `*,*::before,*::after{animation-duration:.001ms !important}` sebagai `!important` pada
|
|
47
|
+
`*` menang atas `.fdy-spinner{animation-duration:2s}`, `.fdy-skeleton{animation:none}` dan
|
|
48
|
+
`.fdy-progress{animation:none}`, jadi ketiga perlakuan yang ditulis khusus untuk setelan itu tidak
|
|
49
|
+
pernah bekerja. Ketiganya satu-satunya animasi di luar pagar `no-preference`, jadi membuang blok
|
|
50
|
+
lama memulihkan semuanya tanpa membuka apa pun. Penjaga 3.9.4 melewatkannya karena regexnya
|
|
51
|
+
menuntut `0.001ms` berawalan nol sementara berkasnya menulis `.001ms`; sekarang ia menerima
|
|
52
|
+
keduanya dan ikut memeriksa `animation-duration`.
|
|
53
|
+
|
|
54
|
+
### Docs
|
|
55
|
+
- **Meta viewport dinyatakan sebagai syarat**, bukan ditampilkan di contoh. Tanpanya mesin mobile
|
|
56
|
+
menata halaman di lebar bawaan sekitar 980px, `(max-width:720px)` tak pernah cocok, dan seluruh
|
|
57
|
+
lapisan responsif kit absen: shell berdiri dalam bentuk desktopnya di telepon. Itu bukan
|
|
58
|
+
hipotetis. Fixture tanpa tag itu melaporkan `window.innerWidth` 981 pada deskriptor iPhone 7 di
|
|
59
|
+
jalanan pertama suite WebKit, bentuk yang sama persis dengan laporan yang memulai suite itu.
|
|
60
|
+
|
|
12
61
|
## [3.9.4] - 2026-10-26
|
|
13
62
|
|
|
14
63
|
**Sembilan dari lima puluh enam, dan empat puluh delapan sisanya ranjau.** Tiga rilis berturut-turut
|
package/README.id.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **Lebih banyak _free day_ buat dev. UI kit-nya sudah siap pakai.**
|
|
6
6
|
|
|
7
7
|
[](https://cahyo-dimas.github.io/freeday-ui-kit/)
|
|
8
|
-
[](https://github.com/cahyo-dimas/freeday-ui-kit/tree/v3.10.0)
|
|
9
9
|
|
|
10
10
|
UI KIT yang token-driven & framework-agnostic. Satu sumber kebenaran untuk warna, tipografi,
|
|
11
11
|
spasi, dan komponen. Blueprint: `docs/superpowers/specs/2026-07-21-freeday-ui-kit-design.md`.
|
|
@@ -256,8 +256,14 @@ terlihat, HTML native dulu sebelum ARIA, komponen interaktif ikut pola WAI-ARIA
|
|
|
256
256
|
|
|
257
257
|
## Dukungan browser
|
|
258
258
|
**Chrome 105 · Safari 15.4 · Firefox 121.** Floor-nya ditentukan `:has()`, dan oleh generasi Safari
|
|
259
|
-
15.4 untuk native `<dialog>`/`::backdrop
|
|
260
|
-
|
|
259
|
+
15.4 untuk native `<dialog>`/`::backdrop` dan `accent-color`. `conic-gradient` dan `scroll-snap`
|
|
260
|
+
lebih tua lagi.
|
|
261
|
+
|
|
262
|
+
`test/baseline.test.mjs` membaca tiga angka itu dari baris di atas, mengenumerasi fitur CSS yang
|
|
263
|
+
dipakai kedua stylesheet yang dikirim, dan gagal kalau salah satunya butuh rilis yang tak dijangkau
|
|
264
|
+
floor itu. Sebelum uji itu ada, floor-nya cuma kalimat yang tak bisa ditegakkan siapa pun, dan di
|
|
265
|
+
hari uji ini ditulis sudah ada lima rilis keluar dalam satu hari, empat di antaranya menambal cacat
|
|
266
|
+
Safari yang ketemu di iPhone 7 sesudah terkirim.
|
|
261
267
|
|
|
262
268
|
Dulu floor itu ditentukan `color-mix()` di Safari 16.4, dan sekarang tidak lagi. Harganya memang tak
|
|
263
269
|
pernah pantas: deklarasi yang mencampur sebuah token membawa `var()`, jadi ia dianggap sah saat
|
|
@@ -268,11 +274,33 @@ sekarang ditulis `rgba(var(--color-primary-rgb), .26)`, warnanya sama dan sudah
|
|
|
268
274
|
Safari 9; empat aturan yang memang tak bisa dijawab secara statis membawa pasangan `@supports` yang
|
|
269
275
|
sungguhan. `test/color-mix.test.mjs` menjaga agar yang berikutnya tetap jujur.
|
|
270
276
|
|
|
271
|
-
Yang paling baru dipakai kit ini
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
277
|
+
Yang paling baru dipakai kit ini memang melewati floor itu, dengan sengaja, dan tiap satunya
|
|
278
|
+
terdaftar di `test/baseline.test.mjs` beserta apa yang hilang di browser di bawah floor:
|
|
279
|
+
|
|
280
|
+
- `@container` di dialog choose-from-list dipagari `@supports`, dan satu media query lebar viewport
|
|
281
|
+
menumpuk barisnya di bawahnya. Yang tak bisa dilihat cadangan itu adalah dialog sempit di dalam
|
|
282
|
+
viewport lebar, yaitu panel yang didok di desktop, dan di situ dialognya tetap memakai tabel yang
|
|
283
|
+
digulir seperti selama ini.
|
|
284
|
+
- `@starting-style` dan transisi `allow-discrete` menganimasikan modal dan drawer. Di bawah floor
|
|
285
|
+
at-rule-nya dilewati dan shorthand-nya dibuang saat parse, jadi keduanya buka dan tutup tanpa
|
|
286
|
+
animasi, selalu di keadaan akhirnya dan tak pernah separuh jalan.
|
|
287
|
+
- `text-wrap: balance` menyeimbangkan dua kelas judul. Tanpa itu judulnya patah di tempat ia patah
|
|
288
|
+
sebelumnya.
|
|
289
|
+
- `overscroll-behavior: contain` menghentikan gulir di ujung nav dan di dua rail halaman yang
|
|
290
|
+
sticky. Tanpa itu gulirnya lanjut ke halaman di belakangnya, seperti sebelum properti ini ada.
|
|
291
|
+
Tidak ada gantinya di CSS di bawah Safari 16; pilihan lainnya scroll lock di JS, dan shell ini
|
|
292
|
+
sengaja tidak melakukannya.
|
|
293
|
+
- `scrollbar-width: none` menyembunyikan scrollbar carousel, dengan `::-webkit-scrollbar` di
|
|
294
|
+
sebelahnya yang mengerjakan hal sama untuk setiap WebKit di dalam floor.
|
|
295
|
+
- `100dvh` membatasi tinggi rail sticky di layar dari 960px. Safari sudah punya unit itu sejak rilis
|
|
296
|
+
floor-nya sendiri, jadi satu-satunya mesin di dalam floor yang belum punya adalah tiga rilis
|
|
297
|
+
Chrome sebelum unit itu mendarat di sana, dan di situ batasnya hilang dan aside yang panjang
|
|
298
|
+
tumbuh melewati viewport alih-alih digulir di dalam dirinya.
|
|
299
|
+
|
|
300
|
+
Blur backdrop pakai `-webkit-backdrop-filter` + `backdrop-filter`, dan `user-select` membawa kembar
|
|
301
|
+
`-webkit-`-nya dengan cara yang sama. Uji yang sama menegaskan kedua pasangan itu aturan per aturan,
|
|
302
|
+
jadi properti standarnya tak pernah dikirim sendirian. Belum ada CSS build/autoprefixer, jadi
|
|
303
|
+
dukungan di bawah floor itu jadi tanggung jawab konsumen.
|
|
276
304
|
|
|
277
305
|
## Lisensi
|
|
278
306
|
[MIT](LICENSE) © 2026 Cahyo D. Kurnianto. Bebas dipakai, diubah, dan didistribusikan asal
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **More free days for devs. The UI kit is ready to use.**
|
|
6
6
|
|
|
7
7
|
[](https://cahyo-dimas.github.io/freeday-ui-kit/)
|
|
8
|
-
[](https://github.com/cahyo-dimas/freeday-ui-kit/tree/v3.10.0)
|
|
9
9
|
|
|
10
10
|
A token-driven, framework-agnostic UI kit. One source of truth for color, typography,
|
|
11
11
|
spacing, and components. Blueprint: `docs/superpowers/specs/2026-07-21-freeday-ui-kit-design.md`.
|
|
@@ -266,8 +266,14 @@ the "Accessibility" section in `docs/index.html`.
|
|
|
266
266
|
|
|
267
267
|
## Browser support
|
|
268
268
|
**Chrome 105 · Safari 15.4 · Firefox 121.** The floor is set by `:has()`, and by the Safari 15.4
|
|
269
|
-
generation of native `<dialog>`/`::backdrop
|
|
270
|
-
|
|
269
|
+
generation of native `<dialog>`/`::backdrop` and `accent-color`. `conic-gradient` and `scroll-snap`
|
|
270
|
+
are older still.
|
|
271
|
+
|
|
272
|
+
`test/baseline.test.mjs` reads those three numbers out of the line above, enumerates the CSS
|
|
273
|
+
features both shipped stylesheets use, and fails when one of them needs a release the floor does not
|
|
274
|
+
reach. Until that test existed the floor was a sentence nobody could enforce, and the day it was
|
|
275
|
+
written five releases had gone out in one day, four of them fixing Safari defects found on an
|
|
276
|
+
iPhone 7 after shipping.
|
|
271
277
|
|
|
272
278
|
`color-mix()` used to set that floor at Safari 16.4, and it no longer does. It was never worth it:
|
|
273
279
|
a declaration that mixes a token carries `var()`, so it is assumed valid at parse time and only
|
|
@@ -278,11 +284,32 @@ written `rgba(var(--color-primary-rgb), .26)`, which is the same colour and pars
|
|
|
278
284
|
the four rules that cannot be answered statically carry a real `@supports` counterpart.
|
|
279
285
|
`test/color-mix.test.mjs` keeps the next one honest.
|
|
280
286
|
|
|
281
|
-
The newest things the kit touches
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
287
|
+
The newest things the kit touches reach past that floor on purpose, and each one is listed in
|
|
288
|
+
`test/baseline.test.mjs` with what a browser below the floor loses:
|
|
289
|
+
|
|
290
|
+
- `@container` in the choose-from-list dialog is fenced with `@supports`, and a viewport-width media
|
|
291
|
+
query stacks the rows underneath it. The case the fallback cannot see is a narrow dialog inside a
|
|
292
|
+
wide viewport, which is a docked panel on a desktop, and there the dialog keeps the scrolling
|
|
293
|
+
table it always had.
|
|
294
|
+
- `@starting-style` and the `allow-discrete` transitions animate the modal and the drawer. Below the
|
|
295
|
+
floor the at-rule is skipped and the shorthand is dropped at parse time, so both open and close
|
|
296
|
+
with no animation, always at their end state and never halfway.
|
|
297
|
+
- `text-wrap: balance` balances two heading classes. Without it a heading wraps where it used to.
|
|
298
|
+
- `overscroll-behavior: contain` stops a scroll at the end of the nav and of the sticky page rails.
|
|
299
|
+
Without it that scroll carries on into the page behind, the way it did before the property
|
|
300
|
+
existed. There is no CSS substitute below Safari 16; the alternative is a scroll lock in JS, which
|
|
301
|
+
this shell deliberately does not do.
|
|
302
|
+
- `scrollbar-width: none` hides the carousel scrollbar, with `::-webkit-scrollbar` beside it doing
|
|
303
|
+
the same job for every WebKit inside the floor.
|
|
304
|
+
- `100dvh` caps the sticky rails on screens from 960px. Safari has had the unit since the floor
|
|
305
|
+
release itself, so the only engines inside the floor without it are the three Chrome releases
|
|
306
|
+
before it landed there, and on those the cap goes away and a long aside grows past the viewport
|
|
307
|
+
instead of scrolling inside itself.
|
|
308
|
+
|
|
309
|
+
Backdrop blur uses `-webkit-backdrop-filter` + `backdrop-filter`, and `user-select` carries its
|
|
310
|
+
`-webkit-` twin the same way. The same test asserts both pairings rule by rule, so the standard
|
|
311
|
+
property never ships alone. There's no CSS build or autoprefixer step, so supporting anything below
|
|
312
|
+
the floor is the consumer's responsibility.
|
|
286
313
|
|
|
287
314
|
## License
|
|
288
315
|
[MIT](LICENSE) © 2026 Cahyo D. Kurnianto. Free to use, modify, and distribute, as long as the
|
package/dist/freeday.bundle.css
CHANGED
|
@@ -1213,9 +1213,6 @@ a { color: var(--color-primary-strong); }
|
|
|
1213
1213
|
* framework with its preflight OFF (the recommended pairing), a semantic <ul>/<ol> keeps native
|
|
1214
1214
|
* bullets + a 40px indent; add this class (or a Freeday list component) to normalise it. */
|
|
1215
1215
|
.fdy-list-reset { list-style: none; margin: 0; padding: 0; }
|
|
1216
|
-
@media (prefers-reduced-motion: reduce) {
|
|
1217
|
-
*, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
|
|
1218
|
-
}
|
|
1219
1216
|
|
|
1220
1217
|
/* ===========================================================================
|
|
1221
1218
|
* Reduce Motion: SETIAP transisi dinetralkan, bukan daftar yang dipelihara tangan.
|
|
@@ -1495,7 +1492,7 @@ a { color: var(--color-primary-strong); }
|
|
|
1495
1492
|
@media (prefers-reduced-motion:no-preference){.fdy-autocomplete__listbox:not([hidden]){animation:fdy-combo-in var(--dur-fast) var(--ease-standard);}}
|
|
1496
1493
|
|
|
1497
1494
|
/* Freeday. Avatar */
|
|
1498
|
-
.fdy-avatar{display:inline-flex;align-items:center;justify-content:center;flex:none;width:2.5rem;height:2.5rem;border-radius:var(--radius-full);background:var(--color-primary-soft);color:var(--color-primary-strong);font-family:var(--font-body);font-weight:var(--weight-semibold);font-size:var(--text-sm);line-height:1;overflow:hidden;user-select:none;}
|
|
1495
|
+
.fdy-avatar{display:inline-flex;align-items:center;justify-content:center;flex:none;width:2.5rem;height:2.5rem;border-radius:var(--radius-full);background:var(--color-primary-soft);color:var(--color-primary-strong);font-family:var(--font-body);font-weight:var(--weight-semibold);font-size:var(--text-sm);line-height:1;overflow:hidden;-webkit-user-select:none;user-select:none;}
|
|
1499
1496
|
.fdy-avatar img{width:100%;height:100%;object-fit:cover;}
|
|
1500
1497
|
/* --xs exists for an avatar INSIDE a control: `.fdy-btn--sm` is exactly 2rem tall, which is also
|
|
1501
1498
|
`--sm`'s size, so a small avatar in a small button fills it edge to edge and the ghost border
|
|
@@ -1651,7 +1648,7 @@ a { color: var(--color-primary-strong); }
|
|
|
1651
1648
|
.fdy-breadcrumb__link:hover{color:var(--color-primary-strong);text-decoration:underline;}
|
|
1652
1649
|
.fdy-breadcrumb__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1653
1650
|
.fdy-breadcrumb__item[aria-current="page"]{color:var(--color-text);font-weight:var(--weight-medium);}
|
|
1654
|
-
.fdy-breadcrumb__sep{color:var(--color-text-subtle);user-select:none;}
|
|
1651
|
+
.fdy-breadcrumb__sep{color:var(--color-text-subtle);-webkit-user-select:none;user-select:none;}
|
|
1655
1652
|
|
|
1656
1653
|
/* Freeday. Responsive display utilities (pairs with freeday-breakpoint.js).
|
|
1657
1654
|
* Breakpoint scale (min-width, px): sm 600 · md 960 · lg 1280 · xl 1920.
|
|
@@ -1957,7 +1954,13 @@ a { color: var(--color-primary-strong); }
|
|
|
1957
1954
|
* size, which is what made `.fdy-stats--inline` collapse to three zero tracks in 3.1.0. This box
|
|
1958
1955
|
* takes its width from the dialog (`min(46rem, 100vw - …)`, an explicit width) and already scrolls
|
|
1959
1956
|
* its own content, so it never sized to the table to begin with. */
|
|
1960
|
-
.fdy-cfl__results{
|
|
1957
|
+
.fdy-cfl__results{overflow:auto;max-height:min(24rem,50vh);}
|
|
1958
|
+
/* Fenced the way composition.css:62 fences its own, so the declaration states the condition it
|
|
1959
|
+
needs instead of relying on a browser to drop it. Safari 15.4 to 15.8 is inside the floor the
|
|
1960
|
+
README states and has no container queries at all. */
|
|
1961
|
+
@supports (container-type:inline-size){
|
|
1962
|
+
.fdy-cfl__results{container:fdy-cfl / inline-size;}
|
|
1963
|
+
}
|
|
1961
1964
|
.fdy-cfl__results .fdy-table th{position:sticky;top:0;z-index:1;}
|
|
1962
1965
|
|
|
1963
1966
|
.fdy-cfl__row{cursor:pointer;}
|
|
@@ -1999,30 +2002,71 @@ a { color: var(--color-primary-strong); }
|
|
|
1999
2002
|
*
|
|
2000
2003
|
* Column headers ARE a real loss here, and a deliberate one: `<thead>` is hidden, because a header
|
|
2001
2004
|
* row that costs a third of the width buys nothing when each row is labelled by its own title. */
|
|
2002
|
-
@
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2005
|
+
@supports (container-type:inline-size){
|
|
2006
|
+
@container fdy-cfl (max-width: 30rem){
|
|
2007
|
+
.fdy-cfl__results .fdy-table,
|
|
2008
|
+
.fdy-cfl__results .fdy-table tbody{display:block;width:100%;}
|
|
2009
|
+
.fdy-cfl__results .fdy-table thead{display:none;}
|
|
2010
|
+
.fdy-cfl__row{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:var(--bw) solid var(--color-border-muted);}
|
|
2011
|
+
.fdy-cfl__results .fdy-table tbody tr:last-child{border-bottom:0;}
|
|
2012
|
+
.fdy-cfl__row > td{display:block;padding:0;border:0;}
|
|
2013
|
+
/* The title takes the whole first line, which is what pushes every remaining cell onto the second
|
|
2014
|
+
one — no selector has to know how many columns there are, or which of them is last. */
|
|
2015
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check),
|
|
2016
|
+
.fdy-cfl__row > .fdy-cfl__check + td{font-weight:var(--weight-semibold);color:var(--color-text);}
|
|
2017
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check){flex:0 0 100%;}
|
|
2018
|
+
/* Multi-select: the checkbox shares line one with the title, so the title claims the rest of it. */
|
|
2019
|
+
.fdy-cfl__row > .fdy-cfl__check + td{flex:1 0 calc(100% - var(--space-6));}
|
|
2020
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td,
|
|
2021
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td{font-size:var(--text-xs);color:var(--color-text-muted);}
|
|
2022
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td:empty,
|
|
2023
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td:empty{display:none;}
|
|
2024
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td::before,
|
|
2025
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td::before{content:"·";margin-right:var(--space-2);color:var(--color-text-subtle);}
|
|
2026
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) + td::before,
|
|
2027
|
+
.fdy-cfl__row > .fdy-cfl__check + td + td::before{content:none;}
|
|
2028
|
+
/* The checkbox keeps its own line position beside the title rather than above it. */
|
|
2029
|
+
.fdy-cfl__row > .fdy-cfl__check{flex:none;width:auto;align-self:center;}
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
/* The same block for a browser that has no container queries, which is every Safari from 15.4 to
|
|
2034
|
+
* 15.8 and inside the floor the README states. There the @supports above is false, the stacked
|
|
2035
|
+
* layout never applied, and a 372px dialog kept a three-column master-data table that scrolls on
|
|
2036
|
+
* both axes.
|
|
2037
|
+
*
|
|
2038
|
+
* The condition is a VIEWPORT width, the only width this path can read. 32rem is derived from the
|
|
2039
|
+
* dialog rather than picked: the dialog is min(46rem, 100vw - var(--space-8)) with --space-8 at
|
|
2040
|
+
* 2rem, and the results box takes that width, so it sits at or under 30rem exactly when the
|
|
2041
|
+
* viewport sits at or under 32rem. What a media query cannot answer is the case the container
|
|
2042
|
+
* query exists for, a narrow dialog inside a wide viewport, which is a docked panel on a desktop;
|
|
2043
|
+
* on those browsers that one case keeps the scrolling table it has always had.
|
|
2044
|
+
*
|
|
2045
|
+
* The body is a copy of the body above, because CSS has no way to share one declaration block
|
|
2046
|
+
* between two different conditions. test/baseline.test.mjs compares the two, so an edit that
|
|
2047
|
+
* reaches one of them and misses the other fails there. */
|
|
2048
|
+
@supports not (container-type:inline-size){
|
|
2049
|
+
@media (max-width:32rem){
|
|
2050
|
+
.fdy-cfl__results .fdy-table,
|
|
2051
|
+
.fdy-cfl__results .fdy-table tbody{display:block;width:100%;}
|
|
2052
|
+
.fdy-cfl__results .fdy-table thead{display:none;}
|
|
2053
|
+
.fdy-cfl__row{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:var(--bw) solid var(--color-border-muted);}
|
|
2054
|
+
.fdy-cfl__results .fdy-table tbody tr:last-child{border-bottom:0;}
|
|
2055
|
+
.fdy-cfl__row > td{display:block;padding:0;border:0;}
|
|
2056
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check),
|
|
2057
|
+
.fdy-cfl__row > .fdy-cfl__check + td{font-weight:var(--weight-semibold);color:var(--color-text);}
|
|
2058
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check){flex:0 0 100%;}
|
|
2059
|
+
.fdy-cfl__row > .fdy-cfl__check + td{flex:1 0 calc(100% - var(--space-6));}
|
|
2060
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td,
|
|
2061
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td{font-size:var(--text-xs);color:var(--color-text-muted);}
|
|
2062
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td:empty,
|
|
2063
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td:empty{display:none;}
|
|
2064
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td::before,
|
|
2065
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td::before{content:"·";margin-right:var(--space-2);color:var(--color-text-subtle);}
|
|
2066
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) + td::before,
|
|
2067
|
+
.fdy-cfl__row > .fdy-cfl__check + td + td::before{content:none;}
|
|
2068
|
+
.fdy-cfl__row > .fdy-cfl__check{flex:none;width:auto;align-self:center;}
|
|
2069
|
+
}
|
|
2026
2070
|
}
|
|
2027
2071
|
|
|
2028
2072
|
/* Freeday. Charts (zero-dependency CSS/SVG, rendered by freeday-chart.js).
|
package/dist/freeday.css
CHANGED
|
@@ -36,9 +36,6 @@ a { color: var(--color-primary-strong); }
|
|
|
36
36
|
* framework with its preflight OFF (the recommended pairing), a semantic <ul>/<ol> keeps native
|
|
37
37
|
* bullets + a 40px indent; add this class (or a Freeday list component) to normalise it. */
|
|
38
38
|
.fdy-list-reset { list-style: none; margin: 0; padding: 0; }
|
|
39
|
-
@media (prefers-reduced-motion: reduce) {
|
|
40
|
-
*, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
|
|
41
|
-
}
|
|
42
39
|
|
|
43
40
|
/* ===========================================================================
|
|
44
41
|
* Reduce Motion: SETIAP transisi dinetralkan, bukan daftar yang dipelihara tangan.
|
|
@@ -318,7 +315,7 @@ a { color: var(--color-primary-strong); }
|
|
|
318
315
|
@media (prefers-reduced-motion:no-preference){.fdy-autocomplete__listbox:not([hidden]){animation:fdy-combo-in var(--dur-fast) var(--ease-standard);}}
|
|
319
316
|
|
|
320
317
|
/* Freeday. Avatar */
|
|
321
|
-
.fdy-avatar{display:inline-flex;align-items:center;justify-content:center;flex:none;width:2.5rem;height:2.5rem;border-radius:var(--radius-full);background:var(--color-primary-soft);color:var(--color-primary-strong);font-family:var(--font-body);font-weight:var(--weight-semibold);font-size:var(--text-sm);line-height:1;overflow:hidden;user-select:none;}
|
|
318
|
+
.fdy-avatar{display:inline-flex;align-items:center;justify-content:center;flex:none;width:2.5rem;height:2.5rem;border-radius:var(--radius-full);background:var(--color-primary-soft);color:var(--color-primary-strong);font-family:var(--font-body);font-weight:var(--weight-semibold);font-size:var(--text-sm);line-height:1;overflow:hidden;-webkit-user-select:none;user-select:none;}
|
|
322
319
|
.fdy-avatar img{width:100%;height:100%;object-fit:cover;}
|
|
323
320
|
/* --xs exists for an avatar INSIDE a control: `.fdy-btn--sm` is exactly 2rem tall, which is also
|
|
324
321
|
`--sm`'s size, so a small avatar in a small button fills it edge to edge and the ghost border
|
|
@@ -474,7 +471,7 @@ a { color: var(--color-primary-strong); }
|
|
|
474
471
|
.fdy-breadcrumb__link:hover{color:var(--color-primary-strong);text-decoration:underline;}
|
|
475
472
|
.fdy-breadcrumb__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
476
473
|
.fdy-breadcrumb__item[aria-current="page"]{color:var(--color-text);font-weight:var(--weight-medium);}
|
|
477
|
-
.fdy-breadcrumb__sep{color:var(--color-text-subtle);user-select:none;}
|
|
474
|
+
.fdy-breadcrumb__sep{color:var(--color-text-subtle);-webkit-user-select:none;user-select:none;}
|
|
478
475
|
|
|
479
476
|
/* Freeday. Responsive display utilities (pairs with freeday-breakpoint.js).
|
|
480
477
|
* Breakpoint scale (min-width, px): sm 600 · md 960 · lg 1280 · xl 1920.
|
|
@@ -780,7 +777,13 @@ a { color: var(--color-primary-strong); }
|
|
|
780
777
|
* size, which is what made `.fdy-stats--inline` collapse to three zero tracks in 3.1.0. This box
|
|
781
778
|
* takes its width from the dialog (`min(46rem, 100vw - …)`, an explicit width) and already scrolls
|
|
782
779
|
* its own content, so it never sized to the table to begin with. */
|
|
783
|
-
.fdy-cfl__results{
|
|
780
|
+
.fdy-cfl__results{overflow:auto;max-height:min(24rem,50vh);}
|
|
781
|
+
/* Fenced the way composition.css:62 fences its own, so the declaration states the condition it
|
|
782
|
+
needs instead of relying on a browser to drop it. Safari 15.4 to 15.8 is inside the floor the
|
|
783
|
+
README states and has no container queries at all. */
|
|
784
|
+
@supports (container-type:inline-size){
|
|
785
|
+
.fdy-cfl__results{container:fdy-cfl / inline-size;}
|
|
786
|
+
}
|
|
784
787
|
.fdy-cfl__results .fdy-table th{position:sticky;top:0;z-index:1;}
|
|
785
788
|
|
|
786
789
|
.fdy-cfl__row{cursor:pointer;}
|
|
@@ -822,30 +825,71 @@ a { color: var(--color-primary-strong); }
|
|
|
822
825
|
*
|
|
823
826
|
* Column headers ARE a real loss here, and a deliberate one: `<thead>` is hidden, because a header
|
|
824
827
|
* row that costs a third of the width buys nothing when each row is labelled by its own title. */
|
|
825
|
-
@
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
828
|
+
@supports (container-type:inline-size){
|
|
829
|
+
@container fdy-cfl (max-width: 30rem){
|
|
830
|
+
.fdy-cfl__results .fdy-table,
|
|
831
|
+
.fdy-cfl__results .fdy-table tbody{display:block;width:100%;}
|
|
832
|
+
.fdy-cfl__results .fdy-table thead{display:none;}
|
|
833
|
+
.fdy-cfl__row{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:var(--bw) solid var(--color-border-muted);}
|
|
834
|
+
.fdy-cfl__results .fdy-table tbody tr:last-child{border-bottom:0;}
|
|
835
|
+
.fdy-cfl__row > td{display:block;padding:0;border:0;}
|
|
836
|
+
/* The title takes the whole first line, which is what pushes every remaining cell onto the second
|
|
837
|
+
one — no selector has to know how many columns there are, or which of them is last. */
|
|
838
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check),
|
|
839
|
+
.fdy-cfl__row > .fdy-cfl__check + td{font-weight:var(--weight-semibold);color:var(--color-text);}
|
|
840
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check){flex:0 0 100%;}
|
|
841
|
+
/* Multi-select: the checkbox shares line one with the title, so the title claims the rest of it. */
|
|
842
|
+
.fdy-cfl__row > .fdy-cfl__check + td{flex:1 0 calc(100% - var(--space-6));}
|
|
843
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td,
|
|
844
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td{font-size:var(--text-xs);color:var(--color-text-muted);}
|
|
845
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td:empty,
|
|
846
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td:empty{display:none;}
|
|
847
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td::before,
|
|
848
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td::before{content:"·";margin-right:var(--space-2);color:var(--color-text-subtle);}
|
|
849
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) + td::before,
|
|
850
|
+
.fdy-cfl__row > .fdy-cfl__check + td + td::before{content:none;}
|
|
851
|
+
/* The checkbox keeps its own line position beside the title rather than above it. */
|
|
852
|
+
.fdy-cfl__row > .fdy-cfl__check{flex:none;width:auto;align-self:center;}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/* The same block for a browser that has no container queries, which is every Safari from 15.4 to
|
|
857
|
+
* 15.8 and inside the floor the README states. There the @supports above is false, the stacked
|
|
858
|
+
* layout never applied, and a 372px dialog kept a three-column master-data table that scrolls on
|
|
859
|
+
* both axes.
|
|
860
|
+
*
|
|
861
|
+
* The condition is a VIEWPORT width, the only width this path can read. 32rem is derived from the
|
|
862
|
+
* dialog rather than picked: the dialog is min(46rem, 100vw - var(--space-8)) with --space-8 at
|
|
863
|
+
* 2rem, and the results box takes that width, so it sits at or under 30rem exactly when the
|
|
864
|
+
* viewport sits at or under 32rem. What a media query cannot answer is the case the container
|
|
865
|
+
* query exists for, a narrow dialog inside a wide viewport, which is a docked panel on a desktop;
|
|
866
|
+
* on those browsers that one case keeps the scrolling table it has always had.
|
|
867
|
+
*
|
|
868
|
+
* The body is a copy of the body above, because CSS has no way to share one declaration block
|
|
869
|
+
* between two different conditions. test/baseline.test.mjs compares the two, so an edit that
|
|
870
|
+
* reaches one of them and misses the other fails there. */
|
|
871
|
+
@supports not (container-type:inline-size){
|
|
872
|
+
@media (max-width:32rem){
|
|
873
|
+
.fdy-cfl__results .fdy-table,
|
|
874
|
+
.fdy-cfl__results .fdy-table tbody{display:block;width:100%;}
|
|
875
|
+
.fdy-cfl__results .fdy-table thead{display:none;}
|
|
876
|
+
.fdy-cfl__row{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:var(--bw) solid var(--color-border-muted);}
|
|
877
|
+
.fdy-cfl__results .fdy-table tbody tr:last-child{border-bottom:0;}
|
|
878
|
+
.fdy-cfl__row > td{display:block;padding:0;border:0;}
|
|
879
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check),
|
|
880
|
+
.fdy-cfl__row > .fdy-cfl__check + td{font-weight:var(--weight-semibold);color:var(--color-text);}
|
|
881
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check){flex:0 0 100%;}
|
|
882
|
+
.fdy-cfl__row > .fdy-cfl__check + td{flex:1 0 calc(100% - var(--space-6));}
|
|
883
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td,
|
|
884
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td{font-size:var(--text-xs);color:var(--color-text-muted);}
|
|
885
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td:empty,
|
|
886
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td:empty{display:none;}
|
|
887
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td::before,
|
|
888
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td::before{content:"·";margin-right:var(--space-2);color:var(--color-text-subtle);}
|
|
889
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) + td::before,
|
|
890
|
+
.fdy-cfl__row > .fdy-cfl__check + td + td::before{content:none;}
|
|
891
|
+
.fdy-cfl__row > .fdy-cfl__check{flex:none;width:auto;align-self:center;}
|
|
892
|
+
}
|
|
849
893
|
}
|
|
850
894
|
|
|
851
895
|
/* Freeday. Charts (zero-dependency CSS/SVG, rendered by freeday-chart.js).
|
package/docs/getting-started.md
CHANGED
|
@@ -156,6 +156,13 @@ cp -r node_modules/@cahyo-dimas/freeday/dist ./assets/freeday # copy into your
|
|
|
156
156
|
```
|
|
157
157
|
> Two-file alternative: `freeday.tokens.css` (tokens) + `freeday.css` (components).
|
|
158
158
|
|
|
159
|
+
> **The viewport meta is required, not decoration.** Without it a mobile engine lays the page out at
|
|
160
|
+
> a default width near 980px, so `(max-width: 720px)` never matches and the kit's entire responsive
|
|
161
|
+
> layer is absent: the app shell stands in its desktop form on a phone, sidebar visible and bottom
|
|
162
|
+
> nav gone. That is not a hypothetical. It is what a fixture without the tag did on the first run of
|
|
163
|
+
> the WebKit suite, reporting `window.innerWidth` 981 on an iPhone 7 descriptor, and it is the same
|
|
164
|
+
> shape as the report that started that suite.
|
|
165
|
+
|
|
159
166
|
### 3. Load the enhancers before `</body>`
|
|
160
167
|
```html
|
|
161
168
|
<script src="assets/freeday/freeday.js" defer></script>
|
|
@@ -191,7 +198,7 @@ live docs also have a copy button per component.
|
|
|
191
198
|
```bash
|
|
192
199
|
npm i @cahyo-dimas/freeday
|
|
193
200
|
```
|
|
194
|
-
Lands in `package.json` as `"@cahyo-dimas/freeday": "^3.
|
|
201
|
+
Lands in `package.json` as `"@cahyo-dimas/freeday": "^3.10.0"` (public npm package). `dist/` is
|
|
195
202
|
committed and published → no build step; `npm ci` runs without auth.
|
|
196
203
|
|
|
197
204
|
### 2. Import the CSS + enhancers **once** in your entry (`src/main.ts`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cahyo-dimas/freeday",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.0",
|
|
4
4
|
"description": "Freeday: token-driven, framework-agnostic UI KIT (design source-of-truth).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -101,9 +101,11 @@
|
|
|
101
101
|
"version": "node tokens/build.mjs && git add dist",
|
|
102
102
|
"typecheck:react": "tsc -p adapters/react/tsconfig.json --noEmit",
|
|
103
103
|
"test:blazor": "dotnet test test/blazor -v quiet --nologo",
|
|
104
|
+
"test:webkit": "playwright test",
|
|
104
105
|
"test:blazor-server": "node --test browser/blazor-server.mjs"
|
|
105
106
|
},
|
|
106
107
|
"devDependencies": {
|
|
108
|
+
"@playwright/test": "^1.64.1",
|
|
107
109
|
"@types/react": "^19.2.17",
|
|
108
110
|
"esbuild": "^0.28.1",
|
|
109
111
|
"react": "^19.2.8",
|
package/src/base.css
CHANGED
|
@@ -35,9 +35,6 @@ a { color: var(--color-primary-strong); }
|
|
|
35
35
|
* framework with its preflight OFF (the recommended pairing), a semantic <ul>/<ol> keeps native
|
|
36
36
|
* bullets + a 40px indent; add this class (or a Freeday list component) to normalise it. */
|
|
37
37
|
.fdy-list-reset { list-style: none; margin: 0; padding: 0; }
|
|
38
|
-
@media (prefers-reduced-motion: reduce) {
|
|
39
|
-
*, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
|
|
40
|
-
}
|
|
41
38
|
|
|
42
39
|
/* ===========================================================================
|
|
43
40
|
* Reduce Motion: SETIAP transisi dinetralkan, bukan daftar yang dipelihara tangan.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Freeday. Avatar */
|
|
2
|
-
.fdy-avatar{display:inline-flex;align-items:center;justify-content:center;flex:none;width:2.5rem;height:2.5rem;border-radius:var(--radius-full);background:var(--color-primary-soft);color:var(--color-primary-strong);font-family:var(--font-body);font-weight:var(--weight-semibold);font-size:var(--text-sm);line-height:1;overflow:hidden;user-select:none;}
|
|
2
|
+
.fdy-avatar{display:inline-flex;align-items:center;justify-content:center;flex:none;width:2.5rem;height:2.5rem;border-radius:var(--radius-full);background:var(--color-primary-soft);color:var(--color-primary-strong);font-family:var(--font-body);font-weight:var(--weight-semibold);font-size:var(--text-sm);line-height:1;overflow:hidden;-webkit-user-select:none;user-select:none;}
|
|
3
3
|
.fdy-avatar img{width:100%;height:100%;object-fit:cover;}
|
|
4
4
|
/* --xs exists for an avatar INSIDE a control: `.fdy-btn--sm` is exactly 2rem tall, which is also
|
|
5
5
|
`--sm`'s size, so a small avatar in a small button fills it edge to edge and the ghost border
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
.fdy-breadcrumb__link:hover{color:var(--color-primary-strong);text-decoration:underline;}
|
|
7
7
|
.fdy-breadcrumb__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
8
8
|
.fdy-breadcrumb__item[aria-current="page"]{color:var(--color-text);font-weight:var(--weight-medium);}
|
|
9
|
-
.fdy-breadcrumb__sep{color:var(--color-text-subtle);user-select:none;}
|
|
9
|
+
.fdy-breadcrumb__sep{color:var(--color-text-subtle);-webkit-user-select:none;user-select:none;}
|
package/src/components/cfl.css
CHANGED
|
@@ -23,7 +23,13 @@
|
|
|
23
23
|
* size, which is what made `.fdy-stats--inline` collapse to three zero tracks in 3.1.0. This box
|
|
24
24
|
* takes its width from the dialog (`min(46rem, 100vw - …)`, an explicit width) and already scrolls
|
|
25
25
|
* its own content, so it never sized to the table to begin with. */
|
|
26
|
-
.fdy-cfl__results{
|
|
26
|
+
.fdy-cfl__results{overflow:auto;max-height:min(24rem,50vh);}
|
|
27
|
+
/* Fenced the way composition.css:62 fences its own, so the declaration states the condition it
|
|
28
|
+
needs instead of relying on a browser to drop it. Safari 15.4 to 15.8 is inside the floor the
|
|
29
|
+
README states and has no container queries at all. */
|
|
30
|
+
@supports (container-type:inline-size){
|
|
31
|
+
.fdy-cfl__results{container:fdy-cfl / inline-size;}
|
|
32
|
+
}
|
|
27
33
|
.fdy-cfl__results .fdy-table th{position:sticky;top:0;z-index:1;}
|
|
28
34
|
|
|
29
35
|
.fdy-cfl__row{cursor:pointer;}
|
|
@@ -65,28 +71,69 @@
|
|
|
65
71
|
*
|
|
66
72
|
* Column headers ARE a real loss here, and a deliberate one: `<thead>` is hidden, because a header
|
|
67
73
|
* row that costs a third of the width buys nothing when each row is labelled by its own title. */
|
|
68
|
-
@
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
74
|
+
@supports (container-type:inline-size){
|
|
75
|
+
@container fdy-cfl (max-width: 30rem){
|
|
76
|
+
.fdy-cfl__results .fdy-table,
|
|
77
|
+
.fdy-cfl__results .fdy-table tbody{display:block;width:100%;}
|
|
78
|
+
.fdy-cfl__results .fdy-table thead{display:none;}
|
|
79
|
+
.fdy-cfl__row{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:var(--bw) solid var(--color-border-muted);}
|
|
80
|
+
.fdy-cfl__results .fdy-table tbody tr:last-child{border-bottom:0;}
|
|
81
|
+
.fdy-cfl__row > td{display:block;padding:0;border:0;}
|
|
82
|
+
/* The title takes the whole first line, which is what pushes every remaining cell onto the second
|
|
83
|
+
one — no selector has to know how many columns there are, or which of them is last. */
|
|
84
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check),
|
|
85
|
+
.fdy-cfl__row > .fdy-cfl__check + td{font-weight:var(--weight-semibold);color:var(--color-text);}
|
|
86
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check){flex:0 0 100%;}
|
|
87
|
+
/* Multi-select: the checkbox shares line one with the title, so the title claims the rest of it. */
|
|
88
|
+
.fdy-cfl__row > .fdy-cfl__check + td{flex:1 0 calc(100% - var(--space-6));}
|
|
89
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td,
|
|
90
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td{font-size:var(--text-xs);color:var(--color-text-muted);}
|
|
91
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td:empty,
|
|
92
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td:empty{display:none;}
|
|
93
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td::before,
|
|
94
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td::before{content:"·";margin-right:var(--space-2);color:var(--color-text-subtle);}
|
|
95
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) + td::before,
|
|
96
|
+
.fdy-cfl__row > .fdy-cfl__check + td + td::before{content:none;}
|
|
97
|
+
/* The checkbox keeps its own line position beside the title rather than above it. */
|
|
98
|
+
.fdy-cfl__row > .fdy-cfl__check{flex:none;width:auto;align-self:center;}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* The same block for a browser that has no container queries, which is every Safari from 15.4 to
|
|
103
|
+
* 15.8 and inside the floor the README states. There the @supports above is false, the stacked
|
|
104
|
+
* layout never applied, and a 372px dialog kept a three-column master-data table that scrolls on
|
|
105
|
+
* both axes.
|
|
106
|
+
*
|
|
107
|
+
* The condition is a VIEWPORT width, the only width this path can read. 32rem is derived from the
|
|
108
|
+
* dialog rather than picked: the dialog is min(46rem, 100vw - var(--space-8)) with --space-8 at
|
|
109
|
+
* 2rem, and the results box takes that width, so it sits at or under 30rem exactly when the
|
|
110
|
+
* viewport sits at or under 32rem. What a media query cannot answer is the case the container
|
|
111
|
+
* query exists for, a narrow dialog inside a wide viewport, which is a docked panel on a desktop;
|
|
112
|
+
* on those browsers that one case keeps the scrolling table it has always had.
|
|
113
|
+
*
|
|
114
|
+
* The body is a copy of the body above, because CSS has no way to share one declaration block
|
|
115
|
+
* between two different conditions. test/baseline.test.mjs compares the two, so an edit that
|
|
116
|
+
* reaches one of them and misses the other fails there. */
|
|
117
|
+
@supports not (container-type:inline-size){
|
|
118
|
+
@media (max-width:32rem){
|
|
119
|
+
.fdy-cfl__results .fdy-table,
|
|
120
|
+
.fdy-cfl__results .fdy-table tbody{display:block;width:100%;}
|
|
121
|
+
.fdy-cfl__results .fdy-table thead{display:none;}
|
|
122
|
+
.fdy-cfl__row{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:var(--bw) solid var(--color-border-muted);}
|
|
123
|
+
.fdy-cfl__results .fdy-table tbody tr:last-child{border-bottom:0;}
|
|
124
|
+
.fdy-cfl__row > td{display:block;padding:0;border:0;}
|
|
125
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check),
|
|
126
|
+
.fdy-cfl__row > .fdy-cfl__check + td{font-weight:var(--weight-semibold);color:var(--color-text);}
|
|
127
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check){flex:0 0 100%;}
|
|
128
|
+
.fdy-cfl__row > .fdy-cfl__check + td{flex:1 0 calc(100% - var(--space-6));}
|
|
129
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td,
|
|
130
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td{font-size:var(--text-xs);color:var(--color-text-muted);}
|
|
131
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td:empty,
|
|
132
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td:empty{display:none;}
|
|
133
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) ~ td::before,
|
|
134
|
+
.fdy-cfl__row > .fdy-cfl__check + td ~ td::before{content:"·";margin-right:var(--space-2);color:var(--color-text-subtle);}
|
|
135
|
+
.fdy-cfl__row > td:first-child:not(.fdy-cfl__check) + td::before,
|
|
136
|
+
.fdy-cfl__row > .fdy-cfl__check + td + td::before{content:none;}
|
|
137
|
+
.fdy-cfl__row > .fdy-cfl__check{flex:none;width:auto;align-self:center;}
|
|
138
|
+
}
|
|
92
139
|
}
|