@lapismd/design-core 0.1.2 → 0.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE.md +3 -3
  3. package/README.md +20 -0
  4. package/package.json +24 -9
  5. package/spec/src/styling-and-themes.md +2 -0
  6. package/src/shared/ai/chat.css +23 -0
  7. package/src/shared/ai/chat.ts +12 -0
  8. package/src/shared/ai/context.svelte.ts +2 -0
  9. package/src/shared/ai/layout/Layout.svelte +116 -10
  10. package/src/shared/ai/message-list/MessageList.svelte +123 -43
  11. package/src/shared/ai/message-list/MessageListHistoryFixture.svelte +112 -0
  12. package/src/shared/ai/message-list/MessageListLegacyFixture.svelte +52 -0
  13. package/src/shared/ai/message-list/VirtualizedMessageRows.svelte +299 -0
  14. package/src/shared/ai/message-list/position.ts +7 -0
  15. package/src/shared/ai/new-messages.svelte.ts +24 -5
  16. package/src/shared/ai/stream-scroll.svelte.ts +135 -6
  17. package/src/shared/ai/tool-call-detail/ToolCallDetail.svelte +71 -0
  18. package/src/shared/ai/tool-call-detail/tool-call-detail.ts +209 -0
  19. package/src/shared/diff/core/merge/actions.ts +4 -3
  20. package/src/shared/diff/core/merge/render-model.ts +14 -10
  21. package/src/shared/diff/file-diff/FileDiff.css +68 -1
  22. package/src/shared/diff/file-diff/FileDiff.svelte +22 -6
  23. package/src/shared/diff/file-diff/FileDiffComposer.svelte +98 -16
  24. package/src/shared/diff/file-diff/index.ts +2 -0
  25. package/src/shared/diff/file-diff/types.ts +13 -0
  26. package/src/shared/diff/index.ts +2 -0
  27. package/src/shared/forms/confirm-button/ConfirmButton.svelte +38 -0
  28. package/src/shared/forms/confirm-button/ConfirmButtonExample.svelte +14 -0
  29. package/src/shared/forms/confirm-button/index.ts +1 -0
  30. package/src/shared/forms/confirm-dialog/ConfirmDialog.css +21 -0
  31. package/src/shared/forms/confirm-dialog/ConfirmDialog.svelte +116 -0
  32. package/src/shared/forms/confirm-dialog/ConfirmDialogExample.svelte +17 -0
  33. package/src/shared/forms/confirm-dialog/index.ts +2 -0
  34. package/src/shared/forms/dialog-frame/DialogFrame.css +130 -0
  35. package/src/shared/forms/dialog-frame/DialogFrame.svelte +108 -0
  36. package/src/shared/forms/dialog-frame/DialogFrameExample.svelte +37 -0
  37. package/src/shared/forms/dialog-frame/index.ts +6 -0
  38. package/src/shared/forms/dialog.ts +8 -0
  39. package/src/shared/forms/index.ts +11 -0
  40. package/src/shared/shadcn/button/button.svelte +4 -0
  41. package/src/shared/shadcn/code-block/highlightRanges.ts +10 -6
  42. package/src/shared/shadcn/code-block/syntax/defineSyntaxTheme.ts +4 -2
  43. package/src/shared/shadcn/code-block/tokenizer.ts +3 -3
  44. package/src/shared/shadcn/dialog/dialog-content.svelte +3 -4
  45. package/src/shared/shadcn/dialog/dialog-portal.svelte +10 -2
  46. package/src/shared/shadcn/tooltip/tooltip-content.svelte +10 -4
  47. package/src/shared/shadcn/tooltip/tooltip.tokens.ts +4 -0
  48. package/src/shared/shell/app-shell/AppShell.css +112 -32
  49. package/src/shared/shell/app-shell/AppShellMain.svelte +12 -1
  50. package/src/shared/shell/app-shell/AppShellRoot.svelte +27 -13
  51. package/src/shared/shell/app-shell/AppShellSidebar.svelte +121 -19
  52. package/src/shared/shell/app-shell/AppShellSidebarClose.svelte +17 -17
  53. package/src/shared/shell/app-shell/AppShellSidebarToggle.svelte +38 -58
  54. package/src/shared/shell/app-shell/AppShellSurfaceLayer.svelte +173 -0
  55. package/src/shared/shell/app-shell/AppShellSurfaceLayerBody.svelte +32 -0
  56. package/src/shared/shell/app-shell/AppShellSurfaceLayerHeader.svelte +26 -0
  57. package/src/shared/shell/app-shell/app-shell-context.svelte.ts +6 -3
  58. package/src/shared/shell/app-shell/app-shell-controller.svelte.ts +246 -2
  59. package/src/shared/shell/app-shell/app-shell-sidebar-context.svelte.ts +1 -0
  60. package/src/shared/shell/app-shell/examples/AppShellExamples.css +103 -0
  61. package/src/shared/shell/app-shell/examples/AppShellMultiPanelDemo.svelte +187 -0
  62. package/src/shared/shell/app-shell/index.ts +14 -0
  63. package/src/shared/shell/shell.tokens.css +2 -0
  64. package/src/shared/shell/shell.tokens.ts +5 -0
  65. package/src/theme.css +10 -0
