@flytedan/flytebot-design-system 0.12.8 → 0.12.10

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.8",
3
+ "version": "0.12.10",
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",
@@ -231,6 +231,41 @@
231
231
  .fd-btn-icon-solid:focus-visible {
232
232
  box-shadow: var(--focus-ring);
233
233
  }
234
+ /* Soft: a lighter fill than solid, with a visibly darker border drawn around it (MP-52's
235
+ "lighter fill, darker border" row action). Same --btn-soft-* tokens (tokens.css), same
236
+ per-theme measurement discipline as solid, and the same pressed-selector-specificity
237
+ fix baked in from the start (see the comment on .fd-btn-icon-solid:active above). */
238
+ .fd-btn-icon-soft {
239
+ background: var(--btn-soft-bg);
240
+ color: var(--btn-soft-ink);
241
+ border-color: var(--btn-soft-border);
242
+ box-shadow: var(--e-1);
243
+ }
244
+ .fd-btn-icon-soft.is-ok {
245
+ --btn-soft-bg: var(--btn-soft-ok-bg);
246
+ --btn-soft-border: var(--btn-soft-ok-border);
247
+ --btn-soft-ink: var(--btn-soft-ok-ink);
248
+ }
249
+ .fd-btn-icon-soft.is-danger {
250
+ --btn-soft-bg: var(--btn-soft-danger-bg);
251
+ --btn-soft-border: var(--btn-soft-danger-border);
252
+ --btn-soft-ink: var(--btn-soft-danger-ink);
253
+ }
254
+ .fd-btn-icon-soft:hover,
255
+ .fd-btn-icon-soft.is-ok:hover,
256
+ .fd-btn-icon-soft.is-danger:hover {
257
+ filter: brightness(1.08);
258
+ color: var(--btn-soft-ink);
259
+ }
260
+ .fd-btn-icon-soft:active,
261
+ .fd-btn-icon-soft.is-ok:active,
262
+ .fd-btn-icon-soft.is-danger:active {
263
+ filter: brightness(0.92);
264
+ box-shadow: none;
265
+ }
266
+ .fd-btn-icon-soft:focus-visible {
267
+ box-shadow: var(--focus-ring);
268
+ }
234
269
  .fd-btn-icon-sm {
235
270
  width: var(--control-h-sm);
236
271
  height: var(--control-h-sm);
@@ -4054,6 +4089,13 @@
4054
4089
  itself uses (--r-md here rather than Card's --r-lg — a compact list row reads
4055
4090
  better with the tighter radius; --e-1/--e-2 are the same elevation tokens). */
4056
4091
  .fd-erow {
4092
+ /* display/align-items/gap live here, not on the component's inline style (where
4093
+ they used to be, MP-114 follow-up) — an inline style always wins over a
4094
+ stylesheet rule, which would make it impossible for the narrow-container rule
4095
+ below to ever switch this row from a flex row to a grid. */
4096
+ display: flex;
4097
+ align-items: center;
4098
+ gap: 10px;
4057
4099
  background: var(--surface-2);
4058
4100
  border: 1px solid var(--erow-border);
4059
4101
  border-radius: var(--r-md);
@@ -4126,6 +4168,43 @@
4126
4168
  overflow: hidden;
4127
4169
  text-overflow: ellipsis;
4128
4170
  }
4171
+ /* The title-icon Tooltip trigger (MP-52): icon and title share one hoverable/focusable
4172
+ region rather than two, so hovering either opens the same explanation. Carries the same
4173
+ flex floor .fd-erow-title has on its own (see the comment above it) so wrapping the
4174
+ title in a button never changes how the titleline shares space with `meta`. Reset to a
4175
+ plain inline button — no border/background/font change — because visually this must
4176
+ read exactly like a title with an icon in front of it, not a control. */
4177
+ .fd-erow-title-icon {
4178
+ display: inline-flex;
4179
+ align-items: center;
4180
+ gap: 4px;
4181
+ flex: 1 1 auto;
4182
+ min-width: 45%;
4183
+ border: 0;
4184
+ background: none;
4185
+ padding: 0;
4186
+ margin: 0;
4187
+ font: inherit;
4188
+ color: inherit;
4189
+ text-align: left;
4190
+ cursor: pointer;
4191
+ }
4192
+ .fd-erow-title-icon .fd-erow-title {
4193
+ min-width: 0;
4194
+ }
4195
+ .fd-erow-title-icon > .ph {
4196
+ flex: none;
4197
+ font-size: 14px;
4198
+ color: var(--text-muted);
4199
+ }
4200
+ .fd-erow-title-icon.is-danger > .ph {
4201
+ color: var(--danger-solid);
4202
+ }
4203
+ .fd-erow-title-icon:focus-visible {
4204
+ outline: none;
4205
+ box-shadow: var(--focus-ring);
4206
+ border-radius: var(--r-sm);
4207
+ }
4129
4208
  .fd-erow-strip {
4130
4209
  display: flex;
4131
4210
  align-items: center;
@@ -4267,22 +4346,96 @@ button.fd-erow-metric:focus-visible {
4267
4346
  flex-direction: column;
4268
4347
  align-items: stretch;
4269
4348
  }
4270
- /* MP-114: below the same width EntityRow's metric strip stops having room to keep
4271
- every column at the desktop's fixed --erow-metric-w (set so rows line up with a
4272
- multi-digit totals footer, see EntityRowMetrics/.fd-erow-cell above) even each
4273
- cell's own un-wrapped figure (`.fd-erow-metric`'s `white-space: nowrap` makes its
4274
- min-content equal its full width) no longer fits together in the strip, and
4275
- `.fd-erow-metrics`'s `overflow: hidden` was clipping the ones that didn't. A
4276
- stacked phone pane never regains that room, so the fixed-column alignment this
4277
- component is built for is traded, at this width only, for every metric staying a
4278
- whole, readable button: cells size to their own content instead of the desktop
4279
- column width, and the strip wraps instead of clipping. */
4349
+ /* MP-114 (second follow-up). The first follow-up kept every `.fd-erow-cell` at its
4350
+ exact fixed `--erow-metric-w` down here (never `width: auto` see the alignment
4351
+ argument in EntityRowMetrics/.fd-erow-metrics's own comments above, which this
4352
+ still honours) and let `.fd-erow-metrics` scroll instead of clip when the strip ran
4353
+ out of room. That satisfied the alignment contract, but media-planner's
4354
+ audience-list-affordances.spec.ts (375px, touch) caught what it traded away: a
4355
+ scrollable strip still HIDES figures behind a scroll a touch user has no reason to
4356
+ discover, which the spec's `stripClipsNothing` check treats as no better than
4357
+ clipping at phone width every figure has to be actually, fully visible.
4358
+
4359
+ The real room was never in the strip itself — it was in the REST of the row.
4360
+ EntityRow is `title (+ titleIcon/meta)` above `metrics (+ accessory)` beside
4361
+ `action`, with a drag grip down the side: at desktop width that two-line-plus-rail
4362
+ shape is what lets metrics and a school's name and its preference-meter accessory
4363
+ and its +/- action all fit on a compact row. At a stacked phone pane that shape is
4364
+ the problem — cramming metrics onto the SAME line as an accessory (media-planner's
4365
+ TransferList rows carry a ScoreMeter accessory) leaves the strip a fraction of the
4366
+ row's own width even though the row has plenty of width overall.
4367
+
4368
+ So below this width the row becomes a two-row GRID instead: name (+ its icon/meta)
4369
+ with the accessory and the +/- action all on row one, and the metric strip ALONE
4370
+ spanning the full row width on row two — the same width `.fd-tlist-footer`'s totals
4371
+ line gets (see below), which is what keeps the two aligned. `.fd-erow-body` and
4372
+ `.fd-erow-strip` contribute no box of their own any more here (`display: contents`
4373
+ unwraps them, MDN's own documented way to let a grid reach through a wrapper
4374
+ without changing the component's DOM/JSX) — every element that actually needs a
4375
+ grid position (title line, grip, accessory, metrics, action) becomes a direct
4376
+ grid child by that unwrapping alone. `grid-template-areas` uses one row with no
4377
+ "strip" cell in it for a plain row that has neither metrics nor an accessory (an
4378
+ unfilled `auto` grid row is 0-height), so a name-only row still stays one line
4379
+ tall exactly as `.fd-erow-body`'s own base-rule comment describes.
4380
+
4381
+ Even spanning the full row, three columns this wide (media-planner: 96/82/92px)
4382
+ can still be tight once the row also loses width to its drag grip and a 44px
4383
+ touch-target action button — so `--erow-metric-w` itself also shrinks by a flat,
4384
+ modest 15% here, identically for a row's own cells and the totals footer's (both
4385
+ read the SAME custom property, so both shrink the same and stay aligned). 15% is a
4386
+ deliberate buffer, not a measured minimum: it keeps real figures (media-planner's
4387
+ own test data reaches "958,000") comfortably clear of `.fd-erow-metric-value`'s
4388
+ own `text-overflow: ellipsis` floor rather than sizing to the exact edge of it. */
4389
+ .fd-erow {
4390
+ display: grid;
4391
+ grid-template-columns: auto minmax(0, 1fr) auto auto;
4392
+ grid-template-areas:
4393
+ "grip title accessory action"
4394
+ "strip strip strip strip";
4395
+ gap: 4px 10px;
4396
+ }
4397
+ .fd-erow-body,
4398
+ .fd-erow-strip {
4399
+ display: contents;
4400
+ }
4401
+ .fd-erow-grip {
4402
+ grid-area: grip;
4403
+ }
4404
+ .fd-erow-titleline {
4405
+ grid-area: title;
4406
+ }
4407
+ .fd-erow-accessory {
4408
+ grid-area: accessory;
4409
+ }
4410
+ .fd-erow-action {
4411
+ grid-area: action;
4412
+ }
4280
4413
  .fd-erow-cell {
4281
- width: auto;
4414
+ flex-shrink: 0;
4415
+ width: calc(var(--erow-metric-w) * 0.85);
4282
4416
  }
4283
4417
  .fd-erow-metrics {
4418
+ /* Row context (.fd-erow is the grid above): claims the whole second grid row.
4419
+ Footer context (.fd-tlist-footer is a plain flex row, see below): `grid-area`
4420
+ is a no-op there since its parent isn't a grid, and `flex: 1 1 100%` is what
4421
+ does the equivalent job — combined with that flex row's own `flex-wrap: wrap`,
4422
+ claiming the full line pushes the "Totals · N schools" caption after it onto
4423
+ a second line, the same shape the row now has. Only one of the two rules ever
4424
+ actually applies in a given parent, so both can live on this one selector. */
4425
+ grid-area: strip;
4426
+ flex: 1 1 100%;
4427
+ /* Belt-and-suspenders, not the primary mechanism any more: if some OTHER
4428
+ consumer's columns still don't fit even the whole row's width after the 15%
4429
+ reduction above, this scrolls that overflow rather than clipping it (the same
4430
+ "wide content gets its own scroll container" rule DataTable's `.fd-table-wrap`
4431
+ follows, and the layout auditor already treats an `overflow: auto` ancestor as
4432
+ fine by design) — never reached by media-planner's own audience columns, which
4433
+ the full-width row and the 15% reduction together already fit. */
4434
+ overflow-x: auto;
4435
+ overflow-y: hidden;
4436
+ }
4437
+ .fd-tlist-footer {
4284
4438
  flex-wrap: wrap;
4285
- overflow: visible;
4286
4439
  }
4287
4440
  }
4288
4441
  .fd-tlist-side {
package/styles/tokens.css CHANGED
@@ -100,6 +100,20 @@
100
100
  --btn-solid-ok-bg:#1E7A4C;--btn-solid-ok-bg-hover:#18663F;--btn-solid-ok-bg-active:#145A38;--btn-solid-ok-ink:#FFFFFF;
101
101
  --btn-solid-danger-bg:#B93A31;--btn-solid-danger-bg-hover:#9E2F27;--btn-solid-danger-bg-active:#862720;--btn-solid-danger-ink:#FFFFFF;
102
102
 
103
+ /* Soft icon button (IconButton variant="soft") — MP-52's "lighter fill, darker border"
104
+ row action. A lighter, less saturated fill than --btn-solid-* with a visibly darker
105
+ border drawn around it, so the button still reads as a button rather than a solid
106
+ colour chip. Measured exactly like --btn-solid-* above, against the same two grounds
107
+ (--surface-2 #F7F8FA and --erow-danger-fill #FCE9E6): white ink on the fill is 4.53:1
108
+ or better and the fill itself is 3.87:1 or better against either ground. Going any
109
+ lighter breaks one of those two floors — a fill light enough to read as "soft" in the
110
+ usual badge sense (e.g. --ok-fill/--danger-fill) is only ~1.05:1 from --erow-danger-fill
111
+ and fails outright; this is the lightest fill that still clears the bar next to a red
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;
116
+
103
117
  --ok-fill:#DFF3E8;--ok-border:#A8DDC2;--ok-text:#0E5233;--ok-solid:#34A26B;--ok-emph:#57C68C;
104
118
  --warn-fill:#FDF1DA;--warn-border:#F0D49A;--warn-text:#6B4A05;--warn-solid:#C8890B;
105
119
  --danger-fill:#FCE7E5;--danger-border:#F2BDB8;--danger-text:#7A241D;--danger-solid:#D0473D;
@@ -256,6 +270,19 @@
256
270
  --btn-solid-ok-bg:#3FB37A;--btn-solid-ok-bg-hover:#57C68C;--btn-solid-ok-bg-active:#35A26D;--btn-solid-ok-ink:#0B2A1B;
257
271
  --btn-solid-danger-bg:#E8776D;--btn-solid-danger-bg-hover:#F08A80;--btn-solid-danger-bg-active:#D9685E;--btn-solid-danger-ink:#2A0B08;
258
272
 
273
+ /* Soft icon button — see the :root block above. On dark ground the direction flips the
274
+ same way --btn-solid-* already does: a lighter fill cannot separate from a near-black
275
+ card by luminance, so the soft fill goes DARKER and saturated (not lighter, the way
276
+ light theme reads "lighter") with a light ink and a lighter border drawn around it —
277
+ the same "still a button, one step down from --btn-solid-*" relationship, expressed in
278
+ whichever direction actually clears the floor on this ground. Measured against
279
+ --surface-2 (#1B1F27) and --erow-danger-fill (#331813): white ink is 5.4:1 or better,
280
+ the fill is 3.0:1 or better against either ground, and the border (the theme's own
281
+ --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;
285
+
259
286
  /* chat kit — see the :root block above */
260
287
  --chat-code-bg:#12151B;
261
288
  --code-kw:#B3A6F0;--code-str:#E9C377;--code-num:#EFA8BE;--code-com:#6C7686;