daftcss 1.3.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.
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Checkbox, radio, and switch styles
3
+ */
4
+
5
+ /* Base checkbox and radio */
6
+ input[type="checkbox"],
7
+ input[type="radio"] {
8
+ width: var(--control-size);
9
+ height: var(--control-size);
10
+ margin: 0;
11
+ vertical-align: middle;
12
+ cursor: pointer;
13
+ appearance: none;
14
+ background-color: var(--background);
15
+ border: var(--border-width) solid var(--input);
16
+ position: relative;
17
+ transition: background-color var(--transition-default),
18
+ border-color var(--transition-default),
19
+ box-shadow var(--transition-default);
20
+ }
21
+
22
+ input[type="checkbox"] {
23
+ border-radius: var(--radius-sm);
24
+ }
25
+
26
+ input[type="radio"] {
27
+ border-radius: var(--radius-full);
28
+ }
29
+
30
+ /* Checked state */
31
+ input[type="checkbox"]:checked,
32
+ input[type="radio"]:checked {
33
+ background-color: var(--primary);
34
+ border-color: var(--primary);
35
+ }
36
+
37
+ /* Checkbox checkmark using mask */
38
+ input[type="checkbox"]:checked::after {
39
+ content: "";
40
+ position: absolute;
41
+ inset: 0;
42
+ background-color: var(--primary-foreground);
43
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
44
+ mask-size: 0.875rem;
45
+ mask-position: center;
46
+ mask-repeat: no-repeat;
47
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
48
+ -webkit-mask-size: 0.875rem;
49
+ -webkit-mask-position: center;
50
+ -webkit-mask-repeat: no-repeat;
51
+ }
52
+
53
+ /* Radio dot using mask */
54
+ input[type="radio"]:checked::after {
55
+ content: "";
56
+ position: absolute;
57
+ inset: 0;
58
+ background-color: var(--primary-foreground);
59
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='black'%3E%3Ccircle cx='12' cy='12' r='5'/%3E%3C/svg%3E");
60
+ mask-size: 0.875rem;
61
+ mask-position: center;
62
+ mask-repeat: no-repeat;
63
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='black'%3E%3Ccircle cx='12' cy='12' r='5'/%3E%3C/svg%3E");
64
+ -webkit-mask-size: 0.875rem;
65
+ -webkit-mask-position: center;
66
+ -webkit-mask-repeat: no-repeat;
67
+ }
68
+
69
+ /* Indeterminate checkbox using mask */
70
+ input[type="checkbox"]:indeterminate {
71
+ background-color: var(--primary);
72
+ border-color: var(--primary);
73
+ }
74
+
75
+ input[type="checkbox"]:indeterminate::after {
76
+ content: "";
77
+ position: absolute;
78
+ inset: 0;
79
+ background-color: var(--primary-foreground);
80
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
81
+ mask-size: 0.875rem;
82
+ mask-position: center;
83
+ mask-repeat: no-repeat;
84
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
85
+ -webkit-mask-size: 0.875rem;
86
+ -webkit-mask-position: center;
87
+ -webkit-mask-repeat: no-repeat;
88
+ }
89
+
90
+ /* Focus state */
91
+ input[type="checkbox"]:focus-visible,
92
+ input[type="radio"]:focus-visible {
93
+ outline: none;
94
+ border-color: var(--ring);
95
+ box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--ring) var(--focus-ring-opacity), transparent);
96
+ }
97
+
98
+ /* Disabled state */
99
+ input[type="checkbox"]:disabled,
100
+ input[type="radio"]:disabled {
101
+ cursor: not-allowed;
102
+ opacity: var(--disabled-opacity);
103
+ }
104
+
105
+ /* Label with checkbox/radio inline */
106
+ label:has(> input[type="checkbox"]),
107
+ label:has(> input[type="radio"]) {
108
+ display: flex;
109
+ align-items: center;
110
+ gap: var(--spacing-sm);
111
+ margin-bottom: var(--spacing-sm);
112
+ font-weight: var(--font-normal);
113
+ cursor: pointer;
114
+
115
+ & > input {
116
+ margin-top: 0;
117
+ flex-shrink: 0;
118
+ }
119
+ }
120
+
121
+ /* Disabled label */
122
+ label:has(> input:disabled) {
123
+ cursor: not-allowed;
124
+ opacity: var(--disabled-opacity);
125
+ }
126
+
127
+ label[aria-disabled="true"] {
128
+ cursor: not-allowed;
129
+ opacity: var(--disabled-opacity);
130
+ }
131
+
132
+ /* Switch (checkbox with role="switch") */
133
+ input[type="checkbox"][role="switch"] {
134
+ width: var(--switch-width);
135
+ height: var(--switch-height);
136
+ border-radius: var(--radius-full);
137
+ background-color: var(--muted-foreground);
138
+ border-color: var(--muted-foreground);
139
+ position: relative;
140
+ transition: background-color var(--transition-default);
141
+ }
142
+
143
+ input[type="checkbox"][role="switch"]::before {
144
+ content: "";
145
+ position: absolute;
146
+ top: 0;
147
+ bottom: 0;
148
+ left: 1px;
149
+ margin: auto 0;
150
+ width: var(--switch-thumb);
151
+ height: var(--switch-thumb);
152
+ background-color: var(--background);
153
+ border-radius: var(--radius-full);
154
+ transition: transform var(--transition-default);
155
+ }
156
+
157
+ /* Switch checked - disable the checkmark ::after */
158
+ input[type="checkbox"][role="switch"]:checked::after {
159
+ display: none;
160
+ }
161
+
162
+ input[type="checkbox"][role="switch"]:checked {
163
+ background-color: var(--primary);
164
+ border-color: var(--primary);
165
+ }
166
+
167
+ input[type="checkbox"][role="switch"]:checked::before {
168
+ transform: translateX(calc(var(--switch-width) - var(--switch-thumb) - 2 * var(--border-width) - 2px));
169
+ }
170
+
171
+ input[type="checkbox"][role="switch"]:focus-visible {
172
+ box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--ring) var(--focus-ring-opacity), transparent);
173
+ }
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Input styles
3
+ * Text inputs, textarea, select, and file inputs
4
+ */
5
+
6
+ /* Base input styles */
7
+ /* :where() keeps the long :not() chain at specificity 0 so type-specific rules
8
+ below (search pill radius, etc.) can override without an arms race. */
9
+ input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="submit"]):not([type="reset"]):not([type="button"])),
10
+ textarea,
11
+ select {
12
+ display: block;
13
+ width: 100%;
14
+ height: var(--input-height);
15
+ padding: var(--spacing-sm) var(--spacing-md);
16
+ font-family: inherit;
17
+ font-size: var(--text-base);
18
+ font-weight: var(--font-normal);
19
+ line-height: var(--line-height);
20
+ color: var(--foreground);
21
+ background-color: var(--input-background);
22
+ border: var(--border-width) solid var(--input);
23
+ border-radius: var(--input-radius);
24
+ transition: border-color var(--transition-default),
25
+ box-shadow var(--transition-default);
26
+ appearance: none;
27
+
28
+ &::placeholder {
29
+ color: var(--muted-foreground);
30
+ opacity: 1;
31
+ }
32
+
33
+ &:focus-visible {
34
+ outline: none;
35
+ border-color: var(--ring);
36
+ box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--ring) var(--focus-ring-opacity), transparent);
37
+ }
38
+
39
+ &:disabled {
40
+ cursor: not-allowed;
41
+ opacity: var(--disabled-opacity);
42
+ background-color: var(--muted);
43
+ border-color: var(--muted-foreground);
44
+ }
45
+ }
46
+
47
+ /* Form buttons span full width — except in search forms, which stay inline. */
48
+ form:not([role="search"]) :is(button, [type="submit"], [type="reset"], [type="button"]):not(.icon) {
49
+ width: 100%;
50
+ }
51
+
52
+ /* Read-only state - only for text inputs and textarea, not select */
53
+ input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="submit"]):not([type="reset"]):not([type="button"])):read-only,
54
+ textarea:read-only {
55
+ background-color: var(--muted);
56
+ }
57
+
58
+ /* Textarea specific */
59
+ textarea {
60
+ height: auto;
61
+ min-height: calc(var(--input-height) * 2);
62
+ padding: var(--spacing-md);
63
+ resize: vertical;
64
+ }
65
+
66
+ /* Select specific */
67
+ select {
68
+ /* Line-height calculated to fill available space: height - borders - padding */
69
+ line-height: calc(var(--input-height) - 2 * var(--border-width) - 2 * var(--spacing-sm));
70
+ padding-right: var(--spacing-xl);
71
+ background-image: var(--icon-select-chevron);
72
+ background-repeat: no-repeat;
73
+ background-position: right var(--spacing-md) center;
74
+ background-size: var(--icon-size);
75
+
76
+ &[multiple] {
77
+ height: auto;
78
+ padding-right: var(--spacing-md);
79
+ background-image: none;
80
+ }
81
+ }
82
+
83
+ /* File input */
84
+ input[type="file"] {
85
+ width: 100%;
86
+ height: var(--input-height);
87
+ padding: 0 var(--spacing-sm);
88
+ font-size: var(--text-sm);
89
+ font-weight: var(--font-medium);
90
+ /* Line-height for vertical centering (flex doesn't work on file inputs) */
91
+ line-height: calc(var(--input-height) - 2 * var(--border-width));
92
+ color: var(--foreground);
93
+ background-color: var(--input-background);
94
+ border: var(--border-width) solid var(--input);
95
+ border-radius: var(--input-radius);
96
+ cursor: pointer;
97
+ transition: border-color var(--transition-default);
98
+
99
+ &::file-selector-button {
100
+ padding: var(--spacing-xs) var(--spacing-md);
101
+ margin-right: var(--spacing-md);
102
+ font-weight: var(--font-medium);
103
+ color: var(--foreground);
104
+ background-color: var(--accent);
105
+ border: none;
106
+ border-radius: var(--radius-sm);
107
+ cursor: pointer;
108
+ transition: background-color var(--transition-default);
109
+ }
110
+
111
+ &:hover::file-selector-button {
112
+ background-color: color-mix(in oklch, var(--accent) 80%, var(--foreground) 5%);
113
+ }
114
+
115
+ &:focus-visible {
116
+ outline: none;
117
+ border-color: var(--ring);
118
+ box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--ring) var(--focus-ring-opacity), transparent);
119
+ }
120
+ }
121
+
122
+ /* Color input */
123
+ input[type="color"] {
124
+ width: 100%;
125
+ height: var(--input-height);
126
+ padding: 6px;
127
+ background-color: var(--input-background);
128
+ border: var(--border-width) solid var(--input);
129
+ border-radius: var(--input-radius);
130
+ cursor: pointer;
131
+
132
+ &::-webkit-color-swatch-wrapper {
133
+ padding: 0;
134
+ }
135
+
136
+ &::-webkit-color-swatch {
137
+ border: none;
138
+ border-radius: var(--radius-sm);
139
+ }
140
+
141
+ &::-moz-color-swatch {
142
+ border: none;
143
+ border-radius: var(--radius-sm);
144
+ }
145
+ }
146
+
147
+ /* Search input - rounded */
148
+ input[type="search"] {
149
+ border-radius: var(--radius-full);
150
+ padding-left: var(--spacing);
151
+ padding-right: var(--spacing);
152
+
153
+ /* Remove default clear button */
154
+ &::-webkit-search-cancel-button {
155
+ -webkit-appearance: none;
156
+ appearance: none;
157
+ }
158
+ }
159
+
160
+ /* Date/time inputs */
161
+ input[type="date"],
162
+ input[type="datetime-local"],
163
+ input[type="month"],
164
+ input[type="time"],
165
+ input[type="week"] {
166
+ &::-webkit-calendar-picker-indicator {
167
+ cursor: pointer;
168
+ opacity: 0.6;
169
+ transition: opacity var(--transition-default);
170
+ }
171
+
172
+ &::-webkit-calendar-picker-indicator:hover {
173
+ opacity: 1;
174
+ }
175
+ }
176
+
177
+ /* Labels */
178
+ label {
179
+ display: block;
180
+ margin-bottom: var(--spacing-sm);
181
+ font-size: var(--text-sm);
182
+ font-weight: var(--font-medium);
183
+ color: var(--foreground);
184
+ }
185
+
186
+ /* Label wrapping input */
187
+ label:has(> input),
188
+ label:has(> select),
189
+ label:has(> textarea) {
190
+ display: block;
191
+
192
+ & > input,
193
+ & > select,
194
+ & > textarea {
195
+ margin-top: var(--spacing-sm);
196
+ }
197
+ }
198
+
199
+ /* Helper text */
200
+ small {
201
+ display: block;
202
+ margin-top: var(--spacing-xs);
203
+ font-size: var(--text-sm);
204
+ color: var(--muted-foreground);
205
+ }
206
+
207
+ /* Form layout */
208
+ form {
209
+ & > label,
210
+ & > input,
211
+ & > textarea,
212
+ & > select,
213
+ & > fieldset,
214
+ & > div,
215
+ & > p,
216
+ & > small {
217
+ margin-bottom: var(--spacing);
218
+ }
219
+
220
+ & > :last-child {
221
+ margin-bottom: 0;
222
+ }
223
+ }
224
+
225
+ /* Fieldset */
226
+ fieldset {
227
+ margin-bottom: var(--spacing);
228
+ }
229
+
230
+ fieldset:last-child {
231
+ margin-bottom: 0;
232
+ }
233
+
234
+ legend {
235
+ font-size: var(--text-sm);
236
+ font-weight: var(--font-semibold);
237
+ color: var(--foreground);
238
+ margin-bottom: var(--spacing-md);
239
+ }
240
+
241
+ /* Disabled fieldset */
242
+ fieldset:disabled {
243
+ opacity: var(--disabled-opacity);
244
+ }
245
+
246
+ fieldset:disabled * {
247
+ cursor: not-allowed;
248
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Range slider styles
3
+ */
4
+
5
+ input[type="range"] {
6
+ width: 100%;
7
+ height: 1.5rem;
8
+ padding: 0;
9
+ background: transparent;
10
+ cursor: pointer;
11
+ appearance: none;
12
+ }
13
+
14
+ /* Track */
15
+ input[type="range"]::-webkit-slider-runnable-track {
16
+ width: 100%;
17
+ height: 0.5rem;
18
+ background-color: var(--muted);
19
+ border-radius: var(--radius-full);
20
+ transition: background-color var(--transition-default);
21
+ }
22
+
23
+ input[type="range"]::-moz-range-track {
24
+ width: 100%;
25
+ height: 0.5rem;
26
+ background-color: var(--muted);
27
+ border-radius: var(--radius-full);
28
+ transition: background-color var(--transition-default);
29
+ }
30
+
31
+ /* Thumb */
32
+ input[type="range"]::-webkit-slider-thumb {
33
+ width: var(--control-size);
34
+ height: var(--control-size);
35
+ margin-top: calc((0.5rem - var(--control-size)) / 2);
36
+ background-color: var(--foreground);
37
+ border: none;
38
+ border-radius: var(--radius-md);
39
+ cursor: pointer;
40
+ appearance: none;
41
+ transition: background-color var(--transition-default),
42
+ transform var(--transition-default);
43
+ }
44
+
45
+ input[type="range"]::-moz-range-thumb {
46
+ width: var(--control-size);
47
+ height: var(--control-size);
48
+ background-color: var(--foreground);
49
+ border: none;
50
+ border-radius: var(--radius-md);
51
+ cursor: pointer;
52
+ transition: background-color var(--transition-default),
53
+ transform var(--transition-default);
54
+ }
55
+
56
+ /* Hover state */
57
+ input[type="range"]:hover::-webkit-slider-thumb {
58
+ background-color: var(--primary);
59
+ transform: scale(1.1);
60
+ }
61
+
62
+ input[type="range"]:hover::-moz-range-thumb {
63
+ background-color: var(--primary);
64
+ transform: scale(1.1);
65
+ }
66
+
67
+ /* Active state */
68
+ input[type="range"]:active::-webkit-slider-thumb {
69
+ background-color: var(--primary);
70
+ transform: scale(1.15);
71
+ }
72
+
73
+ input[type="range"]:active::-moz-range-thumb {
74
+ background-color: var(--primary);
75
+ transform: scale(1.15);
76
+ }
77
+
78
+ /* Focus state */
79
+ input[type="range"]:focus-visible {
80
+ outline: none;
81
+ }
82
+
83
+ input[type="range"]:focus-visible::-webkit-slider-thumb {
84
+ box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--ring) var(--focus-ring-opacity), transparent);
85
+ }
86
+
87
+ input[type="range"]:focus-visible::-moz-range-thumb {
88
+ box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--ring) var(--focus-ring-opacity), transparent);
89
+ }
90
+
91
+ /* Disabled state */
92
+ input[type="range"]:disabled {
93
+ cursor: not-allowed;
94
+ opacity: var(--disabled-opacity);
95
+ }
96
+
97
+ input[type="range"]:disabled::-webkit-slider-thumb {
98
+ cursor: not-allowed;
99
+ }
100
+
101
+ input[type="range"]:disabled::-moz-range-thumb {
102
+ cursor: not-allowed;
103
+ }
104
+
105
+ /* Label with range */
106
+ label:has(> input[type="range"]) {
107
+ display: block;
108
+
109
+ & > input[type="range"] {
110
+ margin-top: var(--spacing-sm);
111
+ }
112
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Form validation styles
3
+ * Uses aria-invalid for semantic validation states
4
+ */
5
+
6
+ /* Invalid state */
7
+ input[aria-invalid="true"],
8
+ textarea[aria-invalid="true"],
9
+ select[aria-invalid="true"] {
10
+ border-color: var(--destructive);
11
+ }
12
+
13
+ /* Valid state */
14
+ input[aria-invalid="false"],
15
+ textarea[aria-invalid="false"],
16
+ select[aria-invalid="false"] {
17
+ border-color: var(--primary);
18
+ }
19
+
20
+ /* Helper text colors for validation */
21
+ input[aria-invalid="true"] + small,
22
+ textarea[aria-invalid="true"] + small,
23
+ select[aria-invalid="true"] + small,
24
+ input[aria-invalid="true"] ~ small,
25
+ textarea[aria-invalid="true"] ~ small,
26
+ select[aria-invalid="true"] ~ small {
27
+ color: var(--destructive);
28
+ }
29
+
30
+ input[aria-invalid="false"] + small,
31
+ textarea[aria-invalid="false"] + small,
32
+ select[aria-invalid="false"] + small,
33
+ input[aria-invalid="false"] ~ small,
34
+ textarea[aria-invalid="false"] ~ small,
35
+ select[aria-invalid="false"] ~ small {
36
+ color: var(--primary);
37
+ }
38
+
39
+ /* Checkbox/radio validation */
40
+ input[type="checkbox"][aria-invalid="true"],
41
+ input[type="radio"][aria-invalid="true"] {
42
+ border-color: var(--destructive);
43
+ }
44
+
45
+ input[type="checkbox"][aria-invalid="false"],
46
+ input[type="radio"][aria-invalid="false"] {
47
+ border-color: var(--primary);
48
+ }
49
+
50
+ /* Native browser validation (optional enhancement) */
51
+ input:user-invalid:not([type="checkbox"]):not([type="radio"]),
52
+ textarea:user-invalid {
53
+ border-color: var(--destructive);
54
+ }
55
+
56
+ input:user-valid:not(:placeholder-shown):not([type="checkbox"]):not([type="radio"]),
57
+ textarea:user-valid:not(:placeholder-shown) {
58
+ border-color: var(--primary);
59
+ }
60
+
61
+ /* Required field indicator */
62
+ label:has(+ input:required)::after,
63
+ label:has(+ textarea:required)::after,
64
+ label:has(+ select:required)::after,
65
+ label:has(> input:required)::after,
66
+ label:has(> textarea:required)::after,
67
+ label:has(> select:required)::after {
68
+ content: " *";
69
+ color: var(--destructive);
70
+ }
71
+
72
+ /* Dropdown validation */
73
+ details.dropdown[aria-invalid="true"] > summary {
74
+ border-color: var(--destructive);
75
+ }
76
+
77
+ details.dropdown[aria-invalid="false"] > summary {
78
+ border-color: var(--primary);
79
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Container styles
3
+ * Centered content containers with responsive max-widths
4
+ */
5
+
6
+ .container {
7
+ width: 100%;
8
+ margin-left: auto;
9
+ margin-right: auto;
10
+ padding-left: var(--spacing);
11
+ padding-right: var(--spacing);
12
+ }
13
+
14
+ /* Responsive max-widths */
15
+ @media (min-width: 576px) {
16
+ .container {
17
+ max-width: 540px;
18
+ padding-left: 0;
19
+ padding-right: 0;
20
+ }
21
+ }
22
+
23
+ @media (min-width: 768px) {
24
+ .container {
25
+ max-width: 720px;
26
+ }
27
+ }
28
+
29
+ @media (min-width: 1024px) {
30
+ .container {
31
+ max-width: 960px;
32
+ }
33
+ }
34
+
35
+ @media (min-width: 1280px) {
36
+ .container {
37
+ max-width: 1140px;
38
+ }
39
+ }
40
+
41
+ @media (min-width: 1536px) {
42
+ .container {
43
+ max-width: 1320px;
44
+ }
45
+ }
46
+
47
+ /* Fluid container - full width with padding */
48
+ .container-fluid {
49
+ width: 100%;
50
+ margin-left: auto;
51
+ margin-right: auto;
52
+ padding-left: var(--spacing);
53
+ padding-right: var(--spacing);
54
+ }
55
+
56
+ @media (min-width: 768px) {
57
+ .container-fluid {
58
+ padding-left: var(--spacing-lg);
59
+ padding-right: var(--spacing-lg);
60
+ }
61
+ }
62
+
63
+ @media (min-width: 1024px) {
64
+ .container-fluid {
65
+ padding-left: var(--spacing-xl);
66
+ padding-right: var(--spacing-xl);
67
+ }
68
+ }