@leavepulse/ui 0.58.1 → 0.59.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.
Files changed (87) hide show
  1. package/dist/assets/{LpCommandPalette-DmQUsJqA.css → LpCommandPalette-BM_IyzwB.css} +21 -21
  2. package/dist/assets/{LpTable-BNzavdlv.css → LpTable-B_QCQCbB.css} +19 -19
  3. package/dist/chunks/{ContextMenuItems-BY5sTVQF.js → ContextMenuItems-CioDScj3.js} +1 -1
  4. package/dist/chunks/{LpAddressInput-Dio6Sqed.js → LpAddressInput-D-H94m4q.js} +1 -1
  5. package/dist/chunks/{LpAppShell-Be6T96td.js → LpAppShell-BeMuKEjh.js} +1 -1
  6. package/dist/chunks/{LpAvatar-BxNs23Xu.js → LpAvatar-CeW4Z5CL.js} +1 -1
  7. package/dist/chunks/{LpCard-DhR7u0d8.js → LpCard-Gbr8a1xK.js} +1 -1
  8. package/dist/chunks/{LpCodeBlock-CXsqJwDy.js → LpCodeBlock-D6zhp30a.js} +4 -4
  9. package/dist/chunks/{LpColorPicker-DQ88niXq.js → LpColorPicker-CVXwjEtX.js} +5 -5
  10. package/dist/chunks/{LpConfirmDialog-DxlSdjmk.js → LpConfirmDialog-DkgIT-Xg.js} +1 -1
  11. package/dist/chunks/{LpConfirmHost-BcrmTNu_.js → LpConfirmHost-CYzXWFOI.js} +1 -1
  12. package/dist/chunks/{LpContextMenu-B1NGfpp1.js → LpContextMenu-DRFd-iyc.js} +2 -2
  13. package/dist/chunks/{LpDrawer-DSknigxH.js → LpDrawer-Rc6eAJrr.js} +1 -1
  14. package/dist/chunks/{LpDropdownMenu-C7oHVlKY.js → LpDropdownMenu-BoJQsjzt.js} +2 -2
  15. package/dist/chunks/{LpFileTree-CMA0_rsB.js → LpFileTree-Bs57DhVa.js} +1 -1
  16. package/dist/chunks/{LpFileTreeNode-B4T258hF.js → LpFileTreeNode-XgJW65v5.js} +1 -1
  17. package/dist/chunks/{LpLogViewer-DwiYE32z.js → LpLogViewer-B92bAftG.js} +1 -1
  18. package/dist/chunks/{LpModal-BxYssnXg.js → LpModal-DvGD6kEe.js} +1 -1
  19. package/dist/chunks/{LpModalNav-Bn2ws64b.js → LpModalNav-B-_zRTS-.js} +2 -2
  20. package/dist/chunks/{LpNotificationBell-DJfs4JjQ.js → LpNotificationBell-63pvatBj.js} +3 -3
  21. package/dist/chunks/{LpPasswordInput-Bg5uTZbx.js → LpPasswordInput-BK25_vNG.js} +1 -1
  22. package/dist/chunks/{LpPhoneInput-DStwcbnQ.js → LpPhoneInput-Bxg7a_qD.js} +1 -1
  23. package/dist/chunks/{LpPie-DeTkbbOK.js → LpPie-Coa2GMHt.js} +2 -2
  24. package/dist/chunks/{LpSegmented-D3Eam8sa.js → LpSegmented-DbrUjuSA.js} +2 -2
  25. package/dist/chunks/{LpSidebar-CshW0fqC.js → LpSidebar-CKamWtPo.js} +2 -2
  26. package/dist/chunks/{LpSidebarNav-C9b3i9G2.js → LpSidebarNav-Y4LV0ZEn.js} +3 -3
  27. package/dist/chunks/{LpTabs-BBGRHY38.js → LpTabs-D01b8jBI.js} +6 -5
  28. package/dist/chunks/{LpThemeSwitcher-B_qhSl7q.js → LpThemeSwitcher-CbzL6ipO.js} +1 -1
  29. package/dist/chunks/{LpToaster-Bo9Q4QBP.js → LpToaster-C9EacEfR.js} +2 -2
  30. package/dist/chunks/{MenuTitle-DQP6hc2N.js → MenuTitle-B9HdaBwE.js} +2 -2
  31. package/dist/components/ContextMenuItems.vue.js +1 -1
  32. package/dist/components/LpAddressInput.vue.js +1 -1
  33. package/dist/components/LpAppShell.vue.js +1 -1
  34. package/dist/components/LpAvatar.vue.js +1 -1
  35. package/dist/components/LpCard.vue.js +1 -1
  36. package/dist/components/LpChart.vue.js +3 -3
  37. package/dist/components/LpCodeBlock.vue.js +1 -1
  38. package/dist/components/LpColorPicker.vue.js +1 -1
  39. package/dist/components/LpCommandPalette.vue.js +14 -14
  40. package/dist/components/LpConfirmDialog.vue.js +1 -1
  41. package/dist/components/LpConfirmHost.vue.js +1 -1
  42. package/dist/components/LpContextMenu.vue.js +1 -1
  43. package/dist/components/LpDrawer.vue.js +1 -1
  44. package/dist/components/LpDropdownMenu.vue.js +1 -1
  45. package/dist/components/LpFileTree.vue.js +1 -1
  46. package/dist/components/LpFileTreeNode.vue.js +1 -1
  47. package/dist/components/LpLogViewer.vue.js +1 -1
  48. package/dist/components/LpModal.vue.js +1 -1
  49. package/dist/components/LpModalNav.vue.js +1 -1
  50. package/dist/components/LpNotificationBell.vue.js +1 -1
  51. package/dist/components/LpPaletteHeader.vue.js +1 -1
  52. package/dist/components/LpPasswordInput.vue.js +1 -1
  53. package/dist/components/LpPhoneInput.vue.js +1 -1
  54. package/dist/components/LpPie.vue.js +1 -1
  55. package/dist/components/LpSegmented.vue.js +1 -1
  56. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  57. package/dist/components/LpSidebar.vue.js +1 -1
  58. package/dist/components/LpSidebarNav.vue.js +1 -1
  59. package/dist/components/LpTable.vue.js +5 -5
  60. package/dist/components/LpTabs.vue.d.ts +7 -0
  61. package/dist/components/LpTabs.vue.js +1 -1
  62. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  63. package/dist/components/LpToaster.vue.js +1 -1
  64. package/dist/components/MenuTitle.vue.js +1 -1
  65. package/dist/components/dropdown.js +1 -1
  66. package/dist/index.js +24 -24
  67. package/package.json +1 -1
  68. package/src/components/ContextMenuItems.vue +1 -1
  69. package/src/components/LpChart.vue +1 -1
  70. package/src/components/LpCodeBlock.vue +4 -4
  71. package/src/components/LpColorPicker.vue +4 -4
  72. package/src/components/LpCommandPalette.vue +11 -11
  73. package/src/components/LpDrawer.vue +1 -1
  74. package/src/components/LpDropdownMenu.vue +1 -1
  75. package/src/components/LpModal.vue +1 -1
  76. package/src/components/LpNotificationBell.vue +2 -2
  77. package/src/components/LpPasswordInput.vue +1 -1
  78. package/src/components/LpPhoneInput.vue +1 -1
  79. package/src/components/LpPie.vue +1 -1
  80. package/src/components/LpSegmented.vue +2 -2
  81. package/src/components/LpSidebarNav.vue +2 -2
  82. package/src/components/LpTable.vue +2 -2
  83. package/src/components/LpTabs.vue +11 -5
  84. package/src/components/LpToaster.vue +2 -2
  85. package/src/components/MenuTitle.vue +2 -2
  86. package/src/components/dropdown.ts +1 -1
  87. package/src/tokens/tokens.css +6 -0
