@zylem/ui 0.1.0 → 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.
- package/dist/chunk-VGOOWBSO.js +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +75 -2
- package/dist/index.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.js +1 -1
- package/package.json +13 -11
- package/src/components/Accordion/Accordion.tsx +60 -0
- package/src/components/Badge/Badge.css.ts +52 -0
- package/src/components/Badge/Badge.tsx +23 -0
- package/src/components/Button/Button.css.ts +127 -0
- package/src/components/Button/Button.tsx +34 -0
- package/src/components/Card/Card.css.ts +62 -0
- package/src/components/Card/Card.tsx +54 -0
- package/src/{global/checkbox.css.ts → components/Checkbox/Checkbox.css.ts} +23 -23
- package/src/components/Checkbox/Checkbox.tsx +41 -0
- package/src/components/Console/Console.css.ts +67 -0
- package/src/components/Console/Console.tsx +51 -0
- package/src/components/Dialog/Dialog.css.ts +86 -0
- package/src/components/Dialog/Dialog.tsx +89 -0
- package/src/components/DropdownMenu/DropdownMenu.css.ts +76 -0
- package/src/components/DropdownMenu/DropdownMenu.tsx +63 -0
- package/src/components/EmptyState/EmptyState.css.ts +29 -0
- package/src/components/EmptyState/EmptyState.tsx +32 -0
- package/src/components/Kbd/Kbd.css.ts +27 -0
- package/src/components/Kbd/Kbd.tsx +17 -0
- package/src/components/NumberField/NumberField.css.ts +47 -0
- package/src/components/NumberField/NumberField.tsx +66 -0
- package/src/components/Panel/Panel.css.ts +88 -0
- package/src/components/Panel/Panel.tsx +66 -0
- package/src/components/Progress/Progress.css.ts +51 -0
- package/src/components/Progress/Progress.tsx +43 -0
- package/src/components/Property/Property.css.ts +70 -0
- package/src/components/Property/Property.tsx +118 -0
- package/src/components/ScrollArea/ScrollArea.tsx +41 -0
- package/src/components/SearchInput/SearchInput.css.ts +25 -0
- package/src/components/SearchInput/SearchInput.tsx +31 -0
- package/src/components/Select/Select.css.ts +93 -0
- package/src/components/Select/Select.tsx +68 -0
- package/src/components/Separator/Separator.css.ts +22 -0
- package/src/components/Separator/Separator.tsx +18 -0
- package/src/components/Sidebar/Sidebar.css.ts +79 -0
- package/src/components/Sidebar/Sidebar.tsx +69 -0
- package/src/components/Slider/Slider.css.ts +91 -0
- package/src/components/Slider/Slider.tsx +51 -0
- package/src/components/Switch/Switch.css.ts +72 -0
- package/src/components/Switch/Switch.tsx +36 -0
- package/src/components/Tabs/Tabs.css.ts +70 -0
- package/src/components/Tabs/Tabs.tsx +79 -0
- package/src/components/TextField/TextField.css.ts +16 -0
- package/src/components/TextField/TextField.tsx +76 -0
- package/src/components/TitleBar/TitleBar.css.ts +46 -0
- package/src/components/TitleBar/TitleBar.tsx +60 -0
- package/src/components/Toolbar/Toolbar.css.ts +29 -0
- package/src/components/Toolbar/Toolbar.tsx +30 -0
- package/src/components/ToolbarButton/ToolbarButton.css.ts +67 -0
- package/src/components/ToolbarButton/ToolbarButton.tsx +42 -0
- package/src/components/Tooltip/Tooltip.css.ts +35 -0
- package/src/components/Tooltip/Tooltip.tsx +33 -0
- package/src/components/WindowControls/WindowControls.css.ts +59 -0
- package/src/components/WindowControls/WindowControls.tsx +51 -0
- package/src/components/index.ts +67 -6
- package/src/components/shared/field.css.ts +60 -0
- package/src/global/accordion.css.ts +32 -18
- package/src/global/common.css.ts +14 -17
- package/src/global/detached-panel.css.ts +31 -8
- package/src/global/editor-base.css.ts +96 -121
- package/src/global/entities.css.ts +19 -15
- package/src/global/hyperglass-base.css.ts +166 -0
- package/src/global/menu.css.ts +8 -3
- package/src/sprinkles.css.ts +22 -0
- package/src/styles.ts +32 -4
- package/src/theme.css.ts +190 -99
- package/dist/chunk-3R5KFBTB.js +0 -1
- package/src/components/Button.tsx +0 -19
- package/src/global/console.css.ts +0 -43
- package/src/global/sidebar.css.ts +0 -18
- package/src/global/toolbar.css.ts +0 -62
package/dist/styles.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./chunk-
|
|
1
|
+
import"./chunk-VGOOWBSO.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zylem/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Design tokens, global styles, and Solid components for Zylem, built with vanilla-extract",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -40,13 +40,6 @@
|
|
|
40
40
|
"dist",
|
|
41
41
|
"src"
|
|
42
42
|
],
|
|
43
|
-
"scripts": {
|
|
44
|
-
"build": "tsup",
|
|
45
|
-
"prepublishOnly": "NODE_ENV=production tsup",
|
|
46
|
-
"dev": "tsup --watch",
|
|
47
|
-
"showcase": "vite --host",
|
|
48
|
-
"lint": "biome check ."
|
|
49
|
-
},
|
|
50
43
|
"peerDependencies": {
|
|
51
44
|
"solid-js": "^1.9.9"
|
|
52
45
|
},
|
|
@@ -57,10 +50,9 @@
|
|
|
57
50
|
},
|
|
58
51
|
"devDependencies": {
|
|
59
52
|
"@biomejs/biome": "^2.3.7",
|
|
60
|
-
"@
|
|
53
|
+
"@clack/prompts": "^1.6.0",
|
|
61
54
|
"@vanilla-extract/esbuild-plugin": "^2.3.22",
|
|
62
55
|
"@vanilla-extract/vite-plugin": "^5.2.2",
|
|
63
|
-
"lucide-solid": "^0.511.0",
|
|
64
56
|
"solid-js": "^1.9.9",
|
|
65
57
|
"tsup": "^8.5.1",
|
|
66
58
|
"typescript": "6.0.3",
|
|
@@ -68,7 +60,17 @@
|
|
|
68
60
|
"vite-plugin-solid": "^2.11.8"
|
|
69
61
|
},
|
|
70
62
|
"dependencies": {
|
|
63
|
+
"@kobalte/core": "^0.13.11",
|
|
71
64
|
"@vanilla-extract/css": "^1.20.1",
|
|
72
|
-
"@vanilla-extract/
|
|
65
|
+
"@vanilla-extract/recipes": "^0.5.7",
|
|
66
|
+
"@vanilla-extract/sprinkles": "^1.6.5",
|
|
67
|
+
"lucide-solid": "^0.511.0"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"zylem": "node --experimental-strip-types ./scripts/zylem-runner.ts",
|
|
71
|
+
"build": "tsup",
|
|
72
|
+
"dev": "tsup --watch",
|
|
73
|
+
"showcase": "vite --host",
|
|
74
|
+
"lint": "biome check ."
|
|
73
75
|
}
|
|
74
76
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Accordion as KAccordion } from '@kobalte/core';
|
|
2
|
+
import { For } from 'solid-js';
|
|
3
|
+
import type { JSX } from 'solid-js';
|
|
4
|
+
|
|
5
|
+
export interface AccordionItemConfig {
|
|
6
|
+
id: string;
|
|
7
|
+
title: JSX.Element;
|
|
8
|
+
content: () => JSX.Element;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface AccordionProps {
|
|
12
|
+
items: AccordionItemConfig[];
|
|
13
|
+
multiple?: boolean;
|
|
14
|
+
collapsible?: boolean;
|
|
15
|
+
value?: string[];
|
|
16
|
+
onChange?: (value: string[]) => void;
|
|
17
|
+
defaultValue?: string[];
|
|
18
|
+
class?: string;
|
|
19
|
+
/** Extra class applied to each content region (e.g. scroll helpers). */
|
|
20
|
+
contentClass?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* HyperGlass accordion: stack of glossy card headers over glass content
|
|
25
|
+
* regions. Uses the same `.zylem-accordion` / `.accordion-*` classes as the
|
|
26
|
+
* editor markup, so both stay visually in sync.
|
|
27
|
+
*/
|
|
28
|
+
export function Accordion(props: AccordionProps) {
|
|
29
|
+
return (
|
|
30
|
+
<KAccordion.Root
|
|
31
|
+
class={props.class ? `zylem-accordion ${props.class}` : 'zylem-accordion'}
|
|
32
|
+
multiple={props.multiple}
|
|
33
|
+
collapsible={props.collapsible ?? true}
|
|
34
|
+
value={props.value}
|
|
35
|
+
onChange={props.onChange}
|
|
36
|
+
defaultValue={props.defaultValue}
|
|
37
|
+
>
|
|
38
|
+
<For each={props.items}>
|
|
39
|
+
{(item) => (
|
|
40
|
+
<KAccordion.Item value={item.id} class="accordion-item">
|
|
41
|
+
<KAccordion.Header class="accordion-header">
|
|
42
|
+
<KAccordion.Trigger class="accordion-trigger">
|
|
43
|
+
{item.title}
|
|
44
|
+
</KAccordion.Trigger>
|
|
45
|
+
</KAccordion.Header>
|
|
46
|
+
<KAccordion.Content
|
|
47
|
+
class={
|
|
48
|
+
props.contentClass
|
|
49
|
+
? `accordion-content ${props.contentClass}`
|
|
50
|
+
: 'accordion-content'
|
|
51
|
+
}
|
|
52
|
+
>
|
|
53
|
+
{item.content()}
|
|
54
|
+
</KAccordion.Content>
|
|
55
|
+
</KAccordion.Item>
|
|
56
|
+
)}
|
|
57
|
+
</For>
|
|
58
|
+
</KAccordion.Root>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { globalStyle } from '@vanilla-extract/css';
|
|
2
|
+
import { vars } from '../../theme.css';
|
|
3
|
+
|
|
4
|
+
globalStyle('.zylem-badge', {
|
|
5
|
+
display: 'inline-flex',
|
|
6
|
+
alignItems: 'center',
|
|
7
|
+
gap: vars.spacing.xxs,
|
|
8
|
+
padding: `1px ${vars.spacing.sm}`,
|
|
9
|
+
borderRadius: '5px',
|
|
10
|
+
fontFamily: vars.typography.fontFamily,
|
|
11
|
+
fontSize: `calc(${vars.typography.fontSize} - 3px)`,
|
|
12
|
+
fontWeight: 700,
|
|
13
|
+
letterSpacing: '0.05em',
|
|
14
|
+
textTransform: 'uppercase',
|
|
15
|
+
textShadow: '0 1px 1px rgba(0,0,0,0.6)',
|
|
16
|
+
color: '#F4FAFF',
|
|
17
|
+
boxShadow:
|
|
18
|
+
'inset 0 1px 0 rgba(255,255,255,0.32), inset 0 -1px 0 rgba(0,0,0,0.4)',
|
|
19
|
+
whiteSpace: 'nowrap',
|
|
20
|
+
userSelect: 'none',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
globalStyle('.zylem-badge[data-tone="info"], .zylem-badge:not([data-tone])', {
|
|
24
|
+
border: '1px solid rgba(150, 210, 255, 0.55)',
|
|
25
|
+
background:
|
|
26
|
+
'linear-gradient(180deg, rgba(178, 219, 255, 0.4), rgba(30, 94, 148, 0.85))',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
globalStyle('.zylem-badge[data-tone="warning"]', {
|
|
30
|
+
border: '1px solid rgba(255, 226, 150, 0.6)',
|
|
31
|
+
background:
|
|
32
|
+
'linear-gradient(180deg, rgba(255, 240, 168, 0.45), rgba(180, 128, 20, 0.85))',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
globalStyle('.zylem-badge[data-tone="error"]', {
|
|
36
|
+
border: '1px solid rgba(255, 132, 114, 0.65)',
|
|
37
|
+
background:
|
|
38
|
+
'linear-gradient(180deg, rgba(255, 179, 168, 0.45), rgba(190, 52, 38, 0.88))',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
globalStyle('.zylem-badge[data-tone="success"]', {
|
|
42
|
+
border: '1px solid rgba(120, 255, 150, 0.55)',
|
|
43
|
+
background:
|
|
44
|
+
'linear-gradient(180deg, rgba(182, 255, 195, 0.42), rgba(18, 130, 46, 0.86))',
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
globalStyle('.zylem-badge[data-tone="neutral"]', {
|
|
48
|
+
border: '1px solid rgba(97, 166, 232, 0.35)',
|
|
49
|
+
background:
|
|
50
|
+
'linear-gradient(180deg, rgba(60, 80, 105, 0.6), rgba(26, 31, 39, 0.85))',
|
|
51
|
+
color: vars.colors.text,
|
|
52
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js';
|
|
2
|
+
|
|
3
|
+
export type BadgeTone = 'info' | 'warning' | 'error' | 'success' | 'neutral';
|
|
4
|
+
|
|
5
|
+
export interface BadgeProps {
|
|
6
|
+
tone?: BadgeTone;
|
|
7
|
+
children: JSX.Element;
|
|
8
|
+
class?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* HyperGlass badge: small beveled glass tag for statuses and counts.
|
|
13
|
+
*/
|
|
14
|
+
export function Badge(props: BadgeProps) {
|
|
15
|
+
return (
|
|
16
|
+
<span
|
|
17
|
+
class={props.class ? `zylem-badge ${props.class}` : 'zylem-badge'}
|
|
18
|
+
data-tone={props.tone ?? 'info'}
|
|
19
|
+
>
|
|
20
|
+
{props.children}
|
|
21
|
+
</span>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { globalStyle } from '@vanilla-extract/css';
|
|
2
|
+
import { vars } from '../../theme.css';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* HyperGlass button — owns the `.zylem-button` class (previously defined in
|
|
6
|
+
* global/editor-base.css.ts). Variants are selected via `data-variant` and
|
|
7
|
+
* sizes via `data-size`, so the styles work from the raw CSS bundle without
|
|
8
|
+
* requiring consumers to compile vanilla-extract.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
globalStyle('.zylem-button', {
|
|
12
|
+
boxSizing: 'border-box',
|
|
13
|
+
display: 'inline-flex',
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
justifyContent: 'center',
|
|
16
|
+
gap: vars.spacing.xs,
|
|
17
|
+
minHeight: '28px',
|
|
18
|
+
padding: `0 ${vars.spacing.md}`,
|
|
19
|
+
cursor: 'pointer',
|
|
20
|
+
userSelect: 'none',
|
|
21
|
+
whiteSpace: 'nowrap',
|
|
22
|
+
borderRadius: vars.radii.button,
|
|
23
|
+
border: '1px solid rgba(150, 210, 255, 0.55)',
|
|
24
|
+
color: '#F4FAFF',
|
|
25
|
+
background: vars.material.buttonGlass,
|
|
26
|
+
boxShadow: vars.effects.shadowButton,
|
|
27
|
+
textShadow: '0 1px 1px rgba(0,0,0,0.72)',
|
|
28
|
+
fontFamily: vars.typography.fontFamily,
|
|
29
|
+
fontSize: vars.typography.fontSize,
|
|
30
|
+
fontWeight: 600,
|
|
31
|
+
transition: `transform ${vars.motion.fast} ${vars.motion.easeOut}, box-shadow ${vars.motion.fast} ${vars.motion.easeOut}, filter ${vars.motion.fast} ${vars.motion.easeOut}, background ${vars.motion.fast} ${vars.motion.easeOut}`,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
globalStyle('.zylem-button:hover:not([disabled])', {
|
|
35
|
+
background: vars.material.buttonGlassHover,
|
|
36
|
+
boxShadow: `${vars.effects.shadowButton}, ${vars.effects.glowPrimary}`,
|
|
37
|
+
transform: 'translateY(-1px)',
|
|
38
|
+
color: '#F4FAFF',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
globalStyle('.zylem-button:active:not([disabled])', {
|
|
42
|
+
transform: 'translateY(1px)',
|
|
43
|
+
filter: 'brightness(0.92)',
|
|
44
|
+
// CodePen-inspired press: compressed drop shadow + bright bottom rim flash.
|
|
45
|
+
boxShadow:
|
|
46
|
+
'inset 0 1px 0 rgba(255,255,255,0.22), inset 0 -1px 0 rgba(255,255,255,0.55), inset 0 2px 3px rgba(0,0,0,0.28), 0 1px 3px rgba(0,0,0,0.28)',
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
globalStyle('.zylem-button:focus-visible', {
|
|
50
|
+
outline: 'none',
|
|
51
|
+
boxShadow: `${vars.effects.shadowButton}, ${vars.effects.focusRing}`,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
globalStyle('.zylem-button[disabled], .zylem-button[data-disabled]', {
|
|
55
|
+
opacity: 0.45,
|
|
56
|
+
cursor: 'not-allowed',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Variants
|
|
60
|
+
|
|
61
|
+
globalStyle('.zylem-button[data-variant="primary"]', {
|
|
62
|
+
borderColor: 'rgba(178, 219, 255, 0.8)',
|
|
63
|
+
background: vars.material.buttonGlassHover,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
globalStyle('.zylem-button[data-variant="primary"]:hover:not([disabled])', {
|
|
67
|
+
filter: 'brightness(1.08)',
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
globalStyle('.zylem-button[data-variant="active"]', {
|
|
71
|
+
borderColor: 'rgba(20, 255, 60, 0.78)',
|
|
72
|
+
background: vars.material.buttonGlassActive,
|
|
73
|
+
boxShadow: `${vars.effects.shadowButton}, ${vars.effects.glowActive}`,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
globalStyle('.zylem-button[data-variant="active"]:hover:not([disabled])', {
|
|
77
|
+
background: vars.material.buttonGlassActive,
|
|
78
|
+
boxShadow: `${vars.effects.shadowButton}, ${vars.effects.glowActive}`,
|
|
79
|
+
filter: 'brightness(1.1)',
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
globalStyle('.zylem-button[data-variant="danger"]', {
|
|
83
|
+
borderColor: 'rgba(255, 132, 114, 0.78)',
|
|
84
|
+
background: vars.material.buttonGlassDanger,
|
|
85
|
+
boxShadow: `${vars.effects.shadowButton}, ${vars.effects.glowDanger}`,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
globalStyle('.zylem-button[data-variant="danger"]:hover:not([disabled])', {
|
|
89
|
+
background: vars.material.buttonGlassDanger,
|
|
90
|
+
boxShadow: `${vars.effects.shadowButton}, ${vars.effects.glowDanger}`,
|
|
91
|
+
filter: 'brightness(1.1)',
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
globalStyle('.zylem-button[data-variant="ghost"]', {
|
|
95
|
+
border: '1px solid rgba(97, 166, 232, 0.35)',
|
|
96
|
+
background: 'transparent',
|
|
97
|
+
boxShadow: 'none',
|
|
98
|
+
color: vars.colors.primary,
|
|
99
|
+
textShadow: 'none',
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
globalStyle('.zylem-button[data-variant="ghost"]:hover:not([disabled])', {
|
|
103
|
+
background: 'rgba(97, 166, 232, 0.12)',
|
|
104
|
+
boxShadow: vars.effects.glowPrimary,
|
|
105
|
+
color: vars.colors.primary,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Sizes
|
|
109
|
+
|
|
110
|
+
globalStyle('.zylem-button[data-size="sm"]', {
|
|
111
|
+
minHeight: '22px',
|
|
112
|
+
padding: `0 ${vars.spacing.sm}`,
|
|
113
|
+
fontSize: `calc(${vars.typography.fontSize} - 2px)`,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
globalStyle('.zylem-button[data-size="lg"]', {
|
|
117
|
+
minHeight: '36px',
|
|
118
|
+
padding: `0 ${vars.spacing.lg}`,
|
|
119
|
+
fontSize: `calc(${vars.typography.fontSize} + 1px)`,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
globalStyle('.zylem-button[data-size="icon"]', {
|
|
123
|
+
minHeight: '28px',
|
|
124
|
+
minWidth: '28px',
|
|
125
|
+
padding: vars.spacing.xs,
|
|
126
|
+
borderRadius: vars.radii.control,
|
|
127
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js';
|
|
2
|
+
import { splitProps } from 'solid-js';
|
|
3
|
+
|
|
4
|
+
export type ButtonVariant = 'default' | 'primary' | 'active' | 'danger' | 'ghost';
|
|
5
|
+
export type ButtonSize = 'sm' | 'md' | 'lg' | 'icon';
|
|
6
|
+
|
|
7
|
+
export interface ButtonProps
|
|
8
|
+
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
9
|
+
variant?: ButtonVariant;
|
|
10
|
+
size?: ButtonSize;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* HyperGlass button: squared Aqua-like bevel with glass depth. Variants map
|
|
15
|
+
* to the Zylem palette — `active` for live/run actions, `danger` for
|
|
16
|
+
* destructive actions, `ghost` for low-emphasis chrome.
|
|
17
|
+
*
|
|
18
|
+
* Styling lives on the global `.zylem-button` class (bundled in
|
|
19
|
+
* `@zylem/ui/styles.css`), selected via `data-variant` / `data-size`.
|
|
20
|
+
*/
|
|
21
|
+
export function Button(props: ButtonProps) {
|
|
22
|
+
const [local, rest] = splitProps(props, ['variant', 'size', 'class', 'children']);
|
|
23
|
+
return (
|
|
24
|
+
<button
|
|
25
|
+
type="button"
|
|
26
|
+
class={local.class ? `zylem-button ${local.class}` : 'zylem-button'}
|
|
27
|
+
data-variant={local.variant ?? 'default'}
|
|
28
|
+
data-size={local.size ?? 'md'}
|
|
29
|
+
{...rest}
|
|
30
|
+
>
|
|
31
|
+
{local.children}
|
|
32
|
+
</button>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { globalStyle } from '@vanilla-extract/css';
|
|
2
|
+
import { vars } from '../../theme.css';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Index card: small HyperCard-style tile with a blue glow on hover.
|
|
6
|
+
*/
|
|
7
|
+
globalStyle('.zylem-card', {
|
|
8
|
+
boxSizing: 'border-box',
|
|
9
|
+
display: 'flex',
|
|
10
|
+
flexDirection: 'column',
|
|
11
|
+
gap: vars.spacing.xs,
|
|
12
|
+
padding: vars.spacing.md,
|
|
13
|
+
borderRadius: vars.radii.card,
|
|
14
|
+
border: '1px solid rgba(97, 166, 232, 0.32)',
|
|
15
|
+
background: vars.material.glassPanelDark,
|
|
16
|
+
boxShadow:
|
|
17
|
+
'0 8px 20px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.08)',
|
|
18
|
+
color: vars.colors.text,
|
|
19
|
+
fontFamily: vars.typography.fontFamily,
|
|
20
|
+
transition: `transform ${vars.motion.fast} ${vars.motion.easeOut}, box-shadow ${vars.motion.fast} ${vars.motion.easeOut}, border-color ${vars.motion.fast} ${vars.motion.easeOut}`,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
globalStyle('.zylem-card--interactive', {
|
|
24
|
+
cursor: 'pointer',
|
|
25
|
+
textAlign: 'left',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
globalStyle('.zylem-card--interactive:hover', {
|
|
29
|
+
borderColor: 'rgba(150, 210, 255, 0.6)',
|
|
30
|
+
boxShadow: `0 8px 20px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.08), ${vars.effects.glowPrimary}`,
|
|
31
|
+
transform: 'translateY(-1px)',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
globalStyle('.zylem-card--interactive:active', {
|
|
35
|
+
transform: 'translateY(1px)',
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
globalStyle('.zylem-card--interactive:focus-visible', {
|
|
39
|
+
outline: 'none',
|
|
40
|
+
boxShadow: `0 8px 20px rgba(0,0,0,0.3), ${vars.effects.focusRing}`,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
globalStyle('.zylem-card--selected', {
|
|
44
|
+
borderColor: 'rgba(20, 255, 60, 0.6)',
|
|
45
|
+
boxShadow: `0 8px 20px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.08), ${vars.effects.glowActive}`,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
globalStyle('.zylem-card-title', {
|
|
49
|
+
fontSize: vars.typography.fontSize,
|
|
50
|
+
fontWeight: 700,
|
|
51
|
+
color: '#F4FAFF',
|
|
52
|
+
textShadow: '0 1px 1px rgba(0,0,0,0.55)',
|
|
53
|
+
overflow: 'hidden',
|
|
54
|
+
textOverflow: 'ellipsis',
|
|
55
|
+
whiteSpace: 'nowrap',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
globalStyle('.zylem-card-description', {
|
|
59
|
+
fontSize: `calc(${vars.typography.fontSize} - 2px)`,
|
|
60
|
+
color: vars.colors.textSecondary,
|
|
61
|
+
lineHeight: 1.4,
|
|
62
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Show, splitProps } from 'solid-js';
|
|
2
|
+
import type { JSX } from 'solid-js';
|
|
3
|
+
|
|
4
|
+
export interface CardProps
|
|
5
|
+
extends Omit<JSX.HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
6
|
+
title?: JSX.Element;
|
|
7
|
+
description?: JSX.Element;
|
|
8
|
+
/** Renders hover glow + pointer cursor and click affordances. */
|
|
9
|
+
interactive?: boolean;
|
|
10
|
+
selected?: boolean;
|
|
11
|
+
children?: JSX.Element;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* HyperGlass card: small index-card tile with a blue glow. Use for entity
|
|
16
|
+
* tiles, project tiles, and asset thumbnails.
|
|
17
|
+
*/
|
|
18
|
+
export function Card(props: CardProps) {
|
|
19
|
+
const [local, rest] = splitProps(props, [
|
|
20
|
+
'title',
|
|
21
|
+
'description',
|
|
22
|
+
'interactive',
|
|
23
|
+
'selected',
|
|
24
|
+
'children',
|
|
25
|
+
'class',
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
const classes = () =>
|
|
29
|
+
[
|
|
30
|
+
'zylem-card',
|
|
31
|
+
local.interactive ? 'zylem-card--interactive' : '',
|
|
32
|
+
local.selected ? 'zylem-card--selected' : '',
|
|
33
|
+
local.class ?? '',
|
|
34
|
+
]
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.join(' ');
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
class={classes()}
|
|
41
|
+
role={local.interactive ? 'button' : undefined}
|
|
42
|
+
tabIndex={local.interactive ? 0 : undefined}
|
|
43
|
+
{...rest}
|
|
44
|
+
>
|
|
45
|
+
<Show when={local.title}>
|
|
46
|
+
<div class="zylem-card-title">{local.title}</div>
|
|
47
|
+
</Show>
|
|
48
|
+
{local.children}
|
|
49
|
+
<Show when={local.description}>
|
|
50
|
+
<div class="zylem-card-description">{local.description}</div>
|
|
51
|
+
</Show>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { globalStyle } from '@vanilla-extract/css';
|
|
2
|
-
import { vars } from '
|
|
2
|
+
import { vars } from '../../theme.css';
|
|
3
3
|
|
|
4
4
|
globalStyle('.zylem-checkbox-root', {
|
|
5
5
|
display: 'inline-flex',
|
|
6
6
|
alignItems: 'center',
|
|
7
|
-
gap: vars.spacing.
|
|
7
|
+
gap: vars.spacing.sm,
|
|
8
8
|
cursor: 'pointer',
|
|
9
9
|
userSelect: 'none',
|
|
10
10
|
});
|
|
@@ -26,41 +26,41 @@ globalStyle('.zylem-checkbox-input', {
|
|
|
26
26
|
border: 0,
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
// Square glass toggle: beveled jewel that fills with blue glass when checked.
|
|
29
30
|
globalStyle('.zylem-checkbox-control', {
|
|
30
31
|
display: 'flex',
|
|
31
32
|
alignItems: 'center',
|
|
32
33
|
justifyContent: 'center',
|
|
33
|
-
width: '
|
|
34
|
-
height: '
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
background:
|
|
38
|
-
|
|
34
|
+
width: '18px',
|
|
35
|
+
height: '18px',
|
|
36
|
+
borderRadius: vars.radii.control,
|
|
37
|
+
border: '1px solid rgba(97, 166, 232, 0.5)',
|
|
38
|
+
background: vars.material.fieldGlass,
|
|
39
|
+
boxShadow: vars.effects.shadowInset,
|
|
40
|
+
transition: `background ${vars.motion.fast} ${vars.motion.easeOut}, box-shadow ${vars.motion.fast} ${vars.motion.easeOut}, border-color ${vars.motion.fast} ${vars.motion.easeOut}`,
|
|
39
41
|
});
|
|
40
42
|
|
|
41
43
|
globalStyle('.zylem-checkbox-root:hover .zylem-checkbox-control', {
|
|
42
|
-
borderColor:
|
|
43
|
-
|
|
44
|
+
borderColor: 'rgba(150, 210, 255, 0.7)',
|
|
45
|
+
boxShadow: `${vars.effects.shadowInset}, ${vars.effects.glowPrimary}`,
|
|
44
46
|
});
|
|
45
47
|
|
|
46
48
|
globalStyle('.zylem-checkbox-root[data-checked] .zylem-checkbox-control', {
|
|
47
|
-
background: vars.
|
|
48
|
-
|
|
49
|
+
background: vars.material.buttonGlass,
|
|
50
|
+
border: '1px solid rgba(150, 210, 255, 0.65)',
|
|
51
|
+
boxShadow: vars.effects.shadowButton,
|
|
49
52
|
});
|
|
50
53
|
|
|
51
|
-
globalStyle(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
background: vars.colors.primaryHover,
|
|
55
|
-
borderColor: vars.colors.primaryHover,
|
|
56
|
-
},
|
|
57
|
-
);
|
|
54
|
+
globalStyle('.zylem-checkbox-root:focus-within .zylem-checkbox-control', {
|
|
55
|
+
boxShadow: `${vars.effects.shadowInset}, ${vars.effects.focusRing}`,
|
|
56
|
+
});
|
|
58
57
|
|
|
59
58
|
globalStyle('.zylem-checkbox-icon', {
|
|
60
|
-
width: '
|
|
61
|
-
height: '
|
|
62
|
-
color:
|
|
63
|
-
strokeWidth: 3,
|
|
59
|
+
width: '12px',
|
|
60
|
+
height: '12px',
|
|
61
|
+
color: '#F4FAFF',
|
|
62
|
+
strokeWidth: 3.5,
|
|
63
|
+
filter: 'drop-shadow(0 1px 1px rgba(0,0,0,0.6))',
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
globalStyle('.zylem-checkbox-label', {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Checkbox as KCheckbox } from '@kobalte/core';
|
|
2
|
+
import Check from 'lucide-solid/icons/check';
|
|
3
|
+
import { Show } from 'solid-js';
|
|
4
|
+
|
|
5
|
+
export interface CheckboxProps {
|
|
6
|
+
label?: string;
|
|
7
|
+
checked?: boolean;
|
|
8
|
+
defaultChecked?: boolean;
|
|
9
|
+
onChange?: (checked: boolean) => void;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
name?: string;
|
|
12
|
+
class?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* HyperGlass checkbox: square glass jewel with a beveled checked state.
|
|
17
|
+
*/
|
|
18
|
+
export function Checkbox(props: CheckboxProps) {
|
|
19
|
+
return (
|
|
20
|
+
<KCheckbox.Root
|
|
21
|
+
class={props.class ? `zylem-checkbox-root ${props.class}` : 'zylem-checkbox-root'}
|
|
22
|
+
checked={props.checked}
|
|
23
|
+
defaultChecked={props.defaultChecked}
|
|
24
|
+
onChange={props.onChange}
|
|
25
|
+
disabled={props.disabled}
|
|
26
|
+
name={props.name}
|
|
27
|
+
>
|
|
28
|
+
<KCheckbox.Input class="zylem-checkbox-input" />
|
|
29
|
+
<KCheckbox.Control class="zylem-checkbox-control">
|
|
30
|
+
<KCheckbox.Indicator>
|
|
31
|
+
<Check class="zylem-checkbox-icon" />
|
|
32
|
+
</KCheckbox.Indicator>
|
|
33
|
+
</KCheckbox.Control>
|
|
34
|
+
<Show when={props.label}>
|
|
35
|
+
<KCheckbox.Label class="zylem-checkbox-label">
|
|
36
|
+
{props.label}
|
|
37
|
+
</KCheckbox.Label>
|
|
38
|
+
</Show>
|
|
39
|
+
</KCheckbox.Root>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { globalStyle } from '@vanilla-extract/css';
|
|
2
|
+
import { vars } from '../../theme.css';
|
|
3
|
+
|
|
4
|
+
globalStyle('.zylem-console-container', {
|
|
5
|
+
position: 'relative',
|
|
6
|
+
display: 'flex',
|
|
7
|
+
flexDirection: 'column',
|
|
8
|
+
minHeight: 0,
|
|
9
|
+
height: '100%',
|
|
10
|
+
width: '100%',
|
|
11
|
+
boxSizing: 'border-box',
|
|
12
|
+
padding: vars.spacing.sm,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
globalStyle('.zylem-console-wrapper', {
|
|
16
|
+
position: 'relative',
|
|
17
|
+
display: 'flex',
|
|
18
|
+
flex: 1,
|
|
19
|
+
minHeight: 0,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
/** Dark low-gloss terminal field — owns the `.zylem-console` class. */
|
|
23
|
+
globalStyle('.zylem-console', {
|
|
24
|
+
flex: 1,
|
|
25
|
+
minHeight: '96px',
|
|
26
|
+
width: '100%',
|
|
27
|
+
height: '100%',
|
|
28
|
+
boxSizing: 'border-box',
|
|
29
|
+
margin: 0,
|
|
30
|
+
padding: vars.spacing.sm,
|
|
31
|
+
resize: 'none',
|
|
32
|
+
overflowY: 'auto',
|
|
33
|
+
borderRadius: vars.radii.control,
|
|
34
|
+
border: '1px solid rgba(97, 166, 232, 0.28)',
|
|
35
|
+
background: 'rgba(4, 12, 20, 0.72)',
|
|
36
|
+
boxShadow: vars.effects.shadowInset,
|
|
37
|
+
color: vars.colors.consoleText,
|
|
38
|
+
fontFamily: "'Courier New', monospace",
|
|
39
|
+
fontSize: `calc(${vars.typography.fontSize} - 1px)`,
|
|
40
|
+
lineHeight: 1.45,
|
|
41
|
+
outline: 'none',
|
|
42
|
+
whiteSpace: 'pre-wrap',
|
|
43
|
+
wordBreak: 'break-word',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
globalStyle('.zylem-console:focus-visible', {
|
|
47
|
+
boxShadow: `${vars.effects.shadowInset}, ${vars.effects.focusRing}`,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
globalStyle('.zylem-console-actions', {
|
|
51
|
+
position: 'absolute',
|
|
52
|
+
top: vars.spacing.xs,
|
|
53
|
+
right: vars.spacing.sm,
|
|
54
|
+
display: 'flex',
|
|
55
|
+
gap: vars.spacing.xs,
|
|
56
|
+
zIndex: 1,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Legacy hook used by the editor's clear button. Keep specificity above the
|
|
60
|
+
// HyperGlass sheen host rule (`.zylem-hyperglass-root .zylem-button`) so the
|
|
61
|
+
// overlay stays absolutely positioned in the console wrapper.
|
|
62
|
+
globalStyle('.zylem-console-clear.zylem-button, .zylem-console-clear', {
|
|
63
|
+
position: 'absolute',
|
|
64
|
+
top: vars.spacing.sm,
|
|
65
|
+
right: vars.spacing.sm,
|
|
66
|
+
zIndex: 1,
|
|
67
|
+
});
|