@kouji-ui/components 0.9.1 → 0.9.3

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.
Files changed (73) hide show
  1. package/fesm2022/kouji-ui-components.mjs +137 -65
  2. package/fesm2022/kouji-ui-components.mjs.map +1 -1
  3. package/package.json +1 -1
  4. package/src/accordion/accordion.css +68 -0
  5. package/src/action-sheet/action-sheet.css +79 -0
  6. package/src/alert/alert.css +133 -0
  7. package/src/avatar/avatar.css +93 -0
  8. package/src/badge/badge.css +59 -0
  9. package/src/breadcrumb/breadcrumb.css +145 -0
  10. package/src/button/button.css +295 -0
  11. package/src/button-group/button-group.css +114 -0
  12. package/src/calendar/calendar.css +129 -0
  13. package/src/card/card.css +120 -0
  14. package/src/carousel/carousel.css +181 -0
  15. package/src/cascade-select/cascade-select.css +120 -0
  16. package/src/chart/chart.css +26 -0
  17. package/src/chat/chat-ai.css +352 -0
  18. package/src/chat/chat.css +231 -0
  19. package/src/checkbox/checkbox.css +74 -0
  20. package/src/color-picker/color-picker.css +183 -0
  21. package/src/combobox/combobox.css +101 -0
  22. package/src/command-palette/command-palette.css +234 -0
  23. package/src/confirm-popup/confirm-popup.css +47 -0
  24. package/src/date-picker/date-picker.css +61 -0
  25. package/src/date-range-presets/date-range-presets.css +49 -0
  26. package/src/datetime-picker/datetime-picker.css +84 -0
  27. package/src/dialog/dialog.css +56 -0
  28. package/src/direction-toggle/direction-toggle.css +55 -0
  29. package/src/divider/divider.css +93 -0
  30. package/src/drawer/drawer.css +130 -0
  31. package/src/dropdown-menu/dropdown-menu.css +108 -0
  32. package/src/editor/editor.css +140 -0
  33. package/src/empty-state/empty-state.css +114 -0
  34. package/src/field/field.css +148 -0
  35. package/src/file-upload/file-upload.css +207 -0
  36. package/src/form/form.css +63 -0
  37. package/src/input/input.css +70 -0
  38. package/src/input-group/input-group.css +125 -0
  39. package/src/input-mask/input-mask.css +39 -0
  40. package/src/input-otp/input-otp.css +87 -0
  41. package/src/kbd/kbd.css +67 -0
  42. package/src/link/link.css +104 -0
  43. package/src/list/list.css +166 -0
  44. package/src/menubar/menubar.css +62 -0
  45. package/src/number-input/number-input.css +115 -0
  46. package/src/overflow/overflow.css +43 -0
  47. package/src/overlay/overlay.css +45 -0
  48. package/src/overlay-badge/overlay-badge.css +118 -0
  49. package/src/pagination/pagination.css +146 -0
  50. package/src/password-input/password-input.css +155 -0
  51. package/src/popover/popover.css +71 -0
  52. package/src/progress-bar/progress-bar.css +113 -0
  53. package/src/radio/radio.css +58 -0
  54. package/src/rich-text/rich-text-editor.css +351 -0
  55. package/src/select/select.css +91 -0
  56. package/src/sheet/sheet.css +121 -0
  57. package/src/skeleton/skeleton.css +111 -0
  58. package/src/skip-link/skip-link.css +58 -0
  59. package/src/slider/slider.css +172 -0
  60. package/src/speed-dial/speed-dial.css +137 -0
  61. package/src/spinner/spinner.css +161 -0
  62. package/src/stepper/stepper.css +147 -0
  63. package/src/table/table-filters/filters.css +53 -0
  64. package/src/table/table.css +509 -0
  65. package/src/tabs/tabs.css +162 -0
  66. package/src/tag/tag.css +183 -0
  67. package/src/textarea/textarea.css +117 -0
  68. package/src/time-picker/time-picker.css +126 -0
  69. package/src/toast/toast.css +115 -0
  70. package/src/toggle/toggle.css +123 -0
  71. package/src/tooltip/tooltip.css +61 -0
  72. package/src/tree-select/tree-select.css +220 -0
  73. package/types/kouji-ui-components.d.ts +17 -1
