use-wc 1.0.0-pre.68 → 1.0.0-pre.69

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.
@@ -89,6 +89,76 @@
89
89
  }
90
90
  ]
91
91
  },
92
+ {
93
+ "kind": "javascript-module",
94
+ "path": "src/elements/use-avatar/use-avatar.ts",
95
+ "declarations": [
96
+ {
97
+ "kind": "class",
98
+ "description": "`use-avatar` renders a small, fixed-size, clipped container for a person or entity's\nlikeness. Slot in an `<img>` (or `<picture>`) for a photo, an inline `<svg>` for a\ngenerated or stylized mark, or arbitrary markup (a `<div>` of initials, a calendar badge);\nwhatever is slotted is centered and clipped to the avatar's shape. With nothing slotted,\n`use-avatar` falls back to initials derived from the `name` attribute.\n\n```html\n<use-avatar><img src=\"ada.jpg\" alt=\"\" /></use-avatar>\n<use-avatar name=\"Riley Quinn\"></use-avatar>\n<use-avatar><svg viewBox=\"0 0 32 32\">…</svg></use-avatar>\n```\n\nSize it with plain CSS — `inline-size` for the size and `aspect-ratio` for the proportions —\nfrom a stylesheet, a style attribute, or the design system's theme layer. The element takes no\ncustom properties of its own: it is a query container, so the initials scale from whatever box\nit ends up with. A non-square `aspect-ratio` suits a wide thumbnail or poster.\n\nThe element clips its content but gives it no shape of its own — that is the theme's, through\nthe affordance classes it defines: `.circle` (the themed default), `.square`, `.squircle` in\n`theme/avatar.css`. A circle only reads right at a `1` ratio, so a wide avatar wants one of the\nothers.\n\nThe element takes no ARIA role of its own. A slotted `<img>` carries its own `alt`, and the\ninitials fallback is plain text in the accessibility tree — an avatar is decorative beside a\nname far more often than it is the name itself, so labelling it here would mean announcing\nthat name twice.",
99
+ "name": "UseAvatar",
100
+ "cssParts": [
101
+ {
102
+ "description": "The span that renders the `name` fallback.",
103
+ "name": "initials"
104
+ }
105
+ ],
106
+ "slots": [
107
+ {
108
+ "description": "The avatar's content: an `<img>`/`<picture>`, an `<svg>`, or arbitrary markup. Left empty, the `name` attribute's initials are shown instead, as the slot's own fallback. A photo fills the frame and crops; anything else keeps its own size, capped at the frame. Give an `<svg>` a `width`/`height` — without one it defaults to filling the box, and a rounded shape will clip its corners.",
109
+ "name": ""
110
+ }
111
+ ],
112
+ "members": [
113
+ {
114
+ "kind": "field",
115
+ "name": "name",
116
+ "type": {
117
+ "text": "string"
118
+ },
119
+ "default": "\"\"",
120
+ "attribute": "name",
121
+ "reflects": true
122
+ }
123
+ ],
124
+ "attributes": [
125
+ {
126
+ "description": "The full name, used for the initials fallback (first + last whitespace-separated token, uppercased) when the slot is empty.",
127
+ "name": "name",
128
+ "type": {
129
+ "text": "string"
130
+ },
131
+ "default": "\"\"",
132
+ "fieldName": "name"
133
+ }
134
+ ],
135
+ "superclass": {
136
+ "name": "LitElement",
137
+ "package": "lit"
138
+ },
139
+ "tagName": "use-avatar",
140
+ "customElement": true
141
+ }
142
+ ],
143
+ "exports": [
144
+ {
145
+ "kind": "js",
146
+ "name": "UseAvatar",
147
+ "declaration": {
148
+ "name": "UseAvatar",
149
+ "module": "src/elements/use-avatar/use-avatar.ts"
150
+ }
151
+ },
152
+ {
153
+ "kind": "custom-element-definition",
154
+ "name": "use-avatar",
155
+ "declaration": {
156
+ "name": "UseAvatar",
157
+ "module": "src/elements/use-avatar/use-avatar.ts"
158
+ }
159
+ }
160
+ ]
161
+ },
92
162
  {
93
163
  "kind": "javascript-module",
94
164
  "path": "src/elements/use-badge/use-badge.ts",
@@ -232,76 +302,6 @@
232
302
  }
233
303
  ]
234
304
  },
235
- {
236
- "kind": "javascript-module",
237
- "path": "src/elements/use-avatar/use-avatar.ts",
238
- "declarations": [
239
- {
240
- "kind": "class",
241
- "description": "`use-avatar` renders a small, fixed-size, clipped container for a person or entity's\nlikeness. Slot in an `<img>` (or `<picture>`) for a photo, an inline `<svg>` for a\ngenerated or stylized mark, or arbitrary markup (a `<div>` of initials, a calendar badge);\nwhatever is slotted is centered and clipped to the avatar's shape. With nothing slotted,\n`use-avatar` falls back to initials derived from the `name` attribute.\n\n```html\n<use-avatar><img src=\"ada.jpg\" alt=\"\" /></use-avatar>\n<use-avatar name=\"Riley Quinn\"></use-avatar>\n<use-avatar><svg viewBox=\"0 0 32 32\">…</svg></use-avatar>\n```\n\nSize it with plain CSS — `inline-size` for the size and `aspect-ratio` for the proportions —\nfrom a stylesheet, a style attribute, or the design system's theme layer. The element takes no\ncustom properties of its own: it is a query container, so the initials scale from whatever box\nit ends up with. A non-square `aspect-ratio` suits a wide thumbnail or poster.\n\nThe element clips its content but gives it no shape of its own — that is the theme's, through\nthe affordance classes it defines: `.circle` (the themed default), `.square`, `.squircle` in\n`theme/avatar.css`. A circle only reads right at a `1` ratio, so a wide avatar wants one of the\nothers.\n\nThe element takes no ARIA role of its own. A slotted `<img>` carries its own `alt`, and the\ninitials fallback is plain text in the accessibility tree — an avatar is decorative beside a\nname far more often than it is the name itself, so labelling it here would mean announcing\nthat name twice.",
242
- "name": "UseAvatar",
243
- "cssParts": [
244
- {
245
- "description": "The span that renders the `name` fallback.",
246
- "name": "initials"
247
- }
248
- ],
249
- "slots": [
250
- {
251
- "description": "The avatar's content: an `<img>`/`<picture>`, an `<svg>`, or arbitrary markup. Left empty, the `name` attribute's initials are shown instead, as the slot's own fallback. A photo fills the frame and crops; anything else keeps its own size, capped at the frame. Give an `<svg>` a `width`/`height` — without one it defaults to filling the box, and a rounded shape will clip its corners.",
252
- "name": ""
253
- }
254
- ],
255
- "members": [
256
- {
257
- "kind": "field",
258
- "name": "name",
259
- "type": {
260
- "text": "string"
261
- },
262
- "default": "\"\"",
263
- "attribute": "name",
264
- "reflects": true
265
- }
266
- ],
267
- "attributes": [
268
- {
269
- "description": "The full name, used for the initials fallback (first + last whitespace-separated token, uppercased) when the slot is empty.",
270
- "name": "name",
271
- "type": {
272
- "text": "string"
273
- },
274
- "default": "\"\"",
275
- "fieldName": "name"
276
- }
277
- ],
278
- "superclass": {
279
- "name": "LitElement",
280
- "package": "lit"
281
- },
282
- "tagName": "use-avatar",
283
- "customElement": true
284
- }
285
- ],
286
- "exports": [
287
- {
288
- "kind": "js",
289
- "name": "UseAvatar",
290
- "declaration": {
291
- "name": "UseAvatar",
292
- "module": "src/elements/use-avatar/use-avatar.ts"
293
- }
294
- },
295
- {
296
- "kind": "custom-element-definition",
297
- "name": "use-avatar",
298
- "declaration": {
299
- "name": "UseAvatar",
300
- "module": "src/elements/use-avatar/use-avatar.ts"
301
- }
302
- }
303
- ]
304
- },
305
305
  {
306
306
  "kind": "javascript-module",
307
307
  "path": "src/elements/use-calendar-base/use-calendar-base.ts",
@@ -3667,6 +3667,63 @@
3667
3667
  }
