@heyramzi/ui 2.15.1 → 2.16.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/COMPONENTS.md
CHANGED
|
@@ -136,6 +136,7 @@ Generic pieces built on the primitives, imported from `@heyramzi/ui/components/<
|
|
|
136
136
|
## Record (`src/record`)
|
|
137
137
|
|
|
138
138
|
- `info-list` — InfoList. An editable label and value `<dl>`; `layout="row"` makes it a read-only band of items that wrap and truncate, with `term`, `content` and `action` snippets per row and a `trailing` snippet after the list
|
|
139
|
+
- `record-rail` — RecordRail, RecordRailTab. A record's side rail split into tabs (fields in one, a comment thread in the next), each with an optional count. A single tab draws no strip
|
|
139
140
|
|
|
140
141
|
---
|
|
141
142
|
|
package/dist/record/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { default as RecordTimeline } from "../../src/record/record-timeline.svel
|
|
|
8
8
|
export { default as ProjectList } from "../../src/record/project-list.svelte";
|
|
9
9
|
export { default as FieldSection } from "../../src/record/field-section.svelte";
|
|
10
10
|
export { default as InfoList } from "../../src/record/info-list.svelte";
|
|
11
|
+
export { default as RecordRail } from "../../src/record/record-rail.svelte";
|
|
11
12
|
export { DEFAULT_RECORD_FILTERS, DEFAULT_RECORD_KINDS } from "./kinds.js";
|
|
12
13
|
export { DEFAULT_RECORD_LABELS, resolveLabels } from "./types.js";
|
|
13
14
|
export { activeProjects, dayRelation, eventsForFilter, filterCounts, foldGroups, groupEventsByDay, groupSteps, latestWhereWeAre, localDay, mergeClientEvents, nextAcrossProjects, nudgeStep, reorderIds, rollupProjects, stepMarkers, stepProgress } from "./logic.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heyramzi/ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.1",
|
|
4
4
|
"description": "Svelte 5 UI for apps: primitives, effects and animations, plus work (tasks and docs), charts, slides, an editor, onboarding and a canvas as subpaths.",
|
|
5
5
|
"homepage": "https://ui.heyramzi.com",
|
|
6
6
|
"license": "MIT",
|
package/src/record/index.ts
CHANGED
|
@@ -8,6 +8,8 @@ export { default as RecordTimeline } from "./record-timeline.svelte";
|
|
|
8
8
|
export { default as ProjectList } from "./project-list.svelte";
|
|
9
9
|
export { default as FieldSection } from "./field-section.svelte";
|
|
10
10
|
export { default as InfoList } from "./info-list.svelte";
|
|
11
|
+
export { default as RecordRail } from "./record-rail.svelte";
|
|
12
|
+
export type { RecordRailTab } from "./record-rail.svelte";
|
|
11
13
|
|
|
12
14
|
export { DEFAULT_RECORD_FILTERS, DEFAULT_RECORD_KINDS } from "./kinds.js";
|
|
13
15
|
export { DEFAULT_RECORD_LABELS, resolveLabels } from "./types.js";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
import { cn } from "../lib/utils.js";
|
|
7
|
+
import * as Tabs from "../shadcn/tabs/index.js";
|
|
8
|
+
|
|
9
|
+
// =========================
|
|
10
|
+
// TYPES
|
|
11
|
+
// =========================
|
|
12
|
+
export interface RecordRailTab {
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
/** Drawn beside the label, such as the number of comments. Hidden at 0 or when left out. */
|
|
16
|
+
count?: number;
|
|
17
|
+
content: Snippet;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface Props {
|
|
21
|
+
tabs: RecordRailTab[];
|
|
22
|
+
/** The open tab's id. Defaults to the first tab. */
|
|
23
|
+
value?: string;
|
|
24
|
+
/** Names the tab list for a screen reader, such as "Task sidebar". */
|
|
25
|
+
label: string;
|
|
26
|
+
class?: string;
|
|
27
|
+
/** Classes for the strip that holds the tab list. */
|
|
28
|
+
listClass?: string;
|
|
29
|
+
/** Classes for each tab's panel. */
|
|
30
|
+
contentClass?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// =========================
|
|
34
|
+
// PROPS
|
|
35
|
+
// =========================
|
|
36
|
+
let {
|
|
37
|
+
tabs,
|
|
38
|
+
value = $bindable(),
|
|
39
|
+
label,
|
|
40
|
+
class: className,
|
|
41
|
+
listClass,
|
|
42
|
+
contentClass,
|
|
43
|
+
}: Props = $props();
|
|
44
|
+
|
|
45
|
+
// =========================
|
|
46
|
+
// DERIVED
|
|
47
|
+
// =========================
|
|
48
|
+
// WHY a fallback and not a write: the caller may hand over a new tab set where the open id is gone.
|
|
49
|
+
let open = $derived(tabs.some((tab) => tab.id === value) ? value : tabs[0]?.id);
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<!-- A record's side rail with tabs: the fields in one, a thread or a log in the next,
|
|
53
|
+
so the thread sits beside the record and not a screen below it. One tab draws no strip. -->
|
|
54
|
+
<Tabs.Root value={open} onValueChange={(next) => (value = next)} class={cn("min-w-0 gap-0", className)}>
|
|
55
|
+
{#if tabs.length > 1}
|
|
56
|
+
<div class={cn("pb-3", listClass)}>
|
|
57
|
+
<Tabs.List size="sm" class="w-full" aria-label={label}>
|
|
58
|
+
{#each tabs as tab (tab.id)}
|
|
59
|
+
<Tabs.Trigger value={tab.id}>
|
|
60
|
+
{tab.label}
|
|
61
|
+
{#if tab.count}
|
|
62
|
+
<span class="text-xs tabular-nums text-muted-foreground">{tab.count}</span>
|
|
63
|
+
{/if}
|
|
64
|
+
</Tabs.Trigger>
|
|
65
|
+
{/each}
|
|
66
|
+
</Tabs.List>
|
|
67
|
+
</div>
|
|
68
|
+
{/if}
|
|
69
|
+
{#each tabs as tab (tab.id)}
|
|
70
|
+
<Tabs.Content value={tab.id} class={cn("min-w-0", contentClass)}>
|
|
71
|
+
{@render tab.content()}
|
|
72
|
+
</Tabs.Content>
|
|
73
|
+
{/each}
|
|
74
|
+
</Tabs.Root>
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
<div class="flex flex-col items-start gap-1">
|
|
18
18
|
<p
|
|
19
19
|
class={cn(
|
|
20
|
-
|
|
20
|
+
// A long unbroken word, such as a class name, otherwise widens a narrow rail.
|
|
21
|
+
"max-w-full text-sm leading-relaxed font-normal whitespace-pre-wrap text-pretty wrap-break-word",
|
|
21
22
|
long && !open && "line-clamp-6",
|
|
22
23
|
className,
|
|
23
24
|
)}
|
package/src/thread/thread.svelte
CHANGED
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
onAnchor?: (comment: ThreadComment) => void;
|
|
47
47
|
/** Whose comments carry the edit and delete buttons. A rich comment can't be edited here. */
|
|
48
48
|
canEdit?: (comment: ThreadComment) => boolean;
|
|
49
|
+
/** False hides the visible title, for a thread already named by its tab. Screen readers still get it. */
|
|
50
|
+
heading?: boolean;
|
|
49
51
|
class?: string;
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -66,6 +68,7 @@
|
|
|
66
68
|
onResolve,
|
|
67
69
|
onAnchor,
|
|
68
70
|
canEdit = () => false,
|
|
71
|
+
heading = true,
|
|
69
72
|
class: className,
|
|
70
73
|
}: Props = $props();
|
|
71
74
|
|
|
@@ -273,8 +276,8 @@
|
|
|
273
276
|
{/snippet}
|
|
274
277
|
|
|
275
278
|
<section aria-label={labels.title} class={cn("flex flex-col gap-3", className)}>
|
|
276
|
-
<div class="flex h-7 items-center justify-between">
|
|
277
|
-
<h2 class="text-xs font-medium text-muted-foreground">{labels.title}</h2>
|
|
279
|
+
<div class={cn("flex h-7 items-center justify-between", !heading && resolved === 0 && "sr-only")}>
|
|
280
|
+
<h2 class={cn("text-xs font-medium text-muted-foreground", !heading && "sr-only")}>{labels.title}</h2>
|
|
278
281
|
{#if resolved > 0}
|
|
279
282
|
<button
|
|
280
283
|
type="button"
|
|
@@ -366,8 +366,11 @@
|
|
|
366
366
|
opacity: 1;
|
|
367
367
|
}
|
|
368
368
|
|
|
369
|
-
/* clip, not hidden: the margin lets a lifted card's shadow out while the fold stays shut.
|
|
369
|
+
/* clip, not hidden: the margin lets a lifted card's shadow out while the fold stays shut.
|
|
370
|
+
relative: a card's sr-only labels are absolute, and clip only cuts what this box contains.
|
|
371
|
+
Without it they hang below a shut fold and the page scrolls past its last lane (TSK-1617). */
|
|
370
372
|
.kanban-fold-inner {
|
|
373
|
+
position: relative;
|
|
371
374
|
display: flex;
|
|
372
375
|
flex-direction: column;
|
|
373
376
|
gap: 0.375rem;
|