@flytedan/flytebot-design-system 0.12.11 → 0.12.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +250 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -9
- package/dist/index.d.ts +57 -9
- package/dist/index.js +246 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +236 -9
- package/styles/tokens.css +22 -6
package/package.json
CHANGED
package/styles/components.css
CHANGED
|
@@ -244,7 +244,22 @@
|
|
|
244
244
|
/* Soft: a lighter fill than solid, with a visibly darker border drawn around it (MP-52's
|
|
245
245
|
"lighter fill, darker border" row action). Same --btn-soft-* tokens (tokens.css), same
|
|
246
246
|
per-theme measurement discipline as solid, and the same pressed-selector-specificity
|
|
247
|
-
fix baked in from the start (see the comment on .fd-btn-icon-solid:active above).
|
|
247
|
+
fix baked in from the start (see the comment on .fd-btn-icon-solid:active above).
|
|
248
|
+
|
|
249
|
+
MP-114 hover/active: the base `.fd-btn-icon:hover`/`:active` rules above (plain
|
|
250
|
+
`.fd-btn-icon`, no variant) set `background` too, at the same (0,2,0) specificity as
|
|
251
|
+
`.fd-btn-icon-soft:hover`/`:active` — a tie the cascade breaks by source order, so
|
|
252
|
+
whichever rule sets `background` LAST wins. The old hover/active rules here only set
|
|
253
|
+
`filter` and `color`, never `background`, so they never entered that tie for the
|
|
254
|
+
`background` property at all: the base rule's `background: var(--surface-3)` /
|
|
255
|
+
`var(--border)` was the only declaration left standing, and the soft fill vanished
|
|
256
|
+
under a plain neutral surface colour while the ink stayed tuned for the soft fill —
|
|
257
|
+
e2e-measured at 1.11:1. `filter: brightness()` made it worse in a way no contrast
|
|
258
|
+
check (this file's or a screen reader user's own eye) could catch: a filter changes
|
|
259
|
+
the pixels without ever touching `background-color`, so it cannot be reasoned about
|
|
260
|
+
from the declared colours at all. Fixed on both counts: every state below restates a
|
|
261
|
+
real `background` from a real token, so it wins its own tie the same way solid's
|
|
262
|
+
already does, and there is no filter left to hide behind. */
|
|
248
263
|
.fd-btn-icon-soft {
|
|
249
264
|
background: var(--btn-soft-bg);
|
|
250
265
|
color: var(--btn-soft-ink);
|
|
@@ -253,26 +268,36 @@
|
|
|
253
268
|
}
|
|
254
269
|
.fd-btn-icon-soft.is-ok {
|
|
255
270
|
--btn-soft-bg: var(--btn-soft-ok-bg);
|
|
271
|
+
--btn-soft-bg-hover: var(--btn-soft-ok-bg-hover);
|
|
272
|
+
--btn-soft-bg-active: var(--btn-soft-ok-bg-active);
|
|
256
273
|
--btn-soft-border: var(--btn-soft-ok-border);
|
|
257
274
|
--btn-soft-ink: var(--btn-soft-ok-ink);
|
|
258
275
|
}
|
|
259
276
|
.fd-btn-icon-soft.is-danger {
|
|
260
277
|
--btn-soft-bg: var(--btn-soft-danger-bg);
|
|
278
|
+
--btn-soft-bg-hover: var(--btn-soft-danger-bg-hover);
|
|
279
|
+
--btn-soft-bg-active: var(--btn-soft-danger-bg-active);
|
|
261
280
|
--btn-soft-border: var(--btn-soft-danger-border);
|
|
262
281
|
--btn-soft-ink: var(--btn-soft-danger-ink);
|
|
263
282
|
}
|
|
264
283
|
.fd-btn-icon-soft:hover,
|
|
265
284
|
.fd-btn-icon-soft.is-ok:hover,
|
|
266
285
|
.fd-btn-icon-soft.is-danger:hover {
|
|
267
|
-
|
|
286
|
+
background: var(--btn-soft-bg-hover);
|
|
268
287
|
color: var(--btn-soft-ink);
|
|
269
288
|
}
|
|
289
|
+
/* Pressed restates every selector hover uses, same reasoning as
|
|
290
|
+
.fd-btn-icon-solid:active above. */
|
|
270
291
|
.fd-btn-icon-soft:active,
|
|
271
292
|
.fd-btn-icon-soft.is-ok:active,
|
|
272
293
|
.fd-btn-icon-soft.is-danger:active {
|
|
273
|
-
|
|
294
|
+
background: var(--btn-soft-bg-active);
|
|
295
|
+
color: var(--btn-soft-ink);
|
|
274
296
|
box-shadow: none;
|
|
275
297
|
}
|
|
298
|
+
/* Restated after :active, same reasoning as .fd-btn-icon-solid:focus-visible above: a
|
|
299
|
+
pressed-while-focused button must keep the ring, not the pressed rule's `box-shadow:
|
|
300
|
+
none`. */
|
|
276
301
|
.fd-btn-icon-soft:focus-visible {
|
|
277
302
|
box-shadow: var(--focus-ring);
|
|
278
303
|
}
|
|
@@ -1699,6 +1724,14 @@
|
|
|
1699
1724
|
}
|
|
1700
1725
|
|
|
1701
1726
|
/* ============ Stat tile ============ */
|
|
1727
|
+
/* MP-141: kit-wide truncation rule for Stat (and every future text class here) —
|
|
1728
|
+
* explanatory/label copy (.fd-stat-sub, .fd-stat-label) always WRAPS, never
|
|
1729
|
+
* ellipsizes: a client reading a narrow tile must never lose part of a sentence
|
|
1730
|
+
* behind a "…" with no way to read the rest, and a tooltip is not a substitute
|
|
1731
|
+
* for readable client-facing copy. Only a user-data identifier displayed in a
|
|
1732
|
+
* dense row (a table cell, a chip) may ellipsize — and only when it also exposes
|
|
1733
|
+
* its full text via `title`/tooltip. Decide this once, here, for every Stat
|
|
1734
|
+
* consumer, not per screen. */
|
|
1702
1735
|
.fd-stat {
|
|
1703
1736
|
background: var(--surface);
|
|
1704
1737
|
border: 1px solid var(--border);
|
|
@@ -1715,16 +1748,23 @@
|
|
|
1715
1748
|
min-width: 0;
|
|
1716
1749
|
}
|
|
1717
1750
|
.fd-stat-sub {
|
|
1751
|
+
/* MP-141: this is explanatory copy ("on every funded campus, at minimum"),
|
|
1752
|
+
* never a user-data identifier — per the kit's truncation rule (see this
|
|
1753
|
+
* file's own header note above .fd-stat), explanatory/label copy always
|
|
1754
|
+
* wraps instead of ellipsizing, so a client reading a narrow tile never
|
|
1755
|
+
* loses part of the sentence behind a "…" with no way to read the rest. */
|
|
1718
1756
|
display: block;
|
|
1719
1757
|
margin-top: 4px;
|
|
1720
1758
|
font-size: var(--body-sm-size);
|
|
1721
1759
|
color: var(--text-2);
|
|
1722
1760
|
min-width: 0;
|
|
1723
|
-
overflow:
|
|
1724
|
-
|
|
1725
|
-
white-space: nowrap;
|
|
1761
|
+
overflow-wrap: break-word;
|
|
1762
|
+
white-space: normal;
|
|
1726
1763
|
}
|
|
1727
1764
|
.fd-stat-label {
|
|
1765
|
+
/* MP-141: same rule as .fd-stat-sub above — this is the tile's fixed
|
|
1766
|
+
* caption, not a user-entered identifier, so it wraps rather than losing
|
|
1767
|
+
* words to an ellipsis. */
|
|
1728
1768
|
display: block;
|
|
1729
1769
|
margin-top: 6px;
|
|
1730
1770
|
font-size: var(--overline-size);
|
|
@@ -1732,9 +1772,8 @@
|
|
|
1732
1772
|
text-transform: uppercase;
|
|
1733
1773
|
font-weight: var(--w-bold);
|
|
1734
1774
|
color: var(--text-muted);
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
text-overflow: ellipsis;
|
|
1775
|
+
overflow-wrap: break-word;
|
|
1776
|
+
white-space: normal;
|
|
1738
1777
|
}
|
|
1739
1778
|
.fd-stat-figure {
|
|
1740
1779
|
flex: none;
|
|
@@ -6629,3 +6668,191 @@ button.fd-erow-metric:focus-visible {
|
|
|
6629
6668
|
.fd-spinner{animation-duration:1.6s}
|
|
6630
6669
|
.fd-arrived{animation:none}
|
|
6631
6670
|
}
|
|
6671
|
+
|
|
6672
|
+
/* FileViewer (MP-130): a preview pane plus an optional host-supplied side panel — the
|
|
6673
|
+
companion notes/metadata surface the app composes in, generic here as `sidePanel`.
|
|
6674
|
+
Two regions, one scroll region each (R-8): `.fd-fv-body` never scrolls, each pane owns
|
|
6675
|
+
its own overflow. Side by side while there's room; below a narrow width of the
|
|
6676
|
+
component's OWN box (a container query, not a media query — the same reasoning as
|
|
6677
|
+
`.fd-tlist`'s above, since a FileViewer opened full-page and one opened in a Drawer see
|
|
6678
|
+
completely different widths at the same viewport) the side panel becomes a tab next to
|
|
6679
|
+
Preview and exactly one pane is visible at a time. */
|
|
6680
|
+
.fd-fv {
|
|
6681
|
+
container-type: inline-size;
|
|
6682
|
+
display: flex;
|
|
6683
|
+
flex-direction: column;
|
|
6684
|
+
height: 100%;
|
|
6685
|
+
min-height: 0;
|
|
6686
|
+
background: var(--surface);
|
|
6687
|
+
color: var(--text);
|
|
6688
|
+
}
|
|
6689
|
+
.fd-fv-head {
|
|
6690
|
+
display: flex;
|
|
6691
|
+
align-items: center;
|
|
6692
|
+
gap: 10px;
|
|
6693
|
+
padding: 12px 16px;
|
|
6694
|
+
border-bottom: 1px solid var(--border);
|
|
6695
|
+
flex: none;
|
|
6696
|
+
}
|
|
6697
|
+
.fd-fv-head-icon {
|
|
6698
|
+
display: grid;
|
|
6699
|
+
place-items: center;
|
|
6700
|
+
width: 32px;
|
|
6701
|
+
height: 32px;
|
|
6702
|
+
border-radius: var(--r-md);
|
|
6703
|
+
background: var(--surface-2);
|
|
6704
|
+
color: var(--text-2);
|
|
6705
|
+
font-size: 17px;
|
|
6706
|
+
flex: none;
|
|
6707
|
+
}
|
|
6708
|
+
.fd-fv-head-titles {
|
|
6709
|
+
display: flex;
|
|
6710
|
+
flex-direction: column;
|
|
6711
|
+
min-width: 0;
|
|
6712
|
+
flex: 1 1 auto;
|
|
6713
|
+
}
|
|
6714
|
+
.fd-fv-head-title {
|
|
6715
|
+
font-weight: 600;
|
|
6716
|
+
overflow: hidden;
|
|
6717
|
+
text-overflow: ellipsis;
|
|
6718
|
+
white-space: nowrap;
|
|
6719
|
+
}
|
|
6720
|
+
.fd-fv-head-meta {
|
|
6721
|
+
font-size: var(--body-sm-size);
|
|
6722
|
+
color: var(--text-2);
|
|
6723
|
+
}
|
|
6724
|
+
.fd-fv-head-actions {
|
|
6725
|
+
display: flex;
|
|
6726
|
+
align-items: center;
|
|
6727
|
+
gap: 8px;
|
|
6728
|
+
flex: none;
|
|
6729
|
+
}
|
|
6730
|
+
.fd-fv-download-error {
|
|
6731
|
+
margin: 10px 16px 0;
|
|
6732
|
+
padding: 8px 12px;
|
|
6733
|
+
border-radius: var(--r-md);
|
|
6734
|
+
background: var(--danger-fill);
|
|
6735
|
+
border: 1px solid var(--danger-border);
|
|
6736
|
+
color: var(--danger-text);
|
|
6737
|
+
font-size: var(--body-sm-size);
|
|
6738
|
+
}
|
|
6739
|
+
/* Only ever shown below the narrow container-query breakpoint (see the block at the
|
|
6740
|
+
bottom of this section) — at full width both panes are already visible, so a tab
|
|
6741
|
+
bar choosing between them would be a control with nothing to do. */
|
|
6742
|
+
.fd-fv-tabs {
|
|
6743
|
+
display: none;
|
|
6744
|
+
flex: none;
|
|
6745
|
+
padding: 0 16px;
|
|
6746
|
+
border-bottom: 1px solid var(--border);
|
|
6747
|
+
}
|
|
6748
|
+
.fd-fv-body {
|
|
6749
|
+
display: flex;
|
|
6750
|
+
flex: 1 1 auto;
|
|
6751
|
+
min-height: 0;
|
|
6752
|
+
overflow: hidden;
|
|
6753
|
+
}
|
|
6754
|
+
.fd-fv-preview {
|
|
6755
|
+
flex: 1 1 auto;
|
|
6756
|
+
min-width: 0;
|
|
6757
|
+
min-height: 0;
|
|
6758
|
+
overflow: auto;
|
|
6759
|
+
padding: 16px;
|
|
6760
|
+
}
|
|
6761
|
+
.fd-fv-side {
|
|
6762
|
+
flex: 0 0 320px;
|
|
6763
|
+
min-width: 0;
|
|
6764
|
+
min-height: 0;
|
|
6765
|
+
overflow: auto;
|
|
6766
|
+
padding: 16px;
|
|
6767
|
+
border-left: 1px solid var(--border);
|
|
6768
|
+
background: var(--surface-2);
|
|
6769
|
+
}
|
|
6770
|
+
.fd-fv-image {
|
|
6771
|
+
display: block;
|
|
6772
|
+
max-width: 100%;
|
|
6773
|
+
height: auto;
|
|
6774
|
+
margin: 0 auto;
|
|
6775
|
+
border-radius: var(--r-md);
|
|
6776
|
+
}
|
|
6777
|
+
.fd-fv-pdf {
|
|
6778
|
+
display: block;
|
|
6779
|
+
width: 100%;
|
|
6780
|
+
height: 100%;
|
|
6781
|
+
min-height: 480px;
|
|
6782
|
+
border: 0;
|
|
6783
|
+
border-radius: var(--r-md);
|
|
6784
|
+
background: var(--surface-2);
|
|
6785
|
+
}
|
|
6786
|
+
.fd-fv-fallback {
|
|
6787
|
+
display: flex;
|
|
6788
|
+
flex-direction: column;
|
|
6789
|
+
align-items: center;
|
|
6790
|
+
justify-content: center;
|
|
6791
|
+
gap: 8px;
|
|
6792
|
+
height: 100%;
|
|
6793
|
+
min-height: 220px;
|
|
6794
|
+
text-align: center;
|
|
6795
|
+
color: var(--text-2);
|
|
6796
|
+
}
|
|
6797
|
+
.fd-fv-fallback-icon {
|
|
6798
|
+
display: grid;
|
|
6799
|
+
place-items: center;
|
|
6800
|
+
width: 56px;
|
|
6801
|
+
height: 56px;
|
|
6802
|
+
border-radius: var(--r-full);
|
|
6803
|
+
background: var(--surface-2);
|
|
6804
|
+
font-size: 26px;
|
|
6805
|
+
}
|
|
6806
|
+
.fd-fv-fallback-title {
|
|
6807
|
+
font-weight: 600;
|
|
6808
|
+
color: var(--text);
|
|
6809
|
+
}
|
|
6810
|
+
.fd-fv-fallback-meta {
|
|
6811
|
+
font-size: var(--body-sm-size);
|
|
6812
|
+
}
|
|
6813
|
+
.fd-fv-csv-table {
|
|
6814
|
+
width: 100%;
|
|
6815
|
+
border-collapse: collapse;
|
|
6816
|
+
font-size: var(--body-sm-size);
|
|
6817
|
+
}
|
|
6818
|
+
.fd-fv-csv-table th,
|
|
6819
|
+
.fd-fv-csv-table td {
|
|
6820
|
+
padding: 6px 10px;
|
|
6821
|
+
border-bottom: 1px solid var(--border);
|
|
6822
|
+
text-align: left;
|
|
6823
|
+
white-space: nowrap;
|
|
6824
|
+
}
|
|
6825
|
+
.fd-fv-csv-table th {
|
|
6826
|
+
color: var(--text-2);
|
|
6827
|
+
font-weight: 600;
|
|
6828
|
+
background: var(--surface-2);
|
|
6829
|
+
position: sticky;
|
|
6830
|
+
top: 0;
|
|
6831
|
+
}
|
|
6832
|
+
.fd-fv-csv-note {
|
|
6833
|
+
margin-top: 10px;
|
|
6834
|
+
}
|
|
6835
|
+
/* Below 640px of `.fd-fv`'s OWN width (not the viewport's — see the block comment
|
|
6836
|
+
above) there is no room for a preview beside a side panel: the tab bar takes over
|
|
6837
|
+
choosing which one is visible, and the two panes stack full-width instead of sitting
|
|
6838
|
+
side by side. Each pane keeps its own `overflow: auto` from the base rules above, so
|
|
6839
|
+
R-8 (one scroll region per pane) holds at this width too — there is just one pane on
|
|
6840
|
+
screen at a time instead of two. */
|
|
6841
|
+
@container (max-width: 640px) {
|
|
6842
|
+
.fd-fv-tabs {
|
|
6843
|
+
display: flex;
|
|
6844
|
+
}
|
|
6845
|
+
.fd-fv-body {
|
|
6846
|
+
flex-direction: column;
|
|
6847
|
+
}
|
|
6848
|
+
.fd-fv-side {
|
|
6849
|
+
border-left: 0;
|
|
6850
|
+
border-top: 1px solid var(--border);
|
|
6851
|
+
}
|
|
6852
|
+
.fd-fv.is-tab-preview .fd-fv-side {
|
|
6853
|
+
display: none;
|
|
6854
|
+
}
|
|
6855
|
+
.fd-fv.is-tab-side .fd-fv-preview {
|
|
6856
|
+
display: none;
|
|
6857
|
+
}
|
|
6858
|
+
}
|
package/styles/tokens.css
CHANGED
|
@@ -110,9 +110,18 @@
|
|
|
110
110
|
usual badge sense (e.g. --ok-fill/--danger-fill) is only ~1.05:1 from --erow-danger-fill
|
|
111
111
|
and fails outright; this is the lightest fill that still clears the bar next to a red
|
|
112
112
|
row. The border reuses the darker --btn-solid-*-bg-active token, 1.8-2:1 off the new
|
|
113
|
-
fill and 7:1+ off both grounds, so it reads even where hue alone would not.
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
fill and 7:1+ off both grounds, so it reads even where hue alone would not.
|
|
114
|
+
|
|
115
|
+
MP-114 hover/active: darkened the same way --btn-solid-* darkens for its own
|
|
116
|
+
hover/active (light theme gets darker as you press deeper). -bg-hover is 8% darker
|
|
117
|
+
than -bg, -bg-active 16% darker; white ink stays 5.19:1+ / 5.97:1+ and the fill stays
|
|
118
|
+
4.45:1+ against --erow-danger-fill (the tighter of the two grounds) at every step.
|
|
119
|
+
These are real fills, not a `filter: brightness()` restatement — a filter changes
|
|
120
|
+
what the eye sees without changing `background-color`, so a contrast check (and a
|
|
121
|
+
person's actual reading of the button) that goes by the declared colour never sees
|
|
122
|
+
it move. */
|
|
123
|
+
--btn-soft-ok-bg:#557F6A;--btn-soft-ok-bg-hover:#4E7562;--btn-soft-ok-bg-active:#476B59;--btn-soft-ok-border:#145A38;--btn-soft-ok-ink:#FFFFFF;
|
|
124
|
+
--btn-soft-danger-bg:#C84E43;--btn-soft-danger-bg-hover:#B8483E;--btn-soft-danger-bg-active:#A84238;--btn-soft-danger-border:#862720;--btn-soft-danger-ink:#FFFFFF;
|
|
116
125
|
|
|
117
126
|
--ok-fill:#DFF3E8;--ok-border:#A8DDC2;--ok-text:#0E5233;--ok-solid:#34A26B;--ok-emph:#57C68C;
|
|
118
127
|
--warn-fill:#FDF1DA;--warn-border:#F0D49A;--warn-text:#6B4A05;--warn-solid:#C8890B;
|
|
@@ -279,9 +288,16 @@
|
|
|
279
288
|
--surface-2 (#1B1F27) and --erow-danger-fill (#331813): white ink is 5.4:1 or better,
|
|
280
289
|
the fill is 3.0:1 or better against either ground, and the border (the theme's own
|
|
281
290
|
--btn-solid-*-bg, already proven legible here) is 1.9:1+ off the fill and 5.7:1+ off
|
|
282
|
-
both grounds.
|
|
283
|
-
|
|
284
|
-
|
|
291
|
+
both grounds.
|
|
292
|
+
|
|
293
|
+
MP-114 hover/active: rest is already only ~3.0:1 off --surface-2, the floor, so
|
|
294
|
+
darkening further (the light-theme direction) would drop the fill below 3:1 — both
|
|
295
|
+
states have to LIGHTEN here instead, same direction as --btn-solid-* on this ground.
|
|
296
|
+
-bg-hover is +6% toward white, -bg-active +9%/+12% (ok/danger): white ink stays
|
|
297
|
+
4.61:1+ and the fill stays 3.30:1+ against both --surface-2 and --erow-danger-fill at
|
|
298
|
+
every step. Real fills, not `filter: brightness()` — see the :root comment above. */
|
|
299
|
+
--btn-soft-ok-bg:#007A3D;--btn-soft-ok-bg-hover:#0F8249;--btn-soft-ok-bg-active:#17864E;--btn-soft-ok-border:#3FB37A;--btn-soft-ok-ink:#FFFFFF;
|
|
300
|
+
--btn-soft-danger-bg:#D41200;--btn-soft-danger-bg-hover:#D7200F;--btn-soft-danger-bg-active:#D92E1F;--btn-soft-danger-border:#E8776D;--btn-soft-danger-ink:#FFFFFF;
|
|
285
301
|
|
|
286
302
|
/* chat kit — see the :root block above */
|
|
287
303
|
--chat-code-bg:#12151B;
|