3668
3668
  ]
3669
3669
  },
3670
+ {
3671
+ "kind": "javascript-module",
3672
+ "path": "src/elements/use-scrollarea/index.ts",
3673
+ "declarations": [],
3674
+ "exports": [
3675
+ {
3676
+ "kind": "js",
3677
+ "name": "UseScrollarea",
3678
+ "declaration": {
3679
+ "name": "UseScrollarea",
3680
+ "module": "./use-scrollarea"
3681
+ }
3682
+ }
3683
+ ]
3684
+ },
3685
+ {
3686
+ "kind": "javascript-module",
3687
+ "path": "src/elements/use-scrollarea/use-scrollarea.ts",
3688
+ "declarations": [
3689
+ {
3690
+ "kind": "class",
3691
+ "description": "A scroll container that exposes custom states for scroll edge detection.\n\n## Custom States\nThe following CSS custom states are available for styling:\n\n- `:state(at-block-start)` — scrolled to the block-start edge (top in horizontal writing modes)\n- `:state(at-block-end)` — scrolled to the block-end edge (bottom in horizontal writing modes)\n- `:state(at-inline-start)` — scrolled to the inline-start edge (left in LTR)\n- `:state(at-inline-end)` — scrolled to the inline-end edge (right in LTR)",
3692
+ "name": "UseScrollarea",
3693
+ "slots": [
3694
+ {
3695
+ "description": "Scrollable content",
3696
+ "name": ""
3697
+ }
3698
+ ],
3699
+ "members": [],
3700
+ "superclass": {
3701
+ "name": "LitElement",
3702
+ "package": "lit"
3703
+ },
3704
+ "tagName": "use-scrollarea",
3705
+ "customElement": true
3706
+ }
3707
+ ],
3708
+ "exports": [
3709
+ {
3710
+ "kind": "js",
3711
+ "name": "UseScrollarea",
3712
+ "declaration": {
3713
+ "name": "UseScrollarea",
3714
+ "module": "src/elements/use-scrollarea/use-scrollarea.ts"
3715
+ }
3716
+ },
3717
+ {
3718
+ "kind": "custom-element-definition",
3719
+ "name": "use-scrollarea",
3720
+ "declaration": {
3721
+ "name": "UseScrollarea",
3722
+ "module": "src/elements/use-scrollarea/use-scrollarea.ts"
3723
+ }
3724
+ }
3725
+ ]
3726
+ },
3670
3727
  {
3671
3728
  "kind": "javascript-module",
3672
3729
  "path": "src/elements/use-option/use-option.ts",
@@ -3781,63 +3838,6 @@
3781
3838
  }
3782
3839
  ]
3783
3840
  },
3784
- {
3785
- "kind": "javascript-module",
3786
- "path": "src/elements/use-scrollarea/index.ts",
3787
- "declarations": [],
3788
- "exports": [
3789
- {
3790
- "kind": "js",
3791
- "name": "UseScrollarea",
3792
- "declaration": {
3793
- "name": "UseScrollarea",
3794
- "module": "./use-scrollarea"
3795
- }
3796
- }
3797
- ]
3798
- },
3799
- {
3800
- "kind": "javascript-module",
3801
- "path": "src/elements/use-scrollarea/use-scrollarea.ts",
3802
- "declarations": [
3803
- {
3804
- "kind": "class",
3805
- "description": "A scroll container that exposes custom states for scroll edge detection.\n\n## Custom States\nThe following CSS custom states are available for styling:\n\n- `:state(at-block-start)` — scrolled to the block-start edge (top in horizontal writing modes)\n- `:state(at-block-end)` — scrolled to the block-end edge (bottom in horizontal writing modes)\n- `:state(at-inline-start)` — scrolled to the inline-start edge (left in LTR)\n- `:state(at-inline-end)` — scrolled to the inline-end edge (right in LTR)",
3806
- "name": "UseScrollarea",
3807
- "slots": [
3808
- {
3809
- "description": "Scrollable content",
3810
- "name": ""
3811
- }
3812
- ],
3813
- "members": [],
3814
- "superclass": {
3815
- "name": "LitElement",
3816
- "package": "lit"
3817
- },
3818
- "tagName": "use-scrollarea",
3819
- "customElement": true
3820
- }
3821
- ],
3822
- "exports": [
3823
- {
3824
- "kind": "js",
3825
- "name": "UseScrollarea",
3826
- "declaration": {
3827
- "name": "UseScrollarea",
3828
- "module": "src/elements/use-scrollarea/use-scrollarea.ts"
3829
- }
3830
- },
3831
- {
3832
- "kind": "custom-element-definition",
3833
- "name": "use-scrollarea",
3834
- "declaration": {
3835
- "name": "UseScrollarea",
3836
- "module": "src/elements/use-scrollarea/use-scrollarea.ts"
3837
- }
3838
- }
3839
- ]
3840
- },
3841
3841
  {
3842
3842
  "kind": "javascript-module",
3843
3843
  "path": "src/elements/use-time-input/use-time-input.ts",
@@ -1992,7 +1992,7 @@
1992
1992
  on a `use-layout`, and only as a direct child, so an `<svg fill="…">` or an author's own
1993
1993
  `fill` attribute anywhere in the tree is untouched — no exclusion list needed.
1994
1994
 
1995
- Four variant classes name what the container *is*, and its semantic `<figure>` / `<header>` /
1995
+ Five variant classes name what the container *is*, and its semantic `<figure>` / `<header>` /
1996
1996
  `<main>` / `<footer>` regions are arranged to match:
1997
1997
 
1998
1998
  use-layout.page an app frame — ruled topbar and footer, roomy
@@ -2000,17 +2000,20 @@
2000
2000
  use-layout.message a chat or comment — `.entry`'s layout at chat density
2001
2001
  use-layout.card a panel — avatar + hgroup + actions, end-aligned ruled
2002
2002
  footer, compact, plus the chrome at end of file
2003
+ use-layout.media a media object — a rail cell beside an anonymous body cell holding
2004
+ the stacked regions (à la Bootstrap 3's .media)
2003
2005
 
2004
2006
  All four regions are optional and any combination lays out correctly: `header` + `footer` is a
2005
2007
  confirm dialog, `header` + `main` a bare card, `main` alone a grouped chat message. Source
2006
2008
  order is canonical — figure, header, main, footer — and a variant may re-position regions
2007
2009
  visually but never asks an author to reorder markup.
2008
2010
 
2009
- Rather than four arrangements, a variant class sets *only* a density scale on itself
2011
+ Rather than five arrangements, a variant class sets *only* a density scale on itself
2010
2012
  (`--usewc-layout-region-padding`, `-gap`, `-avatar-size`, `--usewc-layout-header-rule`,
2011
2013
  `-footer-rule`, `--usewc-layout-footer-justify`, `-row-gap`) and one generic set of region
2012
2014
  rules reads them. Only a couple of arrangements can't be said in a property — the entry and
2013
- message rail, and message's inline hgroup — and those follow as structural overrides. The mechanic isn't repeated per variant either: a `use-layout.page` is a
2015
+ message rail, the media object's table cells, and message's inline hgroup — and those follow
2016
+ as structural overrides. The mechanic isn't repeated per variant either: a `use-layout.page` is a
2014
2017
  `use-layout`, so the base pin/grow rules above already cover it.
2015
2018
 
2016
2019
  Every selector stays compound (`use-layout.page`, never a bare `.page`) so none of these
@@ -2258,232 +2261,253 @@
2258
2261
  }
2259
2262
  }
