@heyramzi/ui 2.20.0 → 2.21.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 (176) hide show
  1. package/README.md +2 -0
  2. package/dist/charts/dashboard/data-table.js +1 -2
  3. package/dist/components/list-page/filter-section.js +1 -1
  4. package/dist/components/list-page/list-table.js +5 -6
  5. package/dist/components/list-page/queue-rail.js +2 -1
  6. package/dist/components/picker/trigger.js +3 -3
  7. package/dist/components/segmented/segmented.js +5 -5
  8. package/dist/components/work-parts/looks.js +1 -1
  9. package/dist/shadcn/dialog/index.js +3 -2
  10. package/dist/shadcn/dropdown-menu/menu-item.js +1 -1
  11. package/dist/shadcn/sheet/index.js +3 -2
  12. package/dist/shadcn/skeleton/index.js +3 -2
  13. package/dist/status/index.js +1 -0
  14. package/dist/work/kanban-drag.js +13 -7
  15. package/package.json +1 -1
  16. package/src/ai/confirmation/ConfirmationTitle.svelte +1 -4
  17. package/src/ai/loading-state/PixelLoader.svelte +1 -1
  18. package/src/animations/dropdown.css +19 -10
  19. package/src/animations/modal.css +7 -2
  20. package/src/charts/charts.css +3 -5
  21. package/src/charts/dashboard/dashboard-section.svelte +1 -1
  22. package/src/charts/dashboard/data-table.ts +1 -2
  23. package/src/charts/dashboard/stat-tile.svelte +1 -1
  24. package/src/charts/number-chart.css +8 -7
  25. package/src/charts/pop-value.svelte +68 -0
  26. package/src/charts/primitives/chart-tooltip.svelte +1 -1
  27. package/src/charts/reference-line.css +1 -1
  28. package/src/charts/stat-card.css +4 -4
  29. package/src/components/copy/copy-button.svelte +11 -10
  30. package/src/components/data-table/row-arrow.svelte +1 -1
  31. package/src/components/data-table/row-context-menu.svelte +1 -1
  32. package/src/components/data-table/sortable-head.svelte +2 -2
  33. package/src/components/data-table/table-skeleton.svelte +5 -5
  34. package/src/components/docs/doc-page.svelte +1 -3
  35. package/src/components/docs/on-this-page.svelte +4 -4
  36. package/src/components/field-row/field-row.svelte +1 -1
  37. package/src/components/list-page/detail-empty.svelte +3 -8
  38. package/src/components/list-page/detail-header.svelte +1 -1
  39. package/src/components/list-page/detail-row.svelte +2 -1
  40. package/src/components/list-page/empty-state.svelte +15 -7
  41. package/src/components/list-page/filter-item.svelte +2 -2
  42. package/src/components/list-page/filter-popover.svelte +1 -1
  43. package/src/components/list-page/filter-section.ts +1 -4
  44. package/src/components/list-page/grouped-list.svelte +37 -8
  45. package/src/components/list-page/list-page-shell.svelte +1 -1
  46. package/src/components/list-page/list-table.ts +6 -6
  47. package/src/components/list-page/master-detail.svelte +1 -1
  48. package/src/components/list-page/queue-rail.ts +2 -2
  49. package/src/components/list-page/rail-empty.svelte +1 -1
  50. package/src/components/list-page/rail-row.svelte +5 -5
  51. package/src/components/open-in/open-in.svelte +2 -1
  52. package/src/components/picker/trigger.ts +6 -5
  53. package/src/components/section-card/section-card.svelte +1 -1
  54. package/src/components/section-header/section-header.svelte +4 -2
  55. package/src/components/section-header/section-label.svelte +2 -2
  56. package/src/components/segmented/animated-tabs.svelte +1 -1
  57. package/src/components/segmented/section-runs.svelte +1 -1
  58. package/src/components/segmented/segment.svelte +4 -6
  59. package/src/components/segmented/segmented-track.svelte +18 -52
  60. package/src/components/segmented/segmented.ts +5 -5
  61. package/src/components/table-view/table-view.svelte +43 -24
  62. package/src/components/tags-input/tags-input.svelte +17 -31
  63. package/src/components/work-parts/looks.ts +1 -1
  64. package/src/editor/content.css +3 -3
  65. package/src/editor/editor.svelte +1 -1
  66. package/src/inbox/thread-inbox.svelte +2 -9
  67. package/src/panel/side-panel.svelte +9 -4
  68. package/src/record/info-list.svelte +7 -8
  69. package/src/record/project-list.svelte +1 -1
  70. package/src/record/record-demo.svelte +2 -4
  71. package/src/record/record-shell.svelte +1 -1
  72. package/src/record/record-stats.svelte +9 -3
  73. package/src/record/steps-rail.svelte +7 -11
  74. package/src/shadcn/accordion/accordion-trigger.svelte +1 -1
  75. package/src/shadcn/alert-dialog/alert-dialog-content.svelte +5 -1
  76. package/src/shadcn/alert-dialog/alert-dialog-footer.svelte +12 -2
  77. package/src/shadcn/alert-dialog/alert-dialog-header.svelte +1 -1
  78. package/src/shadcn/alert-dialog/alert-dialog-title.svelte +1 -1
  79. package/src/shadcn/badge/badge.svelte +3 -1
  80. package/src/shadcn/bubble/bubble-content.svelte +1 -1
  81. package/src/shadcn/bubble/bubble.svelte +1 -1
  82. package/src/shadcn/button/button.svelte +11 -5
  83. package/src/shadcn/calendar/calendar-month-select.svelte +1 -1
  84. package/src/shadcn/calendar/calendar-year-select.svelte +1 -1
  85. package/src/shadcn/calendar/calendar.svelte +1 -1
  86. package/src/shadcn/card/card.svelte +2 -1
  87. package/src/shadcn/checkbox/checkbox.svelte +1 -1
  88. package/src/shadcn/code-block/code-block-actions.svelte +1 -1
  89. package/src/shadcn/command/command-dialog.svelte +2 -2
  90. package/src/shadcn/command/command-group.svelte +1 -1
  91. package/src/shadcn/command/command-input.svelte +1 -1
  92. package/src/shadcn/command/command-item.svelte +1 -1
  93. package/src/shadcn/dialog/dialog-body.svelte +22 -0
  94. package/src/shadcn/dialog/dialog-content.svelte +19 -4
  95. package/src/shadcn/dialog/dialog-footer.svelte +19 -1
  96. package/src/shadcn/dialog/dialog-header.svelte +6 -1
  97. package/src/shadcn/dialog/dialog-title.svelte +2 -1
  98. package/src/shadcn/dialog/index.ts +3 -0
  99. package/src/shadcn/dropdown-menu/dropdown-menu-content.svelte +5 -1
  100. package/src/shadcn/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  101. package/src/shadcn/dropdown-menu/menu-item.ts +1 -1
  102. package/src/shadcn/field/field-separator.svelte +1 -1
  103. package/src/shadcn/hover-card/hover-card-content.svelte +1 -1
  104. package/src/shadcn/input/input.svelte +2 -2
  105. package/src/shadcn/input-otp/input-otp-slot.svelte +1 -1
  106. package/src/shadcn/message-scroller/message-scroller-button.svelte +1 -1
  107. package/src/shadcn/popover/popover-content.svelte +1 -1
  108. package/src/shadcn/radio-group/radio-group-item.svelte +1 -1
  109. package/src/shadcn/scroll-area/scroll-area.svelte +1 -1
  110. package/src/shadcn/select/select-content.svelte +6 -2
  111. package/src/shadcn/select/select-item.svelte +1 -1
  112. package/src/shadcn/select/select-trigger.svelte +1 -1
  113. package/src/shadcn/sheet/index.ts +3 -0
  114. package/src/shadcn/sheet/sheet-body.svelte +22 -0
  115. package/src/shadcn/sheet/sheet-content.svelte +27 -5
  116. package/src/shadcn/sheet/sheet-footer.svelte +14 -2
  117. package/src/shadcn/sheet/sheet-header.svelte +1 -1
  118. package/src/shadcn/sheet/sheet-title.svelte +1 -1
  119. package/src/shadcn/sheet/sheet.css +11 -5
  120. package/src/shadcn/sidebar/sidebar-group-action.svelte +1 -1
  121. package/src/shadcn/sidebar/sidebar-group-label.svelte +1 -1
  122. package/src/shadcn/sidebar/sidebar-inset.svelte +1 -1
  123. package/src/shadcn/sidebar/sidebar-menu-action.svelte +1 -1
  124. package/src/shadcn/sidebar/sidebar-menu-button.svelte +2 -2
  125. package/src/shadcn/sidebar/sidebar-menu-sub-button.svelte +1 -1
  126. package/src/shadcn/sidebar/sidebar-menu.svelte +1 -1
  127. package/src/shadcn/sidebar/sidebar.svelte +1 -1
  128. package/src/shadcn/skeleton/index.ts +3 -0
  129. package/src/shadcn/skeleton/skeleton-delay.svelte +63 -0
  130. package/src/shadcn/skeleton/skeleton-delay.svelte.test.ts +57 -0
  131. package/src/shadcn/skeleton/skeleton.svelte +5 -1
  132. package/src/shadcn/slider/slider.svelte +1 -1
  133. package/src/shadcn/switch/switch.svelte +2 -2
  134. package/src/shadcn/table/table-row.svelte +1 -1
  135. package/src/shadcn/tabs/tabs-list.svelte +1 -1
  136. package/src/shadcn/tabs/tabs-trigger.svelte +2 -1
  137. package/src/shadcn/textarea/textarea.svelte +1 -1
  138. package/src/shadcn/toggle/toggle.svelte +2 -2
  139. package/src/shadcn/toggle-group/toggle-group.svelte +1 -1
  140. package/src/shadcn/tooltip/tooltip-content.svelte +1 -1
  141. package/src/shadcn/trace/trace-collapsible-trigger.svelte +1 -1
  142. package/src/shadcn/trace/trace.svelte +1 -1
  143. package/src/status/README.md +1 -1
  144. package/src/status/index.ts +1 -0
  145. package/src/status/status-badge.svelte +21 -7
  146. package/src/status/status-dot.svelte +6 -11
  147. package/src/status/status-pill.svelte +50 -0
  148. package/src/thread/thread.svelte +54 -136
  149. package/src/tokens/craft.css +55 -36
  150. package/src/tokens/palette.css +16 -9
  151. package/src/work/demo.svelte +48 -42
  152. package/src/work/detail/detail-demo.svelte +33 -24
  153. package/src/work/detail/task-chip.svelte +4 -4
  154. package/src/work/detail/task-detail.svelte +41 -108
  155. package/src/work/detail/task-property.svelte +7 -13
  156. package/src/work/detail/task-thread.svelte +48 -119
  157. package/src/work/docs/doc-editor-page.svelte +5 -4
  158. package/src/work/docs/doc-menu.svelte +9 -4
  159. package/src/work/docs/docs-demo.svelte +4 -4
  160. package/src/work/docs/edited-chip.svelte +11 -4
  161. package/src/work/gantt/gantt-bar.svelte +18 -14
  162. package/src/work/gantt/gantt-grid.svelte +7 -7
  163. package/src/work/gantt/gantt-group-row.svelte +7 -10
  164. package/src/work/gantt/gantt-header.svelte +3 -1
  165. package/src/work/gantt/gantt-task-row.svelte +19 -9
  166. package/src/work/gantt/gantt.css +4 -5
  167. package/src/work/inbox/inbox-card.svelte +32 -10
  168. package/src/work/inbox/inbox-draft.svelte +2 -2
  169. package/src/work/kanban-column.svelte +7 -15
  170. package/src/work/kanban-drag.ts +13 -8
  171. package/src/work/task-gantt.svelte +2 -1
  172. package/src/work/task-list.svelte +54 -53
  173. package/src/work/time/time-chip.svelte +16 -19
  174. package/src/work/time/time-dot.svelte +2 -1
  175. package/src/work/time/time-ring.svelte +2 -3
  176. package/src/work/time/time-tracker.svelte +72 -166
