@redseed/redseed-ui-tailwindcss 7.61.0 → 7.64.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.
@@ -153,6 +153,82 @@
153
153
  @apply absolute inset-0 size-full pointer-events-none rounded-xl border-border-secondary;
154
154
  }
155
155
 
156
+ /* ── Category accent ──────────────────────────────────────────────────────────
157
+ A colour-coded edge for TAXONOMY, which the semantic variants above cannot
158
+ express: they say what state a card is in, not which category it belongs to.
159
+
160
+ Two deliberate choices:
161
+
162
+ 1. It is a BORDER, not a pseudo-element. The card's ::before is already the
163
+ hover scrim and its ::after is free, but a border is what actually delivers
164
+ the behaviour the API promises — "the accent replaces that edge's border
165
+ rather than sitting alongside it". A border on that edge IS that edge's
166
+ border, so there is no double rule to suppress, it composes with `bordered`
167
+ for free (unbordered cards have 0-width edges, so only the accent paints),
168
+ and the content inset comes along with it instead of needing separate
169
+ padding. It also stays clear of the hover scrim and the action layer, both
170
+ of which are `absolute inset-0` and therefore resolve against the PADDING
171
+ box — so neither tints nor covers the accent.
172
+
173
+ 2. Thickness is a token. On the ARC insights page the same "this card belongs
174
+ to domain X" idea was hand-rolled twice in one sitting at 4px and 3px,
175
+ because nothing told the author what the weight should be. 4px — the
176
+ heavier of the two — so the bar still reads as a category marker against
177
+ the 1px hairline on the card's other three edges.
178
+
179
+ These rules are (0,2,0) and sit AFTER the variant border rules on purpose.
180
+ `.rsui-card--bordered.rsui-card--draft` zeroes every border width and
181
+ `.rsui-card--bordered.rsui-card--ai-bold` makes every border colour
182
+ transparent, both at the same specificity; landing later lets the accent edge
183
+ survive on those two variants rather than being silently swallowed.
184
+
185
+ `left` maps to the INLINE-START edge, not the physical left, matching the
186
+ logical `padding-inline` this stylesheet already uses. The accent marks the
187
+ leading edge of the card, so it should follow writing direction. */
188
+ .rsui-card {
189
+ /* Neutral when the consumer supplies no `color`, so an accent edge is never
190
+ invisible. Same fallback token as Pill's resting accent. */
191
+ --rsui-card-accent: var(--color-background-secondary-contrast);
192
+
193
+ --rsui-card-accent-w: 0.25rem; /* space-xxs, 4px */
194
+ }
195
+
196
+ .rsui-card.rsui-card--accent-left {
197
+ border-inline-start-style: solid;
198
+ border-inline-start-width: var(--rsui-card-accent-w);
199
+ border-inline-start-color: var(--rsui-card-accent);
200
+ }
201
+
202
+ .rsui-card.rsui-card--accent-top {
203
+ border-block-start-style: solid;
204
+ border-block-start-width: var(--rsui-card-accent-w);
205
+ border-block-start-color: var(--rsui-card-accent);
206
+ }
207
+
208
+ /* Hold the accent clear of the action layer's ring.
209
+
210
+ The hover scrim and the action layer are both `absolute inset-0`, so they stop
211
+ at the padding box and cannot reach the border — but a RING is not bounded by
212
+ its element. `ring-2 ring-offset-2` paints `0 0 0 2px` of offset colour and
213
+ then `0 0 0 4px` of ring colour OUTWARD from the layer's border box, and a
214
+ child's box-shadow paints above its parent's border. Measured against this
215
+ accent that is a 4px band landing exactly on a 4px edge, so a `pressed` or
216
+ `current` card — or merely a focused one, since focus-visible uses the same
217
+ geometry — lost its category colour entirely at the moment it mattered most.
218
+
219
+ Pulling the layer in by the accent width on that edge puts the ring's outer
220
+ limit at the padding box, where the accent begins. Both then render: ring
221
+ around the content, accent around the card. Only the accented edge moves, so
222
+ every other card keeps the ring exactly where it was, and the 4px of click
223
+ area given up sits under a decorative bar. */
224
+ .rsui-card--accent-left .rsui-card__action-layer {
225
+ inset-inline-start: var(--rsui-card-accent-w);
226
+ }
227
+
228
+ .rsui-card--accent-top .rsui-card__action-layer {
229
+ inset-block-start: var(--rsui-card-accent-w);
230
+ }
231
+
156
232
  /* Prevent table row hover background from bleeding past card rounded corners.
157
233
  Opt out while a dropdown menu is open inside the card — otherwise the menu
158
234
  gets clipped by the card's overflow boundary. */
