@livelayer/react 0.9.7 → 0.10.1

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/styles.css CHANGED
@@ -114,6 +114,33 @@
114
114
  }
115
115
  /* "custom" position relies on consumer-supplied style. */
116
116
 
117
+ /* Floating chrome (HiddenLayout / MinimizedLayout) — portaled to
118
+ document.body so its fixed-position chrome anchors to the viewport
119
+ regardless of where the package is rendered in the host's DOM tree.
120
+ Without this, EMBEDDED hosts that wrap the slot in a transformed
121
+ ancestor (translateZ, scale, etc.) capture the fixed chrome and
122
+ pin it to the slot rather than the viewport edge — that's what
123
+ made the side-tab and audio-waveform pill unreachable in EMBEDDED
124
+ pre-0.10.0. The .ll-widget base rules above apply unchanged.
125
+
126
+ The position rules INSIDE this container (HiddenLayout's
127
+ `position: fixed` on the side-tab) follow normal containing-block
128
+ rules: when the consumer scopes the portal to a specific element
129
+ via `floatingChromeContainer` (a fork-demo card, for example),
130
+ that element's `position: relative` becomes the containing block
131
+ if the chrome's positioning is `absolute` rather than `fixed`. We
132
+ leave HiddenLayout / MinimizedLayout's existing `position: fixed`
133
+ alone — consumers who pass a scoped container should mark it with
134
+ `transform: translateZ(0)` so `position: fixed` descendants
135
+ capture to the container instead of the viewport. */
136
+ .ll-widget--floating {
137
+ position: fixed;
138
+ pointer-events: none;
139
+ }
140
+ .ll-widget--floating > * {
141
+ pointer-events: auto;
142
+ }
143
+
117
144
  /* Mobile: minimized + expanded ignore position, always full-width bottom. */
118
145
  .ll-widget--mobile.ll-widget--minimized,
119
146
  .ll-widget--mobile.ll-widget--expanded {
@@ -170,6 +197,23 @@
170
197
  box-shadow: none;
171
198
  }
172
199
 
200
+ /* When an EMBEDDED widget is in hidden/minimized state, the main
201
+ container inside the host slot is empty (HiddenLayout /
202
+ MinimizedLayout are portaled to document.body). Fade the empty
203
+ container so a transitioning host slot doesn't expose blank space
204
+ in the cinematic moment. The 0.25s opacity matches the floating
205
+ chrome's mount fade for a coordinated handoff. */
206
+ .ll-widget[data-experience-mode="embedded"][data-display-mode="expanded"] {
207
+ opacity: 1;
208
+ transition: opacity 0.25s ease;
209
+ }
210
+ .ll-widget[data-experience-mode="embedded"][data-display-mode="hidden"],
211
+ .ll-widget[data-experience-mode="embedded"][data-display-mode="minimized"] {
212
+ opacity: 0;
213
+ pointer-events: none;
214
+ transition: opacity 0.25s ease;
215
+ }
216
+
173
217
  /* ── Hidden mode: edge chevron tab ────────────────────────────────── */
174
218
  /* Solid-black tab docked to the screen edge with a white chevron.
175
219
  Designed to be unmistakably visible on light AND dark pages — no
@@ -1007,19 +1051,22 @@
1007
1051
  }
1008
1052
 
1009
1053
  /* Captions affordance for deaf-friendly UX: when the latest transcript
1010
- line is the AGENT's spoken output, tint the pill ORANGE so it reads
1011
- unambiguously as "this text is coming from Live Layer." The user's
1012
- STT pill keeps default dark styling so the two voices contrast
1013
- immediately at a glance. Previous opacity (0.18) was so faint
1014
- testers couldn't tell the agent line was differentiated at all —
1015
- now the pill is brand-orange, with a saturated glow + warm white
1016
- text on the colored background. */
1054
+ line is the AGENT's spoken output, render the pill in fully-saturated
1055
+ brand orange with crisp white text. The user's STT pill keeps the
1056
+ default dark styling so the two voices contrast immediately at a
1057
+ glance. Pre-0.10.1 the orange was rendered as a soft tint over a
1058
+ semi-transparent black backdrop, which compressed the color into
1059
+ a muddy brown the user couldn't see "the agent is talking" at
1060
+ all. Now: solid #e06540 background, white 500-weight text, no
1061
+ blur (removed the dark backdrop-filter that was washing it out). */
1017
1062
  .ll-expanded__transcript--agent {
1018
- background: rgba(224, 101, 64, 0.85);
1019
- border-color: rgba(255, 175, 110, 0.6);
1063
+ background: #e06540;
1064
+ border-color: rgba(255, 200, 160, 0.55);
1065
+ -webkit-backdrop-filter: none;
1066
+ backdrop-filter: none;
1020
1067
  box-shadow:
1021
- 0 0 24px rgba(224, 101, 64, 0.4),
1022
- inset 0 0 0 1px rgba(255, 200, 160, 0.25);
1068
+ 0 0 28px rgba(224, 101, 64, 0.5),
1069
+ inset 0 0 0 1px rgba(255, 215, 180, 0.3);
1023
1070
  }
