@aiaiai-pt/design-system 0.1.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/components/Alert.svelte +100 -0
- package/components/Badge.svelte +108 -0
- package/components/BottomNav.svelte +37 -0
- package/components/BottomNavItem.svelte +121 -0
- package/components/Button.svelte +269 -0
- package/components/Card.svelte +108 -0
- package/components/Checkbox.svelte +138 -0
- package/components/CodeBlock.svelte +187 -0
- package/components/CodeEditor.svelte +221 -0
- package/components/CollapsibleSection.svelte +160 -0
- package/components/Combobox.svelte +396 -0
- package/components/EmptyState.svelte +148 -0
- package/components/FileUpload.svelte +280 -0
- package/components/FileUploadItem.svelte +222 -0
- package/components/Input.svelte +222 -0
- package/components/KeyValue.svelte +79 -0
- package/components/Label.svelte +49 -0
- package/components/List.svelte +70 -0
- package/components/ListItem.svelte +125 -0
- package/components/Menu.svelte +161 -0
- package/components/MenuItem.svelte +120 -0
- package/components/MenuSeparator.svelte +34 -0
- package/components/Modal.svelte +260 -0
- package/components/OptionGrid.svelte +195 -0
- package/components/Panel.svelte +256 -0
- package/components/Popover.svelte +194 -0
- package/components/Progress.svelte +78 -0
- package/components/Select.svelte +182 -0
- package/components/Separator.svelte +47 -0
- package/components/Sidebar.svelte +106 -0
- package/components/SidebarItem.svelte +154 -0
- package/components/SidebarSection.svelte +43 -0
- package/components/Skeleton.svelte +79 -0
- package/components/Status.svelte +104 -0
- package/components/Stepper.svelte +142 -0
- package/components/Tab.svelte +94 -0
- package/components/TabList.svelte +36 -0
- package/components/TabPanel.svelte +45 -0
- package/components/Tabs.svelte +46 -0
- package/components/Tag.svelte +96 -0
- package/components/Textarea.svelte +143 -0
- package/components/Toast.svelte +114 -0
- package/components/Toggle.svelte +132 -0
- package/components/index.js +70 -0
- package/package.json +45 -0
- package/tokens/base.css +175 -0
- package/tokens/components.css +530 -0
- package/tokens/semantic.css +211 -0
- package/tokens/themes/aiaiai.css +53 -0
- package/tokens/themes/bespoke-example.css +148 -0
- package/tokens/themes/branded-example.css +55 -0
- package/tokens/utilities.css +1865 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component Tabs
|
|
3
|
+
|
|
4
|
+
Container for tabbed interface. Provides context to TabList, Tab, and TabPanel.
|
|
5
|
+
Consumes --tabs-* tokens from components.css.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
<Tabs bind:value={activeTab}>
|
|
9
|
+
<TabList>
|
|
10
|
+
<Tab value="overview">OVERVIEW</Tab>
|
|
11
|
+
<Tab value="settings">SETTINGS</Tab>
|
|
12
|
+
</TabList>
|
|
13
|
+
<TabPanel value="overview">Overview content</TabPanel>
|
|
14
|
+
<TabPanel value="settings">Settings content</TabPanel>
|
|
15
|
+
</Tabs>
|
|
16
|
+
-->
|
|
17
|
+
<script>
|
|
18
|
+
import { setContext } from 'svelte';
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
/** @type {string} */
|
|
22
|
+
value = $bindable(''),
|
|
23
|
+
/** @type {string} */
|
|
24
|
+
class: className = '',
|
|
25
|
+
/** @type {import('svelte').Snippet | undefined} */
|
|
26
|
+
children = undefined,
|
|
27
|
+
...rest
|
|
28
|
+
} = $props();
|
|
29
|
+
|
|
30
|
+
setContext('tabs', {
|
|
31
|
+
get value() { return value; },
|
|
32
|
+
/** @param {string} v */
|
|
33
|
+
setValue(v) { value = v; }
|
|
34
|
+
});
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<div class="tabs {className}" {...rest}>
|
|
38
|
+
{#if children}{@render children()}{/if}
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<style>
|
|
42
|
+
.tabs {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
}
|
|
46
|
+
</style>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component Tag
|
|
3
|
+
|
|
4
|
+
Categorization label. Bordered, optionally removable.
|
|
5
|
+
Consumes --tag-* tokens from components.css.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
<Tag>SVELTE</Tag>
|
|
9
|
+
|
|
10
|
+
@example Removable
|
|
11
|
+
<Tag removable onremove={() => console.log('removed')}>CSS</Tag>
|
|
12
|
+
-->
|
|
13
|
+
<script>
|
|
14
|
+
let {
|
|
15
|
+
/** @type {boolean} */
|
|
16
|
+
removable = false,
|
|
17
|
+
/** @type {(() => void) | undefined} */
|
|
18
|
+
onremove = undefined,
|
|
19
|
+
/** @type {string} */
|
|
20
|
+
class: className = '',
|
|
21
|
+
/** @type {import('svelte').Snippet | undefined} */
|
|
22
|
+
children = undefined,
|
|
23
|
+
...rest
|
|
24
|
+
} = $props();
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<span
|
|
28
|
+
class="tag {className}"
|
|
29
|
+
class:tag-removable={removable}
|
|
30
|
+
{...rest}
|
|
31
|
+
>
|
|
32
|
+
{#if children}
|
|
33
|
+
{@render children()}
|
|
34
|
+
{/if}
|
|
35
|
+
{#if removable}
|
|
36
|
+
<button
|
|
37
|
+
class="tag-remove"
|
|
38
|
+
aria-label="Remove tag"
|
|
39
|
+
onclick={(e) => {
|
|
40
|
+
e.stopPropagation();
|
|
41
|
+
onremove?.();
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
<svg viewBox="0 0 10 10" fill="none" class="tag-remove-icon" aria-hidden="true">
|
|
45
|
+
<path d="M2 2l6 6M8 2l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
|
46
|
+
</svg>
|
|
47
|
+
</button>
|
|
48
|
+
{/if}
|
|
49
|
+
</span>
|
|
50
|
+
|
|
51
|
+
<style>
|
|
52
|
+
.tag {
|
|
53
|
+
display: inline-flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: var(--space-xs);
|
|
56
|
+
font-family: var(--tag-font);
|
|
57
|
+
font-size: var(--tag-size);
|
|
58
|
+
border-radius: var(--tag-radius);
|
|
59
|
+
padding: var(--tag-padding-y) var(--tag-padding-x);
|
|
60
|
+
border: var(--tag-border);
|
|
61
|
+
background: var(--tag-bg);
|
|
62
|
+
color: var(--tag-text);
|
|
63
|
+
white-space: nowrap;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.tag-removable {
|
|
67
|
+
padding-right: var(--space-xs);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.tag-remove {
|
|
71
|
+
all: unset;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
width: 14px;
|
|
77
|
+
height: 14px;
|
|
78
|
+
border-radius: var(--radius-sm);
|
|
79
|
+
color: var(--color-text-muted);
|
|
80
|
+
transition: color var(--duration-instant) var(--easing-default);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.tag-remove:hover {
|
|
84
|
+
color: var(--color-text);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.tag-remove:focus-visible {
|
|
88
|
+
outline: var(--focus-ring-width) solid var(--focus-ring-color);
|
|
89
|
+
outline-offset: var(--focus-ring-offset);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.tag-remove-icon {
|
|
93
|
+
width: 10px;
|
|
94
|
+
height: 10px;
|
|
95
|
+
}
|
|
96
|
+
</style>
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component Textarea
|
|
3
|
+
|
|
4
|
+
Multi-line text input with label, help text, and error state.
|
|
5
|
+
Values displayed in Berkeley Mono (data font).
|
|
6
|
+
Consumes --input-* and --textarea-* tokens from components.css.
|
|
7
|
+
|
|
8
|
+
@example
|
|
9
|
+
<Textarea label="DESCRIPTION" placeholder="Enter a description..." rows={4} />
|
|
10
|
+
|
|
11
|
+
@example With error
|
|
12
|
+
<Textarea label="SQL QUERY" value="SELCT *" error="Syntax error near SELCT" />
|
|
13
|
+
-->
|
|
14
|
+
<script module>
|
|
15
|
+
let _textareaUid = 0;
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<script>
|
|
19
|
+
let {
|
|
20
|
+
/** @type {string | undefined} */
|
|
21
|
+
label = undefined,
|
|
22
|
+
/** @type {string | undefined} */
|
|
23
|
+
placeholder = undefined,
|
|
24
|
+
/** @type {string} */
|
|
25
|
+
value = $bindable(''),
|
|
26
|
+
/** @type {string | undefined} */
|
|
27
|
+
help = undefined,
|
|
28
|
+
/** @type {string | undefined} */
|
|
29
|
+
error = undefined,
|
|
30
|
+
/** @type {number} */
|
|
31
|
+
rows = 3,
|
|
32
|
+
/** @type {boolean} */
|
|
33
|
+
disabled = false,
|
|
34
|
+
/** @type {boolean} */
|
|
35
|
+
readonly = false,
|
|
36
|
+
/** @type {string | undefined} */
|
|
37
|
+
id = undefined,
|
|
38
|
+
/** @type {string} */
|
|
39
|
+
class: className = '',
|
|
40
|
+
...rest
|
|
41
|
+
} = $props();
|
|
42
|
+
|
|
43
|
+
const fallbackId = `textarea-${_textareaUid++}`;
|
|
44
|
+
const textareaId = $derived(id ?? fallbackId);
|
|
45
|
+
const hintId = $derived(`${textareaId}-hint`);
|
|
46
|
+
const hasHint = $derived(!!error || !!help);
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<div class="textarea-group {className}">
|
|
50
|
+
{#if label}
|
|
51
|
+
<label class="textarea-label" for={textareaId}>{label}</label>
|
|
52
|
+
{/if}
|
|
53
|
+
|
|
54
|
+
<textarea
|
|
55
|
+
id={textareaId}
|
|
56
|
+
class="textarea"
|
|
57
|
+
class:textarea-error={!!error}
|
|
58
|
+
class:textarea-readonly={readonly}
|
|
59
|
+
aria-invalid={error ? true : undefined}
|
|
60
|
+
aria-describedby={hasHint ? hintId : undefined}
|
|
61
|
+
{placeholder}
|
|
62
|
+
{disabled}
|
|
63
|
+
{readonly}
|
|
64
|
+
{rows}
|
|
65
|
+
bind:value
|
|
66
|
+
{...rest}
|
|
67
|
+
></textarea>
|
|
68
|
+
|
|
69
|
+
{#if error}
|
|
70
|
+
<span id={hintId} class="textarea-error-text" role="alert">{error}</span>
|
|
71
|
+
{:else if help}
|
|
72
|
+
<span id={hintId} class="textarea-help">{help}</span>
|
|
73
|
+
{/if}
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<style>
|
|
77
|
+
.textarea-group {
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-direction: column;
|
|
80
|
+
gap: var(--input-label-gap);
|
|
81
|
+
width: 100%;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.textarea-label {
|
|
85
|
+
font-family: var(--input-label-font);
|
|
86
|
+
font-size: var(--input-label-size);
|
|
87
|
+
letter-spacing: var(--input-label-tracking);
|
|
88
|
+
color: var(--input-label-color);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.textarea {
|
|
92
|
+
font-family: var(--input-font);
|
|
93
|
+
font-size: var(--input-font-size);
|
|
94
|
+
border: var(--input-border);
|
|
95
|
+
border-radius: var(--input-radius);
|
|
96
|
+
background: var(--input-bg);
|
|
97
|
+
color: var(--input-text);
|
|
98
|
+
transition: border var(--input-transition);
|
|
99
|
+
width: 100%;
|
|
100
|
+
padding: var(--textarea-padding);
|
|
101
|
+
min-height: var(--textarea-min-height);
|
|
102
|
+
resize: vertical;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.textarea::placeholder {
|
|
106
|
+
color: var(--input-placeholder);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.textarea:focus {
|
|
110
|
+
outline: none;
|
|
111
|
+
border: var(--input-border-focus);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.textarea:disabled {
|
|
115
|
+
opacity: 0.5;
|
|
116
|
+
cursor: not-allowed;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.textarea-readonly {
|
|
120
|
+
background: var(--color-surface-secondary);
|
|
121
|
+
cursor: default;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.textarea-error {
|
|
125
|
+
border-color: var(--input-error-border-color);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.textarea-error:focus {
|
|
129
|
+
border-color: var(--input-error-border-color);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.textarea-help {
|
|
133
|
+
font-family: var(--input-help-font);
|
|
134
|
+
font-size: var(--input-help-size);
|
|
135
|
+
color: var(--input-help-color);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.textarea-error-text {
|
|
139
|
+
font-family: var(--input-help-font);
|
|
140
|
+
font-size: var(--input-help-size);
|
|
141
|
+
color: var(--input-error-text);
|
|
142
|
+
}
|
|
143
|
+
</style>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component Toast
|
|
3
|
+
|
|
4
|
+
Non-blocking notification with accent stripe.
|
|
5
|
+
Consumes --toast-* tokens from components.css.
|
|
6
|
+
|
|
7
|
+
This is the visual component only — toast positioning/stacking/auto-dismiss
|
|
8
|
+
is the consumer's responsibility.
|
|
9
|
+
|
|
10
|
+
@example
|
|
11
|
+
<Toast variant="success">
|
|
12
|
+
<strong>Project created.</strong> Your new project is ready.
|
|
13
|
+
</Toast>
|
|
14
|
+
|
|
15
|
+
@example With action
|
|
16
|
+
<Toast variant="info" actionLabel="UNDO" onaction={() => undo()}>
|
|
17
|
+
<strong>Message archived.</strong>
|
|
18
|
+
</Toast>
|
|
19
|
+
-->
|
|
20
|
+
<script>
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {'info' | 'success' | 'warning' | 'error'} Variant
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
let {
|
|
26
|
+
/** @type {Variant} */
|
|
27
|
+
variant = 'info',
|
|
28
|
+
/** @type {string | undefined} */
|
|
29
|
+
actionLabel = undefined,
|
|
30
|
+
/** @type {(() => void) | undefined} */
|
|
31
|
+
onaction = undefined,
|
|
32
|
+
/** @type {string} */
|
|
33
|
+
class: className = '',
|
|
34
|
+
/** @type {import('svelte').Snippet | undefined} */
|
|
35
|
+
children = undefined,
|
|
36
|
+
...rest
|
|
37
|
+
} = $props();
|
|
38
|
+
|
|
39
|
+
/** @type {Record<string, string>} */
|
|
40
|
+
const accentColors = {
|
|
41
|
+
info: 'var(--color-info)',
|
|
42
|
+
success: 'var(--color-success)',
|
|
43
|
+
warning: 'var(--color-warning)',
|
|
44
|
+
error: 'var(--color-destructive)',
|
|
45
|
+
};
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<div class="toast {className}" role={variant === 'error' ? 'alert' : 'status'} {...rest}>
|
|
49
|
+
<div class="toast-accent" style:background={accentColors[variant]}></div>
|
|
50
|
+
<div class="toast-content">
|
|
51
|
+
<span class="toast-message">
|
|
52
|
+
{#if children}{@render children()}{/if}
|
|
53
|
+
</span>
|
|
54
|
+
{#if actionLabel && onaction}
|
|
55
|
+
<button class="toast-action" onclick={onaction}>
|
|
56
|
+
<span class="toast-action-label">{actionLabel}</span>
|
|
57
|
+
</button>
|
|
58
|
+
{/if}
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<style>
|
|
63
|
+
.toast {
|
|
64
|
+
display: flex;
|
|
65
|
+
overflow: hidden;
|
|
66
|
+
border-radius: var(--toast-radius);
|
|
67
|
+
border: var(--toast-border);
|
|
68
|
+
box-shadow: var(--toast-shadow);
|
|
69
|
+
background: var(--toast-bg);
|
|
70
|
+
max-width: var(--toast-max-width);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.toast-accent {
|
|
74
|
+
width: var(--accent-stripe-width);
|
|
75
|
+
flex-shrink: 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.toast-content {
|
|
79
|
+
padding: var(--toast-padding);
|
|
80
|
+
font-family: var(--toast-font);
|
|
81
|
+
font-size: var(--toast-font-size);
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
gap: var(--space-md);
|
|
85
|
+
flex: 1;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.toast-message {
|
|
89
|
+
flex: 1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.toast-action {
|
|
93
|
+
all: unset;
|
|
94
|
+
cursor: pointer;
|
|
95
|
+
flex-shrink: 0;
|
|
96
|
+
transition: opacity var(--duration-instant) var(--easing-default);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.toast-action:hover {
|
|
100
|
+
opacity: 0.8;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.toast-action:focus-visible {
|
|
104
|
+
outline: var(--focus-ring-width) solid var(--focus-ring-color);
|
|
105
|
+
outline-offset: var(--focus-ring-offset);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.toast-action-label {
|
|
109
|
+
font-family: var(--type-label-font);
|
|
110
|
+
font-size: var(--type-label-size);
|
|
111
|
+
letter-spacing: var(--type-label-tracking);
|
|
112
|
+
color: var(--color-accent);
|
|
113
|
+
}
|
|
114
|
+
</style>
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component Toggle
|
|
3
|
+
|
|
4
|
+
On/off switch with label.
|
|
5
|
+
Consumes --toggle-* tokens from components.css.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
<Toggle label="Dark mode" bind:checked />
|
|
9
|
+
|
|
10
|
+
@example Disabled
|
|
11
|
+
<Toggle label="Notifications" checked disabled />
|
|
12
|
+
-->
|
|
13
|
+
<script module>
|
|
14
|
+
let _toggleUid = 0;
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<script>
|
|
18
|
+
let {
|
|
19
|
+
/** @type {boolean} */
|
|
20
|
+
checked = $bindable(false),
|
|
21
|
+
/** @type {boolean} */
|
|
22
|
+
disabled = false,
|
|
23
|
+
/** @type {string | undefined} */
|
|
24
|
+
label = undefined,
|
|
25
|
+
/** @type {string | undefined} */
|
|
26
|
+
id = undefined,
|
|
27
|
+
/** @type {((checked: boolean) => void) | undefined} */
|
|
28
|
+
onchange = undefined,
|
|
29
|
+
/** @type {string} */
|
|
30
|
+
class: className = '',
|
|
31
|
+
...rest
|
|
32
|
+
} = $props();
|
|
33
|
+
|
|
34
|
+
const fallbackId = `toggle-${_toggleUid++}`;
|
|
35
|
+
const toggleId = $derived(id ?? fallbackId);
|
|
36
|
+
|
|
37
|
+
function handleClick() {
|
|
38
|
+
if (!disabled) {
|
|
39
|
+
checked = !checked;
|
|
40
|
+
onchange?.(checked);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<div class="toggle-group {className}">
|
|
46
|
+
<button
|
|
47
|
+
id={toggleId}
|
|
48
|
+
class="toggle"
|
|
49
|
+
class:toggle-on={checked}
|
|
50
|
+
class:toggle-disabled={disabled}
|
|
51
|
+
{disabled}
|
|
52
|
+
role="switch"
|
|
53
|
+
aria-checked={checked}
|
|
54
|
+
aria-labelledby={label ? `${toggleId}-label` : undefined}
|
|
55
|
+
{...rest}
|
|
56
|
+
onclick={handleClick}
|
|
57
|
+
>
|
|
58
|
+
<span class="toggle-knob"></span>
|
|
59
|
+
</button>
|
|
60
|
+
{#if label}
|
|
61
|
+
<span
|
|
62
|
+
id="{toggleId}-label"
|
|
63
|
+
class="toggle-label"
|
|
64
|
+
class:toggle-label-disabled={disabled}
|
|
65
|
+
onclick={handleClick}
|
|
66
|
+
role="none"
|
|
67
|
+
>{label}</span>
|
|
68
|
+
{/if}
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<style>
|
|
72
|
+
.toggle-group {
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
gap: var(--space-sm);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.toggle {
|
|
79
|
+
width: var(--toggle-width);
|
|
80
|
+
height: var(--toggle-height);
|
|
81
|
+
border-radius: var(--toggle-radius);
|
|
82
|
+
background: var(--toggle-bg-off);
|
|
83
|
+
position: relative;
|
|
84
|
+
cursor: pointer;
|
|
85
|
+
transition: background var(--duration-fast) var(--easing-default);
|
|
86
|
+
border: none;
|
|
87
|
+
padding: 0;
|
|
88
|
+
flex-shrink: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.toggle:focus-visible {
|
|
92
|
+
outline: var(--focus-ring-width) solid var(--focus-ring-color);
|
|
93
|
+
outline-offset: var(--focus-ring-offset);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.toggle-on {
|
|
97
|
+
background: var(--toggle-bg-on);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.toggle-disabled {
|
|
101
|
+
opacity: 0.5;
|
|
102
|
+
cursor: not-allowed;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.toggle-knob {
|
|
106
|
+
position: absolute;
|
|
107
|
+
top: var(--space-2xs);
|
|
108
|
+
left: var(--space-2xs);
|
|
109
|
+
width: var(--toggle-knob-size);
|
|
110
|
+
height: var(--toggle-knob-size);
|
|
111
|
+
border-radius: var(--radius-circle);
|
|
112
|
+
background: var(--toggle-knob-color);
|
|
113
|
+
transition: transform var(--duration-fast) var(--easing-default);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.toggle-on .toggle-knob {
|
|
117
|
+
transform: translateX(
|
|
118
|
+
calc(var(--toggle-width) - var(--toggle-knob-size) - calc(2 * var(--space-2xs)))
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.toggle-label {
|
|
123
|
+
font-family: var(--type-body-sm-font);
|
|
124
|
+
font-size: var(--type-body-sm-size);
|
|
125
|
+
color: var(--color-text);
|
|
126
|
+
cursor: pointer;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.toggle-label-disabled {
|
|
130
|
+
color: var(--color-text-muted);
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* aiaiai Design System — Component Library
|
|
3
|
+
*
|
|
4
|
+
* Svelte 5 components consuming tokens from components.css.
|
|
5
|
+
* Import tokens (base.css → semantic.css → components.css) before using.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { Button, Card, Badge } from '$lib/ui';
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// Atoms
|
|
12
|
+
export { default as Badge } from "./Badge.svelte";
|
|
13
|
+
export { default as Tag } from "./Tag.svelte";
|
|
14
|
+
export { default as Status } from "./Status.svelte";
|
|
15
|
+
export { default as Skeleton } from "./Skeleton.svelte";
|
|
16
|
+
export { default as KeyValue } from "./KeyValue.svelte";
|
|
17
|
+
|
|
18
|
+
// Form controls
|
|
19
|
+
export { default as Button } from "./Button.svelte";
|
|
20
|
+
export { default as Input } from "./Input.svelte";
|
|
21
|
+
export { default as Textarea } from "./Textarea.svelte";
|
|
22
|
+
export { default as Select } from "./Select.svelte";
|
|
23
|
+
export { default as Toggle } from "./Toggle.svelte";
|
|
24
|
+
export { default as Checkbox } from "./Checkbox.svelte";
|
|
25
|
+
export { default as Label } from "./Label.svelte";
|
|
26
|
+
export { default as FileUpload } from "./FileUpload.svelte";
|
|
27
|
+
export { default as FileUploadItem } from "./FileUploadItem.svelte";
|
|
28
|
+
|
|
29
|
+
// Layout
|
|
30
|
+
export { default as Separator } from "./Separator.svelte";
|
|
31
|
+
export { default as Progress } from "./Progress.svelte";
|
|
32
|
+
export { default as List } from "./List.svelte";
|
|
33
|
+
export { default as ListItem } from "./ListItem.svelte";
|
|
34
|
+
|
|
35
|
+
// Containers
|
|
36
|
+
export { default as Card } from "./Card.svelte";
|
|
37
|
+
export { default as Panel } from "./Panel.svelte";
|
|
38
|
+
export { default as Modal } from "./Modal.svelte";
|
|
39
|
+
export { default as Popover } from "./Popover.svelte";
|
|
40
|
+
export { default as Menu } from "./Menu.svelte";
|
|
41
|
+
export { default as MenuItem } from "./MenuItem.svelte";
|
|
42
|
+
export { default as MenuSeparator } from "./MenuSeparator.svelte";
|
|
43
|
+
|
|
44
|
+
// Form controls — composite
|
|
45
|
+
export { default as Combobox } from "./Combobox.svelte";
|
|
46
|
+
|
|
47
|
+
// Tabs
|
|
48
|
+
export { default as Tabs } from "./Tabs.svelte";
|
|
49
|
+
export { default as TabList } from "./TabList.svelte";
|
|
50
|
+
export { default as Tab } from "./Tab.svelte";
|
|
51
|
+
export { default as TabPanel } from "./TabPanel.svelte";
|
|
52
|
+
|
|
53
|
+
// Feedback
|
|
54
|
+
export { default as Alert } from "./Alert.svelte";
|
|
55
|
+
export { default as Toast } from "./Toast.svelte";
|
|
56
|
+
export { default as EmptyState } from "./EmptyState.svelte";
|
|
57
|
+
|
|
58
|
+
// Navigation
|
|
59
|
+
export { default as Sidebar } from "./Sidebar.svelte";
|
|
60
|
+
export { default as SidebarItem } from "./SidebarItem.svelte";
|
|
61
|
+
export { default as SidebarSection } from "./SidebarSection.svelte";
|
|
62
|
+
export { default as BottomNav } from "./BottomNav.svelte";
|
|
63
|
+
export { default as BottomNavItem } from "./BottomNavItem.svelte";
|
|
64
|
+
|
|
65
|
+
// Complex
|
|
66
|
+
export { default as Stepper } from "./Stepper.svelte";
|
|
67
|
+
export { default as CodeBlock } from "./CodeBlock.svelte";
|
|
68
|
+
export { default as CodeEditor } from "./CodeEditor.svelte";
|
|
69
|
+
export { default as CollapsibleSection } from "./CollapsibleSection.svelte";
|
|
70
|
+
export { default as OptionGrid } from "./OptionGrid.svelte";
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aiaiai-pt/design-system",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Design system tokens and Svelte components for aiaiai products",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/aiaiai-pt/aiaiai-design-system.git"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"svelte": "./components/index.js",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"svelte": "./components/index.js",
|
|
18
|
+
"default": "./components/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./components": {
|
|
21
|
+
"svelte": "./components/index.js",
|
|
22
|
+
"default": "./components/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./components/*": {
|
|
25
|
+
"svelte": "./components/*",
|
|
26
|
+
"default": "./components/*"
|
|
27
|
+
},
|
|
28
|
+
"./tokens/*": "./tokens/*"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"components",
|
|
32
|
+
"tokens"
|
|
33
|
+
],
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"svelte": "^5.0.0",
|
|
36
|
+
"@codemirror/view": "^6.0.0",
|
|
37
|
+
"@codemirror/state": "^6.0.0",
|
|
38
|
+
"@codemirror/language": "^6.0.0",
|
|
39
|
+
"@codemirror/commands": "^6.0.0",
|
|
40
|
+
"@codemirror/lang-sql": "^6.0.0",
|
|
41
|
+
"@codemirror/lang-python": "^6.0.0",
|
|
42
|
+
"@codemirror/lang-json": "^6.0.0",
|
|
43
|
+
"@lezer/highlight": "^1.0.0"
|
|
44
|
+
}
|
|
45
|
+
}
|