@@ -2,6 +2,109 @@
2
2
  --ui-shell-body-sidebar-width: 10rem;
3
3
  }
4
4
 
5
+ .ui-shell-story-multi-panel {
6
+ width: min(100%, 80rem);
7
+ margin-inline: auto;
8
+ }
9
+
10
+ .ui-shell-story-multi-panel-wide {
11
+ width: min(100%, 94rem);
12
+ }
13
+
14
+ .ui-shell-story-multi-panel-dark {
15
+ color-scheme: dark;
16
+ }
17
+
18
+ .ui-shell-story-multi-panel__toolbar {
19
+ gap: 0.5rem;
20
+ padding-inline: 0.5rem;
21
+ }
22
+
23
+ .ui-shell-story-multi-panel__toolbar > span {
24
+ flex: 1;
25
+ }
26
+
27
+ .ui-shell-story-multi-panel__nav,
28
+ .ui-shell-story-multi-panel__rail {
29
+ display: grid;
30
+ gap: 0.25rem;
31
+ padding: 0.5rem;
32
+ }
33
+
34
+ .ui-shell-story-multi-panel__nav button,
35
+ .ui-shell-story-multi-panel__rail button {
36
+ display: flex;
37
+ min-height: 2.25rem;
38
+ align-items: center;
39
+ justify-content: space-between;
40
+ gap: 0.75rem;
41
+ padding: 0.375rem 0.625rem;
42
+ border: 0;
43
+ border-radius: calc(var(--radius) * 0.75);
44
+ color: var(--foreground);
45
+ background: transparent;
46
+ font: inherit;
47
+ text-align: start;
48
+ }
49
+
50
+ .ui-shell-story-multi-panel__nav button:is(:hover, :focus-visible),
51
+ .ui-shell-story-multi-panel__nav button[data-active],
52
+ .ui-shell-story-multi-panel__rail button:is(:hover, :focus-visible) {
53
+ background: var(--accent);
54
+ }
55
+
56
+ .ui-shell-story-multi-panel__rail small {
57
+ color: var(--muted-foreground);
58
+ }
59
+
60
+ .ui-shell-story-multi-panel__content {
61
+ width: min(100%, 42rem);
62
+ margin-inline: auto;
63
+ padding: clamp(2rem, 8cqw, 6rem) 1.5rem;
64
+ }
65
+
66
+ .ui-shell-story-multi-panel__content > p:first-child,
67
+ .ui-shell-story-multi-panel__panel-copy p {
68
+ color: var(--muted-foreground);
69
+ font-size: 0.75rem;
70
+ font-weight: 600;
71
+ letter-spacing: 0.06em;
72
+ text-transform: uppercase;
73
+ }
74
+
75
+ .ui-shell-story-multi-panel__content h1 {
76
+ margin-block: 0.5rem 1rem;
77
+ font-size: clamp(1.5rem, 4cqw, 3rem);
78
+ line-height: 1;
79
+ }
80
+
81
+ .ui-shell-story-multi-panel__panel-copy,
82
+ .ui-shell-story-multi-panel__reviews {
83
+ display: grid;
84
+ gap: 0.75rem;
85
+ padding: 1rem;
86
+ }
87
+
88
+ .ui-shell-story-multi-panel__panel-copy strong {
89
+ margin-block-end: 0.75rem;
90
+ }
91
+
92
+ .ui-shell-story-multi-panel__reviews article {
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: space-between;
96
+ gap: 1rem;
97
+ padding: 1rem;
98
+ border: 1px solid var(--border);
99
+ border-radius: var(--radius);
100
+ background: var(--card);
101
+ }
102
+
103
+ .ui-shell-story-multi-panel__reviews span {
104
+ color: var(--muted-foreground);
105
+ font-size: 0.75rem;
106
+ }
107
+
5
108
  .ui-shell-story-mode-demo {
6
109
  position: relative;
7
110
  height: 100%;
@@ -0,0 +1,187 @@
1
+ <script lang="ts">
2
+ import { Button } from "../../../shadcn/button/index.js";
3
+ import type {
4
+ AppShellController,
5
+ AppShellDisplayMode,
6
+ AppShellSidebarController,
7
+ } from "../app-shell-controller.svelte.js";
8
+ import { AppShell } from "../index.js";
9
+ import "./AppShellExamples.css";
10
+
11
+ let {
12
+ controller,
13
+ overview,
14
+ activity,
15
+ displayMode = "desktop",
16
+ frameClass,
17
+ direction = "ltr",
18
+ }: {
19
+ controller: AppShellController;
20
+ overview: AppShellSidebarController;
21
+ activity: AppShellSidebarController;
22
+ displayMode?: AppShellDisplayMode;
23
+ frameClass?: string;
24
+ direction?: "ltr" | "rtl";
25
+ } = $props();
26
+
27
+ let surfaceOpen = $state(false);
28
+ let surfaceTrigger = $state<HTMLButtonElement | null>(null);
29
+ </script>
30
+
31
+ <div
32
+ class={["ui-shell-story-frame", "ui-shell-story-multi-panel", frameClass]
33
+ .filter(Boolean)
34
+ .join(" ")}
35
+ dir={direction}
36
+ >
37
+ <AppShell.Root
38
+ {controller}
39
+ {displayMode}
40
+ mobileBreakpoint={760}
41
+ desktopMinMainWidth={440}
42
+ class="ui-shell-story-surface"
43
+ >
44
+ <AppShell.Sidebar side="left" label="Navigation" resizable>
45
+ <AppShell.Sidebar.Header>
46
+ <strong>Workspace</strong>
47
+ </AppShell.Sidebar.Header>
48
+ <AppShell.Sidebar.Body>
49
+ <nav class="ui-shell-story-multi-panel__nav" aria-label="Workspace">
50
+ <button type="button" data-active>Inbox</button>
51
+ <button type="button">Projects</button>
52
+ <button type="button">Archive</button>
53
+ </nav>
54
+ </AppShell.Sidebar.Body>
55
+ </AppShell.Sidebar>
56
+
57
+ <AppShell.Main>
58
+ <AppShell.Toolbar class="ui-shell-story-multi-panel__toolbar">
59
+ <AppShell.Sidebar.Toggle side="left" sidebarName="navigation" />
60
+ <strong>Project updates</strong>
61
+ <span></span>
62
+ <AppShell.Sidebar.Toggle side="right" sidebarName="details" />
63
+ <AppShell.Sidebar.Toggle
64
+ side="right"
65
+ sidebarController={overview}
66
+ sidebarName="overview"
67
+ />
68
+ </AppShell.Toolbar>
69
+ <AppShell.Body label="Project workspace">
70
+ <article class="ui-shell-story-multi-panel__content">
71
+ <p>Project workspace</p>
72
+ <h1>Composable same-side panels</h1>
73
+ <p>
74
+ The main surface stays mounted while inspectors, overview rails, and
75
+ structural layers respond to the available width.
76
+ </p>
77
+ <button type="button">Draft update</button>
78
+ </article>
79
+ </AppShell.Body>
80
+ </AppShell.Main>
81
+
82
+ <AppShell.Sidebar
83
+ side="right"
84
+ label="Details"
85
+ constraintPriority={0}
86
+ constrainedPresentation="replace-main"
87
+ closeable
88
+ >
89
+ <AppShell.Sidebar.Header>
90
+ <strong>Details</strong>
91
+ <AppShell.Sidebar.Close />
92
+ </AppShell.Sidebar.Header>
93
+ <AppShell.Sidebar.Body>
94
+ <div class="ui-shell-story-multi-panel__panel-copy">
95
+ <p>Owner</p>
96
+ <strong>Design systems</strong>
97
+ <p>Status</p>
98
+ <strong>In review</strong>
99
+ </div>
100
+ </AppShell.Sidebar.Body>
101
+ </AppShell.Sidebar>
102
+
103
+ <AppShell.Sidebar
104
+ side="right"
105
+ sidebarController={overview}
106
+ label="Overview rail"
107
+ variant="rail"
108
+ constraintPriority={100}
109
+ resizable
110
+ >
111
+ <AppShell.Sidebar.Body>
112
+ <nav class="ui-shell-story-multi-panel__rail" aria-label="Overview">
113
+ <button type="button"><span>Reviews</span><small>4</small></button>
114
+ <button type="button"><span>People</span><small>12</small></button>
115
+ </nav>
116
+ </AppShell.Sidebar.Body>
117
+ </AppShell.Sidebar>
118
+
119
+ <AppShell.Sidebar
120
+ side="right"
121
+ sidebarController={activity}
122
+ label="Activity rail"
123
+ variant="rail"
124
+ constraintPriority={100}
125
+ resizable
126
+ >
127
+ <AppShell.Sidebar.Body>
128
+ <nav class="ui-shell-story-multi-panel__rail" aria-label="Activity">
129
+ <button type="button"><span>Tasks</span><small>7</small></button>
130
+ <button type="button"><span>Commits</span><small>18</small></button>
131
+ <Button
132
+ bind:ref={surfaceTrigger}
133
+ variant="outline"
134
+ size="sm"
135
+ onclick={() => (surfaceOpen = true)}
136
+ >
137
+ Open reviews
138
+ </Button>
139
+ </nav>
140
+ </AppShell.Sidebar.Body>
141
+ </AppShell.Sidebar>
142
+
143
+ <AppShell.SurfaceLayer
144
+ open={surfaceOpen}
145
+ label="Release reviews"
146
+ coverPanelIds={["right"]}
147
+ suspendPanelIds={["overview"]}
148
+ returnFocus={surfaceTrigger}
149
+ dismissLabel="Close reviews"
150
+ onDismiss={() => (surfaceOpen = false)}
151
+ >
152
+ <AppShell.SurfaceLayer.Header>
153
+ <strong>Release reviews</strong>
154
+ <Button
155
+ variant="ghost"
156
+ size="icon-sm"
157
+ aria-label="Close release reviews"
158
+ onclick={() => (surfaceOpen = false)}
159
+ >
160
+ <svg
161
+ xmlns="http://www.w3.org/2000/svg"
162
+ viewBox="0 0 24 24"
163
+ fill="none"
164
+ stroke="currentColor"
165
+ stroke-width="2"
166
+ stroke-linecap="round"
167
+ aria-hidden="true"
168
+ >
169
+ <path d="M18 6 6 18M6 6l12 12"></path>
170
+ </svg>
171
+ </Button>
172
+ </AppShell.SurfaceLayer.Header>
173
+ <AppShell.SurfaceLayer.Body>
174
+ <div class="ui-shell-story-multi-panel__reviews">
175
+ <article>
176
+ <strong>History 0.1.3</strong>
177
+ <span>Pending review</span>
178
+ </article>
179
+ <article>
180
+ <strong>Markdown 0.1.5</strong>
181
+ <span>Approved</span>
182
+ </article>
183
+ </div>
184
+ </AppShell.SurfaceLayer.Body>
185
+ </AppShell.SurfaceLayer>
186
+ </AppShell.Root>
187
+ </div>
@@ -10,6 +10,9 @@ import AppShellSidebarClose from "./AppShellSidebarClose.svelte";
10
10
  import AppShellSidebarFooter from "./AppShellSidebarFooter.svelte";
11
11
  import AppShellSidebarHeader from "./AppShellSidebarHeader.svelte";
12
12
  import AppShellSidebarToggle from "./AppShellSidebarToggle.svelte";
13
+ import AppShellSurfaceLayer from "./AppShellSurfaceLayer.svelte";
14
+ import AppShellSurfaceLayerBody from "./AppShellSurfaceLayerBody.svelte";
15
+ import AppShellSurfaceLayerHeader from "./AppShellSurfaceLayerHeader.svelte";
13
16
  import AppShellToolbar from "./AppShellToolbar.svelte";
14
17
 
15
18
  export const Sidebar = Object.assign(AppShellSidebar, {
@@ -26,6 +29,11 @@ export const Body = Object.assign(AppShellBody, {
26
29
  Toggle: AppShellBodyToggle,
27
30
  });
28
31
 
32
+ export const SurfaceLayer = Object.assign(AppShellSurfaceLayer, {
33
+ Header: AppShellSurfaceLayerHeader,
34
+ Body: AppShellSurfaceLayerBody,
35
+ });
36
+
29
37
  export {
30
38
  AppShellBody,
31
39
  AppShellBodyContent,
@@ -39,6 +47,9 @@ export {
39
47
  AppShellSidebarFooter,
40
48
  AppShellSidebarHeader,
41
49
  AppShellSidebarToggle,
50
+ AppShellSurfaceLayer,
51
+ AppShellSurfaceLayerBody,
52
+ AppShellSurfaceLayerHeader,
42
53
  AppShellToolbar,
43
54
  AppShellBodyContent as BodyContent,
44
55
  AppShellBodySidebar as BodySidebar,
@@ -50,6 +61,8 @@ export {
50
61
  AppShellSidebarFooter as SidebarFooter,
51
62
  AppShellSidebarHeader as SidebarHeader,
52
63
  AppShellSidebarToggle as SidebarToggle,
64
+ AppShellSurfaceLayerBody as SurfaceLayerBody,
65
+ AppShellSurfaceLayerHeader as SurfaceLayerHeader,
53
66
  AppShellToolbar as Toolbar,
54
67
  };
55
68
 
@@ -59,6 +72,7 @@ export const AppShell = {
59
72
  Main: AppShellMain,
60
73
  Toolbar: AppShellToolbar,
61
74
  Body,
75
+ SurfaceLayer,
62
76
  } as const;
63
77
 
64
78
  export * from "./app-shell-body-context.svelte.js";
@@ -19,4 +19,6 @@
19
19
  color-mix(in srgb, var(--foreground) 10%, transparent),
20
20
  0 1px 2px -1px color-mix(in srgb, var(--foreground) 10%, transparent);
21
21
  --ui-shell-main-border: 1px solid var(--border);
22
+ --ui-shell-surface-layer-main-start-allowance: 0px;
23
+ --ui-shell-surface-layer-inline-end-inset: var(--ui-shell-main-block-inset);
22
24
  }
@@ -14,6 +14,9 @@ export const shellTokenNames = {
14
14
  mainRadius: "--ui-shell-main-radius",
15
15
  mainShadow: "--ui-shell-main-shadow",
16
16
  mainBorder: "--ui-shell-main-border",
17
+ surfaceLayerMainStartAllowance:
18
+ "--ui-shell-surface-layer-main-start-allowance",
19
+ surfaceLayerInlineEndInset: "--ui-shell-surface-layer-inline-end-inset",
17
20
  } as const;
18
21
 
19
22
  export type ShellTokenKey = keyof typeof shellTokenNames;
@@ -36,4 +39,6 @@ export const shellTokenDefaults: Record<ShellTokenKey, string> = {
36
39
  mainShadow:
37
40
  "0 1px 3px color-mix(in srgb, var(--foreground) 10%, transparent), 0 1px 2px -1px color-mix(in srgb, var(--foreground) 10%, transparent)",
38
41
  mainBorder: "1px solid var(--border)",
42
+ surfaceLayerMainStartAllowance: "0px",
43
+ surfaceLayerInlineEndInset: "var(--ui-shell-main-block-inset)",
39
44
  };
package/src/theme.css CHANGED
@@ -1,6 +1,16 @@
1
1
  @custom-variant dark (&:is(.dark *));
2
2
 
3
3
  :root {
4
+ /* Runtime defaults must survive consumer Tailwind tree shaking. */
5
+ --container-xs: 20rem;
6
+ --container-md: 28rem;
7
+ --container-lg: 32rem;
8
+ --text-xs: 0.75rem;
9
+ --text-sm: 0.875rem;
10
+ --text-base: 1rem;
11
+ --text-lg: 1.125rem;
12
+ --text-xl: 1.25rem;
13
+ --text-2xl: 1.5rem;
4
14
  /* Compiled shadcn CSS reads these even when a consumer does not reprocess @theme. */
5
15
  --color-white: #ffffff;
6
16
  --color-black: #000000;