@heyramzi/ui 2.20.0 → 2.21.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/README.md +2 -0
- package/dist/charts/dashboard/data-table.js +1 -2
- package/dist/components/list-page/filter-section.js +1 -1
- package/dist/components/list-page/list-table.js +5 -6
- package/dist/components/list-page/queue-rail.js +2 -1
- package/dist/components/picker/trigger.js +3 -3
- package/dist/components/segmented/segmented.js +5 -5
- package/dist/components/work-parts/looks.js +1 -1
- package/dist/shadcn/alert/alert-variants.js +9 -0
- package/dist/shadcn/alert/index.js +1 -1
- package/dist/shadcn/badge/badge-variants.js +17 -0
- package/dist/shadcn/badge/index.js +1 -1
- package/dist/shadcn/dialog/index.js +3 -2
- package/dist/shadcn/dropdown-menu/menu-item.js +1 -1
- package/dist/shadcn/sheet/index.js +3 -2
- package/dist/shadcn/skeleton/index.js +3 -2
- package/dist/shadcn/toggle/index.js +1 -1
- package/dist/shadcn/toggle/toggle-variants.js +20 -0
- package/dist/status/index.js +2 -0
- package/dist/status/pill-tint.js +13 -0
- package/dist/work/kanban-drag.js +13 -7
- package/package.json +23 -23
- package/src/ai/confirmation/ConfirmationTitle.svelte +1 -4
- package/src/ai/loading-state/PixelLoader.svelte +1 -1
- package/src/animations/dropdown.css +19 -10
- package/src/animations/modal.css +7 -2
- package/src/charts/charts.css +3 -5
- package/src/charts/dashboard/dashboard-section.svelte +1 -1
- package/src/charts/dashboard/data-table.ts +1 -2
- package/src/charts/dashboard/stat-tile.svelte +1 -1
- package/src/charts/number-chart.css +8 -7
- package/src/charts/pop-value.svelte +68 -0
- package/src/charts/primitives/chart-tooltip.svelte +1 -1
- package/src/charts/reference-line.css +1 -1
- package/src/charts/stat-card.css +4 -4
- package/src/components/copy/copy-button.svelte +11 -10
- package/src/components/data-table/row-arrow.svelte +1 -1
- package/src/components/data-table/row-context-menu.svelte +1 -1
- package/src/components/data-table/sortable-head.svelte +2 -2
- package/src/components/data-table/table-skeleton.svelte +5 -5
- package/src/components/docs/doc-page.svelte +1 -3
- package/src/components/docs/on-this-page.svelte +4 -4
- package/src/components/field-row/field-row.svelte +1 -1
- package/src/components/list-page/detail-empty.svelte +3 -8
- package/src/components/list-page/detail-header.svelte +1 -1
- package/src/components/list-page/detail-row.svelte +2 -1
- package/src/components/list-page/empty-state.svelte +15 -7
- package/src/components/list-page/filter-item.svelte +2 -2
- package/src/components/list-page/filter-popover.svelte +1 -1
- package/src/components/list-page/filter-section.ts +1 -4
- package/src/components/list-page/grouped-list.svelte +37 -8
- package/src/components/list-page/list-page-shell.svelte +1 -1
- package/src/components/list-page/list-table.ts +6 -6
- package/src/components/list-page/master-detail.svelte +1 -1
- package/src/components/list-page/queue-rail.ts +2 -2
- package/src/components/list-page/rail-empty.svelte +1 -1
- package/src/components/list-page/rail-row.svelte +5 -5
- package/src/components/open-in/open-in.svelte +2 -1
- package/src/components/picker/trigger.ts +6 -5
- package/src/components/section-card/section-card.svelte +1 -1
- package/src/components/section-header/section-header.svelte +4 -2
- package/src/components/section-header/section-label.svelte +2 -2
- package/src/components/segmented/animated-tabs.svelte +1 -1
- package/src/components/segmented/section-runs.svelte +1 -1
- package/src/components/segmented/segment.svelte +4 -6
- package/src/components/segmented/segmented-track.svelte +18 -52
- package/src/components/segmented/segmented.ts +5 -5
- package/src/components/table-view/table-view.svelte +43 -24
- package/src/components/tags-input/tags-input.svelte +17 -31
- package/src/components/work-parts/looks.ts +1 -1
- package/src/editor/content.css +3 -3
- package/src/editor/editor.svelte +1 -1
- package/src/inbox/thread-inbox.svelte +2 -9
- package/src/panel/side-panel.svelte +9 -4
- package/src/record/info-list.svelte +7 -8
- package/src/record/project-list.svelte +1 -1
- package/src/record/record-demo.svelte +2 -4
- package/src/record/record-rail.svelte +5 -1
- package/src/record/record-shell.svelte +1 -1
- package/src/record/record-stats.svelte +9 -3
- package/src/record/steps-rail.svelte +7 -11
- package/src/shadcn/accordion/accordion-trigger.svelte +1 -1
- package/src/shadcn/alert/alert-variants.ts +17 -0
- package/src/shadcn/alert/alert.svelte +2 -16
- package/src/shadcn/alert/index.ts +1 -1
- package/src/shadcn/alert-dialog/alert-dialog-content.svelte +5 -1
- package/src/shadcn/alert-dialog/alert-dialog-footer.svelte +12 -2
- package/src/shadcn/alert-dialog/alert-dialog-header.svelte +1 -1
- package/src/shadcn/alert-dialog/alert-dialog-title.svelte +1 -1
- package/src/shadcn/badge/badge-variants.ts +23 -0
- package/src/shadcn/badge/badge.svelte +2 -20
- package/src/shadcn/badge/index.ts +1 -1
- package/src/shadcn/bubble/bubble-content.svelte +1 -1
- package/src/shadcn/bubble/bubble.svelte +1 -1
- package/src/shadcn/button/button.svelte +11 -5
- package/src/shadcn/calendar/calendar-month-select.svelte +1 -1
- package/src/shadcn/calendar/calendar-year-select.svelte +1 -1
- package/src/shadcn/calendar/calendar.svelte +1 -1
- package/src/shadcn/card/card.svelte +2 -1
- package/src/shadcn/checkbox/checkbox.svelte +1 -1
- package/src/shadcn/code-block/code-block-actions.svelte +1 -1
- package/src/shadcn/command/command-dialog.svelte +2 -2
- package/src/shadcn/command/command-group.svelte +1 -1
- package/src/shadcn/command/command-input.svelte +1 -1
- package/src/shadcn/command/command-item.svelte +1 -1
- package/src/shadcn/dialog/dialog-body.svelte +22 -0
- package/src/shadcn/dialog/dialog-content.svelte +19 -4
- package/src/shadcn/dialog/dialog-footer.svelte +19 -1
- package/src/shadcn/dialog/dialog-header.svelte +6 -1
- package/src/shadcn/dialog/dialog-title.svelte +2 -1
- package/src/shadcn/dialog/index.ts +3 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-content.svelte +5 -1
- package/src/shadcn/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
- package/src/shadcn/dropdown-menu/menu-item.ts +1 -1
- package/src/shadcn/field/field-separator.svelte +1 -1
- package/src/shadcn/hover-card/hover-card-content.svelte +1 -1
- package/src/shadcn/input/input.svelte +2 -2
- package/src/shadcn/input-otp/input-otp-slot.svelte +1 -1
- package/src/shadcn/message-scroller/message-scroller-button.svelte +1 -1
- package/src/shadcn/popover/popover-content.svelte +1 -1
- package/src/shadcn/radio-group/radio-group-item.svelte +1 -1
- package/src/shadcn/scroll-area/scroll-area.svelte +1 -1
- package/src/shadcn/select/select-content.svelte +6 -2
- package/src/shadcn/select/select-item.svelte +1 -1
- package/src/shadcn/select/select-trigger.svelte +1 -1
- package/src/shadcn/sheet/index.ts +3 -0
- package/src/shadcn/sheet/sheet-body.svelte +22 -0
- package/src/shadcn/sheet/sheet-content.svelte +27 -5
- package/src/shadcn/sheet/sheet-footer.svelte +14 -2
- package/src/shadcn/sheet/sheet-header.svelte +1 -1
- package/src/shadcn/sheet/sheet-title.svelte +1 -1
- package/src/shadcn/sheet/sheet.css +11 -5
- package/src/shadcn/sidebar/sidebar-group-action.svelte +1 -1
- package/src/shadcn/sidebar/sidebar-group-label.svelte +1 -1
- package/src/shadcn/sidebar/sidebar-inset.svelte +1 -1
- package/src/shadcn/sidebar/sidebar-menu-action.svelte +1 -1
- package/src/shadcn/sidebar/sidebar-menu-button.svelte +2 -2
- package/src/shadcn/sidebar/sidebar-menu-sub-button.svelte +1 -1
- package/src/shadcn/sidebar/sidebar-menu.svelte +1 -1
- package/src/shadcn/sidebar/sidebar.svelte +1 -1
- package/src/shadcn/skeleton/index.ts +3 -0
- package/src/shadcn/skeleton/skeleton-delay.svelte +63 -0
- package/src/shadcn/skeleton/skeleton-delay.svelte.test.ts +57 -0
- package/src/shadcn/skeleton/skeleton.svelte +5 -1
- package/src/shadcn/slider/slider.svelte +1 -1
- package/src/shadcn/switch/switch.svelte +2 -2
- package/src/shadcn/table/table-row.svelte +1 -1
- package/src/shadcn/tabs/tabs-list.svelte +1 -1
- package/src/shadcn/tabs/tabs-trigger.svelte +2 -1
- package/src/shadcn/textarea/textarea.svelte +1 -1
- package/src/shadcn/toggle/index.ts +1 -1
- package/src/shadcn/toggle/toggle-variants.ts +26 -0
- package/src/shadcn/toggle/toggle.svelte +7 -25
- package/src/shadcn/toggle-group/toggle-group.svelte +1 -1
- package/src/shadcn/tooltip/tooltip-content.svelte +1 -1
- package/src/shadcn/trace/trace-collapsible-trigger.svelte +1 -1
- package/src/shadcn/trace/trace.svelte +1 -1
- package/src/status/README.md +1 -1
- package/src/status/index.ts +2 -0
- package/src/status/pill-tint.ts +16 -0
- package/src/status/status-badge.svelte +21 -7
- package/src/status/status-dot.svelte +6 -11
- package/src/status/status-pill.svelte +40 -0
- package/src/svelte-reexports.test.ts +43 -0
- package/src/thread/thread.svelte +54 -136
- package/src/tokens/craft.css +55 -36
- package/src/tokens/palette.css +16 -9
- package/src/work/demo.svelte +48 -42
- package/src/work/detail/detail-demo.svelte +33 -24
- package/src/work/detail/task-chip.svelte +4 -4
- package/src/work/detail/task-detail.svelte +41 -108
- package/src/work/detail/task-property.svelte +7 -13
- package/src/work/detail/task-thread.svelte +48 -119
- package/src/work/docs/doc-editor-page.svelte +5 -4
- package/src/work/docs/doc-menu.svelte +9 -4
- package/src/work/docs/docs-demo.svelte +4 -4
- package/src/work/docs/edited-chip.svelte +11 -4
- package/src/work/gantt/gantt-bar.svelte +18 -14
- package/src/work/gantt/gantt-grid.svelte +7 -7
- package/src/work/gantt/gantt-group-row.svelte +7 -10
- package/src/work/gantt/gantt-header.svelte +3 -1
- package/src/work/gantt/gantt-task-row.svelte +19 -9
- package/src/work/gantt/gantt.css +4 -5
- package/src/work/inbox/inbox-card.svelte +32 -10
- package/src/work/inbox/inbox-draft.svelte +2 -2
- package/src/work/kanban-column.svelte +7 -15
- package/src/work/kanban-drag.ts +13 -8
- package/src/work/task-gantt.svelte +2 -1
- package/src/work/task-list.svelte +54 -53
- package/src/work/time/time-chip.svelte +16 -19
- package/src/work/time/time-dot.svelte +2 -1
- package/src/work/time/time-ring.svelte +2 -3
- package/src/work/time/time-tracker.svelte +72 -166
package/src/work/demo.svelte
CHANGED
|
@@ -3,7 +3,19 @@
|
|
|
3
3
|
import TaskList from "./task-list.svelte";
|
|
4
4
|
import TaskGantt from "./task-gantt.svelte";
|
|
5
5
|
import { SegmentedFilter } from "../components/segmented/index.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
CalendarBlank,
|
|
8
|
+
CellSignalFull,
|
|
9
|
+
CellSignalLow,
|
|
10
|
+
CellSignalMedium,
|
|
11
|
+
ChartBarHorizontal,
|
|
12
|
+
Kanban,
|
|
13
|
+
ListBullets,
|
|
14
|
+
} from "phosphor-svelte";
|
|
15
|
+
import StatusPill from "../status/status-pill.svelte";
|
|
16
|
+
import { Card } from "../shadcn/card/index.js";
|
|
17
|
+
import WorkCard from "../components/work-parts/work-card.svelte";
|
|
18
|
+
import type { Tone } from "../lib/tone.js";
|
|
7
19
|
import StatusBadge from "../status/status-badge.svelte";
|
|
8
20
|
import StatusDot from "../status/status-dot.svelte";
|
|
9
21
|
import { defineStatuses } from "../status/define-statuses.js";
|
|
@@ -161,11 +173,12 @@
|
|
|
161
173
|
{ id: "due", label: "Due date", compare: (a: Task, b: Task) => a.end.localeCompare(b.end) },
|
|
162
174
|
];
|
|
163
175
|
|
|
164
|
-
const
|
|
165
|
-
low: "
|
|
166
|
-
medium: "
|
|
167
|
-
high: "
|
|
176
|
+
const priorityTone: Record<Priority, Tone> = {
|
|
177
|
+
low: "neutral",
|
|
178
|
+
medium: "warning",
|
|
179
|
+
high: "destructive",
|
|
168
180
|
};
|
|
181
|
+
const priorityIcon = { low: CellSignalLow, medium: CellSignalMedium, high: CellSignalFull };
|
|
169
182
|
|
|
170
183
|
const people: Record<string, string> = {
|
|
171
184
|
Ada: "oklch(0.72 0.12 280)",
|
|
@@ -275,6 +288,14 @@
|
|
|
275
288
|
"grid grid-cols-[minmax(0,1fr)_7rem_5.5rem_4.5rem] items-center gap-3 max-sm:grid-cols-[minmax(0,1fr)_4.5rem]";
|
|
276
289
|
</script>
|
|
277
290
|
|
|
291
|
+
{#snippet priority(level: Priority)}
|
|
292
|
+
{@const Icon = priorityIcon[level]}
|
|
293
|
+
<StatusPill tone={priorityTone[level]} class="capitalize">
|
|
294
|
+
{#snippet icon()}<Icon weight="bold" aria-hidden="true" />{/snippet}
|
|
295
|
+
{level}
|
|
296
|
+
</StatusPill>
|
|
297
|
+
{/snippet}
|
|
298
|
+
|
|
278
299
|
{#snippet avatar(name: string)}
|
|
279
300
|
<span
|
|
280
301
|
class="grid size-5 shrink-0 place-items-center rounded-full text-[10px] font-semibold text-white"
|
|
@@ -285,7 +306,7 @@
|
|
|
285
306
|
</span>
|
|
286
307
|
{/snippet}
|
|
287
308
|
|
|
288
|
-
<
|
|
309
|
+
<Card class="gap-6 p-4">
|
|
289
310
|
<div class="flex h-[600px] flex-col gap-3">
|
|
290
311
|
<div class="flex flex-wrap items-center gap-2">
|
|
291
312
|
<SegmentedFilter options={views} bind:value={view} ariaLabel="Task view" block={false} />
|
|
@@ -312,7 +333,7 @@
|
|
|
312
333
|
<select
|
|
313
334
|
id="tasks-sort"
|
|
314
335
|
bind:value={sortKey}
|
|
315
|
-
class="h-8 rounded-md border border-border bg-
|
|
336
|
+
class="h-8 rounded-md border border-border bg-card px-2 text-xs text-foreground"
|
|
316
337
|
>
|
|
317
338
|
<option value="manual">Manual</option>
|
|
318
339
|
{#each sortKeys as key (key.id)}
|
|
@@ -338,15 +359,15 @@
|
|
|
338
359
|
>
|
|
339
360
|
{#snippet renderCard(task)}
|
|
340
361
|
{@const d = due(task)}
|
|
341
|
-
<
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
{@render avatar(task.assignee)}
|
|
347
|
-
<span class={d.late ? "font-medium text-destructive" : "text-muted-foreground"}
|
|
348
|
-
>{d.label}</span
|
|
362
|
+
<WorkCard>
|
|
363
|
+
{task.title}
|
|
364
|
+
{#snippet meta()}
|
|
365
|
+
<span
|
|
366
|
+
class="flex items-center gap-1 {d.late ? 'font-medium text-destructive' : ''}"
|
|
349
367
|
>
|
|
368
|
+
<CalendarBlank class="size-3.5" aria-hidden="true" />
|
|
369
|
+
{d.label}
|
|
370
|
+
</span>
|
|
350
371
|
{#if tracking}
|
|
351
372
|
<TimeChip
|
|
352
373
|
minutes={minutesByTask[task.id] ?? 0}
|
|
@@ -354,15 +375,12 @@
|
|
|
354
375
|
running={timer?.taskId === task.id}
|
|
355
376
|
/>
|
|
356
377
|
{/if}
|
|
357
|
-
<span
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
]}"
|
|
361
|
-
>
|
|
362
|
-
{task.priority}
|
|
378
|
+
<span class="ms-auto flex items-center gap-1.5">
|
|
379
|
+
{@render priority(task.priority)}
|
|
380
|
+
{@render avatar(task.assignee)}
|
|
363
381
|
</span>
|
|
364
|
-
|
|
365
|
-
</
|
|
382
|
+
{/snippet}
|
|
383
|
+
</WorkCard>
|
|
366
384
|
{/snippet}
|
|
367
385
|
</KanbanBoard>
|
|
368
386
|
{:else if view === "list"}
|
|
@@ -386,7 +404,7 @@
|
|
|
386
404
|
{/snippet}
|
|
387
405
|
{#snippet renderRow(task)}
|
|
388
406
|
{@const d = due(task)}
|
|
389
|
-
<div class="{listGrid}
|
|
407
|
+
<div class="{listGrid} px-2 text-sm">
|
|
390
408
|
<span class="flex min-w-0 items-center gap-2.5">
|
|
391
409
|
{#key task.status}
|
|
392
410
|
<StatusDot {statuses} status={task.status} />
|
|
@@ -410,15 +428,7 @@
|
|
|
410
428
|
{@render avatar(task.assignee)}
|
|
411
429
|
<span class="truncate">{task.assignee}</span>
|
|
412
430
|
</span>
|
|
413
|
-
<span class="max-sm:hidden">
|
|
414
|
-
<span
|
|
415
|
-
class="rounded-full px-1.5 py-0.5 text-xs font-medium capitalize {priorityClass[
|
|
416
|
-
task.priority
|
|
417
|
-
]}"
|
|
418
|
-
>
|
|
419
|
-
{task.priority}
|
|
420
|
-
</span>
|
|
421
|
-
</span>
|
|
431
|
+
<span class="max-sm:hidden">{@render priority(task.priority)}</span>
|
|
422
432
|
<span
|
|
423
433
|
class="text-right text-xs tabular-nums {d.late
|
|
424
434
|
? 'font-medium text-destructive'
|
|
@@ -469,13 +479,11 @@
|
|
|
469
479
|
{#if tracking}
|
|
470
480
|
<section class="flex flex-col gap-3 border-t border-border pt-4">
|
|
471
481
|
<div class="flex items-center justify-between gap-3">
|
|
472
|
-
<h3 class="text-xs font-semibold
|
|
473
|
-
Task time
|
|
474
|
-
</h3>
|
|
482
|
+
<h3 class="text-xs font-semibold text-muted-foreground">Task time</h3>
|
|
475
483
|
<select
|
|
476
484
|
bind:value={timeTaskId}
|
|
477
485
|
aria-label="Task"
|
|
478
|
-
class="h-8 max-w-[60%] rounded-md border border-border bg-
|
|
486
|
+
class="h-8 max-w-[60%] rounded-md border border-border bg-card px-2 text-xs text-foreground"
|
|
479
487
|
>
|
|
480
488
|
{#each tasks as task (task.id)}
|
|
481
489
|
<option value={task.id}>{task.title}</option>
|
|
@@ -483,7 +491,7 @@
|
|
|
483
491
|
</select>
|
|
484
492
|
</div>
|
|
485
493
|
<TimeTracker
|
|
486
|
-
class="
|
|
494
|
+
class="w-full max-w-xl"
|
|
487
495
|
entries={timeEntries}
|
|
488
496
|
getId={(entry) => entry.id}
|
|
489
497
|
getMinutes={(entry) => entry.minutes}
|
|
@@ -505,9 +513,7 @@
|
|
|
505
513
|
{/if}
|
|
506
514
|
|
|
507
515
|
<section class="flex flex-col gap-2 border-t border-border pt-4">
|
|
508
|
-
<h3 class="text-xs font-semibold
|
|
509
|
-
Status badges
|
|
510
|
-
</h3>
|
|
516
|
+
<h3 class="text-xs font-semibold text-muted-foreground">Status badges</h3>
|
|
511
517
|
<div class="flex flex-wrap items-center gap-2">
|
|
512
518
|
{#each salesStatuses.ids as id (id)}
|
|
513
519
|
<StatusBadge statuses={salesStatuses} status={id} />
|
|
@@ -522,7 +528,7 @@
|
|
|
522
528
|
{/each}
|
|
523
529
|
</ul>
|
|
524
530
|
</section>
|
|
525
|
-
</
|
|
531
|
+
</Card>
|
|
526
532
|
|
|
527
533
|
<style>
|
|
528
534
|
/* Switching views: the new one rises in with a touch of blur, the old one is gone at once. */
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
CalendarBlank,
|
|
4
|
+
CircleDashed,
|
|
5
|
+
CircleHalf,
|
|
6
|
+
Flag,
|
|
7
|
+
Folder,
|
|
8
|
+
Timer,
|
|
9
|
+
User,
|
|
10
|
+
UserCircle,
|
|
11
|
+
} from "phosphor-svelte";
|
|
12
|
+
import { Button } from "../../shadcn/button/index.js";
|
|
13
|
+
import { Card } from "../../shadcn/card/index.js";
|
|
14
|
+
import * as Avatar from "../../shadcn/avatar/index.js";
|
|
3
15
|
import TaskDetail from "./task-detail.svelte";
|
|
4
16
|
import TaskProperty from "./task-property.svelte";
|
|
5
17
|
import TaskChip from "./task-chip.svelte";
|
|
@@ -144,29 +156,27 @@
|
|
|
144
156
|
<div class="flex flex-col gap-3">
|
|
145
157
|
<div class="flex flex-wrap items-center gap-1.5" role="group" aria-label="Scenario">
|
|
146
158
|
{#each scenarios as item (item.id)}
|
|
147
|
-
<
|
|
148
|
-
|
|
159
|
+
<Button
|
|
160
|
+
size="sm"
|
|
161
|
+
variant={scenario === item.id ? "default" : "outline"}
|
|
149
162
|
aria-pressed={scenario === item.id}
|
|
150
163
|
onclick={() => (scenario = item.id)}
|
|
151
|
-
class="h-7 rounded-md border border-border px-2.5 text-[13px] font-medium transition-colors hover:bg-muted aria-pressed:bg-foreground aria-pressed:text-background"
|
|
152
164
|
>
|
|
153
165
|
{item.label}
|
|
154
|
-
</
|
|
166
|
+
</Button>
|
|
155
167
|
{/each}
|
|
156
|
-
<
|
|
157
|
-
|
|
168
|
+
<Button
|
|
169
|
+
size="sm"
|
|
170
|
+
variant={narrow ? "default" : "outline"}
|
|
171
|
+
class="ms-auto"
|
|
158
172
|
aria-pressed={narrow}
|
|
159
173
|
onclick={() => (narrow = !narrow)}
|
|
160
|
-
class="ms-auto h-7 rounded-md border border-border px-2.5 text-[13px] font-medium transition-colors hover:bg-muted aria-pressed:bg-foreground aria-pressed:text-background"
|
|
161
174
|
>
|
|
162
175
|
390 wide
|
|
163
|
-
</
|
|
176
|
+
</Button>
|
|
164
177
|
</div>
|
|
165
178
|
|
|
166
|
-
<
|
|
167
|
-
class="mx-auto w-full overflow-hidden rounded-xl border border-border bg-background"
|
|
168
|
-
style:max-width={narrow ? "390px" : "none"}
|
|
169
|
-
>
|
|
179
|
+
<Card class="mx-auto w-full gap-0 py-0" style="max-width: {narrow ? '390px' : 'none'}">
|
|
170
180
|
<TaskDetail
|
|
171
181
|
{title}
|
|
172
182
|
onTitleChange={(next) => {
|
|
@@ -192,35 +202,34 @@
|
|
|
192
202
|
<span class="tabular-nums">Created Sep 9, 2026</span>
|
|
193
203
|
{/snippet}
|
|
194
204
|
{#snippet properties()}
|
|
195
|
-
<TaskProperty label="Status">
|
|
205
|
+
<TaskProperty label="Status" icon={CircleHalf}>
|
|
196
206
|
<TaskChip aria-label="Status: {statusLabel}"
|
|
197
207
|
><StatusDot {statuses} {status} size={14} animate={false} />{statusLabel}</TaskChip
|
|
198
208
|
>
|
|
199
209
|
</TaskProperty>
|
|
200
|
-
<TaskProperty label="Priority">
|
|
210
|
+
<TaskProperty label="Priority" icon={Flag}>
|
|
201
211
|
<TaskChip><Flag weight="fill" class="text-destructive" aria-hidden="true" />High</TaskChip
|
|
202
212
|
>
|
|
203
213
|
</TaskProperty>
|
|
204
|
-
<TaskProperty label="Assignee">
|
|
214
|
+
<TaskProperty label="Assignee" icon={UserCircle}>
|
|
205
215
|
{#if assignee}
|
|
206
216
|
<TaskChip>
|
|
207
|
-
<
|
|
208
|
-
class="
|
|
209
|
-
|
|
210
|
-
>
|
|
217
|
+
<Avatar.Root class="size-4" aria-hidden="true">
|
|
218
|
+
<Avatar.Fallback><User class="size-3" /></Avatar.Fallback>
|
|
219
|
+
</Avatar.Root>
|
|
211
220
|
{assignee}
|
|
212
221
|
</TaskChip>
|
|
213
222
|
{:else}
|
|
214
223
|
<TaskChip empty><CircleDashed aria-hidden="true" />Assign</TaskChip>
|
|
215
224
|
{/if}
|
|
216
225
|
</TaskProperty>
|
|
217
|
-
<TaskProperty label="Due date">
|
|
226
|
+
<TaskProperty label="Due date" icon={CalendarBlank}>
|
|
218
227
|
<TaskChip><CalendarBlank aria-hidden="true" />Oct 9, 2026</TaskChip>
|
|
219
228
|
</TaskProperty>
|
|
220
|
-
<TaskProperty label="Project">
|
|
229
|
+
<TaskProperty label="Project" icon={Folder}>
|
|
221
230
|
<TaskChip><Folder aria-hidden="true" />Agency OS</TaskChip>
|
|
222
231
|
</TaskProperty>
|
|
223
|
-
<TaskProperty label="Time">
|
|
232
|
+
<TaskProperty label="Time" icon={Timer}>
|
|
224
233
|
<TimeTracker
|
|
225
234
|
{entries}
|
|
226
235
|
running={timer}
|
|
@@ -242,5 +251,5 @@
|
|
|
242
251
|
</TaskProperty>
|
|
243
252
|
{/snippet}
|
|
244
253
|
</TaskDetail>
|
|
245
|
-
</
|
|
254
|
+
</Card>
|
|
246
255
|
</div>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import { buttonVariants } from "../../shadcn/button/index.js";
|
|
5
6
|
|
|
6
7
|
interface Props extends Omit<HTMLButtonAttributes, "children"> {
|
|
7
8
|
/** No value yet: the label is a prompt and recedes until hovered. */
|
|
@@ -12,13 +13,12 @@
|
|
|
12
13
|
let { empty = false, class: className, children, ...rest }: Props = $props();
|
|
13
14
|
</script>
|
|
14
15
|
|
|
15
|
-
<!-- The one box every property value sits in: 28px, 40 under a coarse pointer. -->
|
|
16
|
+
<!-- The one box every property value sits in: a quiet ghost Button, 28px, 40 under a coarse pointer. -->
|
|
16
17
|
<button
|
|
17
18
|
type="button"
|
|
18
19
|
class={cn(
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-3.5 [&_svg]:shrink-0",
|
|
20
|
+
buttonVariants({ variant: "ghost", size: "sm" }),
|
|
21
|
+
"min-w-0 justify-start ps-1.5 pe-2.5 text-(length:--text-control) font-normal data-[state=open]:bg-muted",
|
|
22
22
|
empty && "text-muted-foreground hover:text-foreground",
|
|
23
23
|
className,
|
|
24
24
|
)}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import { Circle, CheckCircle, PencilSimple } from "phosphor-svelte";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import { Button } from "../../shadcn/button/index.js";
|
|
6
|
+
import { Textarea } from "../../shadcn/textarea/index.js";
|
|
5
7
|
import {
|
|
6
8
|
DEFAULT_TASK_DETAIL_LABELS,
|
|
7
9
|
type TaskComment,
|
|
@@ -118,13 +120,15 @@
|
|
|
118
120
|
<header class="min-w-0 px-4 pt-6 @3xl:col-start-1 @3xl:px-8">
|
|
119
121
|
<div class="mx-auto w-full max-w-184">
|
|
120
122
|
<div class="flex items-start gap-2">
|
|
121
|
-
<
|
|
122
|
-
|
|
123
|
+
<Button
|
|
124
|
+
variant="ghost"
|
|
125
|
+
size="sm"
|
|
126
|
+
icon
|
|
123
127
|
onclick={onToggleDone}
|
|
124
128
|
disabled={!onToggleDone}
|
|
125
129
|
aria-label={done ? labels.markIncomplete : labels.markComplete}
|
|
126
130
|
class={cn(
|
|
127
|
-
"
|
|
131
|
+
"mt-px disabled:opacity-100",
|
|
128
132
|
done ? "text-success" : "text-muted-foreground/60 hover:text-foreground",
|
|
129
133
|
)}
|
|
130
134
|
>
|
|
@@ -133,30 +137,30 @@
|
|
|
133
137
|
{:else}
|
|
134
138
|
<Circle class="size-5" aria-hidden="true" />
|
|
135
139
|
{/if}
|
|
136
|
-
</
|
|
140
|
+
</Button>
|
|
137
141
|
|
|
138
142
|
{#if editingTitle}
|
|
139
|
-
<
|
|
140
|
-
bind:
|
|
143
|
+
<Textarea
|
|
144
|
+
bind:ref={titleField}
|
|
141
145
|
bind:value={titleDraft}
|
|
142
146
|
onkeydown={onTitleKeydown}
|
|
143
147
|
onblur={commitTitle}
|
|
144
148
|
rows={2}
|
|
145
149
|
aria-label={labels.editTitle}
|
|
146
|
-
class="-mx-2 -my-1 min-w-0 flex-1 resize-none
|
|
147
|
-
|
|
150
|
+
class="-mx-2 -my-1 min-h-0 min-w-0 flex-1 resize-none px-2 py-1 text-2xl leading-tight font-semibold tracking-tight md:text-2xl"
|
|
151
|
+
/>
|
|
148
152
|
{:else}
|
|
149
153
|
<h1
|
|
150
154
|
class="min-w-0 flex-1 text-2xl leading-tight font-semibold tracking-tight text-balance break-words"
|
|
151
155
|
>
|
|
152
|
-
<
|
|
153
|
-
|
|
156
|
+
<Button
|
|
157
|
+
variant="text"
|
|
154
158
|
onclick={startTitle}
|
|
155
159
|
disabled={!onTitleChange}
|
|
156
160
|
aria-label={labels.editTitle}
|
|
157
161
|
class={cn(
|
|
158
|
-
"group -mx-2 -my-1
|
|
159
|
-
onTitleChange && "hover:bg-
|
|
162
|
+
"group -mx-2 -my-1 px-2 py-1 text-2xl leading-tight font-semibold tracking-tight disabled:opacity-100",
|
|
163
|
+
!onTitleChange && "hover:bg-transparent",
|
|
160
164
|
closed && "text-muted-foreground",
|
|
161
165
|
)}
|
|
162
166
|
>
|
|
@@ -167,7 +171,7 @@
|
|
|
167
171
|
aria-hidden="true"
|
|
168
172
|
/>
|
|
169
173
|
{/if}
|
|
170
|
-
</
|
|
174
|
+
</Button>
|
|
171
175
|
</h1>
|
|
172
176
|
{/if}
|
|
173
177
|
</div>
|
|
@@ -203,58 +207,56 @@
|
|
|
203
207
|
<div class="flex h-7 items-center justify-between">
|
|
204
208
|
<h2 class="text-xs font-medium text-muted-foreground">{labels.description}</h2>
|
|
205
209
|
{#if !editingDescription && description && onDescriptionChange}
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
<Button
|
|
211
|
+
variant="ghost"
|
|
212
|
+
size="sm"
|
|
213
|
+
icon
|
|
214
|
+
class="text-muted-foreground"
|
|
209
215
|
onclick={startDescription}
|
|
210
216
|
aria-label={labels.editDescription}
|
|
211
217
|
>
|
|
212
|
-
<PencilSimple
|
|
213
|
-
</
|
|
218
|
+
<PencilSimple aria-hidden="true" />
|
|
219
|
+
</Button>
|
|
214
220
|
{/if}
|
|
215
221
|
</div>
|
|
216
222
|
|
|
217
223
|
{#if editingDescription}
|
|
218
|
-
<
|
|
224
|
+
<Textarea
|
|
219
225
|
bind:value={descriptionDraft}
|
|
220
226
|
rows={8}
|
|
221
227
|
placeholder={labels.addDescription}
|
|
222
228
|
aria-label={labels.description}
|
|
223
|
-
class="
|
|
224
|
-
|
|
229
|
+
class="resize-y px-3 leading-relaxed"
|
|
230
|
+
/>
|
|
225
231
|
<div class="mt-1 flex justify-end gap-1.5">
|
|
226
|
-
<
|
|
227
|
-
>{labels.cancel}</
|
|
228
|
-
>
|
|
229
|
-
<button
|
|
230
|
-
type="button"
|
|
231
|
-
class="tk-button tk-primary"
|
|
232
|
-
onclick={saveDescription}
|
|
233
|
-
disabled={savingDescription}
|
|
232
|
+
<Button variant="ghost" size="sm" onclick={() => (editingDescription = false)}
|
|
233
|
+
>{labels.cancel}</Button
|
|
234
234
|
>
|
|
235
|
+
<Button size="sm" onclick={saveDescription} disabled={savingDescription}>
|
|
235
236
|
{savingDescription ? labels.saving : labels.save}
|
|
236
|
-
</
|
|
237
|
+
</Button>
|
|
237
238
|
</div>
|
|
238
239
|
{:else if description}
|
|
239
|
-
<
|
|
240
|
-
|
|
240
|
+
<Button
|
|
241
|
+
variant="text"
|
|
241
242
|
onclick={startDescription}
|
|
242
243
|
disabled={!onDescriptionChange}
|
|
243
244
|
class={cn(
|
|
244
|
-
"-mx-3 block w-[calc(100%+1.5rem)]
|
|
245
|
-
onDescriptionChange && "hover:bg-
|
|
245
|
+
"-mx-3 block w-[calc(100%+1.5rem)] px-3 py-1.5 leading-relaxed font-normal whitespace-pre-wrap text-pretty disabled:opacity-100",
|
|
246
|
+
!onDescriptionChange && "hover:bg-transparent",
|
|
246
247
|
)}
|
|
247
248
|
>
|
|
248
249
|
{description}
|
|
249
|
-
</
|
|
250
|
+
</Button>
|
|
250
251
|
{:else if onDescriptionChange}
|
|
251
|
-
<
|
|
252
|
-
|
|
252
|
+
<Button
|
|
253
|
+
variant="dashed"
|
|
254
|
+
size="sm"
|
|
253
255
|
onclick={startDescription}
|
|
254
|
-
class="
|
|
256
|
+
class="w-full justify-start text-(length:--text-control) font-normal"
|
|
255
257
|
>
|
|
256
258
|
{labels.addDescription}
|
|
257
|
-
</
|
|
259
|
+
</Button>
|
|
258
260
|
{/if}
|
|
259
261
|
</div>
|
|
260
262
|
|
|
@@ -274,72 +276,3 @@
|
|
|
274
276
|
</section>
|
|
275
277
|
</div>
|
|
276
278
|
</div>
|
|
277
|
-
|
|
278
|
-
<style>
|
|
279
|
-
.tk-icon {
|
|
280
|
-
display: grid;
|
|
281
|
-
place-items: center;
|
|
282
|
-
width: 1.75rem;
|
|
283
|
-
height: 1.75rem;
|
|
284
|
-
flex: none;
|
|
285
|
-
border-radius: var(--radius-md, 0.5rem);
|
|
286
|
-
outline: none;
|
|
287
|
-
transition:
|
|
288
|
-
background-color var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out),
|
|
289
|
-
color var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
@media (hover: hover) and (pointer: fine) {
|
|
293
|
-
.tk-icon:hover:not(:disabled) {
|
|
294
|
-
background: var(--color-muted);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.tk-icon:focus-visible,
|
|
299
|
-
.tk-button:focus-visible {
|
|
300
|
-
box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-ring) 50%, transparent);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
.tk-button {
|
|
304
|
-
height: 1.75rem;
|
|
305
|
-
padding-inline: 0.75rem;
|
|
306
|
-
border-radius: var(--radius-md, 0.5rem);
|
|
307
|
-
font-size: 0.8125rem;
|
|
308
|
-
font-weight: 500;
|
|
309
|
-
outline: none;
|
|
310
|
-
transition: background-color var(--duration-quick, 150ms) var(--ease-smooth-out, ease-out);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
@media (hover: hover) and (pointer: fine) {
|
|
314
|
-
.tk-button:hover:not(:disabled) {
|
|
315
|
-
background: var(--color-muted);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
.tk-button:disabled {
|
|
320
|
-
opacity: 0.5;
|
|
321
|
-
pointer-events: none;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
.tk-primary {
|
|
325
|
-
background: var(--color-primary);
|
|
326
|
-
color: var(--color-primary-foreground);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
@media (hover: hover) and (pointer: fine) {
|
|
330
|
-
.tk-primary:hover:not(:disabled) {
|
|
331
|
-
background: color-mix(in oklab, var(--color-primary) 90%, transparent);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
@media (any-pointer: coarse) {
|
|
336
|
-
.tk-icon {
|
|
337
|
-
width: 2.5rem;
|
|
338
|
-
height: 2.5rem;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
.tk-button {
|
|
342
|
-
height: 2.5rem;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
</style>
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { Snippet } from "svelte";
|
|
2
|
+
import type { Component, Snippet } from "svelte";
|
|
3
|
+
import PropertyRow from "../../components/work-parts/property-row.svelte";
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
6
|
label: string;
|
|
7
|
+
/** A Phosphor icon before the label, shown when the rail is wide. */
|
|
8
|
+
icon?: Component<{ class?: string; "aria-hidden"?: boolean | "true" | "false" }>;
|
|
6
9
|
children: Snippet;
|
|
7
10
|
}
|
|
8
11
|
|
|
9
|
-
let { label, children }: Props = $props();
|
|
12
|
+
let { label, icon, children }: Props = $props();
|
|
10
13
|
</script>
|
|
11
14
|
|
|
12
|
-
<!-- A labelled row in the rail. In the narrow chip row the label hides and
|
|
15
|
+
<!-- A labelled row in the rail: icon, label, value. In the narrow chip row the label hides and
|
|
13
16
|
names the group for assistive tech. -->
|
|
14
|
-
<
|
|
15
|
-
class="flex min-h-7 items-center @3xl:grid @3xl:grid-cols-[6rem_minmax(0,1fr)]"
|
|
16
|
-
role="group"
|
|
17
|
-
aria-label={label}
|
|
18
|
-
>
|
|
19
|
-
<span class="hidden text-xs font-medium text-muted-foreground @3xl:block" aria-hidden="true"
|
|
20
|
-
>{label}</span
|
|
21
|
-
>
|
|
22
|
-
<div class="flex min-w-0 items-center">{@render children()}</div>
|
|
23
|
-
</div>
|
|
17
|
+
<PropertyRow {label} {icon} layout="responsive">{@render children()}</PropertyRow>
|