1024
1071
 
1025
1072
  .ll-expanded__transcript--agent .ll-expanded__transcript-text {
@@ -1051,8 +1098,13 @@
1051
1098
  display: flex;
1052
1099
  align-items: center;
1053
1100
  justify-content: center;
1054
- gap: 4px;
1055
- flex-wrap: wrap;
1101
+ gap: 2px;
1102
+ /* Toolbar must stay on one line. Wrapping produces a "4 buttons +
1103
+ red end-call below" layout in narrow slots (280px-wide marketing
1104
+ dock) — visually broken. Tight gap + slim split paddings below
1105
+ fit screen / camera-split / mic-split / speaker / end-call in
1106
+ ~250px of usable width. */
1107
+ flex-wrap: nowrap;
1056
1108
  }
1057
1109
 
1058
1110
  .ll-tool {
@@ -1131,14 +1183,14 @@
1131
1183
  }
1132
1184
 
1133
1185
  .ll-tool-split .ll-tool--left {
1134
- padding-left: 14px;
1135
- padding-right: 4px;
1186
+ padding-left: 10px;
1187
+ padding-right: 2px;
1136
1188
  width: auto;
1137
1189
  }
1138
1190
 
1139
1191
  .ll-tool-split .ll-tool--right {
1140
- padding-left: 4px;
1141
- padding-right: 10px;
1192
+ padding-left: 2px;
1193
+ padding-right: 8px;
1142
1194
  width: auto;
1143
1195
  color: rgba(255, 255, 255, 0.7);
1144
1196
  }
@@ -1156,6 +1208,14 @@
1156
1208
  /* ── Device selection menu (mic / camera) ───────────────── */
1157
1209
 
1158
1210
  .ll-device-menu {
1211
+ /* Default = absolute (used inline within toolbar split). The
1212
+ ll-device-menu--floating modifier below overrides for the
1213
+ portaled variant rendered to document.body. The inline form
1214
+ was getting clipped by .ll-tool-split's overflow:hidden, which
1215
+ is why chevron clicks looked like no-ops — that's why
1216
+ ExpandedLayout now portals the menu by default. Keep the inline
1217
+ styles for backwards compatibility with consumers calling
1218
+ DeviceMenu directly. */
1159
1219
  position: absolute;
1160
1220
  bottom: calc(100% + 8px);
1161
1221
  left: 50%;
@@ -1174,6 +1234,18 @@
1174
1234
  gap: 2px;
1175
1235
  }
1176
1236
 
1237
+ /* Portaled variant: rendered to document.body so it escapes any
1238
+ ancestor overflow:hidden / transform context. Position is set
1239
+ inline via getBoundingClientRect; reset the static defaults so
1240
+ they don't fight the inline styles. z-index matches the rest of
1241
+ the floating chrome (max-int) so we win over consumer overlays. */
1242
+ .ll-device-menu--floating {
1243
+ position: fixed;
1244
+ bottom: auto;
1245
+ left: auto;
1246
+ z-index: 2147483647;
1247
+ }
1248
+
1177
1249
  .ll-device-menu__label {
1178
1250
  margin: 0;
1179
1251
  padding: 6px 10px 4px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livelayer/react",
3
- "version": "0.9.7",
3
+ "version": "0.10.1",
4
4
  "description": "LiveLayer agent widget for React — avatar video, team switching, responsive layouts, full-fidelity embed",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",