@@ -4,6 +4,9 @@
4
4
  import { initial } from "../../lib/initials.js";
5
5
  import { AgentAvatar } from "../../agents/index.js";
6
6
  import { Skeleton } from "../../shadcn/skeleton/index.js";
7
+ import { Button } from "../../shadcn/button/index.js";
8
+ import { Textarea } from "../../shadcn/textarea/index.js";
9
+ import * as Avatar from "../../shadcn/avatar/index.js";
7
10
  import {
8
11
  DEFAULT_TASK_DETAIL_LABELS,
9
12
  type TaskComment,
@@ -103,7 +106,7 @@
103
106
  {:else if comments.length > 0}
104
107
  <ol class="flex flex-col gap-4">
105
108
  {#each comments as comment (comment.id)}
106
- <li class="group relative flex gap-3">
109
+ <li class="group hover-row relative flex gap-3">
107
110
  <!-- The rail that ties one avatar to the next, as in an activity feed. -->
108
111
  <span
109
112
  class="absolute start-[11.5px] top-8 -bottom-3 w-px bg-border group-last:hidden"
@@ -119,18 +122,18 @@
119
122
  {:else if avatar}
120
123
  {@render avatar(comment)}
121
124
  {:else}
122
- <span
123
- class="grid size-6 place-items-center rounded-full bg-muted text-xs font-medium text-muted-foreground"
124
- aria-hidden="true"
125
- >
126
- {initial(comment.author)}
127
- </span>
125
+ <Avatar.Root class="size-6" aria-hidden="true">
126
+ <Avatar.Fallback class="text-xs font-medium"
127
+ >{initial(comment.author)}</Avatar.Fallback
128
+ >
129
+ </Avatar.Root>
128
130
  {/if}
129
131
  </span>
130
132
 
131
133
  <div class="min-w-0 flex-1">
132
134
  <div class="flex h-6 items-center gap-2">
133
- <span class="truncate text-[13px] font-medium">{comment.author}</span>
135
+ <span class="truncate text-(length:--text-control) font-medium">{comment.author}</span
136
+ >
134
137
  {#if comment.agent}
135
138
  <span class="sr-only">{labels.ai}</span>
136
139
  {/if}
@@ -139,49 +142,47 @@
139
142
  <span class="text-xs text-muted-foreground">{labels.commentEdited}</span>
140
143
  {/if}
141
144
  {#if canEdit(comment) && editingId !== comment.id}
142
- <span
143
- class="ms-auto flex gap-0.5 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100"
144
- >
145
+ <span class="row-action ms-auto flex gap-0.5">
145
146
  {#if onEdit}
146
- <button
147
- type="button"
148
- class="thread-icon"
147
+ <Button
148
+ variant="ghost"
149
+ size="sm"
150
+ icon
151
+ class="text-muted-foreground"
149
152
  aria-label={labels.commentEdit}
150
153
  onclick={() => startEdit(comment)}
151
154
  >
152
- <PencilSimple class="size-3.5" aria-hidden="true" />
153
- </button>
155
+ <PencilSimple aria-hidden="true" />
156
+ </Button>
154
157
  {/if}
155
158
  {#if onDelete}
156
- <button
157
- type="button"
158
- class="thread-icon"
159
+ <Button
160
+ variant="ghost"
161
+ size="sm"
162
+ icon
163
+ class="text-muted-foreground"
159
164
  aria-label={labels.commentDelete}
160
165
  onclick={() => onDelete?.(comment)}
161
166
  >
162
- <Trash class="size-3.5" aria-hidden="true" />
163
- </button>
167
+ <Trash aria-hidden="true" />
168
+ </Button>
164
169
  {/if}
165
170
  </span>
166
171
  {/if}
167
172
  </div>
168
173
 
169
174
  {#if editingId === comment.id}
170
- <textarea
175
+ <Textarea
171
176
  bind:value={editDraft}
172
177
  rows={3}
173
178
  aria-label={labels.comments}
174
- class="mt-1 w-full resize-y rounded-md border border-input bg-transparent px-2.5 py-2 text-sm leading-relaxed outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50"
175
- ></textarea>
179
+ class="mt-1 resize-y leading-relaxed"
180
+ />
176
181
  <div class="mt-2 flex justify-end gap-1.5">
177
- <button type="button" class="thread-button" onclick={() => (editingId = null)}
178
- >{labels.cancel}</button
179
- >
180
- <button
181
- type="button"
182
- class="thread-button thread-primary"
183
- onclick={() => saveEdit(comment)}>{labels.save}</button
182
+ <Button variant="ghost" size="sm" onclick={() => (editingId = null)}
183
+ >{labels.cancel}</Button
184
184
  >
185
+ <Button size="sm" onclick={() => saveEdit(comment)}>{labels.save}</Button>
185
186
  </div>
186
187
  {:else}
187
188
  <p class="text-sm leading-relaxed whitespace-pre-wrap text-pretty">{comment.body}</p>
@@ -191,102 +192,30 @@
191
192
  {/each}
192
193
  </ol>
193
194
  {:else if !onSend}
194
- <p class="text-[13px] text-muted-foreground">{labels.commentsEmpty}</p>
195
+ <p class="text-(length:--text-control) text-muted-foreground">{labels.commentsEmpty}</p>
195
196
  {/if}
196
197
 
197
198
  {#if onSend}
198
- <div
199
- class="rounded-lg border border-input transition-shadow focus-within:ring-3 focus-within:ring-ring/50"
200
- >
201
- <textarea
199
+ <!-- The send button sits inside the field's bottom edge, so the composer reads as one box. -->
200
+ <div class="relative">
201
+ <Textarea
202
202
  bind:value={draft}
203
203
  onkeydown={onComposerKeydown}
204
204
  rows={2}
205
205
  placeholder={labels.commentPlaceholder}
206
206
  aria-label={labels.commentPlaceholder}
207
- class="block max-h-60 min-h-16 w-full resize-none border-0 bg-transparent px-3 py-2 text-sm leading-relaxed outline-none [field-sizing:content] placeholder:text-muted-foreground"
208
- ></textarea>
209
- <div class="flex justify-end px-2 pb-2">
210
- <button
211
- type="button"
212
- class="thread-button thread-primary"
213
- onclick={send}
214
- disabled={!canSend}
215
- >
216
- {sending ? labels.saving : labels.commentSend}
217
- </button>
218
- </div>
207
+ class="max-h-60 resize-none px-3 pb-11 leading-relaxed"
208
+ />
209
+ <!-- An empty draft reads as an outlined button, not a faded fill. -->
210
+ <Button
211
+ size="sm"
212
+ variant={canSend ? "default" : "outline"}
213
+ class="absolute end-2 bottom-2 disabled:opacity-100"
214
+ onclick={send}
215
+ disabled={!canSend}
216
+ >
217
+ {sending ? labels.saving : labels.commentSend}
218
+ </Button>
219
219
  </div>
220
220
  {/if}
221
221
  </section>
222
-
223
- <style>
224
- .thread-icon {
225
- display: grid;
226
- place-items: center;
227
- width: 1.75rem;
228
- height: 1.75rem;
229
- border-radius: var(--radius-md, 0.5rem);
230
- color: var(--color-muted-foreground);
231
- outline: none;
232
- transition: background-color var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out);
233
- }
234
-
235
- @media (hover: hover) and (pointer: fine) {
236
- .thread-icon:hover {
237
- background: var(--color-muted);
238
- color: var(--color-foreground);
239
- }
240
- }
241
-
242
- .thread-icon:focus-visible,
243
- .thread-button:focus-visible {
244
- box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-ring) 50%, transparent);
245
- }
246
-
247
- .thread-button {
248
- height: 1.75rem;
249
- padding-inline: 0.75rem;
250
- border-radius: var(--radius-md, 0.5rem);
251
- font-size: 0.8125rem;
252
- font-weight: 500;
253
- outline: none;
254
- transition: background-color var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out);
255
- }
256
-
257
- @media (hover: hover) and (pointer: fine) {
258
- .thread-button:hover:not(:disabled) {
259
- background: var(--color-muted);
260
- }
261
- }
262
-
263
- .thread-button:disabled {
264
- opacity: 0.5;
265
- pointer-events: none;
266
- }
267
-
268
- .thread-primary {
269
- background: var(--color-primary);
270
- color: var(--color-primary-foreground);
271
- }
272
-
273
- /* An empty draft reads as an outlined button, not a faded fill. */
274
- .thread-primary:disabled {
275
- opacity: 1;
276
- background: transparent;
277
- box-shadow: inset 0 0 0 1px var(--color-border);
278
- color: var(--color-muted-foreground);
279
- }
280
-
281
- @media (hover: hover) and (pointer: fine) {
282
- .thread-primary:hover:not(:disabled) {
283
- background: color-mix(in oklab, var(--color-primary) 90%, transparent);
284
- }
285
- }
286
-
287
- @media (any-pointer: coarse) {
288
- .thread-button {
289
- height: 2.5rem;
290
- }
291
- }
292
- </style>
@@ -2,6 +2,7 @@
2
2
  // =========================
3
3
  // IMPORTS
4
4
  // =========================
5
+ import { docLooks } from "../../components/work-parts/looks.js";
5
6
  import type { Editor } from "@tiptap/core";
6
7
  import { FileText } from "phosphor-svelte";
7
8
  import type { Snippet } from "svelte";
@@ -105,11 +106,11 @@
105
106
  <!-- =========================== -->
106
107
  <!-- MARKUP -->
107
108
  <!-- =========================== -->
108
- <div class="@container/doc flex h-full min-h-0 flex-col bg-background text-foreground">
109
+ <div class="@container/doc flex h-full min-h-0 flex-col bg-card text-foreground">
109
110
  <header
110
111
  class="flex h-11 shrink-0 items-center gap-2 border-b border-border/70 px-3 @2xl/doc:px-4"
111
112
  >
112
- <div class="flex min-w-0 flex-1 items-center gap-1 text-[13px]">
113
+ <div class="flex min-w-0 flex-1 items-center gap-1 text-(length:--text-control)">
113
114
  {#if breadcrumb}{@render breadcrumb()}{/if}
114
115
  {#if menu}{@render menu()}{/if}
115
116
  </div>
@@ -133,7 +134,7 @@
133
134
  </div>
134
135
  <!-- Narrow: the strip the reading pages use, since a phone has no gutter. -->
135
136
  <div
136
- class="absolute inset-x-0 top-0 z-20 border-b border-border/70 bg-background/95 backdrop-blur @4xl/doc:hidden"
137
+ class="absolute inset-x-0 top-0 z-20 border-b border-border/70 bg-card/95 backdrop-blur @4xl/doc:hidden"
137
138
  >
138
139
  <OnThisPage
139
140
  variant="bar"
@@ -152,7 +153,7 @@
152
153
  : 'pt-8 @2xl/doc:pt-14'}"
153
154
  >
154
155
  <div
155
- class="mb-4 flex size-12 items-center justify-center rounded-xl border border-border bg-muted/40 text-muted-foreground"
156
+ class="mb-4 flex size-12 items-center justify-center {docLooks.tile} border border-border bg-muted/40 text-muted-foreground"
156
157
  >
157
158
  {#if icon}{@render icon()}{:else}<FileText size={22} aria-hidden="true" />{/if}
158
159
  </div>
@@ -2,6 +2,7 @@
2
2
  // =========================
3
3
  // IMPORTS
4
4
  // =========================
5
+ import { docLooks } from "../../components/work-parts/looks.js";
5
6
  import {
6
7
  ArrowsOutCardinal,
7
8
  CaretLeft,
@@ -238,7 +239,7 @@
238
239
  <button
239
240
  {...props}
240
241
  type="button"
241
- class="t-press inline-flex size-7 items-center justify-center rounded-md text-muted-foreground transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/6 hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 aria-expanded:bg-foreground/6 aria-expanded:text-foreground any-pointer-coarse:size-10"
242
+ class="t-press inline-flex size-7 items-center justify-center {docLooks.control} text-muted-foreground transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/6 hover:text-foreground focus-visible:shadow-(--ring-focus) aria-expanded:bg-foreground/6 aria-expanded:text-foreground any-pointer-coarse:size-10"
242
243
  >
243
244
  <DotsThree size={18} weight="bold" aria-hidden="true" />
244
245
  </button>
@@ -246,7 +247,7 @@
246
247
  {/snippet}
247
248
  </PopoverTrigger>
248
249
  <PopoverContent align="start" sideOffset={6} class="w-64 gap-0 overflow-hidden p-0">
249
- <Command shouldFilter={false} onkeydown={onListKey} class="rounded-xl">
250
+ <Command shouldFilter={false} onkeydown={onListKey}>
250
251
  <CommandInput
251
252
  bind:value={query}
252
253
  placeholder={page === "copy" ? t.copy : t.filter}
@@ -284,7 +285,9 @@
284
285
  </CommandGroup>
285
286
  {/each}
286
287
  {#if visible.length === 0}
287
- <CommandEmpty class="py-6 text-center text-[13px] text-muted-foreground">
288
+ <CommandEmpty
289
+ class="py-6 text-center text-(length:--text-control) text-muted-foreground"
290
+ >
288
291
  {t.noResults}
289
292
  </CommandEmpty>
290
293
  {/if}
@@ -304,7 +307,9 @@
304
307
  {/each}
305
308
  </CommandGroup>
306
309
  {#if copies.length === 0}
307
- <CommandEmpty class="py-6 text-center text-[13px] text-muted-foreground">
310
+ <CommandEmpty
311
+ class="py-6 text-center text-(length:--text-control) text-muted-foreground"
312
+ >
308
313
  {t.noResults}
309
314
  </CommandEmpty>
310
315
  {/if}
@@ -2,6 +2,7 @@
2
2
  // =========================
3
3
  // IMPORTS
4
4
  // =========================
5
+ import { docLooks } from "../../components/work-parts/looks.js";
5
6
  import { Bell, FileText, LinkSimple, Star } from "phosphor-svelte";
6
7
  import DocEditorPage from "./doc-editor-page.svelte";
7
8
  import DocMenu from "./doc-menu.svelte";
@@ -139,7 +140,7 @@
139
140
  <!-- =========================== -->
140
141
  <div class="flex flex-col gap-2">
141
142
  <div
142
- class="h-[min(48rem,calc(100svh-9rem))] overflow-hidden rounded-xl border border-border bg-background"
143
+ class="h-[min(48rem,calc(100svh-9rem))] overflow-hidden {docLooks.frame} border border-border bg-card"
143
144
  >
144
145
  <DocEditorPage
145
146
  bind:title
@@ -165,7 +166,7 @@
165
166
  aria-label={favorited ? "Remove from favorites" : "Favorite"}
166
167
  aria-pressed={favorited}
167
168
  onclick={() => (favorited = !favorited)}
168
- class="t-press inline-flex size-7 items-center justify-center rounded-md text-muted-foreground transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/6 hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 any-pointer-coarse:size-10"
169
+ class="t-press inline-flex size-7 items-center justify-center {docLooks.control} text-muted-foreground transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/6 hover:text-foreground focus-visible:shadow-(--ring-focus) any-pointer-coarse:size-10"
169
170
  >
170
171
  <Star
171
172
  size={15}
@@ -202,8 +203,7 @@
202
203
  {/snippet}
203
204
 
204
205
  {#snippet actions()}
205
- {@const button =
206
- "t-press inline-flex size-7 items-center justify-center rounded-md text-muted-foreground transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/6 hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 any-pointer-coarse:size-10"}
206
+ {@const button = `t-press inline-flex size-7 items-center justify-center ${docLooks.control} text-muted-foreground transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/6 hover:text-foreground focus-visible:shadow-(--ring-focus) any-pointer-coarse:size-10`}
207
207
  <button
208
208
  type="button"
209
209
  aria-label="Copy link"
@@ -2,6 +2,7 @@
2
2
  // =========================
3
3
  // IMPORTS
4
4
  // =========================
5
+ import { docLooks } from "../../components/work-parts/looks.js";
5
6
  import { ClockCounterClockwise, SlidersHorizontal } from "phosphor-svelte";
6
7
  import { Avatar, AvatarFallback, AvatarImage } from "../../shadcn/avatar/index.js";
7
8
  import { Popover, PopoverContent, PopoverTrigger } from "../../shadcn/popover/index.js";
@@ -70,13 +71,17 @@
70
71
  {#if hasDetails}
71
72
  <Popover>
72
73
  <PopoverTrigger
73
- class="t-press inline-flex h-7 items-center gap-1.5 rounded-md bg-foreground/5 px-2 @max-xl/doc:px-1.5 text-[13px] font-medium text-foreground/90 tabular-nums transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/8 focus-visible:ring-3 focus-visible:ring-ring/50 aria-expanded:bg-foreground/8 any-pointer-coarse:h-10"
74
+ class="t-press inline-flex h-7 items-center gap-1.5 {docLooks.chip} bg-foreground/5 px-2 @max-xl/doc:px-1.5 text-(length:--text-control) font-medium text-foreground/90 tabular-nums transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/8 focus-visible:shadow-(--ring-focus) aria-expanded:bg-foreground/8 any-pointer-coarse:h-10"
74
75
  >
75
76
  <SlidersHorizontal size={14} class="text-muted-foreground" aria-hidden="true" />
76
77
  <!-- On a narrow page the glyph stands alone, so the title keeps the bar. -->
77
78
  <span class="@max-xl/doc:sr-only">{chip}</span>
78
79
  </PopoverTrigger>
79
- <PopoverContent align="end" sideOffset={6} class="w-[21.5rem] gap-0 p-0 text-[13px]">
80
+ <PopoverContent
81
+ align="end"
82
+ sideOffset={6}
83
+ class="w-[21.5rem] gap-0 p-0 text-(length:--text-control)"
84
+ >
80
85
  <div class="divide-y divide-border/70">
81
86
  {#if onshowauthors}
82
87
  <div class="flex items-center justify-between px-4 py-3">
@@ -108,7 +113,7 @@
108
113
  <button
109
114
  type="button"
110
115
  onclick={onhistory}
111
- class="t-press flex h-8 w-full items-center justify-center gap-2 rounded-lg bg-foreground/5 font-medium transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/8 focus-visible:ring-3 focus-visible:ring-ring/50"
116
+ class="t-press flex h-8 w-full items-center justify-center gap-2 {docLooks.control} bg-foreground/5 font-medium transition-colors duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)] outline-none hover:bg-foreground/8 focus-visible:shadow-(--ring-focus)"
112
117
  >
113
118
  <ClockCounterClockwise size={14} aria-hidden="true" />
114
119
  {t.showHistory}
@@ -119,7 +124,9 @@
119
124
  </PopoverContent>
120
125
  </Popover>
121
126
  {:else}
122
- <span class="inline-flex h-7 items-center text-[13px] text-muted-foreground tabular-nums">
127
+ <span
128
+ class="inline-flex h-7 items-center text-(length:--text-control) text-muted-foreground tabular-nums"
129
+ >
123
130
  {chip}
124
131
  </span>
125
132
  {/if}
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { ganttLooks } from "../../components/work-parts/looks.js";
2
3
  import { cn } from "../../lib/utils.js";
3
4
  import { isoFromDay } from "../dates.js";
4
5
  import type { GanttChange } from "../task-types.js";
@@ -101,7 +102,8 @@
101
102
  ? ' Arrow keys move it a day, Shift plus arrow keys change its end.'
102
103
  : ''}"
103
104
  class={cn(
104
- "g-bar g-enter absolute top-1/2 flex -translate-y-1/2 items-center rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-ring/60",
105
+ "g-bar g-enter absolute top-1/2 flex -translate-y-1/2 items-center outline-none focus-visible:shadow-(--ring-focus)",
106
+ ganttLooks.bar,
105
107
  editable && "cursor-grab",
106
108
  dragging && "g-bar-dragging cursor-grabbing",
107
109
  )}
@@ -120,7 +122,7 @@
120
122
  >
121
123
  {#if progress > 0}
122
124
  <!-- The clip keeps the bar's rounded corners while the fill scales. -->
123
- <span class="absolute inset-0 overflow-hidden rounded-lg" aria-hidden="true">
125
+ <span class={cn("absolute inset-0 overflow-hidden", ganttLooks.bar)} aria-hidden="true">
124
126
  <span class="g-progress absolute inset-0 origin-left" style:transform="scaleX({progress})"
125
127
  ></span>
126
128
  </span>
@@ -140,7 +142,8 @@
140
142
  {#if dragging && drag && drag.dx !== 0}
141
143
  <span
142
144
  class={cn(
143
- "g-tip pointer-events-none absolute left-0 z-20 rounded-md bg-foreground px-2 py-1 text-[11px] font-medium whitespace-nowrap text-background tabular-nums shadow-md",
145
+ "g-tip pointer-events-none absolute left-0 z-20",
146
+ ganttLooks.tip,
144
147
  tipBelow ? "top-full mt-1.5" : "bottom-full mb-1.5",
145
148
  )}
146
149
  >
@@ -150,7 +153,10 @@
150
153
  </div>
151
154
  {#if width < inlineTitleMin}
152
155
  <span
153
- class="pointer-events-none absolute top-1/2 -translate-y-1/2 truncate rounded-sm bg-card/90 px-1 text-xs text-muted-foreground"
156
+ class={cn(
157
+ "pointer-events-none absolute top-1/2 -translate-y-1/2 truncate",
158
+ ganttLooks.outsideLabel,
159
+ )}
154
160
  style:left="{dayX(layout, span.end + 1) + 16}px"
155
161
  style:max-width="200px"
156
162
  >
@@ -165,9 +171,9 @@
165
171
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--g-hue) 34%, transparent);
166
172
  /* Snapping to whole days reads as a glide, not a jump. */
167
173
  transition:
168
- left var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)),
169
- width var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)),
170
- box-shadow var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out);
174
+ left var(--duration-quick) var(--ease-smooth-out),
175
+ width var(--duration-quick) var(--ease-smooth-out),
176
+ box-shadow var(--duration-quick) var(--ease-smooth-out);
171
177
  }
172
178
 
173
179
  @media (hover: hover) and (pointer: fine) {
@@ -192,8 +198,7 @@
192
198
 
193
199
  .g-progress {
194
200
  background: color-mix(in oklab, var(--g-hue) 32%, var(--color-card, white));
195
- transition: transform var(--duration-fast, 250ms)
196
- var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
201
+ transition: transform var(--duration-fast) var(--ease-smooth-out);
197
202
  }
198
203
 
199
204
  /* Resize grips: a wide invisible hit area, a slim pill that shows on hover. */
@@ -214,10 +219,9 @@
214
219
  left: 50%;
215
220
  width: 3px;
216
221
  translate: -50% 0;
217
- border-radius: 999px;
218
- background: color-mix(in oklab, var(--g-hue) 70%, var(--color-foreground, black));
222
+ background: color-mix(in oklab, var(--g-hue) 70%, var(--color-foreground));
219
223
  opacity: 0;
220
- transition: opacity var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out);
224
+ transition: opacity var(--duration-quick) var(--ease-smooth-out);
221
225
  }
222
226
 
223
227
  @media (hover: hover) and (pointer: fine) {
@@ -232,13 +236,13 @@
232
236
  }
233
237
 
234
238
  .g-tip {
235
- animation: g-tip-in var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out) both;
239
+ animation: g-tip-in var(--duration-quick) var(--ease-smooth-out) both;
236
240
  }
237
241
 
238
242
  @keyframes g-tip-in {
239
243
  from {
240
244
  opacity: 0;
241
- translate: 0 var(--distance-micro, 4px);
245
+ translate: 0 var(--distance-micro);
242
246
  }
243
247
  }
244
248
 
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { ganttLooks } from "../../components/work-parts/looks.js";
3
+ import { cn } from "../../lib/utils.js";
2
4
  import { dayX, type Arrow, type GanttDay, type Layout } from "./logic.js";
3
5
 
4
6
  interface Props {
@@ -41,7 +43,7 @@
41
43
  class="g-today absolute inset-y-0 w-px bg-primary"
42
44
  style:left="{dayX(layout, layout.todayDay) + layout.dayWidth / 2}px"
43
45
  >
44
- <span class="absolute -top-1 -left-[3px] size-[7px] rounded-full bg-primary"></span>
46
+ <span class={cn("absolute -top-1 -left-[3px] size-[7px] bg-primary", ganttLooks.day)}></span>
45
47
  </div>
46
48
  {/if}
47
49
  <svg
@@ -73,13 +75,12 @@
73
75
  <style>
74
76
  .g-today {
75
77
  transform-origin: top;
76
- animation: g-today-in var(--duration-slow, 300ms)
77
- var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)) backwards;
78
+ animation: g-today-in var(--duration-slow) var(--ease-smooth-out) backwards;
78
79
  }
79
80
 
80
81
  .g-arrow {
81
82
  stroke: color-mix(in oklab, var(--color-muted-foreground, gray) 55%, transparent);
82
- transition: stroke var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out);
83
+ transition: stroke var(--duration-quick) var(--ease-smooth-out);
83
84
  }
84
85
 
85
86
  .g-arrow-lit {
@@ -89,12 +90,11 @@
89
90
  .g-arrow-line {
90
91
  stroke-dasharray: 1;
91
92
  stroke-dashoffset: 0;
92
- animation: g-draw var(--duration-slow, 300ms)
93
- var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)) 300ms backwards;
93
+ animation: g-draw var(--duration-slow) var(--ease-smooth-out) 300ms backwards;
94
94
  }
95
95
 
96
96
  .g-arrow-head {
97
- animation: g-fade var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out) 700ms backwards;
97
+ animation: g-fade var(--duration-quick) var(--ease-smooth-out) 700ms backwards;
98
98
  }
