@linktr.ee/messaging-react 3.31.1 → 3.31.2-rc-1785926144

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.
Files changed (33) hide show
  1. package/dist/{Card-EWN07XIl.cjs → Card-CF1TZXD5.cjs} +2 -2
  2. package/dist/{Card-EWN07XIl.cjs.map → Card-CF1TZXD5.cjs.map} +1 -1
  3. package/dist/{Card-CmlaSw7i.js → Card-Ch6N2pkc.js} +2 -2
  4. package/dist/{Card-CmlaSw7i.js.map → Card-Ch6N2pkc.js.map} +1 -1
  5. package/dist/assets/index.css +1 -1
  6. package/dist/index-BKkCNnea.js +5677 -0
  7. package/dist/index-BKkCNnea.js.map +1 -0
  8. package/dist/index-Ct_Jgy8P.cjs +2 -0
  9. package/dist/index-Ct_Jgy8P.cjs.map +1 -0
  10. package/dist/index.cjs +1 -1
  11. package/dist/index.d.ts +6 -5
  12. package/dist/index.js +1 -1
  13. package/package.json +3 -5
  14. package/src/components/LinkAttachment/LinkAttachment.stories.tsx +44 -27
  15. package/src/components/LinkAttachment/LinkAttachment.test.tsx +47 -39
  16. package/src/components/LinkAttachment/components/Composer/Card.tsx +1 -1
  17. package/src/components/LinkAttachment/components/Received/Card.tsx +2 -2
  18. package/src/components/LinkAttachment/components/Sent/Card.tsx +2 -2
  19. package/src/components/LinkAttachment/components/_shared/BubbleTail.tsx +16 -6
  20. package/src/components/LinkAttachment/components/_shared/CardBody.tsx +4 -5
  21. package/src/components/LinkAttachment/components/_shared/CardShell.tsx +22 -9
  22. package/src/components/LinkAttachment/components/_shared/hex.ts +7 -7
  23. package/src/components/LinkAttachment/components/_shared/useChinPalette.ts +36 -27
  24. package/src/components/LinkAttachment/types.ts +6 -5
  25. package/src/styles.css +39 -0
  26. package/dist/index-CN3errpB.js +0 -7828
  27. package/dist/index-CN3errpB.js.map +0 -1
  28. package/dist/index-CcitzVoW.cjs +0 -5
  29. package/dist/index-CcitzVoW.cjs.map +0 -1
  30. package/src/components/LinkAttachment/components/_shared/accentSurface.test.ts +0 -135
  31. package/src/components/LinkAttachment/components/_shared/accentSurface.ts +0 -95
  32. package/src/components/LinkAttachment/components/_shared/chinContrast.test.ts +0 -95
  33. package/src/components/LinkAttachment/components/_shared/chinContrast.ts +0 -79
@@ -5,10 +5,19 @@ import React from 'react'
5
5
 
6
6
  import type { LinkAttachmentLayout, LinkAttachmentStatus } from '../../types'
7
7
 
8
- import { accentSurface } from './accentSurface'
9
8
  import type { LinkAttachmentVariant } from './CardShell'
10
- import { AUDIO_BG, isPlayableAudio } from './CardThumbnail'
11
- import { BUBBLE_BG_BY_VARIANT, inkFor } from './chinContrast'
9
+ import { isPlayableAudio } from './CardThumbnail'
10
+ import { HEX_PATTERN, toCssHex } from './hex'
11
+
12
+ /** White on the dark stop, near-black on the light stop and the audio strip. */
13
+ const INK_ON_DARK = '#FFFFFF'
14
+ /** The near-black used across the Figma frames. */
15
+ const INK_ON_LIGHT = '#040403'
16
+
17
+ const INK_BY_VARIANT: Record<LinkAttachmentVariant, string> = {
18
+ dark: INK_ON_DARK,
19
+ light: INK_ON_LIGHT,
20
+ }
12
21
 
