@flytedan/flytebot-design-system 0.12.11 → 0.12.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flytedan/flytebot-design-system",
3
- "version": "0.12.11",
3
+ "version": "0.12.12",
4
4
  "description": "flytedesk Design System — shared component library, tokens, and business-logic kits for flytedesk apps.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -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
- filter: brightness(1.08);
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
- filter: brightness(0.92);
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
  }
@@ -6629,3 +6654,191 @@ button.fd-erow-metric:focus-visible {
6629
6654
  .fd-spinner{animation-duration:1.6s}
6630
6655
  .fd-arrived{animation:none}
6631
6656
  }
6657
+
6658
+ /* FileViewer (MP-130): a preview pane plus an optional host-supplied side panel — the
6659
+ companion notes/metadata surface the app composes in, generic here as `sidePanel`.
6660
+ Two regions, one scroll region each (R-8): `.fd-fv-body` never scrolls, each pane owns
6661
+ its own overflow. Side by side while there's room; below a narrow width of the
6662
+ component's OWN box (a container query, not a media query — the same reasoning as
6663
+ `.fd-tlist`'s above, since a FileViewer opened full-page and one opened in a Drawer see
6664
+ completely different widths at the same viewport) the side panel becomes a tab next to
6665
+ Preview and exactly one pane is visible at a time. */
6666
+ .fd-fv {
6667
+ container-type: inline-size;
6668
+ display: flex;
6669
+ flex-direction: column;
6670
+ height: 100%;
6671
+ min-height: 0;
6672
+ background: var(--surface);
6673
+ color: var(--text);
6674
+ }
6675
+ .fd-fv-head {
6676
+ display: flex;
6677
+ align-items: center;
6678
+ gap: 10px;
6679
+ padding: 12px 16px;
6680
+ border-bottom: 1px solid var(--border);
6681
+ flex: none;
6682
+ }
6683
+ .fd-fv-head-icon {
6684
+ display: grid;
6685
+ place-items: center;
6686
+ width: 32px;
6687
+ height: 32px;
6688
+ border-radius: var(--r-md);
6689
+ background: var(--surface-2);
6690
+ color: var(--text-2);
6691
+ font-size: 17px;
6692
+ flex: none;
6693
+ }
6694
+ .fd-fv-head-titles {
6695
+ display: flex;
6696
+ flex-direction: column;
6697
+ min-width: 0;
6698
+ flex: 1 1 auto;
6699
+ }
6700
+ .fd-fv-head-title {
6701
+ font-weight: 600;
6702
+ overflow: hidden;
6703
+ text-overflow: ellipsis;
6704
+ white-space: nowrap;
6705
+ }
6706
+ .fd-fv-head-meta {
6707
+ font-size: var(--body-sm-size);
6708
+ color: var(--text-2);
6709
+ }
6710
+ .fd-fv-head-actions {
6711
+ display: flex;
6712
+ align-items: center;
6713
+ gap: 8px;
6714
+ flex: none;
6715
+ }
6716
+ .fd-fv-download-error {
6717
+ margin: 10px 16px 0;
6718
+ padding: 8px 12px;
6719
+ border-radius: var(--r-md);
6720
+ background: var(--danger-fill);
6721
+ border: 1px solid var(--danger-border);
6722
+ color: var(--danger-text);
6723
+ font-size: var(--body-sm-size);
6724
+ }
6725
+ /* Only ever shown below the narrow container-query breakpoint (see the block at the
6726
+ bottom of this section) — at full width both panes are already visible, so a tab
6727
+ bar choosing between them would be a control with nothing to do. */
6728
+ .fd-fv-tabs {
6729
+ display: none;
6730
+ flex: none;
6731
+ padding: 0 16px;
6732
+ border-bottom: 1px solid var(--border);
6733
+ }
6734
+ .fd-fv-body {
6735
+ display: flex;
6736
+ flex: 1 1 auto;
6737
+ min-height: 0;
6738
+ overflow: hidden;
6739
+ }
6740
+ .fd-fv-preview {
6741
+ flex: 1 1 auto;
6742
+ min-width: 0;
6743
+ min-height: 0;
6744
+ overflow: auto;
6745
+ padding: 16px;
6746
+ }
6747
+ .fd-fv-side {
6748
+ flex: 0 0 320px;
6749
+ min-width: 0;
6750
+ min-height: 0;
6751
+ overflow: auto;
6752
+ padding: 16px;
6753
+ border-left: 1px solid var(--border);
6754
+ background: var(--surface-2);
6755
+ }
6756
+ .fd-fv-image {
6757
+ display: block;
6758
+ max-width: 100%;
6759
+ height: auto;
6760
+ margin: 0 auto;
6761
+ border-radius: var(--r-md);
6762
+ }
6763
+ .fd-fv-pdf {
6764
+ display: block;
6765
+ width: 100%;
6766
+ height: 100%;
6767
+ min-height: 480px;
6768
+ border: 0;
6769
+ border-radius: var(--r-md);
6770
+ background: var(--surface-2);
6771
+ }
6772
+ .fd-fv-fallback {
6773
+ display: flex;
6774
+ flex-direction: column;
6775
+ align-items: center;
6776
+ justify-content: center;
6777
+ gap: 8px;
6778
+ height: 100%;
6779
+ min-height: 220px;
6780
+ text-align: center;
6781
+ color: var(--text-2);
6782
+ }
6783
+ .fd-fv-fallback-icon {
6784
+ display: grid;
6785
+ place-items: center;
6786
+ width: 56px;
6787
+ height: 56px;
6788
+ border-radius: var(--r-full);
6789
+ background: var(--surface-2);
6790
+ font-size: 26px;
6791
+ }
6792
+ .fd-fv-fallback-title {
6793
+ font-weight: 600;
6794
+ color: var(--text);
6795
+ }
6796
+ .fd-fv-fallback-meta {
6797
+ font-size: var(--body-sm-size);
6798
+ }
6799
+ .fd-fv-csv-table {
6800
+ width: 100%;
6801
+ border-collapse: collapse;
6802
+ font-size: var(--body-sm-size);
6803
+ }
6804
+ .fd-fv-csv-table th,
6805
+ .fd-fv-csv-table td {
6806
+ padding: 6px 10px;
6807
+ border-bottom: 1px solid var(--border);
6808
+ text-align: left;
6809
+ white-space: nowrap;
6810
+ }
6811
+ .fd-fv-csv-table th {
6812
+ color: var(--text-2);
6813
+ font-weight: 600;
6814
+ background: var(--surface-2);
6815
+ position: sticky;
6816
+ top: 0;
6817
+ }
6818
+ .fd-fv-csv-note {
6819
+ margin-top: 10px;
6820
+ }
6821
+ /* Below 640px of `.fd-fv`'s OWN width (not the viewport's — see the block comment
6822
+ above) there is no room for a preview beside a side panel: the tab bar takes over
6823
+ choosing which one is visible, and the two panes stack full-width instead of sitting
6824
+ side by side. Each pane keeps its own `overflow: auto` from the base rules above, so
6825
+ R-8 (one scroll region per pane) holds at this width too — there is just one pane on
6826
+ screen at a time instead of two. */
6827
+ @container (max-width: 640px) {
6828
+ .fd-fv-tabs {
6829
+ display: flex;
6830
+ }
6831
+ .fd-fv-body {
6832
+ flex-direction: column;
6833
+ }
6834
+ .fd-fv-side {
6835
+ border-left: 0;
6836
+ border-top: 1px solid var(--border);
6837
+ }
6838
+ .fd-fv.is-tab-preview .fd-fv-side {
6839
+ display: none;
6840
+ }
6841
+ .fd-fv.is-tab-side .fd-fv-preview {
6842
+ display: none;
6843
+ }
6844
+ }
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
- --btn-soft-ok-bg:#557F6A;--btn-soft-ok-border:#145A38;--btn-soft-ok-ink:#FFFFFF;
115
- --btn-soft-danger-bg:#C84E43;--btn-soft-danger-border:#862720;--btn-soft-danger-ink:#FFFFFF;
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
- --btn-soft-ok-bg:#007A3D;--btn-soft-ok-border:#3FB37A;--btn-soft-ok-ink:#FFFFFF;
284
- --btn-soft-danger-bg:#D41200;--btn-soft-danger-border:#E8776D;--btn-soft-danger-ink:#FFFFFF;
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;