99
99
 
100
100
  @keyframes g-today-in {
@@ -1,4 +1,7 @@
1
1
  <script lang="ts">
2
+ import { ganttLooks } from "../../components/work-parts/looks.js";
3
+ import { cn } from "../../lib/utils.js";
4
+ import GroupHead from "../../components/work-parts/group-head.svelte";
2
5
  import { barWidth, dayX, type GroupRow, type Layout } from "./logic.js";
3
6
  import "./gantt.css";
4
7
 
@@ -23,19 +26,13 @@
23
26
  <!-- Opaque card under the row's muted tint, so bars never show through the pinned column. -->
24
27
  <div class="sticky left-0 z-10 w-(--g-label) shrink-0 border-r border-border bg-card">
25
28
  <div class="flex h-full items-center gap-2 bg-muted/30 px-3">
26
- <span class="size-2 shrink-0 rounded-full" style:background={hue}></span>
27
- <span class="truncate text-sm font-medium text-foreground">{row.group.label}</span>
28
- <span
29
- class="grid h-5 min-w-5 place-items-center rounded-sm bg-foreground/5 px-1 text-xs font-medium text-muted-foreground tabular-nums"
30
- >
31
- {row.count.toLocaleString()}
32
- </span>
29
+ <GroupHead label={row.group.label} {hue} count={row.count} />
33
30
  </div>
34
31
  </div>
35
32
  <div class="relative shrink-0" style:width="{layout.timelineWidth}px">
36
33
  {#if row.span}
37
34
  <div
38
- class="g-summary g-enter absolute top-1/2 h-1.5 -translate-y-1/2 rounded-full"
35
+ class={cn("g-summary g-enter absolute top-1/2 h-1.5 -translate-y-1/2", ganttLooks.track)}
39
36
  style:--g-hue={hue}
40
37
  style:--g-i={Math.min(index, staggerCap)}
41
38
  style:left="{dayX(layout, row.span.start) + layout.inset}px"
@@ -49,8 +46,8 @@
49
46
  .g-summary {
50
47
  background: color-mix(in oklab, var(--g-hue) 45%, transparent);
51
48
  transition:
52
- left var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)),
53
- width var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
49
+ left var(--duration-quick) var(--ease-smooth-out),
50
+ width var(--duration-quick) var(--ease-smooth-out);
54
51
  }
55
52
 
56
53
  @media (prefers-reduced-motion: reduce) {
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { ganttLooks } from "../../components/work-parts/looks.js";
2
3
  import { cn } from "../../lib/utils.js";
3
4
  import type { GanttDay, Layout } from "./logic.js";
4
5
 
@@ -62,7 +63,8 @@
62
63
  {#if showNumber}
63
64
  <span
64
65
  class={cn(
65
- "grid h-4 min-w-4 place-items-center rounded-full px-1 font-medium",
66
+ "grid h-4 min-w-4 place-items-center px-1 font-medium",
67
+ ganttLooks.day,
66
68
  layout.dayWidth < 18 && "absolute left-1 whitespace-nowrap",
67
69
  isToday && "bg-primary text-primary-foreground",
68
70
  )}