13
22
  export interface ChinPaletteInput {
14
23
  variant: LinkAttachmentVariant
@@ -31,21 +40,17 @@ export interface ChinPalette {
31
40
  */
32
41
  thumbnailUrl?: string
33
42
  /**
34
- * Inline background for the card shell, or `undefined` to keep the variant's
35
- * own `bg-*` class.
36
- */
37
- accentStyle?: React.CSSProperties
38
- /**
39
- * Ink for both chin lines, chosen against the surface the card actually
40
- * paints — the derived accent, the audio strip, or the fallback fill. Always
41
- * defined for a parseable surface.
43
+ * Raw extracted colour to publish as the `--accent` custom property on the
44
+ * shell and the tail, or `undefined` when there is no paintable accent. The
45
+ * hue-preserving lightness swap is done in CSS (`styles.css`) — see MES-1412.
42
46
  */
43
- chinTextColor?: string
47
+ accentHex?: string
44
48
  /**
45
- * Colour the bubble tail paints in, always defined: the accent when one is
46
- * paintable, otherwise this side's plain bubble fill.
49
+ * Ink for both chin lines: white on the sender's dark stop, near-black on the
50
+ * receiver's pale stop and on the audio strip. Fixed per surface, so no
51
+ * runtime contrast measurement is needed (the stops clear AA by construction).
47
52
  */
48
- tailColor: string
53
+ chinTextColor: string
49
54
  /** True while the card renders as a skeleton. */
50
55
  isLoading: boolean
51
56
  /** Hand to `CardThumbnail` so a broken hero drops the accent with it. */
@@ -114,23 +119,27 @@ export function useChinPalette({
114
119
  const isAudio = isPlayableAudio(mimeType, sourceUrl)
115
120
  const hasHero =
116
121
  layout === 'featured' && !!thumbnailUrl && !isAudio && !heroFailed
117
- const surface =
118
- hasHero && status === 'ready'
119
- ? accentSurface(accentColor, variant)
122
+ const canDerive = hasHero && status === 'ready'
123
+ // Only a validated hex is published: `accent_color` is always a hex from the
124
+ // extractor, and CSS would resolve any colour name — narrowing keeps the input
125
+ // contract the same one the old `accentSurface` enforced. The bare-hex case is
126
+ // supported because the extractor omits the `#` often enough that dropping it
127
+ // would silently lose the colour (MES-1349).
128
+ const accentHex =
129
+ canDerive && accentColor != null && HEX_PATTERN.test(accentColor.trim())
130
+ ? toCssHex(accentColor)
120
131
  : undefined
121
132
 
122
- // Whatever the card ends up painted with, legible or not, the ink is chosen
123
- // against it. The accent is derived to suit this side's ink, but the audio
124
- // strip and the fallback fill are imposed and cannot be refused — a sent
125
- // audio card put white ink on `AUDIO_BG`'s near-white at 1.13:1 (MES-1388).
126
- const painted =
127
- surface ?? (isAudio ? AUDIO_BG : BUBBLE_BG_BY_VARIANT[variant])
133
+ // The accent surface and the sender's dark fallback both take white ink; the
134
+ // pale receiver fallback and the imposed audio strip both take near-black. So
135
+ // the ink is fixed per surface and needs no runtime contrast — a sent audio
136
+ // card put white ink on the strip's near-white at 1.13:1 before (MES-1388).
137
+ const chinTextColor = isAudio ? INK_ON_LIGHT : INK_BY_VARIANT[variant]
128
138
 
129
139
  return {
130
140
  thumbnailUrl: heroFailed ? undefined : thumbnailUrl,
131
- accentStyle: surface ? { backgroundColor: surface } : undefined,
132
- chinTextColor: inkFor(painted),
133
- tailColor: painted,
141
+ accentHex,
142
+ chinTextColor,
134
143
  isLoading: status === 'loading',
135
144
  onImageError,
136
145
  }
@@ -77,16 +77,17 @@ export interface LinkAttachmentBaseProps {
77
77
  /**
78
78
  * Dominant colour extracted from `thumbnailUrl`, as a hex string
79
79
  * (`#RRGGBB` or `#RGB`). Paints the card and — when the card is the last
80
- * bubble in a same-author run — its tail. The card derives its own chin
81
- * text colour from this value for WCAG AA contrast; callers never pass a
80
+ * bubble in a same-author run — its tail. Its hue is kept while the lightness
81
+ * is swapped to a fixed per-side stop (`oklch(from …)` in `styles.css`); the
82
+ * stops clear WCAG AA at every hue by construction, so callers never pass a
82
83
  * text colour.
83
84
  *
84
85
  * Only painted while the hero image it was extracted from is actually on
85
86
  * screen. Omitted, unparseable, `layout: 'classic'`, no `thumbnailUrl`,
86
87
  * `status` other than `'ready'`, a playable-audio `mimeType` + `sourceUrl`
87
- * (whose hero is the native player rather than an image), or a hero that
88
- * fails to load, or the colour cannot clear AA against this side's ink =>
89
- * the card falls back to `BUBBLE_BG_BY_VARIANT[variant]`, the plain bubble fill.
88
+ * (whose hero is the native player rather than an image), or a hero that fails
89
+ * to load => the card keeps the plain bubble fill. Browsers without
90
+ * relative-colour-syntax support also keep that fill (progressive enhancement).
90
91
  */
91
92
  accentColor?: string
92
93
 
package/src/styles.css CHANGED
@@ -1101,6 +1101,26 @@
1101
1101
  }
1102
1102
  }
1103
1103
 
1104
+ /* Derived accent surface for `LinkAttachment` cards (MES-1412). React publishes
1105
+ the raw extracted colour as `--accent`; the hue-preserving lightness swap that
1106
+ used to run in JS (culori) runs natively via relative colour syntax. Only
1107
+ where the syntax resolves and an accent was published does the surface paint —
1108
+ every other browser keeps the plain bubble fill from the card's `bg-[…]` class
1109
+ (the same fallback the old JS guard degraded to). The `--surface-l` stops clear
1110
+ 4.5:1 against each side's ink at every hue by construction. */
1111
+ .messaging-link-card[data-variant='dark'] {
1112
+ --surface-l: 0.3;
1113
+ }
1114
+ .messaging-link-card[data-variant='light'] {
1115
+ --surface-l: 0.9;
1116
+ }
1117
+
1118
+ @supports (background: oklch(from red l c h)) {
1119
+ .messaging-link-card[style*='--accent'] {
1120
+ background: oklch(from var(--accent) var(--surface-l) c h);
1121
+ }
1122
+ }
1123
+
1104
1124
  /* Bubble tail for `LinkAttachment` cards (MES-1349). Same 20x23 geometry and
1105
1125
  mask path as the text-bubble tails above — the difference is that the fill
1106
1126
  arrives as an inline style, because it is a dominant colour extracted from
@@ -1135,6 +1155,25 @@
1135
1155
  transform-origin: center;
1136
1156
  }
1137
1157
 
1158
+ /* The tail paints outside the shell's box, so it can't inherit the shell's
1159
+ computed background — it runs the same derivation itself off its own
1160
+ `--accent`, and falls back to this side's plain bubble fill. Keep these fills
1161
+ in sync with the shell's `bg-[…]` classes and the `--str-chat` bubble vars. */
1162
+ .messaging-link-card-tail[data-variant='dark'] {
1163
+ --surface-l: 0.3;
1164
+ background-color: #1e2330;
1165
+ }
1166
+ .messaging-link-card-tail[data-variant='light'] {
1167
+ --surface-l: 0.9;
1168
+ background-color: #f1f0ee;
1169
+ }
1170
+
1171
+ @supports (background: oklch(from red l c h)) {
1172
+ .messaging-link-card-tail[style*='--accent'] {
1173
+ background-color: oklch(from var(--accent) var(--surface-l) c h);
1174
+ }
1175
+ }
1176
+
1138
1177
  /* Locked attachment wrapper: stack card + text bubble in the correct direction */
1139
1178
  .str-chat__li .str-chat__message--me .str-chat__message-bubble-wrapper {
1140
1179
  display: flex;