@heyramzi/ui 2.1.0 → 2.2.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.
- package/package.json +7 -8
- package/scripts/sync-shadcn.mjs +3 -4
- package/src/agents/agent-avatar.svelte +604 -575
- package/src/agents/agent-cast.svelte +179 -183
- package/src/agents/demo.svelte +125 -113
- package/src/agents/helpers.ts +23 -17
- package/src/agents/index.ts +4 -4
- package/src/agents/page-state.ts +6 -6
- package/src/agents/types.ts +6 -6
- package/src/ai/ai-button/AiButton.svelte +4 -12
- package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
- package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
- package/src/ai/response/Response.css +2 -3
- package/src/animations/avatar-group-hover.css +2 -16
- package/src/animations/card-tilt.css +3 -6
- package/src/animations/digit-pop-in.css +2 -15
- package/src/animations/dropdown.css +4 -17
- package/src/animations/input-clear-dissolve.css +5 -18
- package/src/animations/input-shake.css +9 -41
- package/src/animations/learn-more-hover.css +17 -9
- package/src/animations/like-button.css +2 -4
- package/src/animations/page-side-by-side.css +2 -10
- package/src/animations/plus-menu-morph.css +2 -5
- package/src/animations/shimmer-text.css +5 -18
- package/src/animations/spinning-counter.css +2 -6
- package/src/animations/success-check.css +2 -15
- package/src/animations/thinking-states.css +2 -7
- package/src/brand/brand.test.ts +21 -5
- package/src/brand/index.ts +4 -10
- package/src/canvas/card/card-frame.svelte +43 -39
- package/src/canvas/card/resize-handles.svelte +89 -80
- package/src/canvas/chrome/chrome-zoom.svelte +101 -100
- package/src/canvas/chrome/lock-badge.svelte +8 -8
- package/src/canvas/chrome/side-handles.svelte +24 -19
- package/src/canvas/chrome/size-chip.svelte +30 -30
- package/src/canvas/chrome/snap-guides.svelte +20 -20
- package/src/canvas/components/icons/ToolIcon.svelte +8 -8
- package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
- package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
- package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
- package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
- package/src/canvas/edges/bend-handle.svelte +46 -46
- package/src/canvas/edges/edge-gradient.svelte +10 -10
- package/src/canvas/edges/gradient-edge.svelte +45 -29
- package/src/canvas/editor/lock.test.ts +6 -1
- package/src/canvas/editor/style.ts +7 -1
- package/src/canvas/headless/svg-figure.test.ts +5 -1
- package/src/canvas/lod/lod-switch.svelte +111 -106
- package/src/canvas/pen/PenField.svelte +87 -81
- package/src/canvas/pen/PenOverlay.svelte +127 -127
- package/src/canvas/pen/ShapeNode.svelte +31 -32
- package/src/canvas/pen/TextNode.svelte +54 -53
- package/src/canvas/pen/host-field.test.svelte +7 -7
- package/src/canvas/pen/shapes.ts +7 -1
- package/src/canvas/screen/GlyphIcon.svelte +22 -17
- package/src/canvas/screen/PartView.svelte +138 -72
- package/src/canvas/screen/ScreenBody.svelte +81 -60
- package/src/canvas/screen/ScreenCard.svelte +20 -20
- package/src/canvas/ui/CanvasToolbar.svelte +173 -85
- package/src/canvas/ui/FrameLayer.svelte +59 -59
- package/src/canvas/ui/PenLayer.svelte +39 -30
- package/src/canvas/ui/StylePanel.svelte +119 -102
- package/src/canvas/ui/canvas-grid.svelte +137 -129
- package/src/charts/animated-value.svelte +1 -1
- package/src/charts/area-chart.css +2 -5
- package/src/charts/area-chart.svelte +1 -1
- package/src/charts/bar-chart.css +2 -3
- package/src/charts/bar-chart.svelte +1 -1
- package/src/charts/charts.css +5 -17
- package/src/charts/crosshair.svelte +1 -1
- package/src/charts/dashboard/dashboard-empty.svelte +25 -25
- package/src/charts/dashboard/dashboard-section.svelte +24 -24
- package/src/charts/dashboard/data-panel.svelte +50 -50
- package/src/charts/dashboard/data-sort-head.svelte +56 -56
- package/src/charts/dashboard/data-table.svelte +138 -138
- package/src/charts/dashboard/panel-grid.svelte +30 -30
- package/src/charts/dashboard/period-filter.svelte +25 -25
- package/src/charts/dashboard/rating-chip.svelte +19 -19
- package/src/charts/dashboard/stat-band.svelte +32 -32
- package/src/charts/dashboard/stat-tile.svelte +106 -99
- package/src/charts/donut-chart.svelte +1 -1
- package/src/charts/edge-fade.svelte +1 -1
- package/src/charts/figure.svelte +1 -1
- package/src/charts/gauge-chart.css +4 -7
- package/src/charts/gauge-chart.svelte +1 -1
- package/src/charts/hover-focus.svelte +1 -1
- package/src/charts/legend.css +1 -3
- package/src/charts/legend.svelte +1 -1
- package/src/charts/line-chart.svelte +1 -1
- package/src/charts/number-chart.css +6 -9
- package/src/charts/number-chart.svelte +1 -1
- package/src/charts/reference-line.svelte +19 -19
- package/src/charts/reveal.svelte +1 -1
- package/src/charts/ring-chart.css +2 -4
- package/src/charts/ring-chart.svelte +1 -1
- package/src/charts/sparkline.svelte +5 -2
- package/src/charts/stat-card.svelte +1 -1
- package/src/charts/time-series-chart.css +2 -5
- package/src/charts/trend-pill.css +2 -4
- package/src/charts/trend-pill.svelte +1 -1
- package/src/components/copy/copy-button.svelte +93 -98
- package/src/components/copy/copy-button.test.ts +10 -2
- package/src/components/data-table/infinite-scroll.svelte +42 -42
- package/src/components/data-table/pagination.svelte +34 -22
- package/src/components/data-table/row-arrow.svelte +19 -16
- package/src/components/data-table/row-context-menu.svelte +52 -52
- package/src/components/data-table/sortable-head.svelte +25 -25
- package/src/components/data-table/table-skeleton.svelte +41 -36
- package/src/components/docs/doc-page.svelte +18 -9
- package/src/components/docs/on-this-page.svelte +16 -3
- package/src/components/docs/scroll-spy.svelte.ts +2 -3
- package/src/components/field-row/field-row.svelte +10 -8
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
- package/src/components/icon/icon.svelte +14 -14
- package/src/components/language-flag/language-flag.svelte +3 -1
- package/src/components/list-page/detail-empty.svelte +34 -34
- package/src/components/list-page/detail-header.svelte +55 -47
- package/src/components/list-page/detail-panel.svelte +51 -59
- package/src/components/list-page/detail-row.svelte +19 -19
- package/src/components/list-page/detail-stack.svelte +21 -21
- package/src/components/list-page/empty-state.svelte +30 -30
- package/src/components/list-page/filter-item.svelte +20 -20
- package/src/components/list-page/filter-popover.svelte +60 -55
- package/src/components/list-page/grouped-list.svelte +4 -2
- package/src/components/list-page/index.ts +5 -1
- package/src/components/list-page/list-page-shell.svelte +2 -5
- package/src/components/list-page/master-detail.svelte +87 -88
- package/src/components/list-page/notice-bar.svelte +38 -38
- package/src/components/list-page/prev-next.svelte +63 -63
- package/src/components/list-page/rail-body.svelte +18 -18
- package/src/components/list-page/rail-empty.svelte +23 -30
- package/src/components/list-page/rail-head.svelte +24 -24
- package/src/components/list-page/rail-row.svelte +77 -73
- package/src/components/list-page/section-host.ts +2 -3
- package/src/components/locale-switch/locale-switch.svelte +41 -41
- package/src/components/mark/mark.svelte +34 -38
- package/src/components/open-in/index.ts +1 -5
- package/src/components/open-in/open-in.svelte +40 -40
- package/src/components/picker/mark-picker.svelte +49 -49
- package/src/components/picker/picker.svelte +5 -3
- package/src/components/section-header/section-header.test.ts +7 -1
- package/src/components/section-header/section-label.svelte +20 -20
- package/src/components/segmented/animated-tabs.svelte +31 -2
- package/src/components/segmented/collapse.test.ts +2 -1
- package/src/components/segmented/index.ts +2 -0
- package/src/components/segmented/segment.svelte +52 -49
- package/src/components/segmented/segmented-filter.svelte +79 -80
- package/src/components/segmented/segmented-nav.svelte +34 -40
- package/src/components/segmented/segmented-overflow.svelte +53 -50
- package/src/components/segmented/segmented-track.svelte +62 -46
- package/src/components/segmented/segmented.ts +2 -3
- package/src/components/star-rating-input/star-rating-input.svelte +103 -103
- package/src/components/svg/svg.svelte +4 -4
- package/src/components/table-view/table-view.svelte +17 -2
- package/src/components/table-view/table-view.test.ts +7 -1
- package/src/components/table-view/types.ts +11 -11
- package/src/components/tags-input/index.ts +13 -0
- package/src/components/tags-input/tags-input.svelte +305 -0
- package/src/components/tags-input/tags.test.ts +64 -0
- package/src/components/tags-input/tags.ts +142 -0
- package/src/components/theme/index.ts +2 -4
- package/src/components/theme/theme-provider.svelte +1 -3
- package/src/components/toolbar/toolbar-search.svelte +25 -25
- package/src/components/toolbar/toolbar.svelte +11 -7
- package/src/components/toolbar/toolbar.test.ts +10 -1
- package/src/design/index.css +21 -78
- package/src/design/polish.css +26 -35
- package/src/editor/editor-toolbar.svelte +104 -99
- package/src/editor/editor.svelte +296 -266
- package/src/editor/image-toolbar.svelte +20 -22
- package/src/editor/index.ts +1 -4
- package/src/editor/inline-editor.svelte +280 -238
- package/src/editor/markdown.ts +15 -15
- package/src/editor/renderer.svelte +71 -71
- package/src/editor/slash-menu.svelte +24 -27
- package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
- package/src/effects/image-comparison/ImageComparison.svelte +11 -1
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
- package/src/effects/magic-card/MagicCard.css +14 -7
- package/src/effects/marquee/Marquee.svelte +3 -5
- package/src/effects/reveal/observe.ts +0 -3
- package/src/effects/spotlight/Spotlight.svelte +1 -1
- package/src/effects/theme-toggle/ThemeToggle.css +25 -22
- package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
- package/src/gallery.test.ts +14 -4
- package/src/inbox/README.md +1 -3
- package/src/inbox/inbox.test.ts +181 -138
- package/src/inbox/index.ts +20 -20
- package/src/inbox/logic.ts +114 -111
- package/src/inbox/thread-inbox.svelte +227 -151
- package/src/inbox/types.ts +130 -108
- package/src/lib/theme-transition.ts +2 -4
- package/src/lib/tone.ts +2 -4
- package/src/lib/utils.ts +2 -2
- package/src/modules.test.ts +79 -69
- package/src/onboarding/define-tours.test.ts +55 -40
- package/src/onboarding/define-tours.ts +23 -23
- package/src/onboarding/demo.svelte +24 -5
- package/src/onboarding/index.ts +1 -8
- package/src/onboarding/onboarding-provider.svelte +19 -7
- package/src/onboarding/onboarding.svelte.ts +16 -16
- package/src/onboarding/pick.test.ts +61 -52
- package/src/onboarding/pick.ts +16 -13
- package/src/onboarding/stores.test.ts +80 -80
- package/src/onboarding/stores.ts +41 -39
- package/src/onboarding/tour-card.svelte +30 -5
- package/src/onboarding/tour-runner.svelte +12 -3
- package/src/onboarding/types.ts +20 -12
- package/src/onboarding/wait.ts +22 -22
- package/src/panel/side-panel.svelte +94 -93
- package/src/record/demo-data.ts +291 -225
- package/src/record/field-section.svelte +38 -34
- package/src/record/fields.ts +148 -96
- package/src/record/format.ts +63 -56
- package/src/record/index.ts +49 -35
- package/src/record/info-list.svelte +145 -114
- package/src/record/kinds.ts +31 -31
- package/src/record/logic.ts +216 -214
- package/src/record/next-up.svelte +45 -34
- package/src/record/project-list.svelte +56 -50
- package/src/record/record-demo.svelte +130 -110
- package/src/record/record-header.svelte +37 -28
- package/src/record/record-shell.svelte +54 -54
- package/src/record/record-stats.svelte +25 -25
- package/src/record/record-timeline.svelte +134 -114
- package/src/record/record.test.ts +430 -309
- package/src/record/steps-rail.svelte +225 -216
- package/src/record/types.ts +234 -215
- package/src/record/where-we-are.svelte +62 -58
- package/src/shadcn/button/button.svelte +1 -1
- package/src/shadcn/card/card-title.svelte +1 -5
- package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
- package/src/shadcn/sheet/sheet-content.svelte +2 -4
- package/src/shadcn/table/table-cell.svelte +2 -3
- package/src/shadcn/utilities.css +3 -8
- package/src/slides/Controls.svelte +150 -124
- package/src/slides/Deck.svelte +243 -238
- package/src/slides/Fragment.svelte +64 -57
- package/src/slides/Overview.svelte +106 -101
- package/src/slides/Presenter.svelte +300 -266
- package/src/slides/Slide.svelte +185 -170
- package/src/slides/SlideList.svelte +16 -12
- package/src/slides/ambient.d.ts +1 -1
- package/src/slides/bridges.ts +42 -23
- package/src/slides/deck-controller.svelte.ts +47 -35
- package/src/slides/demo-slides.svelte +330 -306
- package/src/slides/demo.svelte +164 -160
- package/src/slides/export/capture.ts +20 -16
- package/src/slides/export/ffmpeg.ts +43 -38
- package/src/slides/export/index.ts +5 -5
- package/src/slides/export/launch.ts +3 -1
- package/src/slides/export/pdf.ts +30 -27
- package/src/slides/export/types.ts +10 -8
- package/src/slides/index.ts +11 -11
- package/src/slides/labels.ts +22 -19
- package/src/slides/layout.ts +9 -2
- package/src/slides/model.ts +4 -4
- package/src/slides/navigation.ts +43 -31
- package/src/slides/theme.css +5 -7
- package/src/slides/types.ts +9 -10
- package/src/status/define-statuses.ts +17 -24
- package/src/status/index.ts +5 -5
- package/src/status/status-badge.svelte +3 -1
- package/src/status/status-dot.svelte +1 -3
- package/src/status/status-icon.svelte +1 -1
- package/src/status/status-types.ts +21 -21
- package/src/tasks/board-order.ts +2 -4
- package/src/tasks/demo.svelte +189 -31
- package/src/tasks/detail/detail-demo.svelte +73 -13
- package/src/tasks/detail/detail-types.ts +45 -45
- package/src/tasks/detail/task-detail.svelte +40 -10
- package/src/tasks/detail/task-property.svelte +8 -2
- package/src/tasks/detail/task-thread.svelte +53 -12
- package/src/tasks/gantt/gantt-bar.svelte +17 -6
- package/src/tasks/gantt/gantt-grid.svelte +40 -9
- package/src/tasks/gantt/gantt-group-row.svelte +8 -2
- package/src/tasks/gantt/gantt-header.svelte +9 -3
- package/src/tasks/gantt/gantt-task-row.svelte +26 -6
- package/src/tasks/gantt/gantt.css +2 -1
- package/src/tasks/gantt/gantt.test.ts +3 -1
- package/src/tasks/gantt/logic.test.ts +110 -20
- package/src/tasks/gantt/logic.ts +42 -6
- package/src/tasks/inbox/inbox-card.svelte +13 -5
- package/src/tasks/inbox/inbox-draft.svelte +1 -1
- package/src/tasks/inbox/inbox-logic.ts +6 -40
- package/src/tasks/inbox/inbox-statuses.ts +23 -23
- package/src/tasks/inbox/inbox-trace.svelte +9 -3
- package/src/tasks/inbox/inbox-types.ts +54 -58
- package/src/tasks/inbox/index.ts +22 -21
- package/src/tasks/index.ts +49 -52
- package/src/tasks/kanban-board.svelte +16 -12
- package/src/tasks/kanban-types.ts +2 -3
- package/src/tasks/presets/sales.ts +6 -6
- package/src/tasks/task-gantt.svelte +28 -8
- package/src/tasks/task-list.svelte +41 -17
- package/src/tasks/time/duration.ts +40 -40
- package/src/tasks/time/time-chip.svelte +9 -2
- package/src/tasks/time/time-dot.svelte +1 -1
- package/src/tasks/time/time-ring.svelte +11 -3
- package/src/tasks/time/time-tracker.svelte +57 -15
- package/src/tasks/time/time-types.ts +57 -57
- package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
- package/src/thread/index.ts +7 -7
- package/src/thread/logic.ts +36 -33
- package/src/thread/thread.svelte +82 -16
- package/src/thread/thread.test.ts +58 -47
- package/src/thread/types.ts +68 -68
- package/src/tokens/craft.css +17 -53
- package/src/tokens/index.css +3 -13
- package/src/tokens/palette.css +13 -11
- package/src/tokens/primitives.css +10 -23
- package/src/tasks/inbox/inbox.svelte +0 -203
package/src/design/index.css
CHANGED
|
@@ -1,30 +1,12 @@
|
|
|
1
|
-
/* The craft layer,
|
|
2
|
-
*
|
|
3
|
-
* A palette says which colours a product uses. This file says how a surface
|
|
4
|
-
* lifts off the page, how round a control is against a card, and how long an
|
|
5
|
-
* overlay takes to arrive. Those three answers are what separate a kit that
|
|
6
|
-
* looks assembled from one that looks made, and they were the part every app
|
|
7
|
-
* here was re-deciding per component.
|
|
8
|
-
*
|
|
9
|
-
* WHY it ships beside the palette rather than inside it: the palette is the
|
|
10
|
-
* brand and differs per app; elevation, radius and motion are craft and should
|
|
11
|
-
* not. An app imports this, then tints it with `--elev-tint` and nothing else.
|
|
12
|
-
*
|
|
13
|
-
* Studied from beautifului.dev and rareui.com, which both build the same three
|
|
14
|
-
* ladders: a hairline that is a shadow rather than a border, a radius that
|
|
15
|
-
* steps by the role of the box, and a close that is faster than its open.
|
|
16
|
-
*
|
|
17
|
-
* Import once, after Tailwind:
|
|
18
|
-
* @import "@heyramzi/ui/design";
|
|
1
|
+
/* The craft layer, imported once after Tailwind: elevation, radius and motion
|
|
2
|
+
* stay the same in every app, and an app tints it with `--elev-tint` alone.
|
|
19
3
|
*/
|
|
20
4
|
|
|
21
5
|
@import "./polish.css";
|
|
22
6
|
|
|
23
7
|
/* ── Radius, by role not by size ─────────────────────────────
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
home so `rounded-lg` on a button already resolves to the control radius and
|
|
27
|
-
no component has to learn a new class. */
|
|
8
|
+
Nested boxes need radii that step, so the Tailwind names map to roles and
|
|
9
|
+
`rounded-lg` is already the control radius. */
|
|
28
10
|
@theme {
|
|
29
11
|
--radius-xs: 4px; /* tag, dot, inline code */
|
|
30
12
|
--radius-sm: 6px; /* chip, badge, small pill */
|
|
@@ -36,28 +18,8 @@
|
|
|
36
18
|
}
|
|
37
19
|
|
|
38
20
|
/* ── Elevation ───────────────────────────────────────────────
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
WHY the steps are shadow-only and the hairline is its own token: most boxes
|
|
42
|
-
in a kit already draw a border, and an elevation that bakes a `0 0 0 1px`
|
|
43
|
-
ring into every step gives those boxes two edges a pixel apart. Compose them
|
|
44
|
-
where a component drops its border:
|
|
45
|
-
|
|
46
|
-
box-shadow: var(--elev-hairline), var(--elev-card);
|
|
47
|
-
|
|
48
|
-
WHY each step is stacked rather than one blurred drop: a single shadow reads
|
|
49
|
-
as a sticker. Depth is several offsets falling off together, which is what
|
|
50
|
-
the eye reads as distance. They cost nothing extra because every stop is the
|
|
51
|
-
same colour at a different alpha.
|
|
52
|
-
|
|
53
|
-
WHY the blur radii are large and the alphas small: a 4px blur at 20% draws a
|
|
54
|
-
visible grey edge, which the eye reads as a second border. A 28px blur at 7%
|
|
55
|
-
is barely a colour anywhere and reads as height. Reach for more blur before
|
|
56
|
-
more alpha, every time.
|
|
57
|
-
|
|
58
|
-
`--elev-tint` is the one knob an app turns. Pure black greys a warm palette
|
|
59
|
-
out; the hue of the app's own darkest surface keeps the shadow in the
|
|
60
|
-
family. */
|
|
21
|
+
The steps are shadow-only and the hairline is its own token, or a box that
|
|
22
|
+
already draws a border gets two edges a pixel apart. */
|
|
61
23
|
:root {
|
|
62
24
|
--elev-tint: oklch(0 0 0);
|
|
63
25
|
|
|
@@ -84,9 +46,8 @@
|
|
|
84
46
|
0 12px 26px -8px color-mix(in oklab, var(--elev-tint) 12%, transparent),
|
|
85
47
|
0 40px 72px -20px color-mix(in oklab, var(--elev-tint) 20%, transparent);
|
|
86
48
|
|
|
87
|
-
/*
|
|
88
|
-
|
|
89
|
-
read as a physical key rather than a coloured rectangle. */
|
|
49
|
+
/* A hairline separates a surface from what's behind it; a rim lights its top
|
|
50
|
+
edge so a filled control reads as a key, not a coloured box. */
|
|
90
51
|
--elev-hairline: 0 0 0 1px var(--color-border, var(--border));
|
|
91
52
|
--elev-rim: inset 0 1px 0 color-mix(in oklab, white 16%, transparent);
|
|
92
53
|
|
|
@@ -94,10 +55,8 @@
|
|
|
94
55
|
--elev-field: inset 0 1px 2px color-mix(in oklab, var(--elev-tint) 7%, transparent);
|
|
95
56
|
}
|
|
96
57
|
|
|
97
|
-
/* A dark surface
|
|
98
|
-
hairline does the separating
|
|
99
|
-
dark the hairline is white at a low alpha, which is what reads as a lit edge
|
|
100
|
-
rather than as a drawn border. */
|
|
58
|
+
/* A dark surface can't cast a shadow darker than its page, so on dark a
|
|
59
|
+
low-alpha white hairline does the separating. */
|
|
101
60
|
.dark {
|
|
102
61
|
--elev-btn: 0 1px 2px color-mix(in oklab, black 30%, transparent);
|
|
103
62
|
--elev-card:
|
|
@@ -116,25 +75,19 @@
|
|
|
116
75
|
}
|
|
117
76
|
|
|
118
77
|
/* ── Focus ───────────────────────────────────────────────────
|
|
119
|
-
One ring
|
|
120
|
-
|
|
121
|
-
variable so a component spends one line on it and every control focuses the
|
|
122
|
-
same way. */
|
|
78
|
+
One ring in one variable, a solid accent edge plus a soft halo, so every
|
|
79
|
+
control focuses the same way. */
|
|
123
80
|
:root {
|
|
124
81
|
--ring-color: var(--color-ring, var(--ring));
|
|
125
82
|
--ring-halo: color-mix(in oklab, var(--ring-color) 16%, transparent);
|
|
126
|
-
/*
|
|
127
|
-
|
|
128
|
-
is why it is 16% over 4px and not 30% over 2px. */
|
|
83
|
+
/* At a higher alpha the halo reads as a second border, not a glow, which is
|
|
84
|
+
why it's 16% over 4px and not 30% over 2px. */
|
|
129
85
|
--ring-focus: 0 0 0 1px var(--ring-color), 0 0 0 5px var(--ring-halo);
|
|
130
86
|
}
|
|
131
87
|
|
|
132
88
|
/* ── Motion ──────────────────────────────────────────────────
|
|
133
|
-
The transitions-dev scale, verbatim
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
The doctrine in one line: an open is an invitation and a close should get out
|
|
137
|
-
of the way, so every close is shorter than its open and no close bounces. */
|
|
89
|
+
The transitions-dev scale, verbatim so pasted snippets share its names; every
|
|
90
|
+
close is shorter than its open, and no close bounces. */
|
|
138
91
|
:root {
|
|
139
92
|
--duration-stagger: 40ms;
|
|
140
93
|
--duration-micro: 80ms;
|
|
@@ -186,13 +139,9 @@
|
|
|
186
139
|
|
|
187
140
|
--ease-smooth-out: var(--ease-smooth-out);
|
|
188
141
|
|
|
189
|
-
/*
|
|
190
|
-
`duration
|
|
191
|
-
|
|
192
|
-
compiled to nothing and the element ended up at `transition-duration: 0s`:
|
|
193
|
-
no error, no warning, and a component that simply does not animate. The
|
|
194
|
-
comment at the top of this block had claimed `duration-fast` was a class
|
|
195
|
-
since the block was written. Found 31 Aug 2026 by probing a live page. */
|
|
142
|
+
/* Tailwind's `duration-*` reads `--transition-duration-*`, not `--duration-*`,
|
|
143
|
+
so without these `duration-fast` silently compiles to nothing and nothing
|
|
144
|
+
animates (found 31 Aug 2026). */
|
|
196
145
|
--transition-duration-micro: var(--duration-micro);
|
|
197
146
|
--transition-duration-quick: var(--duration-quick);
|
|
198
147
|
--transition-duration-fast: var(--duration-fast);
|
|
@@ -201,14 +150,8 @@
|
|
|
201
150
|
--transition-duration-very-slow: var(--duration-very-slow);
|
|
202
151
|
}
|
|
203
152
|
|
|
204
|
-
/*
|
|
205
|
-
*
|
|
206
|
-
* bits-ui v2 writes `data-checked` / `data-open` and v1 wrote
|
|
207
|
-
* `data-state="checked"`, so each variant matches both and a component does not
|
|
208
|
-
* have to know which it is talking to. They live here rather than in a
|
|
209
|
-
* consumer's stylesheet because the classes that need them ship in this
|
|
210
|
-
* package: an app that defines only the palette rendered a switch that never
|
|
211
|
-
* moved. Moved out of upsys `tokens.css` on 14 Sep 2026, with the kit. */
|
|
153
|
+
/* Each bits-ui variant matches v2's `data-open` and v1's `data-state`, and ships
|
|
154
|
+
* here because an app that defined only the palette got a switch that never moved. */
|
|
212
155
|
@custom-variant data-open {
|
|
213
156
|
&:where([data-state="open"]),
|
|
214
157
|
&:where([data-open]:not([data-open="false"])) {
|
package/src/design/polish.css
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
/*
|
|
2
|
-
*
|
|
3
|
-
* Two layers, on purpose. `base` holds the element defaults (focus, selection,
|
|
4
|
-
* scrollbars) so any component class or utility beats them. `components` holds
|
|
5
|
-
* the three motion primitives, so a utility still beats those too.
|
|
6
|
-
*
|
|
7
|
-
* WHY the layers are not optional: an `@import` at the top of an app stylesheet
|
|
8
|
-
* lands OUTSIDE Tailwind's layers, and unlayered CSS beats every layered rule
|
|
9
|
-
* whatever its specificity. Written bare, a `:where()` selector here would
|
|
10
|
-
* silently outrank `focus-visible:ring-3` on every control in the app.
|
|
11
|
-
*
|
|
12
|
-
* Imported by ./index.css. Do not import it on its own, because it reads the tokens
|
|
13
|
-
* that file declares. */
|
|
1
|
+
/* Keep every rule here inside a layer: unlayered CSS beats all layered rules, so a bare
|
|
2
|
+
* `:where()` would silently outrank `focus-visible:ring-3` on every control. */
|
|
14
3
|
|
|
15
4
|
@layer base {
|
|
16
5
|
/* One ring for the whole kit. `:where` keeps it at specificity zero on top of
|
|
@@ -26,9 +15,8 @@
|
|
|
26
15
|
background: color-mix(in oklab, var(--ring-color) 24%, transparent);
|
|
27
16
|
}
|
|
28
17
|
|
|
29
|
-
/*
|
|
30
|
-
transparent
|
|
31
|
-
is over. The border is what insets the thumb without a second element. */
|
|
18
|
+
/* The default macOS scrollbar paints a black bar on a dark panel, so the track stays
|
|
19
|
+
transparent and the border insets the thumb. */
|
|
32
20
|
:where(html) {
|
|
33
21
|
scrollbar-color: var(--color-border, var(--border)) transparent;
|
|
34
22
|
}
|
|
@@ -49,22 +37,19 @@
|
|
|
49
37
|
background-color: var(--color-border, var(--border));
|
|
50
38
|
}
|
|
51
39
|
|
|
52
|
-
|
|
53
|
-
|
|
40
|
+
@media (hover: hover) and (pointer: fine) {
|
|
41
|
+
::-webkit-scrollbar-thumb:hover {
|
|
42
|
+
background-color: var(--color-muted-foreground, var(--muted-foreground));
|
|
43
|
+
}
|
|
54
44
|
}
|
|
55
45
|
}
|
|
56
46
|
|
|
57
47
|
@layer components {
|
|
58
|
-
/*
|
|
59
|
-
component
|
|
60
|
-
motion guard then lives in one place instead of in every component.
|
|
61
|
-
|
|
62
|
-
Namespaced `t-` to match the transitions-dev snippets, which these sit
|
|
63
|
-
beside rather than duplicate. */
|
|
48
|
+
/* Classes, not tokens, so the reduced motion guard lives here once instead of in
|
|
49
|
+
every component. */
|
|
64
50
|
|
|
65
|
-
/* A
|
|
66
|
-
|
|
67
|
-
state, not as a press. */
|
|
51
|
+
/* A key that travels down a pixel when pressed, because a colour change alone
|
|
52
|
+
reads as hover, not as a press. */
|
|
68
53
|
.t-press {
|
|
69
54
|
transition:
|
|
70
55
|
background-color var(--duration-quick) var(--ease-smooth-out),
|
|
@@ -78,18 +63,19 @@
|
|
|
78
63
|
transform: translateY(1px);
|
|
79
64
|
}
|
|
80
65
|
|
|
81
|
-
/*
|
|
82
|
-
|
|
83
|
-
than as its border changing colour. */
|
|
66
|
+
/* The card rises a pixel and gains an elevation step, so hover reads as the card
|
|
67
|
+
coming forward, not its border changing colour. */
|
|
84
68
|
.t-lift {
|
|
85
69
|
transition:
|
|
86
70
|
box-shadow var(--duration-fast) var(--ease-smooth-out),
|
|
87
71
|
transform var(--duration-fast) var(--ease-smooth-out);
|
|
88
72
|
}
|
|
89
73
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
74
|
+
@media (hover: hover) and (pointer: fine) {
|
|
75
|
+
.t-lift:hover {
|
|
76
|
+
transform: translateY(-1px);
|
|
77
|
+
box-shadow: var(--elev-raised);
|
|
78
|
+
}
|
|
93
79
|
}
|
|
94
80
|
|
|
95
81
|
/* A surface arriving. The open carries the distance, the scale and the blur;
|
|
@@ -109,11 +95,16 @@
|
|
|
109
95
|
transition: none;
|
|
110
96
|
}
|
|
111
97
|
|
|
112
|
-
.t-press:active
|
|
113
|
-
.t-lift:hover {
|
|
98
|
+
.t-press:active {
|
|
114
99
|
transform: none;
|
|
115
100
|
}
|
|
116
101
|
|
|
102
|
+
@media (hover: hover) and (pointer: fine) {
|
|
103
|
+
.t-lift:hover {
|
|
104
|
+
transform: none;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
117
108
|
.t-enter,
|
|
118
109
|
.t-exit {
|
|
119
110
|
animation-duration: 1ms;
|
|
@@ -1,87 +1,87 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import type { Editor } from "@tiptap/core";
|
|
6
|
-
import { Button } from "../shadcn/button/index.js";
|
|
7
|
-
import { Input } from "../shadcn/input/index.js";
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from "phosphor-svelte";
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import type { Editor } from "@tiptap/core";
|
|
6
|
+
import { Button } from "../shadcn/button/index.js";
|
|
7
|
+
import { Input } from "../shadcn/input/index.js";
|
|
8
|
+
import {
|
|
9
|
+
TextB,
|
|
10
|
+
TextItalic,
|
|
11
|
+
TextStrikethrough,
|
|
12
|
+
LinkSimple,
|
|
13
|
+
LinkBreak,
|
|
14
|
+
ListBullets,
|
|
15
|
+
ListNumbers,
|
|
16
|
+
Quotes,
|
|
17
|
+
VideoCamera,
|
|
18
|
+
} from "phosphor-svelte";
|
|
19
19
|
|
|
20
|
-
// =========================
|
|
21
|
-
// TYPES
|
|
22
|
-
// =========================
|
|
23
|
-
interface Props {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
20
|
+
// =========================
|
|
21
|
+
// TYPES
|
|
22
|
+
// =========================
|
|
23
|
+
interface Props {
|
|
24
|
+
editor: Editor | null;
|
|
25
|
+
/** Bumped by the parent on every transaction, so active states re-read. */
|
|
26
|
+
tick: number;
|
|
27
|
+
preset: "full" | "notes";
|
|
28
|
+
onInsertYoutube: () => void;
|
|
29
|
+
}
|
|
30
30
|
|
|
31
|
-
// =========================
|
|
32
|
-
// PROPS
|
|
33
|
-
// =========================
|
|
34
|
-
let { editor: editorProp, tick, preset, onInsertYoutube }: Props = $props();
|
|
31
|
+
// =========================
|
|
32
|
+
// PROPS
|
|
33
|
+
// =========================
|
|
34
|
+
let { editor: editorProp, tick, preset, onInsertYoutube }: Props = $props();
|
|
35
35
|
|
|
36
|
-
// =========================
|
|
37
|
-
// STATE
|
|
38
|
-
// =========================
|
|
39
|
-
let linkUrl = $state("");
|
|
40
|
-
let showLinkPopover = $state(false);
|
|
41
|
-
let linkInputEl: HTMLInputElement | undefined = $state();
|
|
36
|
+
// =========================
|
|
37
|
+
// STATE
|
|
38
|
+
// =========================
|
|
39
|
+
let linkUrl = $state("");
|
|
40
|
+
let showLinkPopover = $state(false);
|
|
41
|
+
let linkInputEl: HTMLInputElement | undefined = $state();
|
|
42
42
|
|
|
43
|
-
// =========================
|
|
44
|
-
// DERIVED
|
|
45
|
-
// =========================
|
|
46
|
-
let editor: Editor | null = $derived(tick >= 0 ? editorProp : null);
|
|
43
|
+
// =========================
|
|
44
|
+
// DERIVED
|
|
45
|
+
// =========================
|
|
46
|
+
let editor: Editor | null = $derived(tick >= 0 ? editorProp : null);
|
|
47
47
|
|
|
48
|
-
// =========================
|
|
49
|
-
// EFFECTS
|
|
50
|
-
// =========================
|
|
51
|
-
$effect(() => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
48
|
+
// =========================
|
|
49
|
+
// EFFECTS
|
|
50
|
+
// =========================
|
|
51
|
+
$effect(() => {
|
|
52
|
+
if (showLinkPopover && linkInputEl) {
|
|
53
|
+
linkInputEl.focus();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
56
|
|
|
57
|
-
// =========================
|
|
58
|
-
// FUNCTIONS
|
|
59
|
-
// =========================
|
|
60
|
-
function toggleLink() {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
// =========================
|
|
58
|
+
// FUNCTIONS
|
|
59
|
+
// =========================
|
|
60
|
+
function toggleLink() {
|
|
61
|
+
if (!editor) return;
|
|
62
|
+
if (editor.isActive("link")) {
|
|
63
|
+
editor.chain().focus().unsetLink().run();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const previousUrl = editor.getAttributes("link").href;
|
|
67
|
+
linkUrl = previousUrl || "";
|
|
68
|
+
showLinkPopover = true;
|
|
65
69
|
}
|
|
66
|
-
const previousUrl = editor.getAttributes("link").href;
|
|
67
|
-
linkUrl = previousUrl || "";
|
|
68
|
-
showLinkPopover = true;
|
|
69
|
-
}
|
|
70
70
|
|
|
71
|
-
function applyLink() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
function applyLink() {
|
|
72
|
+
if (!editor) return;
|
|
73
|
+
if (linkUrl.trim()) {
|
|
74
|
+
editor.chain().focus().setLink({ href: linkUrl.trim() }).run();
|
|
75
|
+
}
|
|
76
|
+
linkUrl = "";
|
|
77
|
+
showLinkPopover = false;
|
|
75
78
|
}
|
|
76
|
-
linkUrl = "";
|
|
77
|
-
showLinkPopover = false;
|
|
78
|
-
}
|
|
79
79
|
|
|
80
|
-
function cancelLink() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
80
|
+
function cancelLink() {
|
|
81
|
+
linkUrl = "";
|
|
82
|
+
showLinkPopover = false;
|
|
83
|
+
editor?.chain().focus().run();
|
|
84
|
+
}
|
|
85
85
|
</script>
|
|
86
86
|
|
|
87
87
|
<!-- =========================== -->
|
|
@@ -98,7 +98,10 @@ function cancelLink() {
|
|
|
98
98
|
placeholder="Paste link..."
|
|
99
99
|
class="h-7 w-52 text-[0.8125rem]"
|
|
100
100
|
onkeydown={(e) => {
|
|
101
|
-
if (e.key === "Enter") {
|
|
101
|
+
if (e.key === "Enter") {
|
|
102
|
+
e.preventDefault();
|
|
103
|
+
applyLink();
|
|
104
|
+
}
|
|
102
105
|
if (e.key === "Escape") cancelLink();
|
|
103
106
|
}}
|
|
104
107
|
/>
|
|
@@ -106,12 +109,12 @@ function cancelLink() {
|
|
|
106
109
|
<LinkSimple size={14} />
|
|
107
110
|
</Button>
|
|
108
111
|
<Button
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
variant="ghost"
|
|
113
|
+
size="sm"
|
|
114
|
+
icon
|
|
115
|
+
class="text-muted-foreground aria-pressed:bg-brand/10 aria-pressed:text-brand"
|
|
116
|
+
onclick={cancelLink}
|
|
117
|
+
title="Cancel"
|
|
115
118
|
>
|
|
116
119
|
×
|
|
117
120
|
</Button>
|
|
@@ -191,24 +194,25 @@ function cancelLink() {
|
|
|
191
194
|
|
|
192
195
|
{#if editor.isActive("link")}
|
|
193
196
|
<Button
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
variant="ghost"
|
|
198
|
+
size="sm"
|
|
199
|
+
icon
|
|
200
|
+
class="text-muted-foreground aria-pressed:bg-brand/10 aria-pressed:text-brand"
|
|
201
|
+
aria-pressed={true}
|
|
202
|
+
onclick={() => editor?.chain().focus().unsetLink().run()}
|
|
200
203
|
title="Remove link"
|
|
201
204
|
>
|
|
202
205
|
<LinkBreak size={15} />
|
|
203
206
|
</Button>
|
|
204
207
|
{:else}
|
|
205
208
|
<Button
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
title="Add link (Cmd+K)"
|
|
209
|
+
variant="ghost"
|
|
210
|
+
size="sm"
|
|
211
|
+
icon
|
|
212
|
+
class="text-muted-foreground aria-pressed:bg-brand/10 aria-pressed:text-brand"
|
|
213
|
+
onclick={toggleLink}
|
|
214
|
+
title="Add link (Cmd+K)"
|
|
215
|
+
>
|
|
212
216
|
<LinkSimple size={15} />
|
|
213
217
|
</Button>
|
|
214
218
|
{/if}
|
|
@@ -253,13 +257,14 @@ function cancelLink() {
|
|
|
253
257
|
<div class="toolbar-divider"></div>
|
|
254
258
|
|
|
255
259
|
<Button
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
title="Insert YouTube video"
|
|
260
|
+
variant="ghost"
|
|
261
|
+
size="sm"
|
|
262
|
+
icon
|
|
263
|
+
class="text-muted-foreground aria-pressed:bg-brand/10 aria-pressed:text-brand"
|
|
264
|
+
aria-pressed={editor.isActive("youtube")}
|
|
265
|
+
onclick={onInsertYoutube}
|
|
266
|
+
title="Insert YouTube video"
|
|
267
|
+
>
|
|
263
268
|
<VideoCamera size={15} />
|
|
264
269
|
</Button>
|
|
265
270
|
{/if}
|