@@ -0,0 +1,234 @@
1
+ /* ── Command Palette (modal) ────────────────────────────────────────── */
2
+
3
+ /* Shell wraps backdrop + dialog. Always rendered for hydration stability;
4
+ the `is-open` modifier toggles visibility. */
5
+ .kj-command-palette__shell {
6
+ display: none;
7
+ }
8
+ .kj-command-palette__shell.is-open {
9
+ display: contents;
10
+ }
11
+
12
+ /* Backdrop covers the viewport behind the dialog. */
13
+ .kj-command-palette__backdrop {
14
+ position: fixed;
15
+ inset: 0;
16
+ background: rgba(0, 0, 0, 0.7);
17
+ backdrop-filter: blur(4px);
18
+ z-index: var(--kj-overlay-z, 1000);
19
+ animation: kj-command-palette-fade 0.1s ease-out;
20
+ }
21
+
22
+ /* The dialog panel itself — centered, fixed, animated in. */
23
+ .kj-command-palette__dialog {
24
+ position: fixed;
25
+ top: 15vh;
26
+ left: 50%;
27
+ transform: translateX(-50%);
28
+ width: min(640px, 92vw);
29
+ display: flex;
30
+ flex-direction: column;
31
+ background: var(--kj-bg-elevated);
32
+ border: 1px solid var(--kj-border-default);
33
+ z-index: calc(var(--kj-overlay-z, 1000) + 1);
34
+ overflow: hidden;
35
+ animation: kj-command-palette-slide 0.15s ease-out;
36
+ }
37
+
38
+ @keyframes kj-command-palette-fade {
39
+ from { opacity: 0; }
40
+ to { opacity: 1; }
41
+ }
42
+
43
+ @keyframes kj-command-palette-slide {
44
+ from { opacity: 0; transform: translateX(-50%) translateY(-8px); }
45
+ to { opacity: 1; transform: translateX(-50%) translateY(0); }
46
+ }
47
+
48
+ @media (prefers-reduced-motion: reduce) {
49
+ .kj-command-palette__backdrop,
50
+ .kj-command-palette__dialog {
51
+ animation: none;
52
+ }
53
+ }
54
+
55
+ /* ── Input wrapper ───────────────────────────────────────────────────── */
56
+
57
+ .kj-command-palette__input-wrapper {
58
+ display: flex;
59
+ align-items: center;
60
+ padding: 0.875rem var(--kj-space-lg, 1.25rem);
61
+ border-bottom: 1px solid var(--kj-border-default);
62
+ gap: var(--kj-space-md, 0.75rem);
63
+ }
64
+
65
+ .kj-command-palette__search-icon {
66
+ flex-shrink: 0;
67
+ width: 1rem;
68
+ height: 1rem;
69
+ color: var(--kj-fg-muted);
70
+ }
71
+
72
+ .kj-command-palette__input {
73
+ flex: 1;
74
+ border: none;
75
+ outline: none;
76
+ background: transparent;
77
+ font-family: var(--kj-font-mono);
78
+ font-size: 0.875rem;
79
+ color: var(--kj-fg-default);
80
+ appearance: none;
81
+ -webkit-appearance: none;
82
+ }
83
+
84
+ .kj-command-palette__input::placeholder {
85
+ color: var(--kj-fg-muted);
86
+ }
87
+
88
+ .kj-command-palette__input::-webkit-search-cancel-button {
89
+ display: none;
90
+ }
91
+
92
+ /* Standalone <kj-command-input> rendered outside the modal. */
93
+ .kj-command-input {
94
+ flex: 1;
95
+ border: none;
96
+ outline: none;
97
+ background: transparent;
98
+ font-family: var(--kj-font-mono);
99
+ font-size: 0.875rem;
100
+ color: var(--kj-fg-default);
101
+ appearance: none;
102
+ -webkit-appearance: none;
103
+ width: 100%;
104
+ padding: 0.875rem var(--kj-space-lg, 1.25rem);
105
+ }
106
+
107
+ /* ── ESC kbd badge in input wrapper ──────────────────────────────────── */
108
+
109
+ .kj-command-palette__esc-kbd {
110
+ font-family: var(--kj-font-mono);
111
+ font-size: 0.65rem;
112
+ color: var(--kj-fg-muted);
113
+ background: var(--kj-bg-surface);
114
+ border: 1px solid var(--kj-border-default);
115
+ padding: 0.15rem 0.4rem;
116
+ flex-shrink: 0;
117
+ cursor: pointer;
118
+ }
119
+
120
+ .kj-command-palette__esc-kbd:hover {
121
+ color: var(--kj-fg-default);
122
+ }
123
+
124
+ /* ── List ────────────────────────────────────────────────────────────── */
125
+
126
+ .kj-command-palette__list {
127
+ overflow-y: auto;
128
+ max-height: 22rem;
129
+ padding: var(--kj-space-sm, 0.375rem) 0;
130
+ }
131
+
132
+ /* ── Empty / hint state ──────────────────────────────────────────────── */
133
+
134
+ .kj-command-palette__empty,
135
+ .kj-command-empty {
136
+ padding: var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);
137
+ text-align: center;
138
+ font-family: var(--kj-font-mono);
139
+ font-size: 0.8rem;
140
+ color: var(--kj-fg-muted);
141
+ }
142
+
143
+ /* ── Command item ─────────────────────────────────────────────────────── */
144
+
145
+ .kj-command-item {
146
+ display: flex;
147
+ flex-direction: var(--kj-command-item-direction, row);
148
+ align-items: var(--kj-command-item-align, center);
149
+ gap: var(--kj-command-item-gap, var(--kj-space-md, 0.75rem));
150
+ width: 100%;
151
+ min-height: 2.75rem;
152
+ padding: 0.625rem var(--kj-space-lg, 1.25rem);
153
+ border: none;
154
+ border-inline-start: 2px solid transparent;
155
+ background: transparent;
156
+ font-family: var(--kj-font-mono);
157
+ font-size: 0.875rem;
158
+ color: var(--kj-fg-default);
159
+ text-align: start;
160
+ cursor: pointer;
161
+ transition: background 0.1s;
162
+ }
163
+
164
+ .kj-command-item:hover,
165
+ .kj-command-item[data-active] {
166
+ background: var(--kj-bg-surface);
167
+ border-inline-start-color: var(--kj-bg-primary);
168
+ }
169
+
170
+ .kj-command-item[aria-disabled="true"] {
171
+ opacity: 0.45;
172
+ cursor: not-allowed;
173
+ pointer-events: none;
174
+ }
175
+
176
+ /* ── Group ───────────────────────────────────────────────────────────── */
177
+
178
+ .kj-command-group {
179
+ padding-block: 0.25rem;
180
+ }
181
+
182
+ .kj-command-group__label {
183
+ padding: 0.375rem var(--kj-space-lg, 1.25rem) 0.125rem;
184
+ font-family: var(--kj-font-mono);
185
+ font-size: 0.6rem;
186
+ font-weight: 600;
187
+ color: var(--kj-fg-muted);
188
+ letter-spacing: 0.1em;
189
+ text-transform: uppercase;
190
+ }
191
+
192
+ /* ── Separator ───────────────────────────────────────────────────────── */
193
+
194
+ .kj-command-separator {
195
+ height: 1px;
196
+ background: var(--kj-border-default);
197
+ margin-block: 0.25rem;
198
+ }
199
+
200
+ /* ── Footer ──────────────────────────────────────────────────────────── */
201
+
202
+ .kj-command-palette__footer {
203
+ display: flex;
204
+ gap: var(--kj-space-xl, 1.5rem);
205
+ padding: var(--kj-space-sm, 0.375rem) var(--kj-space-lg, 1.25rem);
206
+ border-top: 1px solid var(--kj-border-default);
207
+ background: var(--kj-bg-surface);
208
+ }
209
+
210
+ .kj-command-palette__footer span {
211
+ display: flex;
212
+ align-items: center;
213
+ gap: 0.4rem;
214
+ font-family: var(--kj-font-mono);
215
+ font-size: 0.65rem;
216
+ color: var(--kj-fg-muted);
217
+ }
218
+
219
+ .kj-command-palette__footer kbd {
220
+ background: var(--kj-bg-surface);
221
+ border: 1px solid var(--kj-border-default);
222
+ color: var(--kj-fg-muted);
223
+ font-family: var(--kj-font-mono);
224
+ font-size: 0.6rem;
225
+ padding: 0.1rem 0.35rem;
226
+ }
227
+
228
+ /* ── Reduced motion ──────────────────────────────────────────────────── */
229
+
230
+ @media (prefers-reduced-motion: reduce) {
231
+ .kj-command-item {
232
+ transition: none;
233
+ }
234
+ }
@@ -0,0 +1,47 @@
1
+ @layer kj.component {
2
+ .kj-confirm-popup-content {
3
+ --kj-confirm-popup-bg: var(--kj-bg-elevated);
4
+ --kj-confirm-popup-fg: var(--kj-fg-default);
5
+ --kj-confirm-popup-border-color: var(--kj-border-default);
6
+ --kj-confirm-popup-radius: var(--kj-radius-box);
7
+ --kj-confirm-popup-padding-x: var(--kj-space-md);
8
+ --kj-confirm-popup-padding-y: var(--kj-space-md);
9
+ --kj-confirm-popup-shadow: var(--kj-shadow-md);
10
+
11
+ display: block;
12
+ box-sizing: border-box;
13
+ max-width: min(20rem, calc(100vw - 2rem));
14
+ background: var(--kj-confirm-popup-bg);
15
+ color: var(--kj-confirm-popup-fg);
16
+ border: var(--kj-border) solid var(--kj-confirm-popup-border-color);
17
+ border-radius: var(--kj-confirm-popup-radius);
18
+ padding: var(--kj-confirm-popup-padding-y) var(--kj-confirm-popup-padding-x);
19
+ font: 0.875rem / 1.5 var(--kj-font-sans);
20
+ box-shadow: var(--kj-confirm-popup-shadow);
21
+ pointer-events: auto;
22
+ z-index: var(--kj-overlay-z, 1000);
23
+ word-wrap: break-word;
24
+ }
25
+
26
+ .kj-confirm-popup-content[hidden] { display: none; }
27
+
28
+ .kj-confirm-popup-message {
29
+ display: block;
30
+ margin: 0 0 var(--kj-space-sm);
31
+ color: var(--kj-fg-default);
32
+ }
33
+
34
+ .kj-confirm-popup-actions {
35
+ display: flex;
36
+ justify-content: flex-end;
37
+ gap: var(--kj-space-sm);
38
+ }
39
+
40
+ @media (prefers-reduced-motion: no-preference) {
41
+ .kj-confirm-popup-content {
42
+ transition: opacity 140ms ease-out, transform 140ms ease-out;
43
+ }
44
+ .kj-confirm-popup-content[data-state="closed"] { opacity: 0; transform: scale(0.98); }
45
+ .kj-confirm-popup-content[data-state="open"] { opacity: 1; transform: scale(1); }
46
+ }
47
+ }
@@ -0,0 +1,61 @@
1
+ .kj-date-picker {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--kj-space-xs);
5
+ position: relative;
6
+ }
7
+
8
+ .kj-date-picker__input {
9
+ /* Explicit height contract (matches input.css / button.css) so the date
10
+ input lines up with sibling inputs in a form row. */
11
+ --kj-date-picker-input-height: 2.25rem;
12
+ appearance: none;
13
+ border: var(--kj-border) solid var(--kj-border-default);
14
+ border-radius: var(--kj-radius-field);
15
+ padding: 0 var(--kj-space-md);
16
+ height: var(--kj-date-picker-input-height);
17
+ font: inherit;
18
+ background: var(--kj-bg-field);
19
+ color: var(--kj-fg-default);
20
+ min-width: 12ch;
21
+ }
22
+ .kj-date-picker[data-size="xs"] .kj-date-picker__input { --kj-date-picker-input-height: 1.75rem; font-size: 0.75rem; padding-inline: var(--kj-space-sm); min-width: 0; }
23
+ .kj-date-picker[data-size="sm"] .kj-date-picker__input { --kj-date-picker-input-height: 2rem; font-size: 0.8125rem; }
24
+ .kj-date-picker[data-size="lg"] .kj-date-picker__input { --kj-date-picker-input-height: 2.75rem; font-size: 1rem; }
25
+
26
+ .kj-date-picker__input:focus {
27
+ outline: 2px solid var(--kj-border-focus);
28
+ outline-offset: 2px;
29
+ border-color: var(--kj-border-focus);
30
+ }
31
+
32
+ .kj-date-picker__input[disabled] {
33
+ opacity: 0.55;
34
+ cursor: not-allowed;
35
+ }
36
+
37
+ /* Panel owns the elevated surface chrome (bg, border, radius, shadow,
38
+ inset padding). The projected `.kj-calendar` stays chrome-less so it
39
+ reads as a flat grid inside the panel. */
40
+ .kj-date-picker__panel {
41
+ box-sizing: border-box;
42
+ z-index: var(--kj-overlay-z, 50);
43
+ display: inline-block;
44
+ background: var(--kj-bg-elevated);
45
+ color: var(--kj-fg-default);
46
+ border: var(--kj-border) solid var(--kj-border-default);
47
+ border-radius: var(--kj-radius-box);
48
+ box-shadow: var(--kj-shadow-md);
49
+ padding: var(--kj-space-sm);
50
+ }
51
+
52
+ /* When the calendar is projected into the panel it already gets padding
53
+ from above; collapse its own padding so the inner content lines up with
54
+ the panel's inset. */
55
+ .kj-date-picker__panel .kj-calendar {
56
+ padding: 0;
57
+ }
58
+
59
+ .kj-date-picker__panel[hidden] {
60
+ display: none;
61
+ }
@@ -0,0 +1,49 @@
1
+ .kj-date-range-presets {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 2px;
5
+ min-width: var(--kj-date-range-presets-min-width, 12rem);
6
+ padding: var(--kj-space-xs, 0.25rem);
7
+ background: var(--kj-bg-elevated, transparent);
8
+ border: var(--kj-border) solid var(--kj-border-subtle, transparent);
9
+ border-radius: var(--kj-radius-field, 0.375rem);
10
+ font-family: inherit;
11
+ font-size: 0.8125rem;
12
+ color: var(--kj-fg-default);
13
+ }
14
+
15
+ .kj-date-range-presets__option {
16
+ appearance: none;
17
+ display: flex;
18
+ align-items: center;
19
+ /* WCAG 2.5.5 — 44px target height. */
20
+ min-height: 44px;
21
+ padding: 0 var(--kj-space-md, 0.75rem);
22
+ background: transparent;
23
+ border: var(--kj-border) solid transparent;
24
+ border-radius: var(--kj-radius-field, 0.375rem);
25
+ color: inherit;
26
+ font: inherit;
27
+ text-align: start;
28
+ cursor: pointer;
29
+ }
30
+
31
+ .kj-date-range-presets__option:hover:not([disabled]) {
32
+ background: var(--kj-bg-field);
33
+ }
34
+
35
+ .kj-date-range-presets__option:focus-visible {
36
+ outline: 2px solid var(--kj-border-focus);
37
+ outline-offset: -2px;
38
+ }
39
+
40
+ .kj-date-range-presets__option[data-selected] {
41
+ background: var(--kj-bg-primary);
42
+ color: var(--kj-fg-on-primary);
43
+ font-weight: 600;
44
+ }
45
+
46
+ .kj-date-range-presets__option[disabled] {
47
+ opacity: 0.4;
48
+ cursor: not-allowed;
49
+ }
@@ -0,0 +1,84 @@
1
+ .kj-datetime-picker {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--kj-space-xs);
5
+ position: relative;
6
+ }
7
+
8
+ .kj-datetime-picker__input {
9
+ /* Explicit height contract (matches input.css / date-picker.css) so the
10
+ trigger lines up with sibling inputs in a form row. */
11
+ --kj-datetime-picker-input-height: 2.25rem;
12
+ appearance: none;
13
+ border: var(--kj-border) solid var(--kj-border-default);
14
+ border-radius: var(--kj-radius-field);
15
+ padding: 0 var(--kj-space-md);
16
+ height: var(--kj-datetime-picker-input-height);
17
+ font: inherit;
18
+ background: var(--kj-bg-field);
19
+ color: var(--kj-fg-default);
20
+ /* Size to the content ("12/05/2026 14:30" ≈ 16ch) instead of the browser's
21
+ 20-character default — the trigger shouldn't be wider than its text. */
22
+ width: 19ch;
23
+ min-width: 0;
24
+ }
25
+ .kj-datetime-picker[data-size="xs"] .kj-datetime-picker__input { --kj-datetime-picker-input-height: 1.75rem; font-size: 0.75rem; padding-inline: var(--kj-space-sm); min-width: 0; }
26
+ .kj-datetime-picker[data-size="sm"] .kj-datetime-picker__input { --kj-datetime-picker-input-height: 2rem; font-size: 0.8125rem; }
27
+ .kj-datetime-picker[data-size="lg"] .kj-datetime-picker__input { --kj-datetime-picker-input-height: 2.75rem; font-size: 1rem; }
28
+
29
+ .kj-datetime-picker__input:focus {
30
+ outline: 2px solid var(--kj-border-focus);
31
+ outline-offset: 2px;
32
+ border-color: var(--kj-border-focus);
33
+ }
34
+
35
+ .kj-datetime-picker__input[disabled] {
36
+ opacity: 0.55;
37
+ cursor: not-allowed;
38
+ }
39
+
40
+ /* Panel chrome mirrors the date-picker panel. */
41
+ .kj-datetime-picker__panel {
42
+ box-sizing: border-box;
43
+ z-index: var(--kj-overlay-z, 50);
44
+ display: inline-block;
45
+ background: var(--kj-bg-elevated);
46
+ color: var(--kj-fg-default);
47
+ border: var(--kj-border) solid var(--kj-border-default);
48
+ border-radius: var(--kj-radius-box);
49
+ box-shadow: var(--kj-shadow-md);
50
+ padding: var(--kj-space-sm);
51
+ }
52
+ .kj-datetime-picker__panel .kj-calendar {
53
+ padding: 0;
54
+ }
55
+ .kj-datetime-picker__panel[hidden] {
56
+ display: none;
57
+ }
58
+
59
+ /* Time row under the calendar. */
60
+ .kj-datetime-picker__time {
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: space-between;
64
+ gap: var(--kj-space-sm);
65
+ margin-top: var(--kj-space-sm);
66
+ padding: var(--kj-space-sm) var(--kj-space-xs) 0;
67
+ border-top: var(--kj-border) solid var(--kj-border-muted);
68
+ font-size: 0.8125rem;
69
+ color: var(--kj-fg-muted);
70
+ }
71
+ .kj-datetime-picker__time-input {
72
+ appearance: none;
73
+ border: var(--kj-border) solid var(--kj-border-default);
74
+ border-radius: var(--kj-radius-field);
75
+ background: var(--kj-bg-field);
76
+ color: var(--kj-fg-default);
77
+ font: inherit;
78
+ font-size: 0.8125rem;
79
+ padding: 2px var(--kj-space-sm);
80
+ }
81
+ .kj-datetime-picker__time-input:focus {
82
+ outline: 2px solid var(--kj-border-focus);
83
+ outline-offset: 1px;
84
+ }
@@ -0,0 +1,56 @@
1
+ @layer kj.component {
2
+ .kj-dialog-overlay {
3
+ position: fixed;
4
+ inset: 0;
5
+ background: rgb(0 0 0 / 0.5);
6
+ display: flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ z-index: var(--kj-overlay-z, 1000);
10
+ }
11
+ .kj-dialog {
12
+ display: flex;
13
+ flex-direction: column;
14
+ background: var(--kj-bg-elevated);
15
+ color: var(--kj-fg-default);
16
+ border-radius: var(--kj-radius-box);
17
+ box-shadow: var(--kj-shadow-lg);
18
+ min-width: 24rem;
19
+ max-width: min(40rem, calc(100vw - 2rem));
20
+ max-height: calc(100vh - 4rem);
21
+ overflow: hidden;
22
+ padding: var(--kj-space-xl);
23
+ }
24
+ .kj-dialog-header {
25
+ display: flex;
26
+ align-items: center;
27
+ justify-content: flex-start;
28
+ padding: var(--kj-space-lg) var(--kj-space-xl);
29
+ border-bottom: var(--kj-border) solid var(--kj-border-muted);
30
+ }
31
+ .kj-dialog-header[data-align="center"] { justify-content: center; }
32
+ .kj-dialog-title {
33
+ display: block;
34
+ margin: 0;
35
+ font: 600 1.125rem / 1.3 var(--kj-font-sans);
36
+ color: var(--kj-fg-default);
37
+ }
38
+ .kj-dialog-body {
39
+ flex: 1;
40
+ color: var(--kj-fg-default);
41
+ font: 0.9375rem / 1.5 var(--kj-font-sans);
42
+ }
43
+ .kj-dialog-body[data-padded] { padding: var(--kj-space-lg) var(--kj-space-xl); }
44
+ .kj-dialog-body[data-scroll] { overflow-y: auto; }
45
+ .kj-dialog-footer {
46
+ display: flex;
47
+ align-items: center;
48
+ gap: var(--kj-space-sm);
49
+ padding: var(--kj-space-lg) var(--kj-space-xl);
50
+ border-top: var(--kj-border) solid var(--kj-border-muted);
51
+ }
52
+ .kj-dialog-footer[data-align="start"] { justify-content: flex-start; }
53
+ .kj-dialog-footer[data-align="center"] { justify-content: center; }
54
+ .kj-dialog-footer[data-align="end"] { justify-content: flex-end; }
55
+ .kj-dialog-footer[data-align="between"] { justify-content: space-between; }
56
+ }
@@ -0,0 +1,55 @@
1
+ /* ─────────────────────────────────────────────────────────────
2
+ .kj-direction-toggle — accessible LTR/RTL toggle button.
3
+ Tokens default to shared-layer values from @kouji-ui/themes so
4
+ the control blends with the active theme; consumers can override
5
+ any --kj-direction-toggle-* knob.
6
+ ──────────────────────────────────────────────────────────── */
7
+
8
+ @layer kj.component {
9
+ .kj-direction-toggle {
10
+ --kj-direction-toggle-bg: var(--kj-bg-subtle, transparent);
11
+ --kj-direction-toggle-fg: var(--kj-fg, currentColor);
12
+ --kj-direction-toggle-border-color: var(--kj-border-color, currentColor);
13
+ --kj-direction-toggle-radius: var(--kj-radius-field, 0.5rem);
14
+ --kj-direction-toggle-padding-x: var(--kj-space-md, 0.75rem);
15
+ --kj-direction-toggle-padding-y: var(--kj-space-sm, 0.5rem);
16
+
17
+ /* WCAG 2.5.5 — reserve a 44×44 hit area regardless of label size. */
18
+ display: inline-flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ gap: var(--kj-space-xs, 0.25rem);
22
+ min-width: 44px;
23
+ min-height: 44px;
24
+ padding-block: var(--kj-direction-toggle-padding-y);
25
+ padding-inline: var(--kj-direction-toggle-padding-x);
26
+
27
+ background: var(--kj-direction-toggle-bg);
28
+ color: var(--kj-direction-toggle-fg);
29
+ border: var(--kj-border, 1px) solid var(--kj-direction-toggle-border-color);
30
+ border-radius: var(--kj-direction-toggle-radius);
31
+ font: inherit;
32
+ font-size: var(--kj-text-sm, 0.875rem);
33
+ line-height: 1;
34
+ cursor: pointer;
35
+ user-select: none;
36
+ }
37
+
38
+ .kj-direction-toggle:hover {
39
+ background: var(--kj-bg-subtle-hover, var(--kj-direction-toggle-bg));
40
+ }
41
+
42
+ /* Focus ring only for keyboard users. */
43
+ .kj-direction-toggle:focus-visible {
44
+ outline: var(--kj-focus-ring-width, 2px) solid
45
+ var(--kj-focus-ring-color, currentColor);
46
+ outline-offset: 2px;
47
+ }
48
+
49
+ /* Pressed = RTL active. */
50
+ .kj-direction-toggle[aria-pressed='true'] {
51
+ background: var(--kj-bg-primary, var(--kj-direction-toggle-bg));
52
+ color: var(--kj-fg-on-primary, var(--kj-direction-toggle-fg));
53
+ border-color: var(--kj-bg-primary, var(--kj-direction-toggle-border-color));
54
+ }
55
+ }
@@ -0,0 +1,93 @@
1
+ @layer kj.component {
2
+ .kj-divider {
3
+ --kj-divider-color: var(--kj-border-default, color-mix(in oklch, var(--kj-fg-default) 20%, transparent));
4
+ --kj-divider-thickness: 1px;
5
+ --kj-divider-spacing: var(--kj-space-md, 1rem);
6
+ --kj-divider-gap: var(--kj-space-md, 1rem);
7
+
8
+ border: 0;
9
+ color: inherit;
10
+ }
11
+
12
+ /* Rule-only (the <hr> branch and any <div> with no projected label). */
13
+ .kj-divider[data-with-content="false"] {
14
+ block-size: var(--kj-divider-thickness);
15
+ inline-size: 100%;
16
+ margin-block: var(--kj-divider-spacing);
17
+ background-color: var(--kj-divider-color);
18
+ }
19
+
20
+ /* Vertical, rule-only — flips the axis using logical sizing. */
21
+ .kj-divider[data-with-content="false"][data-orientation="vertical"] {
22
+ inline-size: var(--kj-divider-thickness);
23
+ block-size: auto;
24
+ align-self: stretch;
25
+ margin-block: 0;
26
+ margin-inline: var(--kj-divider-spacing);
27
+ }
28
+
29
+ /* With-content (label nestled into the rule). */
30
+ .kj-divider[data-with-content="true"] {
31
+ display: flex;
32
+ align-items: center;
33
+ gap: var(--kj-divider-gap);
34
+ margin-block: var(--kj-divider-spacing);
35
+ }
36
+
37
+ .kj-divider[data-with-content="true"][data-orientation="vertical"] {
38
+ flex-direction: column;
39
+ block-size: 100%;
40
+ margin-block: 0;
41
+ margin-inline: var(--kj-divider-spacing);
42
+ }
43
+
44
+ .kj-divider[data-with-content="true"]::before,
45
+ .kj-divider[data-with-content="true"]::after {
46
+ content: "";
47
+ flex: 1 1 0;
48
+ background-color: var(--kj-divider-color);
49
+ block-size: var(--kj-divider-thickness);
50
+ }
51
+
52
+ .kj-divider[data-with-content="true"][data-orientation="vertical"]::before,
53
+ .kj-divider[data-with-content="true"][data-orientation="vertical"]::after {
54
+ inline-size: var(--kj-divider-thickness);
55
+ block-size: auto;
56
+ }
57
+
58
+ /* Alignment of the projected label within the rule. */
59
+ .kj-divider[data-with-content="true"][data-align="start"]::before { flex-grow: 0; flex-basis: 1rem; }
60
+ .kj-divider[data-with-content="true"][data-align="end"]::after { flex-grow: 0; flex-basis: 1rem; }
61
+
62
+ /* Variant routing — line style. */
63
+ .kj-divider[data-variant="dashed"][data-with-content="false"] {
64
+ background-color: transparent;
65
+ border-block-start: var(--kj-divider-thickness) dashed var(--kj-divider-color);
66
+ block-size: 0;
67
+ }
68
+ .kj-divider[data-variant="dashed"][data-with-content="false"][data-orientation="vertical"] {
69
+ border-block-start: 0;
70
+ border-inline-start: var(--kj-divider-thickness) dashed var(--kj-divider-color);
71
+ inline-size: 0;
72
+ }
73
+ .kj-divider[data-variant="dotted"][data-with-content="false"] {
74
+ background-color: transparent;
75
+ border-block-start: var(--kj-divider-thickness) dotted var(--kj-divider-color);
76
+ block-size: 0;
77
+ }
78
+ .kj-divider[data-variant="dotted"][data-with-content="false"][data-orientation="vertical"] {
79
+ border-block-start: 0;
80
+ border-inline-start: var(--kj-divider-thickness) dotted var(--kj-divider-color);
81
+ inline-size: 0;
82
+ }
83
+
84
+ /* Size routing — spacing + thickness. */
85
+ .kj-divider[data-size="sm"] { --kj-divider-spacing: var(--kj-space-sm, 0.5rem); --kj-divider-thickness: 1px; }
86
+ .kj-divider[data-size="lg"] { --kj-divider-spacing: var(--kj-space-lg, 2rem); --kj-divider-thickness: 2px; }
87
+
88
+ .kj-divider__content {
89
+ color: var(--kj-fg-default);
90
+ font: inherit;
91
+ white-space: nowrap;
92
+ }
93
+ }