@1001-digital/layers.base 0.0.1
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/.editorconfig +12 -0
- package/.nuxtrc +1 -0
- package/.playground/app.config.ts +5 -0
- package/.playground/app.vue +3 -0
- package/.playground/nuxt.config.ts +12 -0
- package/.playground/pages/index.vue +626 -0
- package/AGENTS.md +51 -0
- package/README.md +13 -0
- package/app/app.vue +3 -0
- package/app/assets/styles/base/base.css +52 -0
- package/app/assets/styles/base/forms.css +129 -0
- package/app/assets/styles/base/reset.css +159 -0
- package/app/assets/styles/index.css +28 -0
- package/app/assets/styles/utilities/animations.css +77 -0
- package/app/assets/styles/utilities/utilities.css +58 -0
- package/app/assets/styles/variables/borders.css +18 -0
- package/app/assets/styles/variables/colors.css +75 -0
- package/app/assets/styles/variables/components/alerts.css +13 -0
- package/app/assets/styles/variables/components/buttons.css +18 -0
- package/app/assets/styles/variables/components/cards.css +7 -0
- package/app/assets/styles/variables/components/dialogs.css +7 -0
- package/app/assets/styles/variables/components/forms.css +5 -0
- package/app/assets/styles/variables/components/images.css +5 -0
- package/app/assets/styles/variables/components/index.css +6 -0
- package/app/assets/styles/variables/effects.css +3 -0
- package/app/assets/styles/variables/fonts.css +36 -0
- package/app/assets/styles/variables/index.css +15 -0
- package/app/assets/styles/variables/layout.css +7 -0
- package/app/assets/styles/variables/sizes.css +24 -0
- package/app/assets/styles/variables/timing.css +5 -0
- package/app/assets/styles/variables/ui.css +18 -0
- package/app/assets/styles/variables/z-index.css +7 -0
- package/app/components/Actions.vue +57 -0
- package/app/components/Alert.vue +78 -0
- package/app/components/Button.vue +196 -0
- package/app/components/Card.vue +62 -0
- package/app/components/Dialog.client.vue +217 -0
- package/app/components/Form/Form.vue +27 -0
- package/app/components/Form/FormCheckbox.vue +88 -0
- package/app/components/Form/FormGroup.vue +36 -0
- package/app/components/Form/FormInputGroup.vue +55 -0
- package/app/components/Form/FormItem.vue +53 -0
- package/app/components/Form/FormLabel.vue +39 -0
- package/app/components/Form/FormRadioGroup.vue +109 -0
- package/app/components/Form/FormSelect.vue +155 -0
- package/app/components/HelloWorld.vue +10 -0
- package/app/components/Icon.vue +48 -0
- package/app/components/Loading.vue +58 -0
- package/app/components/Tag.vue +47 -0
- package/app/components/Tags.vue +13 -0
- package/app.config.ts +14 -0
- package/eslint.config.js +3 -0
- package/nuxt.config.ts +19 -0
- package/package.json +29 -0
- package/tsconfig.json +3 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Base Nuxt layer for building modern web applications with accessible components and CSS custom properties.
|
|
4
|
+
|
|
5
|
+
## Setup commands
|
|
6
|
+
|
|
7
|
+
- Install deps: `pnpm install`
|
|
8
|
+
- Start dev server: `pnpm dev`
|
|
9
|
+
- Run tests: `pnpm test`
|
|
10
|
+
|
|
11
|
+
## Code style
|
|
12
|
+
|
|
13
|
+
- TypeScript
|
|
14
|
+
- Single quotes, no semicolons
|
|
15
|
+
|
|
16
|
+
## Styling
|
|
17
|
+
|
|
18
|
+
- CSS custom properties (design tokens) in `app/assets/styles/variables/`
|
|
19
|
+
- CSS layers: `reset` → `base` → `components` → `utilities`
|
|
20
|
+
- oklch color space with `light-dark()` for theme support
|
|
21
|
+
- Component-specific variables in `variables/components/`
|
|
22
|
+
|
|
23
|
+
## Components
|
|
24
|
+
|
|
25
|
+
- Base components use [Reka UI](https://reka-ui.com/llms.txt) for accessibility, with our custom styling framework
|
|
26
|
+
- For tables and virtualization we use Tanstack (e.g. [Tanstack Table](https://tanstack.com/table/latest/docs/introduction.md) and [Tanstack Virtualization](https://tanstack.com/virtual/latest/docs/introduction.md)).
|
|
27
|
+
- Icon.vue maps semantic names (e.g. 'check', 'add') to Lucide/Simple Icons
|
|
28
|
+
|
|
29
|
+
## Component naming
|
|
30
|
+
|
|
31
|
+
Components in nested directories use auto-generated names based on path and filename, with duplicate segments removed.
|
|
32
|
+
|
|
33
|
+
Example: `components/base/foo/Button.vue` → `<BaseFooButton />`
|
|
34
|
+
|
|
35
|
+
For clarity, rename files to match the full component name:
|
|
36
|
+
- ✗ `components/base/foo/Button.vue`
|
|
37
|
+
- ✓ `components/base/foo/BaseFooButton.vue`
|
|
38
|
+
|
|
39
|
+
## Key directories
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
app/
|
|
43
|
+
├── components/ # Vue components
|
|
44
|
+
│ └── Form/ # Form components (Reka UI wrappers)
|
|
45
|
+
├── assets/styles/
|
|
46
|
+
│ ├── base/ # Element defaults, reset
|
|
47
|
+
│ ├── utilities/ # Helper classes, animations
|
|
48
|
+
│ └── variables/ # Design tokens (colors, spacing, etc.)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# BASE LAYER
|
|
2
|
+
|
|
3
|
+
Nuxt layer for web application development with semi opinionated styling setup and components using [Reka UI](https://reka-ui.com).
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm install
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
|
+
|
|
13
|
+
Running `pnpm dev` will prepare and boot `.playground` directory, which imports the layer itself.
|
package/app/app.vue
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Base Layer
|
|
3
|
+
* Core element styling and document defaults
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
html {
|
|
7
|
+
/* Color settings */
|
|
8
|
+
background-color: var(--background);
|
|
9
|
+
color: var(--color);
|
|
10
|
+
|
|
11
|
+
/* Font settings */
|
|
12
|
+
font-size: var(--rem);
|
|
13
|
+
font-family: var(--font-family);
|
|
14
|
+
line-height: var(--line-height-md);
|
|
15
|
+
font-weight: var(--font-weight);
|
|
16
|
+
font-style: normal;
|
|
17
|
+
letter-spacing: var(--letter-spacing);
|
|
18
|
+
text-transform: var(--text-transform);
|
|
19
|
+
font-synthesis: initial;
|
|
20
|
+
text-rendering: optimizeLegibility;
|
|
21
|
+
-webkit-font-smoothing: antialiased;
|
|
22
|
+
-moz-osx-font-smoothing: grayscale;
|
|
23
|
+
-webkit-text-size-adjust: 100%;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
body {
|
|
27
|
+
/* Font size separate from root em */
|
|
28
|
+
font-size: var(--font-base);
|
|
29
|
+
|
|
30
|
+
/* Prevent horizontal overflow */
|
|
31
|
+
overflow-x: hidden;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* Modern Typography
|
|
36
|
+
* text-wrap for balanced headings and prettier paragraphs
|
|
37
|
+
*/
|
|
38
|
+
h1,
|
|
39
|
+
h2,
|
|
40
|
+
h3,
|
|
41
|
+
h4,
|
|
42
|
+
h5,
|
|
43
|
+
h6 {
|
|
44
|
+
text-wrap: balance;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
p,
|
|
48
|
+
li,
|
|
49
|
+
figcaption,
|
|
50
|
+
blockquote {
|
|
51
|
+
text-wrap: pretty;
|
|
52
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Form Elements
|
|
3
|
+
* Global styling for form elements
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
button:not(.unstyled),
|
|
7
|
+
.button:not(.unstyled),
|
|
8
|
+
input:not(.unstyled),
|
|
9
|
+
textarea:not(.unstyled),
|
|
10
|
+
select:not(.unstyled) {
|
|
11
|
+
/* UI font styles */
|
|
12
|
+
font-family: var(--ui-font-family);
|
|
13
|
+
font-size: var(--ui-font-size);
|
|
14
|
+
font-weight: var(--ui-font-weight);
|
|
15
|
+
text-transform: var(--ui-text-transform);
|
|
16
|
+
letter-spacing: var(--ui-letter-spacing);
|
|
17
|
+
line-height: var(--ui-line-height);
|
|
18
|
+
color: var(--ui-color);
|
|
19
|
+
|
|
20
|
+
inline-size: 100%;
|
|
21
|
+
transition: all var(--speed);
|
|
22
|
+
border: none;
|
|
23
|
+
border-radius: var(--button-border-radius);
|
|
24
|
+
box-shadow: var(--border-shadow);
|
|
25
|
+
background: var(--button-background);
|
|
26
|
+
padding: var(--ui-padding-block) var(--ui-padding-inline);
|
|
27
|
+
user-select: none;
|
|
28
|
+
display: flex;
|
|
29
|
+
block-size: var(--form-item-height);
|
|
30
|
+
|
|
31
|
+
&:-internal-autofill-selected {
|
|
32
|
+
background: inherit;
|
|
33
|
+
background-image: none !important;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&:is(:hover, :active, :focus, .active) {
|
|
37
|
+
outline: none;
|
|
38
|
+
box-shadow: var(--border-shadow-highlight);
|
|
39
|
+
background: var(--button-background-highlight);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&::placeholder,
|
|
43
|
+
&::-ms-input-placeholder {
|
|
44
|
+
text-transform: var(--ui-text-transform);
|
|
45
|
+
color: var(--ui-placeholder-color);
|
|
46
|
+
opacity: 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&.small {
|
|
50
|
+
padding: calc(var(--ui-padding-block) / 2) calc(var(--ui-padding-inline) / 2);
|
|
51
|
+
block-size: var(--form-item-height-sm);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
input:not(.unstyled),
|
|
56
|
+
textarea:not(.unstyled) {
|
|
57
|
+
text-transform: var(--input-text-transform);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
select:not(.unstyled),
|
|
61
|
+
select:not(.unstyled):is(:hover, :active, :focus, .active) {
|
|
62
|
+
appearance: none;
|
|
63
|
+
line-height: 1;
|
|
64
|
+
transition-property: box-shadow, background-color, color;
|
|
65
|
+
background:
|
|
66
|
+
url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tZG93biI+PHBvbHlsaW5lIHBvaW50cz0iNiA5IDEyIDE1IDE4IDkiPjwvcG9seWxpbmU+PC9zdmc+),
|
|
67
|
+
var(--button-background);
|
|
68
|
+
background-repeat: no-repeat, no-repeat;
|
|
69
|
+
background-position:
|
|
70
|
+
calc(100% - var(--size-4)) 50%,
|
|
71
|
+
0% 0%;
|
|
72
|
+
background-size:
|
|
73
|
+
var(--size-4),
|
|
74
|
+
100% 100%;
|
|
75
|
+
padding-inline-end: var(--size-7) !important;
|
|
76
|
+
|
|
77
|
+
&.small {
|
|
78
|
+
background-position:
|
|
79
|
+
calc(100% - var(--size-2)) 50%,
|
|
80
|
+
0% 0%;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
input[type='checkbox'] {
|
|
85
|
+
block-size: var(--size-4);
|
|
86
|
+
margin-right: var(--spacer-sm);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
form {
|
|
90
|
+
display: grid;
|
|
91
|
+
gap: var(--spacer);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
form label,
|
|
95
|
+
label.form-label {
|
|
96
|
+
/* UI font styles */
|
|
97
|
+
font-family: var(--ui-font-family);
|
|
98
|
+
font-size: var(--ui-font-size);
|
|
99
|
+
font-weight: var(--ui-font-weight);
|
|
100
|
+
text-transform: var(--ui-text-transform);
|
|
101
|
+
letter-spacing: var(--ui-letter-spacing);
|
|
102
|
+
line-height: var(--ui-line-height);
|
|
103
|
+
color: var(--ui-color);
|
|
104
|
+
|
|
105
|
+
transition: all var(--speed);
|
|
106
|
+
display: grid;
|
|
107
|
+
gap: var(--size-2);
|
|
108
|
+
|
|
109
|
+
&:hover {
|
|
110
|
+
color: var(--color);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
a {
|
|
114
|
+
text-decoration: underline;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
> span:first-child {
|
|
118
|
+
display: block;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
label:has(> input[type='checkbox']) {
|
|
123
|
+
display: flex;
|
|
124
|
+
align-items: center;
|
|
125
|
+
|
|
126
|
+
> * {
|
|
127
|
+
inline-size: auto;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Reset Layer
|
|
3
|
+
* Based on modern-normalize with additional opinionated resets
|
|
4
|
+
* Inspired by Tailwind's preflight
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* Import modern-normalize as the foundation */
|
|
8
|
+
@import 'modern-normalize/modern-normalize.css';
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* Additional resets (SUIT CSS / Tailwind inspired)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* Remove default spacing for semantic elements */
|
|
15
|
+
blockquote,
|
|
16
|
+
dl,
|
|
17
|
+
dd,
|
|
18
|
+
h1,
|
|
19
|
+
h2,
|
|
20
|
+
h3,
|
|
21
|
+
h4,
|
|
22
|
+
h5,
|
|
23
|
+
h6,
|
|
24
|
+
hr,
|
|
25
|
+
figure,
|
|
26
|
+
p,
|
|
27
|
+
pre {
|
|
28
|
+
margin: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Reset fieldset */
|
|
32
|
+
fieldset {
|
|
33
|
+
margin: 0;
|
|
34
|
+
padding: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Reset lists */
|
|
38
|
+
ol,
|
|
39
|
+
ul {
|
|
40
|
+
list-style: none;
|
|
41
|
+
margin: 0;
|
|
42
|
+
padding: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* Base box model
|
|
47
|
+
*/
|
|
48
|
+
*,
|
|
49
|
+
::before,
|
|
50
|
+
::after {
|
|
51
|
+
box-sizing: border-box;
|
|
52
|
+
border-width: 0;
|
|
53
|
+
border-style: solid;
|
|
54
|
+
border-color: #e5e7eb;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Ensure horizontal rules are visible */
|
|
58
|
+
hr {
|
|
59
|
+
border-top-width: 1px;
|
|
60
|
+
border-color: var(--border-color);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Reset italic style on i elements */
|
|
64
|
+
i {
|
|
65
|
+
font-style: normal;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Image border style */
|
|
69
|
+
img {
|
|
70
|
+
border-style: solid;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Textarea resize */
|
|
74
|
+
textarea {
|
|
75
|
+
resize: vertical;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Placeholder styling */
|
|
79
|
+
input::placeholder,
|
|
80
|
+
textarea::placeholder {
|
|
81
|
+
color: var(--ui-placeholder-color);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Pointer cursor for interactive elements */
|
|
85
|
+
button,
|
|
86
|
+
[role='button'] {
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Table border collapse */
|
|
91
|
+
table {
|
|
92
|
+
border-collapse: collapse;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Reset heading styles */
|
|
96
|
+
h1,
|
|
97
|
+
h2,
|
|
98
|
+
h3,
|
|
99
|
+
h4,
|
|
100
|
+
h5,
|
|
101
|
+
h6 {
|
|
102
|
+
font-size: inherit;
|
|
103
|
+
font-weight: inherit;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Reset link styles */
|
|
107
|
+
a {
|
|
108
|
+
color: inherit;
|
|
109
|
+
text-decoration: inherit;
|
|
110
|
+
transition: color var(--speed);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Form element defaults */
|
|
114
|
+
.button,
|
|
115
|
+
button,
|
|
116
|
+
input,
|
|
117
|
+
optgroup,
|
|
118
|
+
select,
|
|
119
|
+
textarea {
|
|
120
|
+
padding: var(--ui-padding-block) var(--ui-padding-inline);
|
|
121
|
+
line-height: inherit;
|
|
122
|
+
color: inherit;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* Monospace elements */
|
|
126
|
+
pre,
|
|
127
|
+
code,
|
|
128
|
+
kbd,
|
|
129
|
+
samp {
|
|
130
|
+
font-family:
|
|
131
|
+
ui-monospace,
|
|
132
|
+
SFMono-Regular,
|
|
133
|
+
Menlo,
|
|
134
|
+
Monaco,
|
|
135
|
+
Consolas,
|
|
136
|
+
'Liberation Mono',
|
|
137
|
+
'Courier New',
|
|
138
|
+
monospace;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Block display for media elements */
|
|
142
|
+
img,
|
|
143
|
+
svg,
|
|
144
|
+
video,
|
|
145
|
+
canvas,
|
|
146
|
+
audio,
|
|
147
|
+
iframe,
|
|
148
|
+
embed,
|
|
149
|
+
object {
|
|
150
|
+
display: block;
|
|
151
|
+
vertical-align: middle;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Responsive images/video */
|
|
155
|
+
img,
|
|
156
|
+
video {
|
|
157
|
+
max-width: 100%;
|
|
158
|
+
height: auto;
|
|
159
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* CSS Layers Order Definition
|
|
3
|
+
* This establishes the cascade priority:
|
|
4
|
+
* reset < base < components < utilities
|
|
5
|
+
*/
|
|
6
|
+
@layer reset, base, components, utilities;
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* CSS Custom Properties (outside layers for proper cascade)
|
|
10
|
+
*/
|
|
11
|
+
@import './variables/index.css';
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* Reset Layer - Modern Normalize
|
|
15
|
+
*/
|
|
16
|
+
@import './base/reset.css' layer(reset);
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
* Base Layer - Element defaults
|
|
20
|
+
*/
|
|
21
|
+
@import './base/base.css' layer(base);
|
|
22
|
+
@import './base/forms.css' layer(base);
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Utilities Layer - Helper classes
|
|
26
|
+
*/
|
|
27
|
+
@import './utilities/utilities.css' layer(utilities);
|
|
28
|
+
@import './utilities/animations.css' layer(utilities);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Animations Layer
|
|
3
|
+
* Vue transitions and keyframe animations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* Default Vue transition */
|
|
7
|
+
.v-enter-active,
|
|
8
|
+
.v-leave-active {
|
|
9
|
+
transition: opacity var(--speed) ease;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.v-enter-from,
|
|
13
|
+
.v-leave-to {
|
|
14
|
+
opacity: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Fade transition */
|
|
18
|
+
.fade-enter-active,
|
|
19
|
+
.fade-leave-active {
|
|
20
|
+
transition: all var(--speed) ease;
|
|
21
|
+
max-block-size: 100%;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.fade-enter-from,
|
|
25
|
+
.fade-leave-to {
|
|
26
|
+
opacity: 0;
|
|
27
|
+
max-block-size: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Keyframe animations */
|
|
31
|
+
@keyframes appear {
|
|
32
|
+
0% {
|
|
33
|
+
opacity: 0;
|
|
34
|
+
}
|
|
35
|
+
100% {
|
|
36
|
+
opacity: 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@keyframes fade-in {
|
|
41
|
+
0% {
|
|
42
|
+
opacity: 0;
|
|
43
|
+
transform: translateY(var(--spacer));
|
|
44
|
+
}
|
|
45
|
+
100% {
|
|
46
|
+
opacity: 1;
|
|
47
|
+
transform: translateY(0);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@keyframes spin {
|
|
52
|
+
0% {
|
|
53
|
+
transform: rotate(0deg);
|
|
54
|
+
}
|
|
55
|
+
100% {
|
|
56
|
+
transform: rotate(360deg);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* Entry Animations with @starting-style
|
|
62
|
+
* For elements transitioning from display: none
|
|
63
|
+
*/
|
|
64
|
+
.appear {
|
|
65
|
+
opacity: 1;
|
|
66
|
+
transform: translateY(0);
|
|
67
|
+
transition:
|
|
68
|
+
opacity var(--speed) ease,
|
|
69
|
+
transform var(--speed) ease,
|
|
70
|
+
display var(--speed) ease allow-discrete;
|
|
71
|
+
|
|
72
|
+
@starting-style {
|
|
73
|
+
opacity: 0;
|
|
74
|
+
transform: translateY(var(--spacer-sm));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Utilities Layer
|
|
3
|
+
* Single-purpose helper classes
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* UI font utility */
|
|
7
|
+
.ui {
|
|
8
|
+
font-family: var(--ui-font-family);
|
|
9
|
+
font-size: var(--ui-font-size);
|
|
10
|
+
font-weight: var(--ui-font-weight);
|
|
11
|
+
text-transform: var(--ui-text-transform);
|
|
12
|
+
letter-spacing: var(--ui-letter-spacing);
|
|
13
|
+
line-height: var(--ui-line-height);
|
|
14
|
+
color: var(--ui-color);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Muted text */
|
|
18
|
+
.muted {
|
|
19
|
+
color: var(--muted);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Font sizes */
|
|
23
|
+
.font-sm {
|
|
24
|
+
font-size: var(--font-sm);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Responsive visibility */
|
|
28
|
+
.visible-sm {
|
|
29
|
+
display: none !important;
|
|
30
|
+
|
|
31
|
+
@media (min-width: 27rem) {
|
|
32
|
+
display: initial !important;
|
|
33
|
+
|
|
34
|
+
&.flex {
|
|
35
|
+
display: flex !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&.inline-flex {
|
|
39
|
+
display: inline-flex !important;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.visible-md {
|
|
45
|
+
display: none !important;
|
|
46
|
+
|
|
47
|
+
@media (min-width: 45rem) {
|
|
48
|
+
display: initial !important;
|
|
49
|
+
|
|
50
|
+
&.flex {
|
|
51
|
+
display: flex !important;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&.inline-flex {
|
|
55
|
+
display: inline-flex !important;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--border-width: 1px;
|
|
3
|
+
--border-radius: 0;
|
|
4
|
+
|
|
5
|
+
/* Border colors */
|
|
6
|
+
--border-color: var(--gray-z-2);
|
|
7
|
+
--border-color-highlight: var(--gray-z-3);
|
|
8
|
+
--border-color-dark: var(--color);
|
|
9
|
+
--border-color-light: var(--color);
|
|
10
|
+
|
|
11
|
+
/* Border shorthand */
|
|
12
|
+
--border: var(--border-width) solid var(--border-color);
|
|
13
|
+
--border-dark: var(--border-width) solid var(--border-color-dark);
|
|
14
|
+
|
|
15
|
+
/* Border effects */
|
|
16
|
+
--border-shadow: 0 0 0 var(--border-width) var(--border-color);
|
|
17
|
+
--border-shadow-highlight: 0 0 0 var(--border-width) var(--border-color-highlight);
|
|
18
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Colors
|
|
3
|
+
* Modern color palette using oklch for perceptual uniformity
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
/* Enable system color scheme support */
|
|
8
|
+
color-scheme: light dark;
|
|
9
|
+
|
|
10
|
+
/* Base colors */
|
|
11
|
+
--black: oklch(0% 0 0);
|
|
12
|
+
--white: oklch(100% 0 0);
|
|
13
|
+
|
|
14
|
+
/* Gray scale (perceptually uniform in oklch) */
|
|
15
|
+
--gray-50: oklch(98% 0 0);
|
|
16
|
+
--gray-100: oklch(96% 0 0);
|
|
17
|
+
--gray-200: oklch(91% 0 0);
|
|
18
|
+
--gray-300: oklch(85% 0 0);
|
|
19
|
+
--gray-400: oklch(70% 0 0);
|
|
20
|
+
--gray-500: oklch(55% 0 0);
|
|
21
|
+
--gray-600: oklch(45% 0 0);
|
|
22
|
+
--gray-700: oklch(37% 0 0);
|
|
23
|
+
--gray-800: oklch(27% 0 0);
|
|
24
|
+
--gray-900: oklch(20% 0 0);
|
|
25
|
+
--gray-950: oklch(14% 0 0);
|
|
26
|
+
|
|
27
|
+
/* Semi-transparent variants */
|
|
28
|
+
--black-semi: color-mix(in oklch, var(--black) 73%, transparent);
|
|
29
|
+
--white-semi: color-mix(in oklch, var(--white) 73%, transparent);
|
|
30
|
+
|
|
31
|
+
/* Semantic colors */
|
|
32
|
+
--primary: var(--color);
|
|
33
|
+
--muted: var(--gray-z-5);
|
|
34
|
+
--error: oklch(55% 0.25 27);
|
|
35
|
+
--success: oklch(75% 0.2 130);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* Color scheme aware values
|
|
40
|
+
* These use light-dark() and re-evaluate based on the element's color-scheme
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
:root {
|
|
44
|
+
--background: light-dark(var(--white), var(--black));
|
|
45
|
+
--background-semi: light-dark(var(--white-semi), var(--black-semi));
|
|
46
|
+
--color: light-dark(var(--black), var(--white));
|
|
47
|
+
--color-semi: light-dark(var(--black-semi), var(--white-semi));
|
|
48
|
+
|
|
49
|
+
/* Z-colors (depth from viewer, 0 = closest to background) */
|
|
50
|
+
--gray-z-0: light-dark(var(--gray-50), var(--gray-950));
|
|
51
|
+
--gray-z-1: light-dark(var(--gray-100), var(--gray-900));
|
|
52
|
+
--gray-z-2: light-dark(var(--gray-200), var(--gray-800));
|
|
53
|
+
--gray-z-3: light-dark(var(--gray-300), var(--gray-700));
|
|
54
|
+
--gray-z-4: light-dark(var(--gray-400), var(--gray-600));
|
|
55
|
+
--gray-z-5: var(--gray-500);
|
|
56
|
+
--gray-z-6: light-dark(var(--gray-600), var(--gray-400));
|
|
57
|
+
--gray-z-7: light-dark(var(--gray-700), var(--gray-300));
|
|
58
|
+
--gray-z-8: light-dark(var(--gray-800), var(--gray-200));
|
|
59
|
+
--gray-z-9: light-dark(var(--gray-900), var(--gray-100));
|
|
60
|
+
--gray-z-10: light-dark(var(--gray-950), var(--gray-50));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* Manual color scheme overrides
|
|
65
|
+
* Force light/dark mode on nested elements
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
.light {
|
|
69
|
+
color-scheme: light;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.dark {
|
|
73
|
+
color-scheme: dark;
|
|
74
|
+
}
|
|
75
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--alert-color: var(--color);
|
|
3
|
+
--alert-background-color: transparent;
|
|
4
|
+
--alert-border-color: var(--border-color);
|
|
5
|
+
|
|
6
|
+
--alert-info-color: var(--alert-color);
|
|
7
|
+
--alert-info-background-color: var(--alert-background-color);
|
|
8
|
+
--alert-info-border-color: var(--alert-border-color);
|
|
9
|
+
|
|
10
|
+
--alert-error-color: var(--error);
|
|
11
|
+
--alert-error-background-color: color-mix(in srgb, var(--error) 10%, transparent);
|
|
12
|
+
--alert-error-border-color: var(--error);
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--button-border-radius: var(--border-radius);
|
|
3
|
+
--button-background: var(--background);
|
|
4
|
+
--button-background-highlight: var(--gray-z-1);
|
|
5
|
+
--button-border-color-highlight: var(--gray-z-3);
|
|
6
|
+
--button-color: var(--ui-color);
|
|
7
|
+
--button-color-highlight: var(--color);
|
|
8
|
+
--button-icon-color: var(--muted);
|
|
9
|
+
--button-icon-color-highlight: var(--color);
|
|
10
|
+
|
|
11
|
+
/* Primary Button Styles */
|
|
12
|
+
--button-primary-background: var(--gray-z-10);
|
|
13
|
+
--button-primary-border-color: var(--gray-z-8);
|
|
14
|
+
--button-primary-color: var(--gray-z-0);
|
|
15
|
+
--button-primary-background-highlight: var(--gray-z-8);
|
|
16
|
+
--button-primary-border-color-highlight: var(--gray-z-6);
|
|
17
|
+
--button-primary-color-highlight: var(--gray-z-0);
|
|
18
|
+
}
|