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,119 @@
1
+ /**
2
+ * Group styles
3
+ * Button groups and form input groups using role="group"
4
+ */
5
+
6
+ [role="group"] {
7
+ display: inline-flex;
8
+ border-radius: var(--radius-md);
9
+ }
10
+
11
+ [role="group"] > * {
12
+ flex: 1 1 auto;
13
+ }
14
+
15
+ /* Remove inner border radius */
16
+ [role="group"] > *:not(:first-child):not(:last-child) {
17
+ border-radius: 0;
18
+ }
19
+
20
+ [role="group"] > *:first-child:not(:last-child) {
21
+ border-top-right-radius: 0;
22
+ border-bottom-right-radius: 0;
23
+ }
24
+
25
+ [role="group"] > *:last-child:not(:first-child) {
26
+ border-top-left-radius: 0;
27
+ border-bottom-left-radius: 0;
28
+ }
29
+
30
+ /* Button groups - merge borders */
31
+ [role="group"] > button:not(:first-child),
32
+ [role="group"] > [type="submit"]:not(:first-child),
33
+ [role="group"] > [type="button"]:not(:first-child),
34
+ [role="group"] > [role="button"]:not(:first-child) {
35
+ margin-left: calc(var(--border-width) * -1);
36
+ }
37
+
38
+ /* Active button in group - raise above siblings for border visibility */
39
+ [role="group"] > button[aria-current="true"],
40
+ [role="group"] > [role="button"][aria-current="true"] {
41
+ z-index: 1;
42
+ }
43
+
44
+ /* Input groups */
45
+ [role="group"] > input,
46
+ [role="group"] > select {
47
+ flex: 1 1 auto;
48
+ }
49
+
50
+ [role="group"] > input:not(:first-child),
51
+ [role="group"] > select:not(:first-child) {
52
+ margin-left: calc(var(--border-width) * -1);
53
+ }
54
+
55
+ /* Focus state raises element */
56
+ [role="group"] > *:focus-visible {
57
+ z-index: 2;
58
+ }
59
+
60
+ /* Fieldset as group */
61
+ fieldset[role="group"] {
62
+ display: flex;
63
+ width: 100%;
64
+ padding: 0;
65
+ border: none;
66
+ }
67
+
68
+ /* Buttons in groups don't flex-grow */
69
+ [role="group"] > :is(button, [type="submit"], [type="reset"], [type="button"]) {
70
+ flex: 0 0 auto;
71
+ width: auto;
72
+ }
73
+
74
+ /* Search form group */
75
+ [role="search"] {
76
+ display: flex;
77
+ }
78
+
79
+ [role="search"] > input[type="search"] {
80
+ flex: 1 1 auto;
81
+ }
82
+
83
+ [role="search"] > input[type="search"]:not(:only-child) {
84
+ border-radius: var(--radius-full) 0 0 var(--radius-full);
85
+ }
86
+
87
+ [role="search"] > [type="submit"],
88
+ [role="search"] > button {
89
+ border-radius: 0 var(--radius-full) var(--radius-full) 0;
90
+ margin-left: calc(var(--border-width) * -1);
91
+ }
92
+
93
+ /* Full width group */
94
+ [role="group"].full-width {
95
+ display: flex;
96
+ width: 100%;
97
+ }
98
+
99
+ /* Vertical group */
100
+ [role="group"].vertical {
101
+ flex-direction: column;
102
+ }
103
+
104
+ [role="group"].vertical > *:not(:first-child):not(:last-child) {
105
+ border-radius: 0;
106
+ }
107
+
108
+ [role="group"].vertical > *:first-child:not(:last-child) {
109
+ border-radius: var(--radius-md) var(--radius-md) 0 0;
110
+ }
111
+
112
+ [role="group"].vertical > *:last-child:not(:first-child) {
113
+ border-radius: 0 0 var(--radius-md) var(--radius-md);
114
+ }
115
+
116
+ [role="group"].vertical > *:not(:first-child) {
117
+ margin-left: 0;
118
+ margin-top: calc(var(--border-width) * -1);
119
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Loading/busy state styles
3
+ * Uses aria-busy attribute for semantic loading states
4
+ */
5
+
6
+ /* Loading spinner keyframes */
7
+ @keyframes spin {
8
+ to {
9
+ transform: rotate(360deg);
10
+ }
11
+ }
12
+
13
+ /* Base busy state - shows spinner */
14
+ [aria-busy="true"] {
15
+ position: relative;
16
+ pointer-events: none;
17
+ }
18
+
19
+ /* Spinner for empty elements (article, button without text, etc.) */
20
+ [aria-busy="true"]:empty::before,
21
+ button[aria-busy="true"]:not(:has(*))::before {
22
+ content: "";
23
+ display: block;
24
+ width: 1.5rem;
25
+ height: 1.5rem;
26
+ margin: var(--spacing) auto;
27
+ border: 2px solid var(--muted);
28
+ border-top-color: var(--primary);
29
+ border-radius: var(--radius-full);
30
+ animation: spin 0.75s linear infinite;
31
+ }
32
+
33
+ /* Inline spinner (before text) */
34
+ [aria-busy="true"]:not(:empty)::before {
35
+ content: "";
36
+ display: inline-block;
37
+ width: 1rem;
38
+ height: 1rem;
39
+ margin-right: var(--spacing-sm);
40
+ vertical-align: middle;
41
+ border: 2px solid currentColor;
42
+ border-top-color: transparent;
43
+ border-radius: var(--radius-full);
44
+ animation: spin 0.75s linear infinite;
45
+ opacity: 0.7;
46
+ }
47
+
48
+ /* Button loading state */
49
+ button[aria-busy="true"] {
50
+ cursor: wait;
51
+ opacity: 0.8;
52
+ }
53
+
54
+ button[aria-busy="true"]::before {
55
+ width: 1rem;
56
+ height: 1rem;
57
+ border-width: 2px;
58
+ margin-right: var(--spacing-sm);
59
+ }
60
+
61
+ /* Icon-only button loading */
62
+ button[aria-busy="true"][aria-label]::before {
63
+ margin-right: 0;
64
+ }
65
+
66
+ /* Article loading state (skeleton) */
67
+ article[aria-busy="true"] {
68
+ min-height: 10rem;
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ }
73
+
74
+ article[aria-busy="true"]::before {
75
+ width: 2rem;
76
+ height: 2rem;
77
+ margin: 0;
78
+ border-width: 3px;
79
+ }
80
+
81
+ /* Span/text loading state */
82
+ span[aria-busy="true"]::before,
83
+ p[aria-busy="true"]::before {
84
+ width: 0.875rem;
85
+ height: 0.875rem;
86
+ }
87
+
88
+ /* Table row loading */
89
+ tr[aria-busy="true"] {
90
+ opacity: 0.5;
91
+ }
92
+
93
+ /* Form loading state */
94
+ form[aria-busy="true"] {
95
+ opacity: 0.7;
96
+ }
97
+
98
+ form[aria-busy="true"]::before {
99
+ position: absolute;
100
+ top: 50%;
101
+ left: 50%;
102
+ transform: translate(-50%, -50%);
103
+ margin: 0;
104
+ }
105
+
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Modal/Dialog styles
3
+ * Supports both native <dialog> and Popover API for no-JS modals
4
+ *
5
+ * Popover usage (no JavaScript needed):
6
+ * <button popovertarget="my-modal">Open</button>
7
+ * <dialog id="my-modal" popover>
8
+ * <article>Content</article>
9
+ * </dialog>
10
+ */
11
+
12
+ /* Base dialog styles (shared by both approaches) */
13
+ dialog {
14
+ position: fixed;
15
+ inset: 0;
16
+ z-index: 100;
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ width: 100%;
21
+ max-width: 100%;
22
+ height: 100%;
23
+ max-height: 100%;
24
+ padding: var(--spacing);
25
+ background-color: transparent;
26
+ border: none;
27
+ overflow: auto;
28
+ }
29
+
30
+ dialog::backdrop {
31
+ background-color: var(--modal-overlay);
32
+ backdrop-filter: blur(4px);
33
+ }
34
+
35
+ dialog:not([open]):not(:popover-open) {
36
+ display: none;
37
+ }
38
+
39
+ /* Popover-based modal (no JS required) */
40
+ dialog[popover] {
41
+ margin: auto;
42
+ }
43
+
44
+ dialog[popover]:popover-open {
45
+ display: flex;
46
+ }
47
+
48
+ /* Modal content (article inside dialog) */
49
+ dialog > article {
50
+ position: relative;
51
+ width: 100%;
52
+ max-width: 32rem;
53
+ max-height: calc(100vh - var(--spacing-xl));
54
+ margin: 0;
55
+ padding: var(--spacing-lg);
56
+ overflow: auto;
57
+ background-color: var(--card);
58
+ border: var(--border-width) solid var(--border);
59
+ border-radius: var(--modal-radius);
60
+ box-shadow: var(--modal-shadow);
61
+ animation: modal-in var(--transition-slow) var(--ease-default);
62
+ }
63
+
64
+ @keyframes modal-in {
65
+ from {
66
+ opacity: 0;
67
+ transform: scale(0.95) translateY(-1rem);
68
+ }
69
+ to {
70
+ opacity: 1;
71
+ transform: scale(1) translateY(0);
72
+ }
73
+ }
74
+
75
+ /* Modal header */
76
+ dialog > article > header {
77
+ display: block;
78
+ padding: 0;
79
+ margin-bottom: var(--spacing-sm);
80
+ }
81
+
82
+ dialog > article > header > p {
83
+ margin: 0;
84
+ }
85
+
86
+ dialog > article > header > strong,
87
+ dialog > article > header > p > strong {
88
+ font-size: var(--text-lg);
89
+ font-weight: var(--font-semibold);
90
+ color: var(--foreground);
91
+ }
92
+
93
+ /* Close button - positioned at corner intersection */
94
+ dialog > article > button[aria-label="Close"],
95
+ dialog > article > header > button[aria-label="Close"],
96
+ dialog > article > button[rel="prev"],
97
+ dialog > article > header > button[rel="prev"] {
98
+ position: absolute;
99
+ top: var(--spacing);
100
+ right: var(--spacing);
101
+ width: 2rem;
102
+ height: 2rem;
103
+ padding: 0;
104
+ color: var(--muted-foreground);
105
+ background-color: transparent;
106
+ border: none;
107
+ border-radius: var(--radius-sm);
108
+ box-shadow: none;
109
+ cursor: pointer;
110
+ transition: background-color var(--transition-default),
111
+ color var(--transition-default);
112
+
113
+ &:hover {
114
+ background-color: var(--accent);
115
+ color: var(--accent-foreground);
116
+ }
117
+
118
+ &::before {
119
+ content: "✕";
120
+ font-size: var(--text-base);
121
+ }
122
+ }
123
+
124
+ /* Modal body */
125
+ dialog > article > p,
126
+ dialog > article > div {
127
+ padding: 0;
128
+ margin-bottom: var(--spacing-sm);
129
+ }
130
+
131
+ dialog > article > p:last-child,
132
+ dialog > article > div:last-child {
133
+ margin-bottom: 0;
134
+ }
135
+
136
+ /* Modal footer */
137
+ dialog > article > footer {
138
+ display: flex;
139
+ align-items: center;
140
+ justify-content: flex-end;
141
+ gap: var(--spacing-sm);
142
+ padding: 0;
143
+ margin-top: var(--spacing-sm);
144
+ }
145
+
146
+ /* Utility classes for HTML element (modal state) */
147
+ html.modal-is-open {
148
+ overflow: hidden;
149
+ pointer-events: none;
150
+ touch-action: none;
151
+ }
152
+
153
+ html.modal-is-open dialog {
154
+ pointer-events: auto;
155
+ }
156
+
157
+ /* Opening animation class */
158
+ html.modal-is-opening dialog > article {
159
+ animation: modal-in var(--transition-slow) var(--ease-default);
160
+ }
161
+
162
+ /* Closing animation class */
163
+ html.modal-is-closing dialog::backdrop {
164
+ animation: backdrop-out var(--transition-default) forwards;
165
+ }
166
+
167
+ html.modal-is-closing dialog > article {
168
+ animation: modal-out var(--transition-default) forwards;
169
+ }
170
+
171
+ @keyframes backdrop-out {
172
+ to {
173
+ opacity: 0;
174
+ }
175
+ }
176
+
177
+ @keyframes modal-out {
178
+ to {
179
+ opacity: 0;
180
+ transform: scale(0.95) translateY(-1rem);
181
+ }
182
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Navigation styles
3
+ * Horizontal nav bars, vertical nav, and breadcrumbs
4
+ */
5
+
6
+ nav {
7
+ display: flex;
8
+ flex-wrap: wrap;
9
+ align-items: center;
10
+ justify-content: space-between;
11
+ gap: var(--spacing);
12
+ }
13
+
14
+ nav > ul {
15
+ display: flex;
16
+ flex-wrap: wrap;
17
+ align-items: center;
18
+ gap: var(--spacing-xs);
19
+ margin: 0;
20
+ padding: 0;
21
+ list-style: none;
22
+ }
23
+
24
+ nav > ul > li {
25
+ margin: 0;
26
+ line-height: var(--line-height);
27
+ }
28
+
29
+ /* Nav links */
30
+ nav a {
31
+ display: inline-flex;
32
+ align-items: center;
33
+ padding: var(--spacing-sm) var(--spacing-md);
34
+ font-size: var(--text-sm);
35
+ font-weight: var(--font-medium);
36
+ color: var(--muted-foreground);
37
+ text-decoration: none;
38
+ border-radius: var(--radius-md);
39
+ transition: color var(--transition-default),
40
+ background-color var(--transition-default);
41
+
42
+ &:hover {
43
+ color: var(--foreground);
44
+ background-color: var(--muted);
45
+ }
46
+ }
47
+
48
+ /* Active page indicator */
49
+ nav a[aria-current="page"],
50
+ nav a[aria-current="true"] {
51
+ color: var(--foreground);
52
+ background-color: var(--muted);
53
+ }
54
+
55
+ /* Nav with strong (brand) */
56
+ nav strong {
57
+ font-size: var(--text-lg);
58
+ font-weight: var(--font-semibold);
59
+ color: var(--foreground);
60
+ }
61
+
62
+ /* Nav buttons */
63
+ nav button {
64
+ height: var(--button-height-sm);
65
+ font-size: var(--text-sm);
66
+ }
67
+
68
+ /* Dropdown in nav */
69
+ nav details.dropdown > summary {
70
+ height: auto;
71
+ padding: var(--spacing-sm) var(--spacing-md);
72
+ color: var(--muted-foreground);
73
+ background-color: transparent;
74
+ border: none;
75
+
76
+ &:hover {
77
+ color: var(--foreground);
78
+ background-color: var(--muted);
79
+ }
80
+ }
81
+
82
+ nav details.dropdown > ul {
83
+ right: 0;
84
+ }
85
+
86
+ /* Breadcrumb navigation */
87
+ nav[aria-label="breadcrumb"] > ul {
88
+ gap: 0;
89
+ }
90
+
91
+ nav[aria-label="breadcrumb"] > ul > li {
92
+ display: flex;
93
+ align-items: center;
94
+ }
95
+
96
+ nav[aria-label="breadcrumb"] > ul > li:not(:last-child)::after {
97
+ content: var(--breadcrumb-divider);
98
+ padding: 0 var(--spacing-sm);
99
+ color: var(--muted-foreground);
100
+ }
101
+
102
+ nav[aria-label="breadcrumb"] a {
103
+ padding: var(--spacing-xs) 0;
104
+ color: var(--muted-foreground);
105
+ background-color: transparent;
106
+ border-radius: 0;
107
+
108
+ &:hover {
109
+ color: var(--foreground);
110
+ background-color: transparent;
111
+ text-decoration: underline;
112
+ }
113
+ }
114
+
115
+ nav[aria-label="breadcrumb"] > ul > li:last-child {
116
+ color: var(--foreground);
117
+ font-weight: var(--font-medium);
118
+ }
119
+
120
+ /* Mobile-friendly nav (stacks on small screens) */
121
+ @media (max-width: 768px) {
122
+ nav {
123
+ flex-direction: column;
124
+ align-items: stretch;
125
+ }
126
+
127
+ nav > ul {
128
+ justify-content: center;
129
+ }
130
+ }
131
+
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Progress bar styles
3
+ */
4
+
5
+ progress {
6
+ display: block;
7
+ width: 100%;
8
+ height: var(--spacing-sm);
9
+ margin-bottom: var(--spacing-sm);
10
+ overflow: hidden;
11
+ background-color: var(--muted);
12
+ border: none;
13
+ border-radius: var(--progress-radius);
14
+ appearance: none;
15
+ }
16
+
17
+ progress:last-child {
18
+ margin-bottom: 0;
19
+ }
20
+
21
+ progress::-webkit-progress-bar {
22
+ background-color: var(--muted);
23
+ border-radius: var(--progress-radius);
24
+ }
25
+
26
+ progress::-webkit-progress-value {
27
+ background-color: var(--primary);
28
+ border-radius: var(--progress-radius);
29
+ transition: width var(--transition-slow) var(--ease-default);
30
+ }
31
+
32
+ progress::-moz-progress-bar {
33
+ background-color: var(--primary);
34
+ border-radius: var(--progress-radius);
35
+ }
36
+
37
+ /* Indeterminate progress */
38
+ progress:not([value]) {
39
+ position: relative;
40
+ background: linear-gradient(
41
+ 90deg,
42
+ var(--muted) 0%,
43
+ var(--muted) 40%,
44
+ var(--primary) 50%,
45
+ var(--muted) 60%,
46
+ var(--muted) 100%
47
+ );
48
+ background-size: 200% 100%;
49
+ animation: progress-indeterminate 1.5s linear infinite;
50
+ }
51
+
52
+ progress:not([value])::-webkit-progress-bar {
53
+ background: transparent;
54
+ }
55
+
56
+ progress:not([value])::-moz-progress-bar {
57
+ background: transparent;
58
+ }
59
+
60
+ @keyframes progress-indeterminate {
61
+ 0% {
62
+ background-position: 200% 0;
63
+ }
64
+ 100% {
65
+ background-position: -200% 0;
66
+ }
67
+ }
68
+
69
+ /* Secondary variant */
70
+ progress.secondary::-webkit-progress-value {
71
+ background-color: var(--muted-foreground);
72
+ }
73
+
74
+ progress.secondary::-moz-progress-bar {
75
+ background-color: var(--muted-foreground);
76
+ }
77
+
78
+ progress.secondary:not([value]) {
79
+ background: linear-gradient(
80
+ 90deg,
81
+ var(--muted) 0%,
82
+ var(--muted) 40%,
83
+ var(--muted-foreground) 50%,
84
+ var(--muted) 60%,
85
+ var(--muted) 100%
86
+ );
87
+ background-size: 200% 100%;
88
+ }
89
+
90
+ /* Success variant */
91
+ progress.success::-webkit-progress-value {
92
+ background-color: var(--success);
93
+ }
94
+
95
+ progress.success::-moz-progress-bar {
96
+ background-color: var(--success);
97
+ }
98
+
99
+ progress.success:not([value]) {
100
+ background: linear-gradient(
101
+ 90deg,
102
+ var(--muted) 0%,
103
+ var(--muted) 40%,
104
+ var(--success) 50%,
105
+ var(--muted) 60%,
106
+ var(--muted) 100%
107
+ );
108
+ background-size: 200% 100%;
109
+ }
110
+
111
+ /* Warning variant */
112
+ progress.warning::-webkit-progress-value {
113
+ background-color: var(--warning);
114
+ }
115
+
116
+ progress.warning::-moz-progress-bar {
117
+ background-color: var(--warning);
118
+ }
119
+
120
+ progress.warning:not([value]) {
121
+ background: linear-gradient(
122
+ 90deg,
123
+ var(--muted) 0%,
124
+ var(--muted) 40%,
125
+ var(--warning) 50%,
126
+ var(--muted) 60%,
127
+ var(--muted) 100%
128
+ );
129
+ background-size: 200% 100%;
130
+ }
131
+
132
+ /* Destructive variant */
133
+ progress.destructive::-webkit-progress-value {
134
+ background-color: var(--destructive);
135
+ }
136
+
137
+ progress.destructive::-moz-progress-bar {
138
+ background-color: var(--destructive);
139
+ }
140
+
141
+ progress.destructive:not([value]) {
142
+ background: linear-gradient(
143
+ 90deg,
144
+ var(--muted) 0%,
145
+ var(--muted) 40%,
146
+ var(--destructive) 50%,
147
+ var(--muted) 60%,
148
+ var(--muted) 100%
149
+ );
150
+ background-size: 200% 100%;
151
+ }
152
+
153
+ /* Label with progress */
154
+ label:has(> progress) {
155
+ display: block;
156
+
157
+ & > progress {
158
+ margin-top: var(--spacing-sm);
159
+ }
160
+ }