@@ -1116,7 +1116,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
1116
1116
  v-for="s in allSeries"
1117
1117
  :key="s.id"
1118
1118
  type="button"
1119
- class="group flex cursor-pointer items-center gap-1.5 rounded-md text-xs outline-none transition-opacity duration-fast focus-visible:ring-2 focus-visible:ring-ring"
1119
+ class="group flex cursor-pointer items-center gap-1.5 rounded-inner text-xs outline-none transition-opacity duration-fast focus-visible:ring-2 focus-visible:ring-ring"
1120
1120
  :class="hidden.has(s.id) ? 'opacity-40' : ''"
1121
1121
  :aria-pressed="!hidden.has(s.id)"
1122
1122
  @click="toggleSeries(s.id)"
@@ -236,14 +236,14 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
236
236
  class="flex items-center gap-2 border-b border-line bg-surface-soft px-3 py-1.5 text-muted"
237
237
  >
238
238
  <span v-if="title" class="truncate text-ink">{{ title }}</span>
239
- <span v-if="lang !== 'plain'" class="rounded bg-surface px-1.5 py-0.5 text-[10px] uppercase tracking-wide">
239
+ <span v-if="lang !== 'plain'" class="rounded-small bg-surface px-1.5 py-0.5 text-[10px] uppercase tracking-wide">
240
240
  {{ lang }}