@@ -263,8 +339,17 @@
263
339
  @apply flex-1 flex flex-col relative gap-y-space-md;
264
340
  }
265
341
 
342
+ /* No min-height. This carried a 64px floor from the original SFC-to-Tailwind migration,
343
+ and it was quietly setting the height of every compact card rather than protecting
344
+ anything: measured across all 108 docs pages, the ONLY cards it changed were
345
+ CheckboxCards — 8px of dead space on a body holding one row of meta (56px natural,
346
+ floored to 64), and 24px on a body holding nothing at all.
347
+
348
+ A card should be as tall as what is in it. A floor here also hides the real bug when a
349
+ body renders empty, which is that it should not have rendered — see CheckboxCard's
350
+ headerOnlyCard. */
266
351
  .rsui-card__content--padded {
267
- @apply py-space-lg min-h-16;
352
+ @apply py-space-lg;
268
353
  }
269
354
 
270
355
  /* The space between the header block and the body is an INTERNAL gap, so it takes the
@@ -74,6 +74,29 @@
74
74
  .rsui-checkbox-card__badge {
75
75
  @apply flex gap-space-xs;
76
76
  }
77
+ /* ── The task title steps DOWN off Header 4 ─────────────────────────────────────────
78
+ The card family's title is Header 4 (20px semibold) and stays there. A task row is
79
+ not that shape: it is a list item, and at 20px semibold it was the same size as the
80
+ title of the card CONTAINING the list, so a task and the panel holding it carried
81
+ equal weight.
82
+
83
+ 16px is the next step on the brand scale (16 / 20 / 28 / 40 / 64) and the last one
84
+ before the body floor — there is nothing below it. It is also exactly what Material
85
+ 3 specifies for a list-item headline, and what M3 gives a card's Title Medium; the
86
+ card family only sits above it because a 16px title would collapse into the 16px
87
+ body beneath it. A task card has no body text to collapse into, so the reason for
88
+ the step up does not apply here.
89
+
90
+ The title still leads: semibold against a 12px medium-weight label, in primary ink
91
+ against tertiary.
92
+
93
+ Set on __title rather than __title-text so the whole line box comes down with it —
94
+ at 24px the box now matches the checkbox's own 24px exactly, so the control and the
95
+ text are one row rather than a control with text beside it. */
96
+ .rsui-checkbox-card .rsui-card-header__title {
97
+ @apply text-base leading-6;
98
+ }
99
+
77
100
  .rsui-checkbox-card__title-text--strikethrough {
78
101
  @apply line-through;
79
102
  }
@@ -23,8 +23,63 @@
23
23
  @apply flex gap-x-space-xs items-center;
24
24
  }
25
25
 
