@olympusoss/canvas 2.14.0 → 2.16.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olympusoss/canvas",
3
- "version": "2.14.0",
3
+ "version": "2.16.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -76,6 +76,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
76
76
  return (
77
77
  <input
78
78
  type={type}
79
+ data-slot="input"
79
80
  className={cn(
80
81
  "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
81
82
  className,
@@ -15,6 +15,7 @@ export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
15
15
  const Card = React.forwardRef<HTMLDivElement, CardProps>(({ className, ...props }, ref) => (
16
16
  <div
17
17
  ref={ref}
18
+ data-slot="card"
18
19
  className={cn("rounded-xl border border-border bg-card text-card-foreground shadow", className)}
19
20
  {...props}
20
21
  />
@@ -32,6 +32,7 @@ const CodeBlock = React.forwardRef<HTMLDivElement, CodeBlockProps>(
32
32
  return (
33
33
  <div
34
34
  ref={ref}
35
+ data-slot="code-block"
35
36
  className={cn(
36
37
  "relative overflow-hidden rounded-md",
37
38
  isDark ? "border border-border" : "bg-muted",
@@ -28,6 +28,7 @@ const EmptyState = React.forwardRef<HTMLDivElement, EmptyStateProps>(
28
28
  return (
29
29
  <div
30
30
  ref={ref}
31
+ data-slot="empty-state"
31
32
  className={cn(
32
33
  "flex flex-col items-center justify-center gap-3 py-12 text-muted-foreground",
33
34
  className,
@@ -61,7 +61,7 @@ export function SectionCard({
61
61
  </div>
62
62
  {resolvedActions && <div className="flex items-center gap-2">{resolvedActions}</div>}
63
63
  </CardHeader>
64
- <div className="mx-5 mb-3.5 h-px bg-border" />
64
+ <div data-slot="card-divider" className="mx-5 mb-3.5 h-px bg-border" />
65
65
  </>
66
66
  )}
67
67
  <CardContent className={cn(padding ? "px-5 pb-[18px] pt-0" : "p-0")}>
@@ -237,7 +237,7 @@ function DataTable<TData>({
237
237
  </div>
238
238
  )}
239
239
 
240
- <div className="rounded-md border border-border">
240
+ <div data-slot="data-table" className="rounded-md border border-border">
241
241
  <Table>
242
242
  <TableHeader>
243
243
  {table.getHeaderGroups().map((headerGroup) => (
@@ -60,6 +60,7 @@ const DrawerContent = React.forwardRef<
60
60
  <DrawerOverlay />
61
61
  <DrawerPrimitive.Content
62
62
  ref={ref}
63
+ data-slot="drawer-content"
63
64
  className={cn(
64
65
  "fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border border-border bg-background",
65
66
  className,
@@ -132,6 +132,7 @@ const PopoverContent = React.forwardRef<
132
132
  <PopoverPrimitive.Portal container={container ?? undefined}>
133
133
  <PopoverPrimitive.Content
134
134
  ref={ref}
135
+ data-slot="popover-content"
135
136
  align={align}
136
137
  sideOffset={sideOffset}
137
138
  className={cn(
@@ -166,6 +166,7 @@ const SheetContent = React.forwardRef<
166
166
  <SheetOverlay />
167
167
  <SheetPrimitive.Content
168
168
  ref={ref}
169
+ data-slot="sheet-content"
169
170
  className={cn(sheetVariants({ side }), className)}
170
171
  {...props}
171
172
  >
@@ -209,6 +209,7 @@ const Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(
209
209
  if (collapsible === "none") {
210
210
  return (
211
211
  <div
212
+ data-slot="sidebar"
212
213
  className={cn(
213
214
  "flex h-full w-[var(--sidebar-width)] flex-col bg-sidebar text-sidebar-foreground",
214
215
  className,
@@ -281,6 +282,7 @@ const Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(
281
282
  >
282
283
  <div
283
284
  data-sidebar="sidebar"
285
+ data-slot="sidebar"
284
286
  className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
285
287
  >
286
288
  {children}
@@ -0,0 +1,137 @@
1
+ /* ---------- Glass surface mode ----------
2
+ *
3
+ * Activated by `html[data-surface="glass"]`. The conceit: an aurora-tinted
4
+ * backdrop shows through every chrome surface (sidebar, topbar, cards,
5
+ * tables) via `backdrop-filter: blur(...)`. Surfaces become tinted glass,
6
+ * with a low-alpha card color so the page palette bleeds through, plus a
7
+ * 1-px inner highlight on the top edge to suggest a refractive lip.
8
+ * Borders drop to white/black at low alpha so the layout reads as layered
9
+ * panes rather than rectangles drawn on flat paint.
10
+ *
11
+ * Two palettes:
12
+ * - Light: pastel peach + sky + lavender washes on near-white
13
+ * - Dark : deep indigo + violet + teal washes on near-black
14
+ *
15
+ * Surfaces opt in via `data-slot` attributes already present on Canvas
16
+ * components (`card`, `sidebar`, `data-table`, `input`, `popover-content`,
17
+ * `sheet-content`, `drawer-content`, `empty-state`, `code-block`). Consumer
18
+ * apps activate the mode by toggling the `data-surface` attribute on
19
+ * `<html>` (e.g. `document.documentElement.dataset.surface = "glass"`).
20
+ *
21
+ * Mirrors the Athena design handoff's `app.css` glass block; do not
22
+ * tighten these values without checking against the handoff bundle.
23
+ */
24
+
25
+ @layer base {
26
+ html[data-surface="glass"] {
27
+ --glass-tint: 0 0% 100%; /* card tint base */
28
+ --glass-tint-alpha: 0.55;
29
+ --glass-border: 0 0% 100%;
30
+ --glass-border-alpha: 0.45;
31
+ --glass-highlight: 0 0% 100%;
32
+ --glass-highlight-alpha: 0.55;
33
+ --glass-shadow: 220 30% 20%;
34
+ --glass-blur: 18px;
35
+ --glass-saturate: 140%;
36
+ }
37
+
38
+ html[data-surface="glass"].dark {
39
+ --glass-tint: 222 22% 18%;
40
+ --glass-tint-alpha: 0.55;
41
+ --glass-border: 0 0% 100%;
42
+ --glass-border-alpha: 0.1;
43
+ --glass-highlight: 0 0% 100%;
44
+ --glass-highlight-alpha: 0.1;
45
+ --glass-shadow: 222 60% 4%;
46
+ }
47
+
48
+ /* ──────────────────────────────────────────────────────────────
49
+ * Aurora backdrop — three soft radial washes anchored to body so
50
+ * they remain stable across route changes and ignore the inner
51
+ * shell's flat fill. The surfaces above are translucent so this
52
+ * is what users actually see "through" the glass.
53
+ * ──────────────────────────────────────────────────────────── */
54
+ html[data-surface="glass"] body {
55
+ background:
56
+ radial-gradient(60% 50% at 12% 10%, hsl(28 100% 80% / 0.55), transparent 60%),
57
+ radial-gradient(55% 55% at 88% 8%, hsl(210 100% 78% / 0.55), transparent 60%),
58
+ radial-gradient(70% 60% at 50% 100%, hsl(270 90% 82% / 0.45), transparent 65%),
59
+ hsl(220 30% 97%);
60
+ background-attachment: fixed;
61
+ }
62
+
63
+ html[data-surface="glass"].dark body {
64
+ background:
65
+ radial-gradient(55% 50% at 10% 8%, hsl(245 90% 60% / 0.4), transparent 60%),
66
+ radial-gradient(50% 55% at 92% 12%, hsl(280 85% 55% / 0.35), transparent 60%),
67
+ radial-gradient(70% 60% at 50% 100%, hsl(190 90% 45% / 0.28), transparent 70%),
68
+ hsl(222 30% 6%);
69
+ background-attachment: fixed;
70
+ }
71
+
72
+ /* ──────────────────────────────────────────────────────────────
73
+ * Frosted-pane mixin. Same translucent fill, blur, and refractive
74
+ * highlight on every load-bearing surface so the whole layout
75
+ * reads as one stack of glass panes.
76
+ * ──────────────────────────────────────────────────────────── */
77
+ html[data-surface="glass"] [data-slot="card"],
78
+ html[data-surface="glass"] [data-slot="sidebar"],
79
+ html[data-surface="glass"] [data-slot="topbar"],
80
+ html[data-surface="glass"] [data-slot="data-table"],
81
+ html[data-surface="glass"] [data-slot="empty-state"],
82
+ html[data-surface="glass"] [data-slot="popover-content"],
83
+ html[data-surface="glass"] [data-slot="sheet-content"],
84
+ html[data-surface="glass"] [data-slot="drawer-content"] {
85
+ background: hsl(var(--glass-tint) / var(--glass-tint-alpha));
86
+ backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
87
+ -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
88
+ border-color: hsl(var(--glass-border) / var(--glass-border-alpha));
89
+ box-shadow:
90
+ inset 0 1px 0 hsl(var(--glass-highlight) / var(--glass-highlight-alpha)),
91
+ 0 1px 2px hsl(var(--glass-shadow) / 0.06),
92
+ 0 8px 24px -12px hsl(var(--glass-shadow) / 0.18);
93
+ }
94
+
95
+ /* Sidebar and topbar take a slightly less-opaque tint so they
96
+ * read as chrome rather than content cards. */
97
+ html[data-surface="glass"] [data-slot="sidebar"],
98
+ html[data-surface="glass"] [data-slot="topbar"] {
99
+ background: hsl(var(--glass-tint) / calc(var(--glass-tint-alpha) - 0.1));
100
+ border-color: hsl(var(--glass-border) / var(--glass-border-alpha));
101
+ }
102
+
103
+ /* DataTable internal rules — header tint, row separators, hover. */
104
+ html[data-surface="glass"] [data-slot="data-table"] thead tr {
105
+ background: hsl(var(--glass-highlight) / 0.1);
106
+ border-bottom: 1px solid hsl(var(--glass-border) / var(--glass-border-alpha));
107
+ }
108
+ html[data-surface="glass"] [data-slot="data-table"] tbody tr {
109
+ border-bottom: 1px solid hsl(var(--glass-border) / calc(var(--glass-border-alpha) - 0.2));
110
+ }
111
+ html[data-surface="glass"] [data-slot="data-table"] tbody tr:hover {
112
+ background: hsl(var(--glass-highlight) / 0.1);
113
+ }
114
+
115
+ /* SectionCard divider matches the border tone. */
116
+ html[data-surface="glass"] [data-slot="card"] [data-slot="card-divider"] {
117
+ background: hsl(var(--glass-border) / var(--glass-border-alpha));
118
+ }
119
+
120
+ /* Inputs, kbd, codeblock — frosted to match. Less blur than full panes
121
+ * so dense form rows stay readable. */
122
+ html[data-surface="glass"] [data-slot="input"],
123
+ html[data-surface="glass"] [data-slot="code-block"] {
124
+ background: hsl(var(--glass-tint) / 0.35);
125
+ border-color: hsl(var(--glass-border) / var(--glass-border-alpha));
126
+ backdrop-filter: blur(8px);
127
+ -webkit-backdrop-filter: blur(8px);
128
+ }
129
+
130
+ /* Popovers/sheets/drawers — slightly more opaque so the content stays
131
+ * legible against the body aurora. */
132
+ html[data-surface="glass"] [data-slot="popover-content"],
133
+ html[data-surface="glass"] [data-slot="sheet-content"],
134
+ html[data-surface="glass"] [data-slot="drawer-content"] {
135
+ background: hsl(var(--glass-tint) / 0.85);
136
+ }
137
+ }
package/styles/tokens.css CHANGED
@@ -12,9 +12,25 @@
12
12
  * v4's `@theme inline { --color-sidebar: var(--sidebar) }` mapping so
13
13
  * `bg-sidebar` / `text-sidebar-foreground` utilities resolve.
14
14
  *
15
- * Typography canonical: Inter for surfaces, JetBrains Mono for code.
15
+ * Typography canonical (per handoff): Roboto for surfaces with Inter as a
16
+ * fallback while a consumer migrates, JetBrains Mono for code. The Roboto
17
+ * variable font is self-hosted at ./fonts/Roboto-VariableFont_wdth_wght.ttf
18
+ * and ships with the package (covered by the `styles` files entry).
16
19
  */
17
20
 
21
+ /* Roboto variable font, self-hosted. Same axis range as the handoff
22
+ * (wght 100–900, wdth 75–100). JetBrains Mono is NOT loaded here:
23
+ * consumer apps own how they pull it in (e.g. Next.js `next/font/google`)
24
+ * so Canvas does not introduce an external @import dependency. */
25
+ @font-face {
26
+ font-family: "Roboto";
27
+ src: url("./fonts/Roboto-VariableFont_wdth_wght.ttf") format("truetype-variations");
28
+ font-weight: 100 900;
29
+ font-stretch: 75% 100%;
30
+ font-style: normal;
31
+ font-display: swap;
32
+ }
33
+
18
34
  @layer base {
19
35
  :root {
20
36
  /* ── Base palette (light) ───────────────────────────────────
@@ -76,7 +92,7 @@
76
92
  --stat-amber: 38 92% 50%; /* #f59e0b */
77
93
 
78
94
  /* ── Typography ────────────────────────────────────────────── */
79
- --font-sans: "Inter", system-ui, -apple-system, sans-serif;
95
+ --font-sans: "Roboto", "Inter", system-ui, -apple-system, sans-serif;
80
96
  --font-mono: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
81
97
 
82
98
  /* ── Letter-spacing scale ──────────────────────────────────── *