241
241
  </span>
242
242
  <div class="ml-auto flex items-center gap-1">
243
243
  <button
244
244
  v-if="lockToggle"
245
245
  type="button"
246
- class="group/lock flex items-center gap-1 rounded px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
246
+ class="group/lock flex items-center gap-1 rounded-small px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
247
247
  :aria-label="locked ? text.unlock : text.lock"
248
248
  @click="toggleLock"
249
249
  >
@@ -256,7 +256,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
256
256
  <button
257
257
  v-if="copyable"
258
258
  type="button"
259
- class="group/copy flex items-center gap-1 rounded px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
259
+ class="group/copy flex items-center gap-1 rounded-small px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
260
260
  :aria-label="copied ? text.copied : text.copy"
261
261
  @click="copy"
262
262
  >
@@ -314,7 +314,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
314
314
  v-else
315
315
  ><button
316
316
  type="button"
317
- class="lp-fold-toggle flex w-full items-center gap-1.5 rounded px-1 py-0.5 text-left text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
317
+ class="lp-fold-toggle flex w-full items-center gap-1.5 rounded-small px-1 py-0.5 text-left text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
318
318
  :aria-expanded="openState[seg.id]"
319
319
  @click="toggleFold(seg.id)"
320
320
  ><LpIcon
@@ -654,11 +654,11 @@ defineExpose({ open })
654
654
  would be painted over the checkerboard and, being translucent
655
655
  white, would show it through as a see-through outline. -->
656
656
  <span
657
- class="relative size-5 shrink-0 overflow-hidden rounded-md"
657
+ class="relative size-5 shrink-0 overflow-hidden rounded-inner"
658
658
  :style="{ background: CHECKERBOARD }"
659
659
  >
660
660
  <span class="block size-full" :style="{ backgroundColor: previewCss }" />
661
- <span class="pointer-events-none absolute inset-0 rounded-md ring-1 ring-inset ring-line" />
661
+ <span class="pointer-events-none absolute inset-0 rounded-inner ring-1 ring-inset ring-line" />
662
662
  </span>
663
663
  <span class="min-w-0 flex-1 truncate font-mono text-xs text-muted-strong">
664
664
  {{ label ?? current }}
@@ -814,7 +814,7 @@ defineExpose({ open })
814
814
  :disabled="disabled"
815
815
  :aria-label="c"
816
816
  :aria-pressed="isActiveSwatch(c)"
817
- class="relative flex items-center justify-center overflow-hidden rounded-md outline-none transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] hover:scale-110 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed motion-reduce:hover:scale-100 motion-reduce:active:scale-95"
817
+ class="relative flex items-center justify-center overflow-hidden rounded-inner outline-none transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] hover:scale-110 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed motion-reduce:hover:scale-100 motion-reduce:active:scale-95"
818
818
  :class="row.size"
819
819
  :style="{ background: CHECKERBOARD }"
820
820
  @click="pickSwatch(c)"
@@ -826,7 +826,7 @@ defineExpose({ open })
826
826
  inset ring painted OVER the colour instead, so it reads
827
827
  as one fixed hairline rather than a translucent gap. -->
828
828
  <span class="absolute inset-0" :style="{ backgroundColor: c }" />
829
- <span class="pointer-events-none absolute inset-0 rounded-md ring-1 ring-inset ring-line" />
829
+ <span class="pointer-events-none absolute inset-0 rounded-inner ring-1 ring-inset ring-line" />
830
830
  <LpIcon