2260
2263
 
2264
+ /* `.media` is a media object — a rail beside a wider body column, at one compact density for
2265
+ both the container inset and the gaps within it. The row gap is the standard region gap, so
2266
+ the header, body and footer stack the same distance apart as the rail sits from the body. */
2267
+ use-layout.media {
2268
+ --usewc-layout-region-padding: var(--usewc-layout-media-padding);
2269
+ --usewc-layout-region-gap: var(--usewc-layout-media-gap);
2270
+ --usewc-layout-region-row-gap: var(--usewc-layout-media-gap);
2271
+ --usewc-layout-region-avatar-size: var(--usewc-layout-region-title-block-size);
2272
+ --usewc-layout-footer-justify: flex-start;
2273
+
2274
+ use-theme-escape & {
2275
+ all: revert-layer;
2276
+ }
2277
+ }
2278
+
2261
2279
  /* A rule token carries the whole border value, not just its colour, so a variant that never
2262
2280
  names one gets `0 solid transparent` — no width. Declaring only a colour and leaving the
2263
2281
  width at 1px would give every ruleless header and footer an invisible pixel of border, which
2264
2282
  is enough to push a 36px control into a 37px region. */
2265
2283
  /* ── Generic regions ────────────────────────────────────────────────────────────────────────
2266
- One ruleset for every variant, reading the properties above. A rule colour left unset
2267
- falls back to `transparent`, so a variant opts into a hairline by naming one rather than by
2268
- having a rule of its own. */
2269
- :where(use-layout:is(.page, .entry, .message, .card)) {
2284
+ One ruleset for every variant, reading the properties above. Nested under the shared variant
2285
+ list rather than repeating it on every selector, so it stays in one place as variants are
2286
+ added. A rule colour left unset falls back to `transparent`, so a variant opts into a
2287
+ hairline by naming one rather than by having a rule of its own. */
2288
+ :where(use-layout:is(.page, .entry, .message, .card, .media)) {
2270
2289
  min-block-size: 0;
2271
2290
 
2272
2291
  use-theme-escape & {
2273
2292
  all: revert-layer;
2274
2293
  }
2275
- }
2276
2294
 
2277
- :where(use-layout:is(.page, .entry, .message, .card)) > use-layout[fill] {
2278
- overflow: auto;
2279
- padding: var(--usewc-layout-region-padding);
2295
+ & > use-layout[fill] {
2296
+ overflow: auto;
2297
+ padding: var(--usewc-layout-region-padding);
2280
2298
 
2281
- use-theme-escape & {
2282
- all: revert-layer;
2299
+ use-theme-escape & {
2300
+ all: revert-layer;
2301
+ }
2283
2302
  }
2284
- }
2285
2303
 
2286
- :where(use-layout:is(.page, .entry, .message, .card)) > main {
2287
- padding: var(--usewc-layout-region-padding);
2304
+ & > main {
2305
+ padding: var(--usewc-layout-region-padding);
2288
2306
 
2289
- use-theme-escape & {
2290
- all: revert-layer;
2307
+ use-theme-escape & {
2308
+ all: revert-layer;
2309
+ }
2291
2310
  }
2292
- }
2293
2311
 
2294
- /* The region owns its outer spacing, so the first and last things in it shed the block margins
2295
- they'd otherwise stack on top of the padding — a leading `<p>`, `<ul>`, `<ol>` or heading
2296
- would otherwise push itself away from an edge that's already spaced. Matched by position
2297
- rather than by tag so it holds for whatever flow content lands there. */
2298
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(main, use-layout[fill]) > :first-child {
2299
- margin-block-start: 0;
2312
+ /* The region owns its outer spacing, so the first and last things in it shed the block
2313
+ margins they'd otherwise stack on top of the padding — a leading `<p>`, `<ul>`, `<ol>` or
2314
+ heading would otherwise push itself away from an edge that's already spaced. Matched by
2315
+ position rather than by tag so it holds for whatever flow content lands there. */
2316
+ & > :is(main, use-layout[fill]) > :first-child {
2317
+ margin-block-start: 0;
2300
2318
 
2301
- use-theme-escape & {
2302
- all: revert-layer;
2319
+ use-theme-escape & {
2320
+ all: revert-layer;
2321
+ }
2303
2322
  }
2304
- }
2305
2323
 
2306
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(main, use-layout[fill]) > :last-child {
2307
- margin-block-end: 0;
2324
+ & > :is(main, use-layout[fill]) > :last-child {
2325
+ margin-block-end: 0;
2308
2326
 
2309
- use-theme-escape & {
2310
- all: revert-layer;
2327
+ use-theme-escape & {
2328
+ all: revert-layer;
2329
+ }
2311
2330
  }
2312
- }
2313
2331
 
2314
- /* A header already supplies the block-start padding, so the body region drops its own and the
2315
- two read as one padded column rather than a double gap under the header. */
2316
- :where(use-layout:is(.page, .entry, .message, .card)) > header + :is(main, use-layout[fill]) {
2317
- padding-block-start: 0;
2332
+ /* A header already supplies the block-start padding, so the body region drops its own and
2333
+ the two read as one padded column rather than a double gap under the header. A scrolling
2334
+ `use-layout[fill]` keeps its padding, though — with `overflow: auto` a zeroed start edge
2335
+ clips the focus ring of whatever sits at the top of the scroll. */
2336
+ & > header + main {
2337
+ padding-block-start: 0;
2318
2338
 
2319
- use-theme-escape & {
2320
- all: revert-layer;
2339
+ use-theme-escape & {
2340
+ all: revert-layer;
2341
+ }
2321
2342
  }
2322
- }
2323
2343
 
2324
- :where(use-layout:is(.page, .entry, .message, .card)) > figure {
2325
- margin: 0;
2344
+ & > figure {
2345
+ margin: 0;
2326
2346
 
2327
- use-theme-escape & {
2328
- all: revert-layer;
2347
+ use-theme-escape & {
2348
+ all: revert-layer;
2349
+ }
2329
2350
  }
2330
- }
2331
2351
 
2332
- :where(use-layout:is(.page, .entry, .message, .card)) > figure > img {
2333
- display: block;
2334
- inline-size: 100%;
2335
- block-size: auto;
2336
- object-fit: cover;
2352
+ & > figure > img {
2353
+ display: block;
2354
+ inline-size: 100%;
2355
+ block-size: auto;
2356
+ object-fit: cover;
2337
2357
 
2338
- use-theme-escape & {
2339
- all: revert-layer;
2358
+ use-theme-escape & {
2359
+ all: revert-layer;
2360
+ }
2340
2361
  }
2341
- }
2342
2362
 
2343
- :where(use-layout:is(.page, .entry, .message, .card)) > header {
2344
- display: flex;
2345
- align-items: center;
2346
- justify-content: flex-start;
2347
- gap: var(--usewc-layout-region-gap);
2348
- padding-block: var(--usewc-layout-region-padding-block, var(--usewc-layout-region-padding));
2349
- padding-inline: var(--usewc-layout-region-padding);
2350
- border-block-end: var(--usewc-layout-header-rule, 0 solid transparent);
2363
+ & > header {
2364
+ display: flex;
2365
+ align-items: center;
2366
+ justify-content: flex-start;
2367
+ gap: var(--usewc-layout-region-gap);
2368
+ padding-block: var(--usewc-layout-region-padding-block, var(--usewc-layout-region-padding));
2369
+ padding-inline: var(--usewc-layout-region-padding);
2370
+ border-block-end: var(--usewc-layout-header-rule, 0 solid transparent);
2351
2371
 
2352
- use-theme-escape & {
2353
- all: revert-layer;
2372
+ use-theme-escape & {
2373
+ all: revert-layer;
2374
+ }
2354
2375
  }
2355
- }
2356
2376
 
2357
- :where(use-layout:is(.page, .entry, .message, .card)) > footer {
2358
- display: flex;
2359
- align-items: center;
2360
- justify-content: var(--usewc-layout-footer-justify, flex-end);
2361
- gap: var(--usewc-layout-region-gap);
2362
- padding-block: var(--usewc-layout-region-padding-block, var(--usewc-layout-region-padding));
2363
- padding-inline: var(--usewc-layout-region-padding);
2364
- border-block-start: var(--usewc-layout-footer-rule, 0 solid transparent);
2377
+ & > footer {
2378
+ display: flex;
2379
+ align-items: center;
2380
+ justify-content: var(--usewc-layout-footer-justify, flex-end);
2381
+ gap: var(--usewc-layout-region-gap);
2382
+ padding-block: var(--usewc-layout-region-padding-block, var(--usewc-layout-region-padding));
2383
+ padding-inline: var(--usewc-layout-region-padding);
2384
+ border-block-start: var(--usewc-layout-footer-rule, 0 solid transparent);
2365
2385
 
2366
- use-theme-escape & {
2367
- all: revert-layer;
2386
+ use-theme-escape & {
2387
+ all: revert-layer;
2388
+ }
2368
2389
  }
2369
- }
2370
2390
 
2371
- /* A header's leading likeness is a `use-avatar` or a `<figure>` — no `img.avatar` convention,
2372
- since a bare `<img>` in a header is as likely to be a logo as a face, and a class would have
2373
- to be remembered where the element already says it. Both are squared to the variant's avatar
2374
- size; a `<figure>` centres whatever it holds, the same way the message rail does. */
2375
- :where(use-layout:is(.page, .entry, .message, .card)) > header > :is(use-avatar, figure) {
2376
- flex: none;
2377
- inline-size: var(--usewc-layout-region-avatar-size);
2378
- block-size: var(--usewc-layout-region-avatar-size);
2379
- border-radius: var(--usewc-effect-surface-avatar-border-radius);
2380
- overflow: hidden;
2391
+ /* A header's leading likeness is a `use-avatar` or a `<figure>` — no `img.avatar`
2392
+ convention, since a bare `<img>` in a header is as likely to be a logo as a face, and a
2393
+ class would have to be remembered where the element already says it. Both are squared to
2394
+ the variant's avatar size; a `<figure>` centres whatever it holds, the same way the
2395
+ message rail does. */
2396
+ & > header > :is(use-avatar, figure) {
2397
+ flex: none;
2398
+ inline-size: var(--usewc-layout-region-avatar-size);
2399
+ block-size: var(--usewc-layout-region-avatar-size);
2400
+ border-radius: var(--usewc-effect-surface-avatar-border-radius);
2401
+ overflow: hidden;
2381
2402
 
2382
- use-theme-escape & {
2383
- all: revert-layer;
2403
+ use-theme-escape & {
2404
+ all: revert-layer;
2405
+ }
2384
2406
  }
2385
- }
2386
2407
 
2387
- :where(use-layout:is(.page, .entry, .message, .card)) > header > figure {
2388
- display: flex;
2389
- align-items: center;
2390
- justify-content: center;
2391
- margin-inline: 0;
2392
- font-size: calc(var(--usewc-layout-region-avatar-size) * 0.4);
2393
- line-height: 1;
2408
+ & > header > figure {
2409
+ display: flex;
2410
+ align-items: center;
2411
+ justify-content: center;
2412
+ margin-inline: 0;
2413
+ font-size: calc(var(--usewc-layout-region-avatar-size) * 0.4);
2414
+ line-height: 1;
2394
2415
 
2395
- use-theme-escape & {
2396
- all: revert-layer;
2416
+ use-theme-escape & {
2417
+ all: revert-layer;
2418
+ }
2397
2419
  }
2398
- }
2399
2420
 
2400
- :where(use-layout:is(.page, .entry, .message, .card)) > header > figure > img {
2401
- inline-size: 100%;
2402
- block-size: 100%;
2403
- object-fit: cover;
2421
+ & > header > figure > img {
2422
+ inline-size: 100%;
2423
+ block-size: 100%;
2424
+ object-fit: cover;
2404
2425
 
2405
- use-theme-escape & {
2406
- all: revert-layer;
2426
+ use-theme-escape & {
2427
+ all: revert-layer;
2428
+ }
2407
2429
  }
2408
- }
2409
2430
 
2410
- /* An `hgroup` is a title stack wherever it turns up in a region — often wrapped in a
2411
- `<section>` in a topbar — so it's matched by descent rather than as a direct child. Only the
2412
- one sitting directly in a header grows, since that's what pushes trailing actions to the
2413
- far end. */
2414
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(header, footer) hgroup {
2415
- display: flex;
2416
- flex-direction: column;
2417
- gap: var(--usewc-layout-region-title-gap);
2418
- min-inline-size: 0;
2431
+ /* An `hgroup` is a title stack wherever it turns up in a region — often wrapped in a
2432
+ `<section>` in a topbar — so it's matched by descent rather than as a direct child. Only
2433
+ the one sitting directly in a header grows, since that's what pushes trailing actions to
2434
+ the far end. */
2435
+ & > :is(header, footer) hgroup {
2436
+ display: flex;
2437
+ flex-direction: column;
2438
+ gap: var(--usewc-layout-region-title-gap);
2439
+ min-inline-size: 0;
2419
2440
 
2420
- use-theme-escape & {
2421
- all: revert-layer;
2441
+ use-theme-escape & {
2442
+ all: revert-layer;
2443
+ }
2422
2444
  }
2423
- }
2424
2445
 
2425
- :where(use-layout:is(.page, .entry, .message, .card)) > header > hgroup {
2426
- flex: 1;
2446
+ & > header > hgroup {
2447
+ flex: 1;
2427
2448
 
2428
- use-theme-escape & {
2429
- all: revert-layer;
2449
+ use-theme-escape & {
2450
+ all: revert-layer;
2451
+ }
2430
2452
  }
2431
- }
2432
2453
 
2433
- /* An `hgroup`'s lines get explicit line boxes so a stacked title and subtitle add up to a
2434
- predictable height beside a fixed-size avatar, and everything after the first steps down a
2435
- size — a timestamp, a byline, a location is secondary to the title it hangs off. */
2436
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(header, footer) hgroup > * {
2437
- line-height: var(--usewc-layout-region-title-line-height);
2454
+ /* An `hgroup`'s lines get explicit line boxes so a stacked title and subtitle add up to a
2455
+ predictable height beside a fixed-size avatar, and everything after the first steps down a
2456
+ size — a timestamp, a byline, a location is secondary to the title it hangs off. The title
2457
+ line box is a floor rather than a fixed value, so a headline larger than an `h4` grows its
2458
+ leading with its font size instead of overlapping the line above. */
2459
+ & > :is(header, footer) hgroup > * {
2460
+ line-height: max(var(--usewc-layout-region-title-line-height), 1.25em);
2438
2461
 
2439
- use-theme-escape & {
2440
- all: revert-layer;
2462
+ use-theme-escape & {
2463
+ all: revert-layer;
2464
+ }
2441
2465
  }
2442
- }
2443
2466
 
2444
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(header, footer) hgroup > * + * {
2445
- font-size: var(--usewc-font-region-subtitle-size);
2446
- line-height: var(--usewc-layout-region-subtitle-line-height);
2447
- color: var(--usewc-color-document-text-muted);
2467
+ & > :is(header, footer) hgroup > * + * {
2468
+ font-size: var(--usewc-font-region-subtitle-size);
2469
+ line-height: var(--usewc-layout-region-subtitle-line-height);
2470
+ color: var(--usewc-color-document-text-muted);
2448
2471
 
2449
- use-theme-escape & {
2450
- all: revert-layer;
2472
+ use-theme-escape & {
2473
+ all: revert-layer;
2474
+ }
2451
2475
  }
2452
- }
2453
2476
 
2454
- /* A header and footer are flex containers and an `hgroup` is a flex column, so `gap` is the
2455
- spacing — a default block margin stacks on top of it and blows the region apart. Headings are
2456
- matched at any depth, since a topbar routinely nests them a `<section>` and an `<hgroup>`
2457
- down; `<p>` and friends only need it where they sit directly in the flex flow. Body copy in
2458
- `<main>` keeps its margins, which is the whole point of a paragraph there. */
2459
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(header, footer) > *,
2460
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(header, footer) hgroup > *,
2461
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(header, footer) :is(h1, h2, h3, h4, h5, h6) {
2462
- margin-block: 0;
2477
+ /* A header and footer are flex containers and an `hgroup` is a flex column, so `gap` is the
2478
+ spacing — a default block margin stacks on top of it and blows the region apart. Headings
2479
+ are matched at any depth, since a topbar routinely nests them a `<section>` and an
2480
+ `<hgroup>` down; `<p>` and friends only need it where they sit directly in the flex flow.
2481
+ Body copy in `<main>` keeps its margins, which is the whole point of a paragraph there. */
2482
+ & > :is(header, footer) > *,
2483
+ & > :is(header, footer) hgroup > *,
2484
+ & > :is(header, footer) :is(h1, h2, h3, h4, h5, h6) {
2485
+ margin-block: 0;
2463
2486
 
2464
- use-theme-escape & {
2465
- all: revert-layer;
2487
+ use-theme-escape & {
2488
+ all: revert-layer;
2489
+ }
2466
2490
  }
2467
- }
2468
2491
 
2469
- /* A `<section>` inside a header or footer is one cluster of related controls. Two or more of
2470
- them means the region has distinct ends, so it splits them apart regardless of the variant's
2471
- default justification. */
2472
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(header, footer) > section {
2473
- display: flex;
2474
- align-items: center;
2475
- gap: var(--usewc-layout-region-gap);
2492
+ /* A `<section>` inside a header or footer is one cluster of related controls. Two or more of
2493
+ them means the region has distinct ends, so it splits them apart regardless of the
2494
+ variant's default justification. */
2495
+ & > :is(header, footer) > section {
2496
+ display: flex;
2497
+ align-items: center;
2498
+ gap: var(--usewc-layout-region-gap);
2476
2499
 
2477
- use-theme-escape & {
2478
- all: revert-layer;
2500
+ use-theme-escape & {
2501
+ all: revert-layer;
2502
+ }
2479
2503
  }
2480
- }
2481
2504
 
2482
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(header, footer):has(> section ~ section) {
2483
- justify-content: space-between;
2505
+ & > :is(header, footer):has(> section ~ section) {
2506
+ justify-content: space-between;
2484
2507
 
2485
- use-theme-escape & {
2486
- all: revert-layer;
2508
+ use-theme-escape & {
2509
+ all: revert-layer;
2510
+ }
2487
2511
  }
2488
2512
  }
2489
2513
 
@@ -2592,7 +2616,7 @@
2592
2616
 
2593
2617
  /* A `<figure>` inside the body is an attachment, not the rail — it keeps the flow but sheds the
2594
2618
  UA margin so the region's own spacing is the only spacing. */
2595
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(main, use-layout[fill]) figure {
2619
+ :where(use-layout:is(.page, .entry, .message, .card, .media)) > :is(main, use-layout[fill]) figure {
2596
2620
  margin-inline: 0;
2597
2621
 
2598
2622
  use-theme-escape & {
@@ -2600,7 +2624,7 @@
2600
2624
  }
2601
2625
  }
2602
2626
 
2603
- :where(use-layout:is(.page, .entry, .message, .card)) > :is(main, use-layout[fill]) figure > img {
2627
+ :where(use-layout:is(.page, .entry, .message, .card, .media)) > :is(main, use-layout[fill]) figure > img {
2604
2628
  display: block;
2605
2629
  inline-size: 100%;
2606
2630
  block-size: auto;
@@ -2623,6 +2647,67 @@
2623
2647
  }
2624
2648
  }
2625
2649
 
2650
+ /* `.media` is a media object — a rail that shrink-wraps whatever it holds — an avatar, a
2651
+ figure, a thumbnail, an inline icon — with the header, body and footer stacked beside it as
2652
+ one column, the way Bootstrap's `.media` + `.media-body` reads. `use-layout` has no body
2653
+ wrapper, so this leans on anonymous table boxes to make one: the container is `display:
2654
+ table`, the rail is a `table-cell`, and CSS wraps the run of regions after it in a single
2655
+ anonymous `table-cell` — that cell *is* the body column.
2656
+
2657
+ Because the body column is one box, the regions inside it are plain block flow: `main` sits
2658
+ exactly one row gap under `header` no matter how tall the rail is, and the container is only
2659
+ ever as tall as its taller cell. The rail cell is `vertical-align: top`, so a rail and the
2660
+ header start level; it sizes to its content, with a `padding-inline-end` standing in for the
2661
+ column gap so no border-spacing leaks onto the outer edges.
2662
+
2663
+ The first child is always the rail — `use-avatar`, `figure`, a bare `img` or `svg` all
2664
+ work — with no tag check, since the anonymous-cell trick only works when something is
2665
+ actually sitting in that first table-cell. A `.media` with no rail isn't a supported shape:
2666
+ `header` would become the cell instead and split away from the rest of the body. */
2667
+ use-layout.media {
2668
+ display: table;
2669
+ inline-size: 100%;
2670
+ border-spacing: 0;
2671
+ padding: var(--usewc-layout-region-padding);
2672
+
2673
+ use-theme-escape & {
2674
+ all: revert-layer;
2675
+ }
2676
+ }
2677
+
2678
+ :where(use-layout.media) > :first-child {
2679
+ display: table-cell;
2680
+ inline-size: 0;
2681
+ vertical-align: top;
2682
+ padding-inline-end: var(--usewc-layout-region-gap);
2683
+
2684
+ use-theme-escape & {
2685
+ all: revert-layer;
2686
+ }
2687
+ }
2688
+
2689
+ /* Every region's own padding lives on the container instead. The rail is always the first
2690
+ child, so everything after it is a region — no need to name `header`/`main`/`footer`
2691
+ explicitly. */
2692
+ :where(use-layout.media) > :not(:first-child) {
2693
+ padding: 0;
2694
+
2695
+ use-theme-escape & {
2696
+ all: revert-layer;
2697
+ }
2698
+ }
2699
+
2700
+ /* The row gap separates the regions from each other, not the rail from the first region — that
2701
+ gap is the rail cell's own `padding-inline-end`. Since the rail is always child 1 and the
2702
+ first region is always child 2, the row gap only starts from the third child on. */
2703
+ :where(use-layout.media) > :nth-child(n + 3) {
2704
+ margin-block-start: var(--usewc-layout-region-row-gap);
2705
+
2706
+ use-theme-escape & {
2707
+ all: revert-layer;
2708
+ }
2709
+ }
2710
+
2626
2711
  /* Card chrome — the one bit of floating surface treatment that isn't layout, and the only
2627
2712
  thing separating `.card` from the other three variants: they arrange regions, this also
2628
2713
  paints a raised panel. `.outlined` keeps the border but drops the shadow, for a flatter
package/dist/tokens.css CHANGED
@@ -710,7 +710,9 @@
710
710
  generic set of header / main / footer rules in `theme/layout.css` then reads. The four
711
711
  variants are deliberately far apart: a document and a card in a feed can't share one
712
712
  padding step and still read as themselves, so each gets its own rather than overriding a
713
- shared base. The hairline colour is shared, since a rule is a rule wherever it lands. */
713
+ shared base. The hairline colour is shared, since a rule is a rule wherever it lands.
714
+ `.media` is the exception that proves it — a compact object with one step for its inset and
715
+ every gap inside it. */
714
716
  --usewc-color-region-border: var(--usewc-color-surface-border);
715
717
  --usewc-layout-region-rule: var(--usewc-layout-surface-border) solid var(--usewc-color-region-border);
716
718
  --usewc-layout-region-title-gap: var(--usewc-space-2);
@@ -736,7 +738,7 @@
736
738
 
737
739
  --usewc-layout-card-padding: var(--usewc-space-12);
738
740
  --usewc-layout-card-gap: var(--usewc-space-8);
739
- --usewc-layout-card-avatar-size: var(--usewc-space-24);
741
+ --usewc-layout-card-avatar-size: var(--usewc-layout-region-title-block-size);
740
742
 
741
743
  /* Avatar sizes match a base button's 36px height, so a likeness and the controls beside it in
742
744
  a header line up on both edges rather than one floating inside the other.
@@ -753,6 +755,12 @@
753
755
  --usewc-layout-message-gap: var(--usewc-space-12);
754
756
  --usewc-layout-message-rail: var(--usewc-layout-region-title-block-size);
755
757
 
758
+ /* A media object is compact — one step drives the container inset, the gap between the rail
759
+ cell and the body, and the row gap stacking the regions in the body. The rail sizes to its
760
+ own content, so there's no rail-width token here. */
761
+ --usewc-layout-media-padding: var(--usewc-space-12);
762
+ --usewc-layout-media-gap: var(--usewc-space-12);
763
+
756
764
  /* Surface — the visible chrome for a surface host (background/border/radius/shadow), the
757
765
  backdrop behind a modal `<dialog>` (non-modal `[popover]` keeps its transparent UA
758
766
  backdrop), and the gap an anchored surface keeps from its anchor. `-padding` is the inset a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "use-wc",
3
- "version": "1.0.0-pre.68",
3
+ "version": "1.0.0-pre.69",
4
4
  "private": false,
5
5
  "homepage": "https://usewc.com",
6
6
  "bugs": "https://github.com/dang-rabbits/use-wc/issues",
@@ -19,6 +19,18 @@
19
19
  ],
20
20
  "references": []
21
21
  },
22
+ {
23
+ "name": "use-avatar",
24
+ "description": "`use-avatar` renders a small, fixed-size, clipped container for a person or entity's\nlikeness. Slot in an `<img>` (or `<picture>`) for a photo, an inline `<svg>` for a\ngenerated or stylized mark, or arbitrary markup (a `<div>` of initials, a calendar badge);\nwhatever is slotted is centered and clipped to the avatar's shape. With nothing slotted,\n`use-avatar` falls back to initials derived from the `name` attribute.\n\n```html\n<use-avatar><img src=\"ada.jpg\" alt=\"\" /></use-avatar>\n<use-avatar name=\"Riley Quinn\"></use-avatar>\n<use-avatar><svg viewBox=\"0 0 32 32\">…</svg></use-avatar>\n```\n\nSize it with plain CSS — `inline-size` for the size and `aspect-ratio` for the proportions —\nfrom a stylesheet, a style attribute, or the design system's theme layer. The element takes no\ncustom properties of its own: it is a query container, so the initials scale from whatever box\nit ends up with. A non-square `aspect-ratio` suits a wide thumbnail or poster.\n\nThe element clips its content but gives it no shape of its own — that is the theme's, through\nthe affordance classes it defines: `.circle` (the themed default), `.square`, `.squircle` in\n`theme/avatar.css`. A circle only reads right at a `1` ratio, so a wide avatar wants one of the\nothers.\n\nThe element takes no ARIA role of its own. A slotted `<img>` carries its own `alt`, and the\ninitials fallback is plain text in the accessibility tree — an avatar is decorative beside a\nname far more often than it is the name itself, so labelling it here would mean announcing\nthat name twice.\n---\n\n\n### **Slots:**\n - _default_ - The avatar's content: an `<img>`/`<picture>`, an `<svg>`, or arbitrary markup. Left empty, the `name` attribute's initials are shown instead, as the slot's own fallback. A photo fills the frame and crops; anything else keeps its own size, capped at the frame. Give an `<svg>` a `width`/`height` — without one it defaults to filling the box, and a rounded shape will clip its corners.\n\n### **CSS Parts:**\n - **initials** - The span that renders the `name` fallback.",
25
+ "attributes": [
26
+ {
27
+ "name": "name",
28
+ "description": "The full name, used for the initials fallback (first + last whitespace-separated token, uppercased) when the slot is empty.",
29
+ "values": []
30
+ }
31
+ ],
32
+ "references": []
33
+ },
22
34
  {
23
35
  "name": "use-badge",
24
36
  "description": "`use-badge` renders a small indicator anchored to another element's corner, using\n[CSS anchor positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_anchor_positioning)\ninstead of the classic `position: absolute` + negative-offset trick. This lets the badge live\nanywhere in the DOM rather than being a child of the element it decorates. A badge's shape,\ncolor, and positioning ship built in — reading from the design system's tokens when\n`tokens.css` is loaded, and falling back to sensible defaults otherwise — so no theme is\nrequired to get a working, visible badge.\n\nPoint a badge at its target with the `anchortarget` attribute, set to the target's `id`\n(named to avoid colliding with the `anchor` content attribute HTML is gaining natively):\n\n```html\n<button type=\"button\" id=\"inbox\">Inbox</button>\n<use-badge anchortarget=\"inbox\">99+</use-badge>\n```\n\nThe badge and its anchor must live in the same DOM tree — a badge cannot reach an anchor\ninside another component's shadow root, and an anchor's `anchor-name` set inside a shadow\ntree's stylesheet is not visible here. No positioned ancestor or shared containing block is\nrequired: anchor positioning resolves the badge's location straight from the anchor's own\ngeometry, so the badge can sit anywhere else in the DOM tree.\n\nWithout a resolved anchor — `anchortarget` unset, pointing at a missing id, or `anchorElement`\nnever assigned — the badge has no `:state(anchored)` and renders as a plain inline chip in\nnormal document flow, still using the same color/shape styling.\n\nSome components render their host as `display: contents`, which has no box of its own for CSS\nanchor positioning to resolve against. If the anchor computes a non-empty `--usewc-anchor-name`\ncustom property, the badge uses that dashed-ident as its `position-anchor` directly instead of\ngenerating and writing its own onto the anchor — letting a component publish the name of a\nreal, box-generating part of itself (already established for its own purposes) for badges to\ntarget instead of its host, even though that part lives inside the component's own shadow root.\nThis mechanism is shared with `use-menu`/`use-anchored` via `AnchorController`; components\nwithout a `display: contents` host don't need to publish anything.\n\n**Known Firefox limitation:** anchoring across a shadow root boundary this way — the case\n`--usewc-anchor-name` exists for — is mispositioned in Firefox as of this writing. Verified\ndirectly: `anchor()`'s logical `start`/`end` keywords resolve backwards on both axes\nspecifically for a cross-shadow-root anchor reference, in Firefox only — the same anchor()\ncalls resolve correctly for a same-tree anchor in Firefox, and cross-shadow anchoring resolves\ncorrectly in Chromium and Safari. A badge anchored to a plain element (button, input, anything\nthat isn't itself relying on this escape hatch) is unaffected in every engine, including\nFirefox.\n\n## Side effects\n\nThe badge is a sibling of its anchor rather than a child, so **as a side effect, a badge\nmutates its anchor element**: it appends its own id to the anchor's `aria-describedby`\n(preserving any ids already there, the same way `anchor-name` is appended rather than\nreplaced) to keep its content connected to the anchor for assistive technology. This means a\nbadge's content, or its `aria-label` when set, is announced as part of interacting with the\nanchor, e.g. \"Inbox button, 3\". A `dot` badge has no content of its own, so set `aria-label`\ndirectly on `<use-badge>` for a meaningful description (e.g. `aria-label=\"3 unread messages\"`);\nwithout one, the description contributes nothing and the anchor announces as before.\n\nAvoid adding `aria-hidden` to `<use-badge>` if you rely on this: while the description\ncomputation is specified to still read a hidden node when it's the direct target of\n`aria-describedby`, support for that specific case is inconsistent across browsers and screen\nreaders.\n\nSet `options=\"noaria\"` to opt a badge out of this and leave the anchor's `aria-describedby`\nuntouched, e.g. when the anchor already documents the badge's meaning some other way.\n---\n\n\n### **Slots:**\n - _default_ - Badge content, e.g. a count or short label. Ignored when `dot` is set.",
@@ -51,18 +63,6 @@
51
63
  ],
52
64
  "references": []
53
65
  },
54
- {
55
- "name": "use-avatar",
56
- "description": "`use-avatar` renders a small, fixed-size, clipped container for a person or entity's\nlikeness. Slot in an `<img>` (or `<picture>`) for a photo, an inline `<svg>` for a\ngenerated or stylized mark, or arbitrary markup (a `<div>` of initials, a calendar badge);\nwhatever is slotted is centered and clipped to the avatar's shape. With nothing slotted,\n`use-avatar` falls back to initials derived from the `name` attribute.\n\n```html\n<use-avatar><img src=\"ada.jpg\" alt=\"\" /></use-avatar>\n<use-avatar name=\"Riley Quinn\"></use-avatar>\n<use-avatar><svg viewBox=\"0 0 32 32\">…</svg></use-avatar>\n```\n\nSize it with plain CSS — `inline-size` for the size and `aspect-ratio` for the proportions —\nfrom a stylesheet, a style attribute, or the design system's theme layer. The element takes no\ncustom properties of its own: it is a query container, so the initials scale from whatever box\nit ends up with. A non-square `aspect-ratio` suits a wide thumbnail or poster.\n\nThe element clips its content but gives it no shape of its own — that is the theme's, through\nthe affordance classes it defines: `.circle` (the themed default), `.square`, `.squircle` in\n`theme/avatar.css`. A circle only reads right at a `1` ratio, so a wide avatar wants one of the\nothers.\n\nThe element takes no ARIA role of its own. A slotted `<img>` carries its own `alt`, and the\ninitials fallback is plain text in the accessibility tree — an avatar is decorative beside a\nname far more often than it is the name itself, so labelling it here would mean announcing\nthat name twice.\n---\n\n\n### **Slots:**\n - _default_ - The avatar's content: an `<img>`/`<picture>`, an `<svg>`, or arbitrary markup. Left empty, the `name` attribute's initials are shown instead, as the slot's own fallback. A photo fills the frame and crops; anything else keeps its own size, capped at the frame. Give an `<svg>` a `width`/`height` — without one it defaults to filling the box, and a rounded shape will clip its corners.\n\n### **CSS Parts:**\n - **initials** - The span that renders the `name` fallback.",
57
- "attributes": [
58
- {
59
- "name": "name",
60
- "description": "The full name, used for the initials fallback (first + last whitespace-separated token, uppercased) when the slot is empty.",
61
- "values": []
62
- }
63
- ],
64
- "references": []
65
- },
66
66
  {
67
67
  "name": "use-calendarday",
68
68
  "description": "A helper component for customizing specific days within `use-calendar`.\nContent placed inside this element will replace the default day number display.\n---\n\n\n### **Slots:**\n - **default** - slot for custom day content (replaces the day number)",
@@ -385,6 +385,12 @@
385
385
  ],
386
386
  "references": []
387
387
  },
388
+ {
389
+ "name": "use-scrollarea",
390
+ "description": "A scroll container that exposes custom states for scroll edge detection.\n\n## Custom States\nThe following CSS custom states are available for styling:\n\n- `:state(at-block-start)` — scrolled to the block-start edge (top in horizontal writing modes)\n- `:state(at-block-end)` — scrolled to the block-end edge (bottom in horizontal writing modes)\n- `:state(at-inline-start)` — scrolled to the inline-start edge (left in LTR)\n- `:state(at-inline-end)` — scrolled to the inline-end edge (right in LTR)\n---\n\n\n### **Slots:**\n - _default_ - Scrollable content",
391
+ "attributes": [],
392
+ "references": []
393
+ },
388
394
  {
389
395
  "name": "use-option",
390
396
  "description": "`use-option` is a custom element that represents an option in a `use-listbox-input` custom\nelement.\n\nThe children of this element are the content of the option and must not contain any\ninteractive elements.\n\nSelection is shown by one of two indicators, swapped based on the option's `selected` state:\na checkmark when selected, nothing (a reserved-space placeholder) when not.\n\nSwapping an indicator **per instance** is a slot: put your own element in the `selected-indicator`\nor `deselected-indicator` slot and it replaces `part(selected-indicator-default)` /\n`part(deselected-indicator-default)` entirely for that option.\n\nSwapping an indicator **for every option in the app** doesn't need touching this component's\n`render()` at all — style `::part(selected-indicator-default)` /\n`::part(deselected-indicator-default)` from an outside stylesheet, the same way any shadow DOM\npart is themed:\n\n```css\nuse-option::part(selected-indicator-default) {\n mask-image: url(\"/icons/my-checkmark.svg\");\n}\n```\n\n(When the design system's `theme.css` is loaded, this is already wired to a pair of tokens —\n`--usewc-effect-selected-indicator-mask-image` for the shape and\n`--usewc-effect-selected-indicator-color` for what paints it (`--usewc-effect-deselected-…`\nfor the other state) — so redefining those custom properties has the same effect without\nwriting a `::part()` rule at all.)\n\n`::part()` only reaches CSS-expressible changes (a mask, a background, a transform). For\nanything else — different markup, an icon font, logic beyond a mask — set the static\n`selectedIcon` and `deselectedIcon` hooks. Every `<use-option>` in the page picks them up;\nconsumers keep writing the same tag, no new element to register or remember to use instead.\nSet them once, as early as possible (an app's entry point, before any options connect) — Lit\ncalls `render()` fresh on every update, so an already-connected instance only reflects the\nchange once something causes it to re-render:\n\n```ts\n// A bare string or TemplateResult is used as-is, on every option:\nUseOption.selectedIcon = \"✓\";\nUseOption.deselectedIcon = \"\";\n\n// A function is called on every render instead:\nUseOption.selectedIcon = (html) => html`<my-icon name=\"check\"></my-icon>`;\n```\n\nThe function form is called with the component's own `html` tag as its (optional) first\nargument rather than requiring the caller to import one — a page can end up with more than one\ncopy of `lit-html` in its module graph, and a `TemplateResult` built from a *different* copy\nthan the one this component renders with can silently fail to render. Taking `html` in as a\nparameter sidesteps that: whatever's returned is guaranteed to come from the same `lit-html`\nthis component already uses. A bare string skips the concern entirely.\n\nA set icon still renders under `part(selected-indicator-default)` /\n`part(deselected-indicator-default)` — the same part the design system's theme masks into the\nbuilt-in glyph. Combining a static hook with `theme.css` means the theme's masking still\napplies to the custom content; reset the relevant `mask-image` token or `::part()` rule if that\nfights with what was set.\n\nOnly need to change the icon on **some** options, not every one in the app? Extend the class,\noverride `render()` normally, and register the subclass under a different tag name so it\ncoexists with the built-in element instead of replacing it everywhere:\n\n```ts\nclass MyOption extends UseOption {\n override render() {\n return html`<slot></slot><slot name=\"selected-indicator\"><my-icon name=\"check\"></my-icon></slot>`;\n }\n}\ncustomElements.define(\"my-option\", MyOption);\n```\n---\n\n\n### **Slots:**\n - **selected-indicator** - Replaces the default checkmark shown when the option is selected.\n- **deselected-indicator** - Replaces the default (empty) indicator shown when the option is not selected.\n- **default** - Option content.",
@@ -395,12 +401,6 @@
395
401
  ],
396
402
  "references": []
397
403
  },
398
- {
399
- "name": "use-scrollarea",
400
- "description": "A scroll container that exposes custom states for scroll edge detection.\n\n## Custom States\nThe following CSS custom states are available for styling:\n\n- `:state(at-block-start)` — scrolled to the block-start edge (top in horizontal writing modes)\n- `:state(at-block-end)` — scrolled to the block-end edge (bottom in horizontal writing modes)\n- `:state(at-inline-start)` — scrolled to the inline-start edge (left in LTR)\n- `:state(at-inline-end)` — scrolled to the inline-end edge (right in LTR)\n---\n\n\n### **Slots:**\n - _default_ - Scrollable content",
401
- "attributes": [],
402
- "references": []
403
- },
404
404
  {
405
405
  "name": "use-time-input",
406
406
  "description": "Displays time picker using [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat).\n\nAllows users to pick time values with proper localization and formatting.\n---\n\n\n### **Events:**\n - **input**",