26
+ /* ── The label icon is a DECORATION OF THE LABEL, so it may never be bigger than the
27
+ line it sits on ───────────────────────────────────────────────────────────────────
28
+ It had no size rule at all, so it rendered at whatever the consumer's SVG brought
29
+ with it. Measured on the CustomLabelIcon story: a 20px icon against a 12px label
30
+ with a 16px line box. Three things wrong with that, all visible:
31
+
32
+ - the icon was 25% taller than the field's own line, so it — not the type — set
33
+ the row height, and the label sat off the field's rhythm
34
+ - at 20px against 12px type the icon read as a control rather than as part of the
35
+ label, which is why a bare pin or calendar in a card's meta looks like a second
36
+ column of buttons next to the checkbox
37
+ - it inherited near-black `text-primary` while the label it decorates is grey
38
+ `text-tertiary` — so the decoration was emphasised OVER the thing it decorates.
39
+ Exactly the hierarchy inversion the label/value rule below already fixed once.
40
+
41
+ The size is therefore pinned to the line box of the step it is in: 16/20/24px for
42
+ sm/md/lg, matching text-xs/sm/base's line-height exactly. An icon that is exactly one
43
+ line box tall can never change the row's height.
44
+
45
+ This deliberately overrides a size the consumer put on `<Icon>`. Every usage in the
46
+ library wraps the icon that way, and letting each caller pick meant the meta row's
47
+ height depended on the call site. Same call `.rsui-card-header__avatar` makes by
48
+ fixing its own width. Reach past `<Icon>`'s wrapper to the svg so a raw heroicon —
49
+ which is what a consumer reaches for first — works too, instead of collapsing to 0x0. */
26
50
  .rsui-meta-info__label-icon {
27
- @apply flex items-center justify-center;
51
+ @apply flex items-center justify-center shrink-0;
52
+ @apply text-text-tertiary;
53
+ }
54
+
55
+ .rsui-meta-info__label-icon svg {
56
+ @apply size-full;
57
+ }
58
+
59
+ /* Colour, for the DEFAULT icon only. Setting `text-text-tertiary` on the box above is
60
+ enough for a raw svg, which inherits — but `<Icon>` paints its child directly
61
+ (`.rsui-icon--primary > * { color }`), and a declaration always beats an inherited
62
+ value however specific the ancestor. IconSlot falls back to `primary` when the
63
+ consumer names no colour, so the near-black was the DEFAULT, not a choice.
64
+
65
+ Scoped to --primary on purpose. `<Icon success>` or `<Icon warning>` on a meta label
66
+ is intent — a status marker — and keeps its colour; only the unchosen default is
67
+ pulled back to match the label it decorates. */
68
+ .rsui-meta-info__label-icon .rsui-icon--primary > * {
69
+ @apply text-text-tertiary;
70
+ }
71
+
72
+ /* ── An avatar in the VALUE is content, not decoration ───────────────────────────────
73
+ So the opposite rule applies: it is allowed to set the row's height, because it is
74
+ part of what the field is saying rather than a marker on the label. "Connected to
75
+ (R) Riley" is a person, and a 16px sliver of a face is not one.
76
+
77
+ `.rsui-avatar-circle` is `w-full h-full` — AvatarText fills whatever box it is given
78
+ and has no size of its own, so without this it collapses in the value's flex row.
79
+ The initials scale with the circle; at these sizes they are a single character. */
80
+ .rsui-meta-info__value .rsui-avatar-circle,
81
+ .rsui-meta-info__value > img {
82
+ @apply shrink-0 rounded-full object-cover;
28
83
  }
29
84
 
30
85
  /* The label is the descriptor, so it recedes: medium weight in the tertiary tone. It used to
@@ -77,6 +132,35 @@
77
132
  @apply text-base;
78
133
  }
79
134
 
135
+ /* Icon = exactly one line box of its step (text-xs/sm/base are 16/20/24px), so it
136
+ never inflates the row. Avatar = one step larger, because it carries content. */
137
+ .rsui-meta-info--sm .rsui-meta-info__label-icon {
138
+ @apply size-4;
139
+ }
140
+
141
+ .rsui-meta-info--md .rsui-meta-info__label-icon {
142
+ @apply size-5;
143
+ }
144
+
145
+ .rsui-meta-info--lg .rsui-meta-info__label-icon {
146
+ @apply size-6;
147
+ }
148
+
149
+ .rsui-meta-info--sm .rsui-meta-info__value .rsui-avatar-circle,
150
+ .rsui-meta-info--sm .rsui-meta-info__value > img {
151
+ @apply size-5 text-[0.625rem];
152
+ }
153
+
154
+ .rsui-meta-info--md .rsui-meta-info__value .rsui-avatar-circle,
155
+ .rsui-meta-info--md .rsui-meta-info__value > img {
156
+ @apply size-6 text-xs;
157
+ }
158
+
159
+ .rsui-meta-info--lg .rsui-meta-info__value .rsui-avatar-circle,
160
+ .rsui-meta-info--lg .rsui-meta-info__value > img {
161
+ @apply size-7 text-sm;
162
+ }
163
+
80
164
  .rsui-meta-info--inline {
81
165
  @apply flex-row flex-wrap items-center gap-x-space-xs gap-y-space-xs;
82
166
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redseed/redseed-ui-tailwindcss",
3
- "version": "7.61.0",
3
+ "version": "7.64.0",
4
4
  "description": "RedSeed UI Tailwindcss",
5
5
  "main": "index.js",
6
6
  "style": "index.css",