@poodle64/ui 2026.10.17 → 2026.10.19
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 +101 -11
- package/dist/components/feedback/report-widget.svelte +4 -1
- package/dist/components/feedback/report-widget.svelte.d.ts +1 -0
- package/dist/components/ui/app-identity/app-identity.svelte +7 -2
- package/dist/components/ui/app-shell/texture.d.ts +5 -5
- package/dist/components/ui/app-shell/texture.js +3 -3
- package/dist/components/ui/breadcrumbs/breadcrumbs.svelte +70 -0
- package/dist/components/ui/breadcrumbs/breadcrumbs.svelte.d.ts +32 -0
- package/dist/components/ui/breadcrumbs/index.d.ts +2 -0
- package/dist/components/ui/breadcrumbs/index.js +2 -0
- package/dist/components/ui/content-skeleton/content-skeleton.svelte +94 -0
- package/dist/components/ui/content-skeleton/content-skeleton.svelte.d.ts +25 -0
- package/dist/components/ui/content-skeleton/index.d.ts +2 -0
- package/dist/components/ui/content-skeleton/index.js +2 -0
- package/dist/components/ui/document-reader/document-reader.svelte +336 -0
- package/dist/components/ui/document-reader/document-reader.svelte.d.ts +65 -0
- package/dist/components/ui/document-reader/index.d.ts +2 -0
- package/dist/components/ui/document-reader/index.js +2 -0
- package/dist/components/ui/graph-canvas/graph-canvas.svelte +69 -2
- package/dist/components/ui/graph-canvas/graph-canvas.svelte.d.ts +2 -0
- package/dist/components/ui/graph-canvas/scene.d.ts +6 -0
- package/dist/components/ui/graph-canvas/scene.js +52 -21
- package/dist/components/ui/graph-canvas/types.d.ts +3 -0
- package/dist/components/ui/page-container/index.d.ts +2 -0
- package/dist/components/ui/page-container/index.js +2 -0
- package/dist/components/ui/page-container/page-container.svelte +39 -0
- package/dist/components/ui/page-container/page-container.svelte.d.ts +24 -0
- package/dist/components/ui/page-header/page-header.svelte +12 -7
- package/dist/components/ui/page-header/page-header.svelte.d.ts +3 -2
- package/dist/components/ui/page-section/index.d.ts +2 -0
- package/dist/components/ui/page-section/index.js +2 -0
- package/dist/components/ui/page-section/page-section.svelte +92 -0
- package/dist/components/ui/page-section/page-section.svelte.d.ts +36 -0
- package/dist/components/ui/sheet/index.d.ts +13 -0
- package/dist/components/ui/sheet/index.js +15 -0
- package/dist/components/ui/sheet/sheet-body.svelte +21 -0
- package/dist/components/ui/sheet/sheet-body.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-close.svelte +11 -0
- package/dist/components/ui/sheet/sheet-close.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-content.svelte +70 -0
- package/dist/components/ui/sheet/sheet-content.svelte.d.ts +37 -0
- package/dist/components/ui/sheet/sheet-description.svelte +20 -0
- package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-footer.svelte +23 -0
- package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-header.svelte +21 -0
- package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte +20 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-portal.svelte +7 -0
- package/dist/components/ui/sheet/sheet-portal.svelte.d.ts +3 -0
- package/dist/components/ui/sheet/sheet-title.svelte +21 -0
- package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-trigger.svelte +11 -0
- package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet.svelte +7 -0
- package/dist/components/ui/sheet/sheet.svelte.d.ts +3 -0
- package/dist/components/ui/skeleton/skeleton.svelte +1 -1
- package/dist/styles.css +22 -0
- package/package.json +2 -1
- package/registry/component-map.json +43 -4
- package/registry/component-map.md +9 -4
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
2
|
+
export declare const sheetVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
side: {
|
|
4
|
+
right: string;
|
|
5
|
+
left: string;
|
|
6
|
+
bottom: string;
|
|
7
|
+
top: string;
|
|
8
|
+
};
|
|
9
|
+
}, undefined, "bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out border-border fixed z-50 flex flex-col text-sm outline-none duration-200 ease-out data-closed:duration-150", {
|
|
10
|
+
side: {
|
|
11
|
+
right: string;
|
|
12
|
+
left: string;
|
|
13
|
+
bottom: string;
|
|
14
|
+
top: string;
|
|
15
|
+
};
|
|
16
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
17
|
+
side: {
|
|
18
|
+
right: string;
|
|
19
|
+
left: string;
|
|
20
|
+
bottom: string;
|
|
21
|
+
top: string;
|
|
22
|
+
};
|
|
23
|
+
}, undefined, "bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out border-border fixed z-50 flex flex-col text-sm outline-none duration-200 ease-out data-closed:duration-150", unknown, unknown, undefined>>;
|
|
24
|
+
export type SheetSide = VariantProps<typeof sheetVariants>['side'];
|
|
25
|
+
import { Dialog as SheetPrimitive } from 'bits-ui';
|
|
26
|
+
import type { ComponentProps, Snippet } from 'svelte';
|
|
27
|
+
import { type WithoutChildrenOrChild } from '../../../utils.js';
|
|
28
|
+
import SheetPortal from './sheet-portal.svelte';
|
|
29
|
+
type $$ComponentProps = WithoutChildrenOrChild<SheetPrimitive.ContentProps> & {
|
|
30
|
+
side?: SheetSide;
|
|
31
|
+
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof SheetPortal>>;
|
|
32
|
+
showCloseButton?: boolean;
|
|
33
|
+
children: Snippet;
|
|
34
|
+
};
|
|
35
|
+
declare const SheetContent: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
36
|
+
type SheetContent = ReturnType<typeof SheetContent>;
|
|
37
|
+
export default SheetContent;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Dialog as DialogPrimitive } from 'bits-ui';
|
|
3
|
+
import { cn } from '../../../utils.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
...restProps
|
|
9
|
+
}: DialogPrimitive.DescriptionProps = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<DialogPrimitive.Description
|
|
13
|
+
bind:ref
|
|
14
|
+
data-slot="sheet-description"
|
|
15
|
+
class={cn(
|
|
16
|
+
'text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3',
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...restProps}
|
|
20
|
+
/>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { cn, type WithElementRef } from '../../../utils.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
children,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div
|
|
14
|
+
bind:this={ref}
|
|
15
|
+
data-slot="sheet-footer"
|
|
16
|
+
class={cn(
|
|
17
|
+
'bg-muted/50 mt-auto flex shrink-0 flex-col-reverse gap-2 border-t p-4 sm:flex-row sm:justify-end',
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...restProps}
|
|
21
|
+
>
|
|
22
|
+
{@render children?.()}
|
|
23
|
+
</div>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
import { type WithElementRef } from '../../../utils.js';
|
|
3
|
+
declare const SheetFooter: import("svelte").Component<WithElementRef<HTMLAttributes<HTMLDivElement>>, {}, "ref">;
|
|
4
|
+
type SheetFooter = ReturnType<typeof SheetFooter>;
|
|
5
|
+
export default SheetFooter;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { cn, type WithElementRef } from '../../../utils.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
children,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<!-- pr-12 keeps the title clear of the content's close button. -->
|
|
14
|
+
<div
|
|
15
|
+
bind:this={ref}
|
|
16
|
+
data-slot="sheet-header"
|
|
17
|
+
class={cn('flex shrink-0 flex-col gap-1.5 border-b p-4 pr-12', className)}
|
|
18
|
+
{...restProps}
|
|
19
|
+
>
|
|
20
|
+
{@render children?.()}
|
|
21
|
+
</div>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
import { type WithElementRef } from '../../../utils.js';
|
|
3
|
+
declare const SheetHeader: import("svelte").Component<WithElementRef<HTMLAttributes<HTMLDivElement>>, {}, "ref">;
|
|
4
|
+
type SheetHeader = ReturnType<typeof SheetHeader>;
|
|
5
|
+
export default SheetHeader;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Dialog as DialogPrimitive } from 'bits-ui';
|
|
3
|
+
import { cn } from '../../../utils.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
...restProps
|
|
9
|
+
}: DialogPrimitive.OverlayProps = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<DialogPrimitive.Overlay
|
|
13
|
+
bind:ref
|
|
14
|
+
data-slot="sheet-overlay"
|
|
15
|
+
class={cn(
|
|
16
|
+
'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs',
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...restProps}
|
|
20
|
+
/>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Dialog as SheetPrimitive } from 'bits-ui';
|
|
3
|
+
import { cn } from '../../../utils.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
...restProps
|
|
9
|
+
}: SheetPrimitive.TitleProps = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<!-- AppDialog's title treatment, so a sheet and a dialogue name themselves alike. -->
|
|
13
|
+
<SheetPrimitive.Title
|
|
14
|
+
bind:ref
|
|
15
|
+
data-slot="sheet-title"
|
|
16
|
+
class={cn(
|
|
17
|
+
'font-display text-lg leading-tight font-semibold tracking-[var(--ds-font-display-tracking,-0.025em)]',
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...restProps}
|
|
21
|
+
/>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Dialog as DialogPrimitive } from 'bits-ui';
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
ref = $bindable(null),
|
|
6
|
+
type = 'button',
|
|
7
|
+
...restProps
|
|
8
|
+
}: DialogPrimitive.TriggerProps = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<DialogPrimitive.Trigger bind:ref data-slot="sheet-trigger" {type} {...restProps} />
|
package/dist/styles.css
CHANGED
|
@@ -296,11 +296,19 @@
|
|
|
296
296
|
/* Eyebrow / column-head tracking — pairs with text-2xs + uppercase. */
|
|
297
297
|
--tracking-eyebrow: 0.06em;
|
|
298
298
|
|
|
299
|
+
/* The type scale, by role (README §The type scale). An app sets none of
|
|
300
|
+
these; a role with no key here is set in the component that owns it. */
|
|
301
|
+
|
|
299
302
|
/* Page-title and large-readout size (PageHeader, StatCard). */
|
|
300
303
|
--text-display: 1.75rem;
|
|
301
304
|
--text-display--line-height: 2.125rem;
|
|
302
305
|
--text-display--letter-spacing: -0.02em;
|
|
303
306
|
|
|
307
|
+
/* A section of a page, under its title (PageSection). */
|
|
308
|
+
--text-section: 1.25rem;
|
|
309
|
+
--text-section--line-height: 1.75rem;
|
|
310
|
+
--text-section--letter-spacing: -0.015em;
|
|
311
|
+
|
|
304
312
|
/* Panel/card heading size — one step above the sm body default. */
|
|
305
313
|
--text-body: 0.9375rem;
|
|
306
314
|
|
|
@@ -433,6 +441,20 @@
|
|
|
433
441
|
--ds-control-pad-icon-lg: 0.625rem;
|
|
434
442
|
}
|
|
435
443
|
|
|
444
|
+
/**
|
|
445
|
+
* Large screens. Past 2560 CSS px the root size grows with the viewport, 1px of
|
|
446
|
+
* root per 160px of width, capped at 1.5rem (a 4K screen at 1x, 3840px, reads
|
|
447
|
+
* 24px), so everything set in rem grows with it: type, the shell's measures
|
|
448
|
+
* (`page` 80rem, `wide` 120rem) and the rail. At 2560px and below the rule
|
|
449
|
+
* resolves to 1rem and nothing moves; it is continuous at the seam. An app that
|
|
450
|
+
* sets its own root size sets it after this import.
|
|
451
|
+
*/
|
|
452
|
+
@media (min-width: 2560px) {
|
|
453
|
+
html {
|
|
454
|
+
font-size: clamp(1rem, 100vw / 160, 1.5rem);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
436
458
|
@layer base {
|
|
437
459
|
/**
|
|
438
460
|
* The milled edge. Cards read as having depth from a hairline border plus a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poodle64/ui",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.19",
|
|
4
4
|
"description": "Household shared component layer: shadcn-svelte primitives (bits-ui) plus the composed page chrome every app builds its routes from, restyled by each app's @poodle64/design-tokens alias layer. One fix reaches every app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -100,6 +100,7 @@
|
|
|
100
100
|
"@testing-library/svelte": "^5.4.2",
|
|
101
101
|
"@types/d3-force": "^3.0.10",
|
|
102
102
|
"@types/node": "^22.20.1",
|
|
103
|
+
"axe-core": "^4.14.0",
|
|
103
104
|
"bits-ui": "^2.18.1",
|
|
104
105
|
"formsnap": "^2.0.1",
|
|
105
106
|
"jsdom": "^29.1.1",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"package": "@poodle64/ui",
|
|
4
|
-
"version": "2026.10.
|
|
4
|
+
"version": "2026.10.19",
|
|
5
5
|
"generatedBy": "scripts/generate-registry.mjs",
|
|
6
6
|
"source": "scripts/situations.json + package source (DO NOT EDIT the outputs by hand)",
|
|
7
|
-
"componentCount":
|
|
7
|
+
"componentCount": 76,
|
|
8
8
|
"situationCount": 20
|
|
9
9
|
},
|
|
10
10
|
"situations": [
|
|
@@ -291,7 +291,7 @@
|
|
|
291
291
|
{
|
|
292
292
|
"key": "library-data",
|
|
293
293
|
"title": "Library data the app fetched",
|
|
294
|
-
"description": "The estate's shared document-library surfaces — a faceted catalogue, one collection's detail, one document's detail, a ranked search answer — rendered from plain props the app maps its own API responses into. The package never fetches and never routes: the app owns the query, the offset and every link. Configuration is the schema-driven half (SchemaForm); library data is fixed components because its shape is stable.",
|
|
294
|
+
"description": "The estate's shared document-library surfaces — a faceted catalogue, one collection's detail, one document's detail, a document to read with its contents, a ranked search answer — rendered from plain props the app maps its own API responses into. The package never fetches and never routes: the app owns the query, the offset and every link. Configuration is the schema-driven half (SchemaForm); library data is fixed components because its shape is stable.",
|
|
295
295
|
"components": [
|
|
296
296
|
{
|
|
297
297
|
"name": "LibraryBrowse",
|
|
@@ -314,6 +314,13 @@
|
|
|
314
314
|
"props": "document, loading?, error?, collectionHref?, onOpenCollection?, actions?, children?",
|
|
315
315
|
"insteadOf": "a bespoke document page: identity dl, locations, tags and memberships hand-laid-out per app"
|
|
316
316
|
},
|
|
317
|
+
{
|
|
318
|
+
"name": "DocumentReader",
|
|
319
|
+
"dir": "document-reader",
|
|
320
|
+
"import": "@poodle64/ui/document-reader",
|
|
321
|
+
"props": "title?, subtitle?, breadcrumbs?, meta?, actions?, html?, children?, contents?, contentsLabel?, aside?, footer?, loading?, error?, onRetry?",
|
|
322
|
+
"insteadOf": "a hand-built markdown page: its own h1, back row, table of contents, scroll-spy and max-w-4xl; or a document body in a box under DocumentDetail"
|
|
323
|
+
},
|
|
317
324
|
{
|
|
318
325
|
"name": "SearchResults",
|
|
319
326
|
"dir": "search-results",
|
|
@@ -361,7 +368,7 @@
|
|
|
361
368
|
{
|
|
362
369
|
"key": "page-frame",
|
|
363
370
|
"title": "The frame every route shares",
|
|
364
|
-
"description": "The standing chrome — the app shell and its nav, the one page-title treatment, the persistent right-hand context column, a foldable working list beside the page's own content.",
|
|
371
|
+
"description": "The standing chrome — the app shell and its nav, the one page-title treatment and its trail, the page's own container and sections, the persistent right-hand context column, a foldable working list beside the page's own content.",
|
|
365
372
|
"components": [
|
|
366
373
|
{
|
|
367
374
|
"name": "AppShell",
|
|
@@ -391,6 +398,27 @@
|
|
|
391
398
|
"props": "title?, eyebrow?, breadcrumbs?, icon?, subtitle?, info?, meta?, actions?",
|
|
392
399
|
"insteadOf": "a hand-written <h1> and title bar (the drift gate fails this)"
|
|
393
400
|
},
|
|
401
|
+
{
|
|
402
|
+
"name": "Breadcrumbs",
|
|
403
|
+
"dir": "breadcrumbs",
|
|
404
|
+
"import": "@poodle64/ui/breadcrumbs",
|
|
405
|
+
"props": "items, label?",
|
|
406
|
+
"insteadOf": "a hand-written chevron trail in PageHeader's breadcrumbs snippet; PageHeader takes the same items as `breadcrumbs={[…]}`"
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"name": "PageContainer",
|
|
410
|
+
"dir": "page-container",
|
|
411
|
+
"import": "@poodle64/ui/page-container",
|
|
412
|
+
"props": "children",
|
|
413
|
+
"insteadOf": "a per-page wrapper picking its own vertical rhythm (space-y-6, gap-10, …)"
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
"name": "PageSection",
|
|
417
|
+
"dir": "page-section",
|
|
418
|
+
"import": "@poodle64/ui/page-section",
|
|
419
|
+
"props": "title, level?, description?, count?, actions?, children?, id?",
|
|
420
|
+
"insteadOf": "a hand-styled section heading (an uppercase kicker, text-lg font-semibold, a display h2) and its own gap to the content under it"
|
|
421
|
+
},
|
|
394
422
|
{
|
|
395
423
|
"name": "RecordSwitcher",
|
|
396
424
|
"dir": "record-switcher",
|
|
@@ -503,6 +531,13 @@
|
|
|
503
531
|
"props": "message?",
|
|
504
532
|
"insteadOf": "a bare spinner or 'Loading…' you place by hand"
|
|
505
533
|
},
|
|
534
|
+
{
|
|
535
|
+
"name": "ContentSkeleton",
|
|
536
|
+
"dir": "content-skeleton",
|
|
537
|
+
"import": "@poodle64/ui/content-skeleton",
|
|
538
|
+
"props": "shape?, count?, label?",
|
|
539
|
+
"insteadOf": "bare Skeleton boxes sized by hand (h-44 rounded-xl, h-24) standing in for a list, tiles or a document body while the page's header is already drawn"
|
|
540
|
+
},
|
|
506
541
|
{
|
|
507
542
|
"name": "ErrorState",
|
|
508
543
|
"dir": "error-state",
|
|
@@ -590,6 +625,10 @@
|
|
|
590
625
|
"dir": "separator",
|
|
591
626
|
"import": "@poodle64/ui/separator"
|
|
592
627
|
},
|
|
628
|
+
{
|
|
629
|
+
"dir": "sheet",
|
|
630
|
+
"import": "@poodle64/ui/sheet"
|
|
631
|
+
},
|
|
593
632
|
{
|
|
594
633
|
"dir": "skeleton",
|
|
595
634
|
"import": "@poodle64/ui/skeleton"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @poodle64/ui — situation → component map
|
|
2
2
|
|
|
3
3
|
<!-- GENERATED by scripts/generate-registry.mjs from scripts/situations.json + package source. DO NOT EDIT. -->
|
|
4
|
-
Generated from `@poodle64/ui@2026.10.
|
|
4
|
+
Generated from `@poodle64/ui@2026.10.19`. 76 components, 20 situations.
|
|
5
5
|
|
|
6
6
|
**Read this before writing a `<div>`.** Find the SITUATION you are in below, then compose the component named for it — do not hand-build it from raw `Card` or utility classes. Import is `import { Name } from '<import path>'`. Props marked `?` are optional. This map is the retrieval step the [`frontend-design` skill] makes mandatory; the [CHI 2026 study] measured composing-from-a-registry at 95% design-system compliance against 71% for writing the CSS from a prose style guide.
|
|
7
7
|
|
|
@@ -128,13 +128,14 @@ _A config object whose shape arrives at runtime as a JSON Schema plus a JSON For
|
|
|
128
128
|
|
|
129
129
|
## Library data the app fetched
|
|
130
130
|
|
|
131
|
-
_The estate's shared document-library surfaces — a faceted catalogue, one collection's detail, one document's detail, a ranked search answer — rendered from plain props the app maps its own API responses into. The package never fetches and never routes: the app owns the query, the offset and every link. Configuration is the schema-driven half (SchemaForm); library data is fixed components because its shape is stable._
|
|
131
|
+
_The estate's shared document-library surfaces — a faceted catalogue, one collection's detail, one document's detail, a document to read with its contents, a ranked search answer — rendered from plain props the app maps its own API responses into. The package never fetches and never routes: the app owns the query, the offset and every link. Configuration is the schema-driven half (SchemaForm); library data is fixed components because its shape is stable._
|
|
132
132
|
|
|
133
133
|
| Component | Import | Key props | Reach for it instead of |
|
|
134
134
|
| --- | --- | --- | --- |
|
|
135
135
|
| `LibraryBrowse` | `@poodle64/ui/library-browse` | `documents, facets?, query?, total?, offset?, limit?, loading?, error?, onQueryChange?, onFacetChange?, onPageChange?, documentHref?, onOpenDocument?, toolbar?` | a hand-built catalogue page: search box, facet rail, filter chips, results table and pager re-derived per app |
|
|
136
136
|
| `CollectionDetail` | `@poodle64/ui/collection-detail` | `collection, stats?, documents?, documentsTotal?, loading?, error?, documentsLoading?, documentsError?, onPageChange?, documentHref?, onOpenDocument?, actions?, children?` | a bespoke collection page assembled from raw Card, a hand-built table and its own stat rows |
|
|
137
137
|
| `DocumentDetail` | `@poodle64/ui/document-detail` | `document, loading?, error?, collectionHref?, onOpenCollection?, actions?, children?` | a bespoke document page: identity dl, locations, tags and memberships hand-laid-out per app |
|
|
138
|
+
| `DocumentReader` | `@poodle64/ui/document-reader` | `title?, subtitle?, breadcrumbs?, meta?, actions?, html?, children?, contents?, contentsLabel?, aside?, footer?, loading?, error?, onRetry?` | a hand-built markdown page: its own h1, back row, table of contents, scroll-spy and max-w-4xl; or a document body in a box under DocumentDetail |
|
|
138
139
|
| `SearchResults` | `@poodle64/ui/search-results` | `results, query?, total?, loading?, error?, resultHref?, onOpen?, onRetry?` | a hand-built ranked hit list minting its own highlight and relevance styling |
|
|
139
140
|
|
|
140
141
|
## A document a machine read, with evidence outlined
|
|
@@ -156,7 +157,7 @@ _People, organisations, sources or any entities as nodes and their relations as
|
|
|
156
157
|
|
|
157
158
|
## The frame every route shares
|
|
158
159
|
|
|
159
|
-
_The standing chrome — the app shell and its nav, the one page-title treatment, the persistent right-hand context column, a foldable working list beside the page's own content._
|
|
160
|
+
_The standing chrome — the app shell and its nav, the one page-title treatment and its trail, the page's own container and sections, the persistent right-hand context column, a foldable working list beside the page's own content._
|
|
160
161
|
|
|
161
162
|
| Component | Import | Key props | Reach for it instead of |
|
|
162
163
|
| --- | --- | --- | --- |
|
|
@@ -164,6 +165,9 @@ _The standing chrome — the app shell and its nav, the one page-title treatment
|
|
|
164
165
|
| `ShellControls` | `@poodle64/ui/app-shell` | `children` | a scope row (entity, financial year, chart/table) hand-placed above the page body; the shell's top bar carries it |
|
|
165
166
|
| `Segmented` | `@poodle64/ui/segmented` | `value, options, label, size?` | a hand-built row of aria-pressed buttons for a small fixed choice |
|
|
166
167
|
| `PageHeader` | `@poodle64/ui/page-header` | `title?, eyebrow?, breadcrumbs?, icon?, subtitle?, info?, meta?, actions?` | a hand-written <h1> and title bar (the drift gate fails this) |
|
|
168
|
+
| `Breadcrumbs` | `@poodle64/ui/breadcrumbs` | `items, label?` | a hand-written chevron trail in PageHeader's breadcrumbs snippet; PageHeader takes the same items as `breadcrumbs={[…]}` |
|
|
169
|
+
| `PageContainer` | `@poodle64/ui/page-container` | `children` | a per-page wrapper picking its own vertical rhythm (space-y-6, gap-10, …) |
|
|
170
|
+
| `PageSection` | `@poodle64/ui/page-section` | `title, level?, description?, count?, actions?, children?, id?` | a hand-styled section heading (an uppercase kicker, text-lg font-semibold, a display h2) and its own gap to the content under it |
|
|
167
171
|
| `RecordSwitcher` | `@poodle64/ui/record-switcher` | `name, groups, current?, noun?, placeholder?, icon?, all?, pages?, separator?` | a bare record name beside a small chevrons button in the top bar, and a dropdown of names with no search, groups or thumbnails; the record's own page tabs come with it |
|
|
168
172
|
| `ContextColumn` | `@poodle64/ui/context-column` | `stats?, statsTitle?, statsInfo?, detail?, title?, subtitle?, onClose?, children?, documentPane?, ariaLabel?` | a hand-built right-hand <aside> with a stat card and a detail pane; on a record page, the one opened item (title, close, an inner scroll) and its DocumentPane, in the column's place or beside it once the page's row has room |
|
|
169
173
|
| `ListShell` | `@poodle64/ui/list-shell` | `title, children, label?, open?, actions?` | a module hand-rolling its own foldable second column beside the rail — a queue, an inbox, a working list |
|
|
@@ -198,11 +202,12 @@ _A surface with nothing to show yet, still loading, or that failed to load — t
|
|
|
198
202
|
| --- | --- | --- | --- |
|
|
199
203
|
| `EmptyState` | `@poodle64/ui/empty-state` | `title, icon?, description?, action?` | a hand-centred 'Nothing here' message |
|
|
200
204
|
| `LoadingState` | `@poodle64/ui/loading-state` | `message?` | a bare spinner or 'Loading…' you place by hand |
|
|
205
|
+
| `ContentSkeleton` | `@poodle64/ui/content-skeleton` | `shape?, count?, label?` | bare Skeleton boxes sized by hand (h-44 rounded-xl, h-24) standing in for a list, tiles or a document body while the page's header is already drawn |
|
|
201
206
|
| `ErrorState` | `@poodle64/ui/error-state` | `message, action?` | a hand-built error message with a retry button |
|
|
202
207
|
|
|
203
208
|
## Primitives you already know
|
|
204
209
|
|
|
205
210
|
_Standard shadcn-svelte / bits-ui primitives — reach for them the same way; no situation lookup needed. Import each from its path below._
|
|
206
211
|
|
|
207
|
-
`@poodle64/ui/alert` · `@poodle64/ui/alert-dialog` · `@poodle64/ui/avatar` · `@poodle64/ui/badge` · `@poodle64/ui/button` · `@poodle64/ui/card` · `@poodle64/ui/checkbox` · `@poodle64/ui/command` · `@poodle64/ui/data-table` · `@poodle64/ui/dialog` · `@poodle64/ui/dropdown-menu` · `@poodle64/ui/input` · `@poodle64/ui/input-group` · `@poodle64/ui/label` · `@poodle64/ui/password-input` · `@poodle64/ui/popover` · `@poodle64/ui/progress` · `@poodle64/ui/select` · `@poodle64/ui/separator` · `@poodle64/ui/skeleton` · `@poodle64/ui/sonner` · `@poodle64/ui/switch` · `@poodle64/ui/table` · `@poodle64/ui/tabs` · `@poodle64/ui/textarea` · `@poodle64/ui/tooltip`
|
|
212
|
+
`@poodle64/ui/alert` · `@poodle64/ui/alert-dialog` · `@poodle64/ui/avatar` · `@poodle64/ui/badge` · `@poodle64/ui/button` · `@poodle64/ui/card` · `@poodle64/ui/checkbox` · `@poodle64/ui/command` · `@poodle64/ui/data-table` · `@poodle64/ui/dialog` · `@poodle64/ui/dropdown-menu` · `@poodle64/ui/input` · `@poodle64/ui/input-group` · `@poodle64/ui/label` · `@poodle64/ui/password-input` · `@poodle64/ui/popover` · `@poodle64/ui/progress` · `@poodle64/ui/select` · `@poodle64/ui/separator` · `@poodle64/ui/sheet` · `@poodle64/ui/skeleton` · `@poodle64/ui/sonner` · `@poodle64/ui/switch` · `@poodle64/ui/table` · `@poodle64/ui/tabs` · `@poodle64/ui/textarea` · `@poodle64/ui/tooltip`
|
|
208
213
|
|