@teamblind-chorus/ui 1.1.0 → 1.2.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/agents/catalog.md +6 -4
- package/agents/components/avatar-rail/avatar-rail.spec.json +19 -0
- package/agents/components/banner/banner.family.json +3 -1
- package/agents/components/banner/banner.md +54 -1
- package/agents/components/banner/banner.spec.json +24 -1
- package/agents/components/button/check.spec.json +19 -0
- package/agents/components/button/fab.spec.json +19 -0
- package/agents/components/button/icon.spec.json +19 -0
- package/agents/components/button/standard.spec.json +19 -0
- package/agents/components/button/text.spec.json +19 -0
- package/agents/components/button/toggle.spec.json +19 -0
- package/agents/components/chip/filter.spec.json +19 -0
- package/agents/components/chip/tag.spec.json +19 -0
- package/agents/components/empty-state/empty-state.family.json +28 -0
- package/agents/components/empty-state/empty-state.md +69 -0
- package/agents/components/empty-state/empty-state.spec.json +87 -0
- package/agents/components/form-field/input.spec.json +8 -1
- package/agents/components/form-field/search.spec.json +8 -1
- package/agents/components/form-field/select.spec.json +9 -1
- package/agents/components/form-field/textarea.spec.json +8 -1
- package/agents/components/list/accordion.spec.json +9 -0
- package/agents/components/list/entry.spec.json +19 -0
- package/agents/components/list/radio.spec.json +19 -0
- package/agents/components/list/standard.md +46 -0
- package/agents/components/list/standard.spec.json +37 -2
- package/agents/components/nav-card/nav-card.spec.json +9 -0
- package/agents/components/page-shell/page-shell.family.json +1 -1
- package/agents/components/page-shell/page-shell.md +33 -0
- package/agents/components/page-shell/page-shell.spec.json +85 -0
- package/agents/components/spinner/spinner.family.json +27 -0
- package/agents/components/spinner/spinner.md +98 -0
- package/agents/components/spinner/spinner.spec.json +82 -0
- package/agents/components/switch/switch.spec.json +9 -0
- package/agents/components/tab-bar/tab-bar.spec.json +16 -0
- package/agents/components/tabs/rounded.spec.json +19 -0
- package/agents/components/tabs/underline.spec.json +19 -0
- package/agents/manifest.json +8 -6
- package/agents/usage.json +12 -0
- package/dist/index.cjs +340 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -2
- package/dist/index.d.ts +46 -2
- package/dist/index.js +339 -61
- package/dist/index.js.map +1 -1
- package/dist/styles.css +182 -0
- package/package.json +1 -1
package/dist/styles.css
CHANGED
|
@@ -2615,6 +2615,31 @@ a.chorus-metadata__name:focus-visible {
|
|
|
2615
2615
|
margin-left: var(--sys-layout-inline-md);
|
|
2616
2616
|
}
|
|
2617
2617
|
|
|
2618
|
+
/* Embedded-Banner row — a Standard row whose text group stacks over a
|
|
2619
|
+
Banner that spans the row's full content width. The row flips from a
|
|
2620
|
+
single horizontal line to a vertical stack: the normal leading + label
|
|
2621
|
+
+ trailing line (`__row-main`) sits on top, the Banner `stack.xs` (8)
|
|
2622
|
+
below it. The stack fills the row's content box so the Banner aligns to
|
|
2623
|
+
the same 16px inline inset as the text group above it. The Banner owns
|
|
2624
|
+
its own tinted fill / radius / padding; the slot only spaces it and
|
|
2625
|
+
marks it a nested-action region (its controls never commit the row). */
|
|
2626
|
+
.chorus-list__stack {
|
|
2627
|
+
display: flex;
|
|
2628
|
+
flex-direction: column;
|
|
2629
|
+
gap: var(--sys-layout-stack-xs);
|
|
2630
|
+
flex: 1 1 auto;
|
|
2631
|
+
min-width: 0;
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
.chorus-list__row-main {
|
|
2635
|
+
display: flex;
|
|
2636
|
+
align-items: center;
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
.chorus-list__banner {
|
|
2640
|
+
display: block;
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2618
2643
|
/* Entry variant — directory-entry row with selectable leading Thumbnail
|
|
2619
2644
|
(32 / 40 / 48 / 56 via `data-size="small|medium|large|xlarge"`), an
|
|
2620
2645
|
identity group (label + optional inline count Badge + optional stacked
|
|
@@ -3278,6 +3303,65 @@ a.chorus-metadata__name:focus-visible {
|
|
|
3278
3303
|
rule already excludes `[data-divider="false"]`, so no extra CSS
|
|
3279
3304
|
is needed to hide it here. */
|
|
3280
3305
|
|
|
3306
|
+
/* ============================================================
|
|
3307
|
+
EmptyState — centered no-data composition. Painted inside the
|
|
3308
|
+
surface that would otherwise hold the data: an optional monochrome
|
|
3309
|
+
illustration, a required headline, optional body copy, and an
|
|
3310
|
+
optional primary-Button CTA. Ships no surface fill of its own —
|
|
3311
|
+
the host supplies the surface tier and the bounding box; EmptyState
|
|
3312
|
+
only centers its column inside it. Inter-slot rhythm follows the
|
|
3313
|
+
stack tokens (illustration→headline 12, headline→body 4, body→CTA
|
|
3314
|
+
16). Distinct from Skeleton (an in-flight loading placeholder).
|
|
3315
|
+
============================================================ */
|
|
3316
|
+
.chorus-empty-state {
|
|
3317
|
+
display: flex;
|
|
3318
|
+
flex-direction: column;
|
|
3319
|
+
align-items: center;
|
|
3320
|
+
text-align: center;
|
|
3321
|
+
}
|
|
3322
|
+
|
|
3323
|
+
/* Optional illustration — a glyph / illustration sized to a 48-box
|
|
3324
|
+
(larger than `sys.icon.lg`, realizing the 'icon.xl or larger' intent
|
|
3325
|
+
since no `sys.icon.xl` rung exists), painted monochrome in
|
|
3326
|
+
`onSurfaceVariant` via `currentColor` so it reads as quiet chrome,
|
|
3327
|
+
not a brand moment. 12 below it to the headline. */
|
|
3328
|
+
.chorus-empty-state__illustration {
|
|
3329
|
+
display: inline-flex;
|
|
3330
|
+
align-items: center;
|
|
3331
|
+
justify-content: center;
|
|
3332
|
+
width: var(--empty-state-illustration-size);
|
|
3333
|
+
height: var(--empty-state-illustration-size);
|
|
3334
|
+
margin-bottom: var(--empty-state-illustration-gap);
|
|
3335
|
+
color: var(--empty-state-illustration-color);
|
|
3336
|
+
}
|
|
3337
|
+
|
|
3338
|
+
.chorus-empty-state__illustration img,
|
|
3339
|
+
.chorus-empty-state__illustration svg {
|
|
3340
|
+
width: var(--empty-state-illustration-size);
|
|
3341
|
+
height: var(--empty-state-illustration-size);
|
|
3342
|
+
display: block;
|
|
3343
|
+
color: currentColor;
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3346
|
+
/* Required headline — heading.sm in `onSurface`. Typography vars are
|
|
3347
|
+
emitted inline by the React file (typoStyles). */
|
|
3348
|
+
.chorus-empty-state__headline {
|
|
3349
|
+
margin: 0;
|
|
3350
|
+
color: var(--empty-state-headline-color);
|
|
3351
|
+
}
|
|
3352
|
+
|
|
3353
|
+
/* Optional body — body.sm in `onSurfaceVariant`, 4 below the headline. */
|
|
3354
|
+
.chorus-empty-state__body {
|
|
3355
|
+
margin: 0;
|
|
3356
|
+
margin-top: var(--empty-state-body-gap);
|
|
3357
|
+
color: var(--empty-state-body-color);
|
|
3358
|
+
}
|
|
3359
|
+
|
|
3360
|
+
/* Optional CTA — a default-size primary Button, 16 below the body. */
|
|
3361
|
+
.chorus-empty-state__action {
|
|
3362
|
+
margin-top: var(--empty-state-action-gap);
|
|
3363
|
+
}
|
|
3364
|
+
|
|
3281
3365
|
/* ============================================================
|
|
3282
3366
|
Banner — in-body explanation block (info / neutral)
|
|
3283
3367
|
============================================================ */
|
|
@@ -3417,6 +3501,21 @@ a.chorus-metadata__name:focus-visible {
|
|
|
3417
3501
|
color: var(--sys-color-primary);
|
|
3418
3502
|
}
|
|
3419
3503
|
|
|
3504
|
+
/* neutral-body — keeps the `accent` fill but lays the Default
|
|
3505
|
+
appearance's neutral foreground over it: title + body re-tone to
|
|
3506
|
+
`onSurface` (quiet, high-legibility body copy) while the action
|
|
3507
|
+
steps to `primary`, exactly as on `default`. The accent tint still
|
|
3508
|
+
pulls the eye; the text just stops shouting in the primary family.
|
|
3509
|
+
Only meaningful combined with `--accent` (default is already
|
|
3510
|
+
`onSurface`; destructive must carry the warning tone through copy). */
|
|
3511
|
+
.chorus-banner--accent.chorus-banner--neutral-body {
|
|
3512
|
+
color: var(--sys-color-onSurface);
|
|
3513
|
+
}
|
|
3514
|
+
|
|
3515
|
+
.chorus-banner--accent.chorus-banner--neutral-body .chorus-banner__action {
|
|
3516
|
+
color: var(--sys-color-primary);
|
|
3517
|
+
}
|
|
3518
|
+
|
|
3420
3519
|
/* Trailing icon slot — a 16 × 16 glyph (`sys.icon.md`) at the trailing
|
|
3421
3520
|
edge, vertically centered against the whole block (`align-self:
|
|
3422
3521
|
center` overrides the container's flex-start). Paints in the
|
|
@@ -3439,6 +3538,23 @@ a.chorus-metadata__name:focus-visible {
|
|
|
3439
3538
|
color: currentColor;
|
|
3440
3539
|
}
|
|
3441
3540
|
|
|
3541
|
+
/* Trailing action slot — hosts an inline Text Button (`<Button
|
|
3542
|
+
variant="text">`) at the trailing edge, vertically centered against
|
|
3543
|
+
the whole block (`align-self: center` overrides the container's
|
|
3544
|
+
flex-start) and footprint-preserving (`flex: 0 0 auto`). The Button
|
|
3545
|
+
owns its own size + appearance per the button/text spec; by default
|
|
3546
|
+
pick the appearance whose color family matches the banner fill
|
|
3547
|
+
(accent → accent, default → default, destructive → destructive
|
|
3548
|
+
flavor) so the commit reads as part of the tinted block. Unlike the
|
|
3549
|
+
trailing icon it is a real interactive control, so it is not
|
|
3550
|
+
aria-hidden. The Text Button's optical-alignment margin lets its
|
|
3551
|
+
visible label sit flush against the container's trailing padding. */
|
|
3552
|
+
.chorus-banner__trailing-action {
|
|
3553
|
+
flex: 0 0 auto;
|
|
3554
|
+
align-self: center;
|
|
3555
|
+
display: inline-flex;
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3442
3558
|
/* ============================================================
|
|
3443
3559
|
Divider — section-break band between adjacent regions that
|
|
3444
3560
|
don't share an enclosing container. Single full-bleed block
|
|
@@ -5505,6 +5621,72 @@ a.chorus-metadata__name:focus-visible {
|
|
|
5505
5621
|
}
|
|
5506
5622
|
}
|
|
5507
5623
|
|
|
5624
|
+
/* ============================================================
|
|
5625
|
+
Spinner — indeterminate rotating-arc loading indicator
|
|
5626
|
+
============================================================ */
|
|
5627
|
+
/* A rotating ring for short, progress-unknown waits (< ~1s) on a
|
|
5628
|
+
neutral host surface. The arc paints `sys.color.primary` as the
|
|
5629
|
+
foreground motion over a faint `sys.color.scrimSubtle` track ring
|
|
5630
|
+
(inverse-tone ~8% tint) so the rotation reads on any surface tier.
|
|
5631
|
+
The ring is drawn with a conic gradient masked to an annulus — no
|
|
5632
|
+
`border:` (per the no-layout-strokes rule). Diameter rides the
|
|
5633
|
+
icon.* ladder via the `--spinner-diameter` plumbing var (sys.icon.lg
|
|
5634
|
+
medium / sys.icon.md small). Rotation modulates position, not
|
|
5635
|
+
luminance, and is suppressed under `prefers-reduced-motion: reduce`,
|
|
5636
|
+
leaving the full ring static as a quiet loading mark. */
|
|
5637
|
+
@keyframes chorus-spinner-rotate {
|
|
5638
|
+
to { transform: rotate(360deg); }
|
|
5639
|
+
}
|
|
5640
|
+
|
|
5641
|
+
.chorus-spinner {
|
|
5642
|
+
display: inline-flex;
|
|
5643
|
+
align-items: center;
|
|
5644
|
+
gap: var(--spinner-gap);
|
|
5645
|
+
}
|
|
5646
|
+
|
|
5647
|
+
.chorus-spinner__arc {
|
|
5648
|
+
display: block;
|
|
5649
|
+
flex: none;
|
|
5650
|
+
width: var(--spinner-diameter);
|
|
5651
|
+
height: var(--spinner-diameter);
|
|
5652
|
+
border-radius: var(--sys-radius-full);
|
|
5653
|
+
/* Foreground arc sweeps from primary to transparent over the track. */
|
|
5654
|
+
background:
|
|
5655
|
+
conic-gradient(var(--sys-color-primary), color-mix(in srgb, var(--sys-color-primary) 0%, transparent) 75%, color-mix(in srgb, var(--sys-color-primary) 0%, transparent));
|
|
5656
|
+
/* Annulus mask: punch out the centre so it reads as a ring, 2px thick.
|
|
5657
|
+
The mask fill is alpha-only — the opaque keep-region of the mask is
|
|
5658
|
+
not a design color, so it is not a token binding. */
|
|
5659
|
+
/* chorus-token-exempt */
|
|
5660
|
+
-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
|
|
5661
|
+
/* chorus-token-exempt */
|
|
5662
|
+
mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
|
|
5663
|
+
animation: chorus-spinner-rotate 0.8s linear infinite;
|
|
5664
|
+
}
|
|
5665
|
+
|
|
5666
|
+
/* Faint full track ring under the rotating arc, painted via box-shadow
|
|
5667
|
+
inset so the bare ring stays visible on any surface tier. */
|
|
5668
|
+
.chorus-spinner__arc::before {
|
|
5669
|
+
content: '';
|
|
5670
|
+
position: absolute;
|
|
5671
|
+
inset: 0;
|
|
5672
|
+
border-radius: inherit;
|
|
5673
|
+
box-shadow: inset 0 0 0 2px var(--sys-color-scrimSubtle);
|
|
5674
|
+
}
|
|
5675
|
+
|
|
5676
|
+
.chorus-spinner__arc {
|
|
5677
|
+
position: relative;
|
|
5678
|
+
}
|
|
5679
|
+
|
|
5680
|
+
.chorus-spinner__label {
|
|
5681
|
+
color: var(--sys-color-onSurfaceVariant);
|
|
5682
|
+
}
|
|
5683
|
+
|
|
5684
|
+
@media (prefers-reduced-motion: reduce) {
|
|
5685
|
+
.chorus-spinner__arc {
|
|
5686
|
+
animation: none;
|
|
5687
|
+
}
|
|
5688
|
+
}
|
|
5689
|
+
|
|
5508
5690
|
/* ============================================================
|
|
5509
5691
|
Switch — binary active/inactive pill with translating thumb
|
|
5510
5692
|
============================================================ */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamblind-chorus/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Chorus React components. Ships prebuilt ESM + CJS bundles (`dist/`) and a single `styles.css`; import `@teamblind-chorus/tokens/tokens.css` + `@teamblind-chorus/ui/styles.css` once at the app entry. The contract every component honors lives in schema/components/<family>/<sub>.spec.json; see schema/manifest.json for the inventory.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Teamblind, Inc.",
|