831
831
  v-if="isActiveSwatch(c)"
832
832
  name="lucide:check"
@@ -1239,7 +1239,7 @@ useHotkeys(() =>
1239
1239
  v-for="(step, i) in trail"
1240
1240
  :key="step.id"
1241
1241
  type="button"
1242
- class="flex shrink-0 items-center gap-1.5 rounded-md bg-brand-soft px-2 py-1 text-xs font-medium text-brand transition-opacity hover:opacity-80"
1242
+ class="flex shrink-0 items-center gap-1.5 rounded-inner bg-brand-soft px-2 py-1 text-xs font-medium text-brand transition-opacity hover:opacity-80"
1243
1243
  :title="text.back"
1244
1244
  @click="popTo(i)"
1245
1245
  >
@@ -1264,7 +1264,7 @@ useHotkeys(() =>
1264
1264
  @keydown.esc="onEscape"
1265
1265
  @keydown.tab="onTab"
1266
1266
  />
1267
- <kbd class="shrink-0 rounded border border-line px-1.5 py-0.5 text-[10px] text-muted">{{ text.esc }}</kbd>
1267
+ <kbd class="shrink-0 rounded-small border border-line px-1.5 py-0.5 text-[10px] text-muted">{{ text.esc }}</kbd>
1268
1268
  </div>
1269
1269
 
1270
1270
  <!-- Results -->
@@ -1305,7 +1305,7 @@ useHotkeys(() =>
1305
1305
  :aria-disabled="c.disabled || undefined"
1306
1306
  :data-cmd-index="flatIndexOf(c)"
1307
1307
  :disabled="c.href ? undefined : c.disabled"
1308
- class="lp-cmd-item flex w-full gap-3 rounded-md px-2.5 py-2 text-left text-sm outline-none transition-colors duration-[var(--duration-fast)] disabled:pointer-events-none disabled:opacity-45 aria-disabled:pointer-events-none aria-disabled:opacity-45"
1308
+ class="lp-cmd-item flex w-full gap-3 rounded-inner px-2.5 py-2 text-left text-sm outline-none transition-colors duration-[var(--duration-fast)] disabled:pointer-events-none disabled:opacity-45 aria-disabled:pointer-events-none aria-disabled:opacity-45"
1309
1309
  :class="[
1310
1310
  c.excerpt ? 'items-start' : 'items-center',
1311
1311
  flatIndexOf(c) === selectedIndex
@@ -1365,7 +1365,7 @@ useHotkeys(() =>
1365
1365
  shortcut is learned by seeing it rather than reading docs. -->
1366
1366
  <kbd
1367
1367
  v-else-if="c.prefix && c.children"
1368
- class="shrink-0 rounded border border-line px-1.5 font-mono text-[11px] whitespace-pre text-muted"
1368
+ class="shrink-0 rounded-small border border-line px-1.5 font-mono text-[11px] whitespace-pre text-muted"
1369
1369
  >{{ c.prefix }}</kbd>
1370
1370
  <!-- Drills in rather than runs: worth saying before the click,
1371
1371
  since the two look identical otherwise. -->
@@ -1390,7 +1390,7 @@ useHotkeys(() =>
1390
1390
  <span>{{ text.searchFailed }}</span>
1391
1391
  <button
1392
1392
  type="button"
1393
- class="rounded-md px-1.5 py-0.5 font-medium text-brand outline-none transition-colors hover:bg-brand-soft focus-visible:ring-2 focus-visible:ring-ring"
1393
+ class="rounded-inner px-1.5 py-0.5 font-medium text-brand outline-none transition-colors hover:bg-brand-soft focus-visible:ring-2 focus-visible:ring-ring"
1394
1394
  @click="refresh(); inputRef?.focus()"
1395
1395
  >
1396
1396
  {{ text.retry }}
@@ -1451,26 +1451,26 @@ useHotkeys(() =>
1451
1451
  class="flex shrink-0 items-center gap-4 border-t border-line px-4 py-2.5 text-[11px] text-muted [@media(hover:none)_and_(pointer:coarse)]:hidden"
1452
1452
  >
1453
1453
  <span class="flex items-center gap-1">
1454
- <kbd class="rounded border border-line px-1 text-[10px]">↑</kbd>
1455
- <kbd class="rounded border border-line px-1 text-[10px]">↓</kbd>
1454
+ <kbd class="rounded-small border border-line px-1 text-[10px]">↑</kbd>
1455
+ <kbd class="rounded-small border border-line px-1 text-[10px]">↓</kbd>
1456
1456
  {{ text.navigate }}
1457
1457
  </span>
1458
1458
  <span class="flex items-center gap-1">
1459
- <kbd class="rounded border border-line px-1 text-[10px]">↵</kbd>
1459
+ <kbd class="rounded-small border border-line px-1 text-[10px]">↵</kbd>
1460
1460
  {{ text.select }}
1461
1461
  </span>
1462
1462
  <!-- Only inside a mode: at the root Backspace just edits the query,
1463
1463
  and advertising it there would be a lie. -->
1464
1464
  <span v-if="selectedActions.length" class="flex items-center gap-1">
1465
- <kbd class="rounded border border-line px-1 text-[10px]">tab</kbd>
1465
+ <kbd class="rounded-small border border-line px-1 text-[10px]">tab</kbd>
1466
1466
  {{ text.actions }}
1467
1467
  </span>
1468
1468
  <span v-if="trail.length" class="flex items-center gap-1">
1469
- <kbd class="rounded border border-line px-1 text-[10px]">⌫</kbd>
1469
+ <kbd class="rounded-small border border-line px-1 text-[10px]">⌫</kbd>
1470
1470
  {{ text.back }}
1471
1471
  </span>
1472
1472
  <span class="ml-auto flex items-center gap-1">
1473
- <kbd class="rounded border border-line px-1 text-[10px]">{{ text.esc }}</kbd>
1473
+ <kbd class="rounded-small border border-line px-1 text-[10px]">{{ text.esc }}</kbd>
1474
1474
  {{ text.close }}
1475
1475
  </span>
1476
1476
  </div>
@@ -552,7 +552,7 @@ const previewStyle = computed(() => {
552
552
  </DrawerDescription>
553
553
  </div>
554
554
  <DrawerClose
555
- class="group flex shrink-0 items-center rounded-md p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
555
+ class="group flex shrink-0 items-center rounded-inner p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
556
556
  :aria-label="text.close"
557
557
  >
558
558
  <LpIcon
@@ -47,7 +47,7 @@ defineProps<{
47
47
  <template v-for="(item, i) in items" :key="i">
48
48
  <DropdownMenuSeparator v-if="item.separatorBefore" class="my-1 h-px bg-line" />
49
49
  <DropdownMenuItem
50
- class="group/item flex cursor-pointer items-center gap-2 rounded-md px-2.5 py-1.5 text-sm outline-none transition-[background-color,color] duration-[var(--duration-fast)] data-[disabled]:pointer-events-none data-[disabled]:opacity-45 data-[highlighted]:bg-brand-soft"
50
+ class="group/item flex cursor-pointer items-center gap-2 rounded-inner px-2.5 py-1.5 text-sm outline-none transition-[background-color,color] duration-[var(--duration-fast)] data-[disabled]:pointer-events-none data-[disabled]:opacity-45 data-[highlighted]:bg-brand-soft"
51
51
  :class="item.danger ? 'text-danger data-[highlighted]:bg-danger-soft data-[highlighted]:text-danger' : 'text-ink data-[highlighted]:text-brand'"
52
52
  :disabled="item.disabled"
53
53
  @select="item.onSelect?.()"
@@ -350,7 +350,7 @@ watch(
350
350
  and last in usefulness. Still reachable by Tab and Escape. -->
351
351
  <DialogClose
352
352
  data-lp-dialog-close
353
- class="group flex shrink-0 items-center rounded-md p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
353
+ class="group flex shrink-0 items-center rounded-inner p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
354
354
  :aria-label="text.close"
355
355
  >
356
356
  <LpIcon
@@ -321,7 +321,7 @@ function timeAgo(iso?: string): string {
321
321
  <button
322
322
  v-if="items.length && handlesClear"
323
323
  type="button"
324
- class="rounded-md px-1.5 py-0.5 text-xs font-medium text-muted outline-none transition-colors hover:bg-surface-soft hover:text-ink focus-visible:bg-surface-soft"
324
+ class="rounded-inner px-1.5 py-0.5 text-xs font-medium text-muted outline-none transition-colors hover:bg-surface-soft hover:text-ink focus-visible:bg-surface-soft"
325
325
  @click="emit('clear')"
326
326
  >
327
327
  {{ l.clear }}
@@ -329,7 +329,7 @@ function timeAgo(iso?: string): string {
329
329
  <button
330
330
  v-if="hasUnread"
331
331
  type="button"
332
- class="rounded-md px-1.5 py-0.5 text-xs font-medium text-brand outline-none transition-colors hover:bg-brand-soft focus-visible:bg-brand-soft"
332
+ class="rounded-inner px-1.5 py-0.5 text-xs font-medium text-brand outline-none transition-colors hover:bg-brand-soft focus-visible:bg-brand-soft"
333
333
  @click="emit('markAllRead')"
334
334
  >
335
335
  {{ l.markAllRead }}
@@ -53,7 +53,7 @@ defineExpose({
53
53
  <template #trailing>
54
54
  <button
55
55
  type="button"
56
- class="group rounded-md p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:text-ink"
56
+ class="group rounded-inner p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:text-ink"
57
57
  :aria-label="visible ? text.hide : text.show"
58
58
  @click="visible = !visible"
59
59
  >
@@ -398,7 +398,7 @@ const inputAttrs = computed(() => {
398
398
  :model-value="query"
399
399
  :placeholder="searchPlaceholder"
400
400
  auto-focus
401
- class="h-(--size-control-sm) w-full rounded-md border border-line bg-surface-soft px-2.5 text-sm text-ink outline-none placeholder:text-muted focus:border-brand"
401
+ class="h-(--size-control-sm) w-full rounded-inner border border-line bg-surface-soft px-2.5 text-sm text-ink outline-none placeholder:text-muted focus:border-brand"
402
402
  @input="query = ($event.target as HTMLInputElement).value"
403
403
  />
404
404
  </div>
@@ -835,7 +835,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
835
835
  v-for="(a, i) in arcs"
836
836
  :key="`${i}-${a.label}`"
837
837
  type="button"
838
- class="group flex cursor-pointer items-center gap-2 rounded-md px-1 py-0.5 text-xs outline-none transition-[opacity,background-color] duration-fast focus-visible:ring-2 focus-visible:ring-ring"
838
+ class="group flex cursor-pointer items-center gap-2 rounded-inner px-1 py-0.5 text-xs outline-none transition-[opacity,background-color] duration-fast focus-visible:ring-2 focus-visible:ring-ring"
839
839
  :class="[dimmed(i) ? 'opacity-45' : '', isSelected(i) ? 'bg-surface-soft' : '']"
840
840
  :aria-pressed="isSelected(i)"
841
841
  @pointerenter="onSlicePointerEnter(i)"
@@ -95,7 +95,7 @@ const pillTransition = usePillTransition()
95
95
  :key="opt.value"
96
96
  :value="opt.value"
97
97
  :aria-label="opt.ariaLabel ?? (opt.label ? undefined : opt.value)"
98
- class="relative inline-flex h-full items-center justify-center gap-1.5 rounded-md px-3 font-medium outline-none transition-colors duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] focus-visible:ring-2 focus-visible:ring-ring data-[state=on]:text-ink data-[state=off]:text-muted data-[state=off]:hover:text-ink disabled:cursor-not-allowed disabled:opacity-55"
98
+ class="relative inline-flex h-full items-center justify-center gap-1.5 rounded-inner px-3 font-medium outline-none transition-colors duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] focus-visible:ring-2 focus-visible:ring-ring data-[state=on]:text-ink data-[state=off]:text-muted data-[state=off]:hover:text-ink disabled:cursor-not-allowed disabled:opacity-55"
99
99
  :class="block ? 'flex-1' : ''"
100
100
  >
101
101
  <!-- Sliding pill behind the active segment. -->
@@ -103,7 +103,7 @@ const pillTransition = usePillTransition()
103
103
  v-if="opt.value === modelValue"
104
104
  :layout-id="pillId"
105
105
  :transition="pillTransition"
106
- class="absolute inset-0 z-0 rounded-md border border-line bg-surface-raised shadow-sm"
106
+ class="absolute inset-0 z-0 rounded-inner border border-line bg-surface-raised shadow-sm"
107
107
  />
108
108
  <LpIcon v-if="opt.icon" :name="opt.icon" :size="14" class="relative z-10 shrink-0" />
109
109
  <span v-if="opt.label" class="relative z-10">{{ opt.label }}</span>
@@ -103,8 +103,8 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
103
103
  <div v-if="skeletonHeader" class="flex items-center gap-3 px-1">
104
104
  <div class="size-10 shrink-0 animate-pulse rounded-pill bg-surface-soft" />
105
105
  <div class="flex-1 space-y-2">
106
- <div class="h-3.5 w-24 animate-pulse rounded bg-surface-soft" />
107
- <div class="h-3 w-16 animate-pulse rounded bg-surface-soft/60" />
106
+ <div class="h-3.5 w-24 animate-pulse rounded-small bg-surface-soft" />
107
+ <div class="h-3 w-16 animate-pulse rounded-small bg-surface-soft/60" />
108
108
  </div>
109
109
  </div>
110
110
  <div class="space-y-1">
@@ -1201,7 +1201,7 @@ const barInsetTop = computed(() =>
1201
1201
  <LpContextMenu v-if="col.sortable || col.filterable" :items="headerMenu(col)">
1202
1202
  <button
1203
1203
  type="button"
1204
- class="group/sort -mx-1 inline-flex items-center gap-1 rounded px-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
1204
+ class="group/sort -mx-1 inline-flex items-center gap-1 rounded-small px-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
1205
1205
  :class="[
1206
1206
  col.align === 'right' ? 'flex-row-reverse' : '',
1207
1207
  activeSort?.key === col.key ? 'text-ink' : '',
@@ -1232,7 +1232,7 @@ const barInsetTop = computed(() =>
1232
1232
  <template #trigger>
1233
1233
  <button
1234
1234
  type="button"
1235
- class="ml-0.5 inline-grid size-5 place-items-center rounded align-middle outline-none transition-colors duration-fast hover:bg-surface-raised hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
1235
+ class="ml-0.5 inline-grid size-5 place-items-center rounded-small align-middle outline-none transition-colors duration-fast hover:bg-surface-raised hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
1236
1236
  :class="hiddenValues[col.key]?.size ? 'text-brand' : 'opacity-60'"
1237
1237
  :aria-label="text.filterColumn.replace('{column}', col.label)"
1238
1238
  :data-lp-filter="col.key"
@@ -38,8 +38,14 @@ const props = withDefaults(
38
38
  block?: boolean
39
39
  /** Accessible name of the tab list, e.g. "Main" for an app's navigation. */
40
40
  label?: string
41
+ /**
42
+ * The marker glides under the hovered tab and springs back on leave (the
43
+ * default). False pins it to the selected tab: calmer for a dense header
44
+ * where the pointer crosses the bar on its way elsewhere.
45
+ */
46
+ hoverFollow?: boolean
41
47
  }>(),
42
- { variant: "contained", accent: false, block: false },
48
+ { variant: "contained", accent: false, block: false, hoverFollow: true },
43
49
  )
44
50
 
45
51
  const bottom = computed(() => props.variant === "bottom")
@@ -154,12 +160,12 @@ function releaseFocusAfterPointer(event: PointerEvent) {
154
160
  ? 'min-h-14 min-w-0 flex-col gap-0.5 px-1 py-1.5 text-[11px] font-medium focus-visible:ring-inset'
155
161
  : 'shrink-0 gap-1.5 whitespace-nowrap text-sm',
156
162
  block && !bottom ? 'flex-1' : '',
157
- variant === 'underline' ? 'rounded-t-md px-3 pt-1.5 pb-2' : '',
158
- variant === 'contained' || variant === 'plain' ? 'rounded-md px-3 py-1.5' : '',
163
+ variant === 'underline' ? 'rounded-t-inner px-3 pt-1.5 pb-2' : '',
164
+ variant === 'contained' || variant === 'plain' ? 'rounded-inner px-3 py-1.5' : '',
159
165
  accent ? 'data-[state=active]:text-brand' : 'data-[state=active]:text-ink',
160
166
  hovered === item.value && !bottom ? 'text-ink' : 'text-muted',
161
167
  ]"
162
- @pointerenter="hovered = item.value"
168
+ @pointerenter="hoverFollow && (hovered = item.value)"
163
169
  @pointerup="releaseFocusAfterPointer"
164
170
  >
165
171
  <!-- Active marker: a bar under the tab in "underline", over it in
@@ -180,7 +186,7 @@ function releaseFocusAfterPointer(event: PointerEvent) {
180
186
  accent ? 'bg-brand' : 'bg-ink',
181
187
  ]
182
188
  : [
183
- 'absolute inset-0 z-0 rounded-md shadow-sm',
189
+ 'absolute inset-0 z-0 rounded-inner shadow-sm',
184
190
  accent
185
191
  ? 'border border-brand/35 bg-brand/12'
186
192
  : 'border border-line bg-surface-raised',
@@ -305,7 +305,7 @@ function runAction(t: ToastItem, action: NonNullable<ToastItem["actions"]>[numbe
305
305
  <button
306
306
  v-if="copyable(t)"
307
307
  type="button"
308
- class="-mt-1 rounded-md p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
308
+ class="-mt-1 rounded-inner p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
309
309
  :aria-label="copiedId === tag(t) ? text.copied : text.copy"
310
310
  :title="copiedId === tag(t) ? text.copied : text.copy"
311
311
  @click.stop="copyToast(t)"
@@ -314,7 +314,7 @@ function runAction(t: ToastItem, action: NonNullable<ToastItem["actions"]>[numbe
314
314
  </button>
315
315
  <button
316
316
  type="button"
317
- class="group -mr-1 -mt-1 rounded-md p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink"
317
+ class="group -mr-1 -mt-1 rounded-inner p-1 text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink"
318
318
  :aria-label="text.dismiss"
319
319
  @click.stop="beginClose(t)"
320
320
  >
@@ -18,10 +18,10 @@ defineProps<{
18
18
 
19
19
  <template>
20
20
  <div class="flex max-w-72 min-w-0 items-center gap-2 px-2.5 pt-1.5 pb-2" aria-hidden="true">
21
- <img v-if="image" :src="image" alt="" class="size-7 shrink-0 rounded-md object-cover" />
21
+ <img v-if="image" :src="image" alt="" class="size-7 shrink-0 rounded-inner object-cover" />
22
22
  <span
23
23
  v-else-if="icon"
24
- class="grid size-7 shrink-0 place-items-center rounded-md bg-surface-soft text-muted"
24
+ class="grid size-7 shrink-0 place-items-center rounded-inner bg-surface-soft text-muted"
25
25
  >
26
26
  <LpIcon :name="icon" :size="15" />
27
27
  </span>
@@ -49,7 +49,7 @@ export const POPOVER_PANEL = PANEL_SURFACE + " " + POPOVER_ANIM
49
49
  * stagger. `flex` + gap are included; add justify/extra layout if needed.
50
50
  */
51
51
  export const OPTION_ITEM =
52
- "flex cursor-pointer items-center gap-2 rounded-md px-2.5 py-1.5 text-sm text-ink outline-none " +
52
+ "flex cursor-pointer items-center gap-2 rounded-inner px-2.5 py-1.5 text-sm text-ink outline-none " +
53
53
  "animate-[option-in_180ms_var(--ease-emphasized)_both] " +
54
54
  "group-data-[side=top]:animate-[option-in-up_180ms_var(--ease-emphasized)_both] " +
55
55
  "data-[highlighted]:bg-brand-soft data-[highlighted]:text-brand"
@@ -64,6 +64,12 @@
64
64
  --radius-control: 8px;
65
65
  --radius-card: 14px;
66
66
  --radius-pill: 9999px;
67
+ /* Nested shapes derive from the control radius instead of fixing pixels: a
68
+ row inside a menu, a segment, a small icon button. They match the old 6px
69
+ and 4px at the default 8px, and follow a theme down to 0 when it squares
70
+ everything (a fixed rounded-md stayed round in a square theme). */
71
+ --radius-inner: max(0px, calc(var(--radius-control) - 2px));
72
+ --radius-small: max(0px, calc(var(--radius-control) - 4px));
67
73
 
68
74
  /* ── density ─────────────────────────────────── */
69
75
  --spacing-unit: 4px; /* base rhythm; scaled per density mode */