@kouji-ui/components 0.9.2 → 0.9.4
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/fesm2022/kouji-ui-components.mjs +49 -3
- package/fesm2022/kouji-ui-components.mjs.map +1 -1
- package/package.json +1 -1
- package/src/accordion/accordion.css +68 -0
- package/src/action-sheet/action-sheet.css +79 -0
- package/src/alert/alert.css +133 -0
- package/src/avatar/avatar.css +93 -0
- package/src/badge/badge.css +59 -0
- package/src/breadcrumb/breadcrumb.css +145 -0
- package/src/button/button.css +295 -0
- package/src/button-group/button-group.css +114 -0
- package/src/calendar/calendar.css +129 -0
- package/src/card/card.css +120 -0
- package/src/carousel/carousel.css +181 -0
- package/src/cascade-select/cascade-select.css +120 -0
- package/src/chart/chart.css +26 -0
- package/src/chat/chat-ai.css +352 -0
- package/src/chat/chat.css +231 -0
- package/src/checkbox/checkbox.css +74 -0
- package/src/color-picker/color-picker.css +183 -0
- package/src/combobox/combobox.css +101 -0
- package/src/command-palette/command-palette.css +234 -0
- package/src/confirm-popup/confirm-popup.css +47 -0
- package/src/date-picker/date-picker.css +61 -0
- package/src/date-range-presets/date-range-presets.css +49 -0
- package/src/datetime-picker/datetime-picker.css +84 -0
- package/src/dialog/dialog.css +56 -0
- package/src/direction-toggle/direction-toggle.css +55 -0
- package/src/divider/divider.css +93 -0
- package/src/drawer/drawer.css +130 -0
- package/src/dropdown-menu/dropdown-menu.css +108 -0
- package/src/editor/editor.css +140 -0
- package/src/empty-state/empty-state.css +114 -0
- package/src/field/field.css +148 -0
- package/src/file-upload/file-upload.css +207 -0
- package/src/form/form.css +63 -0
- package/src/input/input.css +70 -0
- package/src/input-group/input-group.css +125 -0
- package/src/input-mask/input-mask.css +39 -0
- package/src/input-otp/input-otp.css +87 -0
- package/src/kbd/kbd.css +67 -0
- package/src/link/link.css +104 -0
- package/src/list/list.css +166 -0
- package/src/menubar/menubar.css +62 -0
- package/src/number-input/number-input.css +115 -0
- package/src/overflow/overflow.css +43 -0
- package/src/overlay/overlay.css +45 -0
- package/src/overlay-badge/overlay-badge.css +118 -0
- package/src/pagination/pagination.css +146 -0
- package/src/password-input/password-input.css +155 -0
- package/src/popover/popover.css +71 -0
- package/src/progress-bar/progress-bar.css +113 -0
- package/src/radio/radio.css +58 -0
- package/src/rich-text/rich-text-editor.css +351 -0
- package/src/select/select.css +91 -0
- package/src/sheet/sheet.css +121 -0
- package/src/skeleton/skeleton.css +111 -0
- package/src/skip-link/skip-link.css +58 -0
- package/src/slider/slider.css +172 -0
- package/src/speed-dial/speed-dial.css +137 -0
- package/src/spinner/spinner.css +161 -0
- package/src/stepper/stepper.css +147 -0
- package/src/table/table-filters/filters.css +53 -0
- package/src/table/table.css +509 -0
- package/src/tabs/tabs.css +162 -0
- package/src/tag/tag.css +183 -0
- package/src/textarea/textarea.css +117 -0
- package/src/time-picker/time-picker.css +126 -0
- package/src/toast/toast.css +115 -0
- package/src/toggle/toggle.css +123 -0
- package/src/tooltip/tooltip.css +61 -0
- package/src/tree-select/tree-select.css +220 -0
- package/types/kouji-ui-components.d.ts +19 -0
package/package.json
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
@layer kj.component {
|
|
2
|
+
.kj-accordion {
|
|
3
|
+
--kj-accordion-bg: var(--kj-bg-body);
|
|
4
|
+
--kj-accordion-border: var(--kj-border-default);
|
|
5
|
+
--kj-accordion-radius: var(--kj-radius-box);
|
|
6
|
+
|
|
7
|
+
display: block;
|
|
8
|
+
background: var(--kj-accordion-bg);
|
|
9
|
+
border: var(--kj-border) solid var(--kj-accordion-border);
|
|
10
|
+
border-radius: var(--kj-accordion-radius);
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.kj-accordion-item { display: block; }
|
|
15
|
+
.kj-accordion-item + .kj-accordion-item { border-top: var(--kj-border) solid var(--kj-accordion-border); }
|
|
16
|
+
|
|
17
|
+
.kj-accordion-trigger {
|
|
18
|
+
width: 100%;
|
|
19
|
+
text-align: left;
|
|
20
|
+
background: none;
|
|
21
|
+
border: 0;
|
|
22
|
+
padding: var(--kj-space-md) var(--kj-space-lg);
|
|
23
|
+
color: var(--kj-fg-default);
|
|
24
|
+
font: 0.875rem / 1.4 var(--kj-font-sans);
|
|
25
|
+
font-weight: 600;
|
|
26
|
+
cursor: pointer;
|
|
27
|
+
display: flex;
|
|
28
|
+
justify-content: space-between;
|
|
29
|
+
align-items: center;
|
|
30
|
+
}
|
|
31
|
+
.kj-accordion-trigger::after {
|
|
32
|
+
content: '▾';
|
|
33
|
+
transition: transform 0.15s;
|
|
34
|
+
}
|
|
35
|
+
.kj-accordion-trigger[aria-expanded="true"]::after { transform: rotate(180deg); }
|
|
36
|
+
.kj-accordion-trigger:focus-visible { outline: 2px solid var(--kj-border-focus); outline-offset: -2px; }
|
|
37
|
+
.kj-accordion-trigger[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
|
|
38
|
+
|
|
39
|
+
/* Always in the DOM so open/close can animate; visual state is driven by
|
|
40
|
+
`[data-state]` from the headless directive. `overflow: hidden` clips the
|
|
41
|
+
content during the max-height transition so children don't bleed out. */
|
|
42
|
+
.kj-accordion-content {
|
|
43
|
+
color: var(--kj-fg-default);
|
|
44
|
+
font: 0.875rem / 1.5 var(--kj-font-sans);
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
max-height: 0;
|
|
47
|
+
opacity: 0;
|
|
48
|
+
/* `padding` participates in the height transition — collapses to 0 when
|
|
49
|
+
closed so the panel reads as fully hidden. */
|
|
50
|
+
padding: 0 var(--kj-space-lg);
|
|
51
|
+
transition:
|
|
52
|
+
max-height var(--kj-transition, 0.2s ease),
|
|
53
|
+
opacity var(--kj-transition, 0.2s ease),
|
|
54
|
+
padding var(--kj-transition, 0.2s ease);
|
|
55
|
+
}
|
|
56
|
+
.kj-accordion-content[data-state="open"] {
|
|
57
|
+
/* `1000px` is the conventional "tall enough" ceiling for height tweens
|
|
58
|
+
on content of unknown size. If panels routinely exceed this, raise the
|
|
59
|
+
value — the cost is only a slightly slower expand animation. */
|
|
60
|
+
max-height: 1000px;
|
|
61
|
+
opacity: 1;
|
|
62
|
+
padding: 0 var(--kj-space-lg) var(--kj-space-md);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@media (prefers-reduced-motion: reduce) {
|
|
66
|
+
.kj-accordion-content { transition: none; }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
@layer kj.component {
|
|
2
|
+
.kj-action-sheet__title {
|
|
3
|
+
margin: 0 0 var(--kj-space-xs);
|
|
4
|
+
font: 600 1.0625rem / 1.3 var(--kj-font-sans);
|
|
5
|
+
color: var(--kj-fg-default);
|
|
6
|
+
text-align: center;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.kj-action-sheet__description {
|
|
10
|
+
margin: 0 0 var(--kj-space-md);
|
|
11
|
+
font: 0.875rem / 1.4 var(--kj-font-sans);
|
|
12
|
+
color: var(--kj-fg-muted);
|
|
13
|
+
text-align: center;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.kj-action-sheet__list {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
gap: var(--kj-space-2xs, 0.25rem);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.kj-action-sheet__item,
|
|
23
|
+
.kj-action-sheet__cancel {
|
|
24
|
+
appearance: none;
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
gap: var(--kj-space-sm);
|
|
28
|
+
width: 100%;
|
|
29
|
+
min-height: 44px;
|
|
30
|
+
padding: var(--kj-space-sm) var(--kj-space-md);
|
|
31
|
+
border: 0;
|
|
32
|
+
border-radius: var(--kj-radius-md, 0.5rem);
|
|
33
|
+
background: var(--kj-bg-subtle, transparent);
|
|
34
|
+
color: var(--kj-fg-default);
|
|
35
|
+
font: 500 0.9375rem / 1.4 var(--kj-font-sans);
|
|
36
|
+
text-align: left;
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.kj-action-sheet__item:hover:not(:disabled),
|
|
41
|
+
.kj-action-sheet__cancel:hover {
|
|
42
|
+
background: var(--kj-bg-muted, var(--kj-border-muted));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.kj-action-sheet__item:focus-visible,
|
|
46
|
+
.kj-action-sheet__cancel:focus-visible {
|
|
47
|
+
outline: var(--kj-focus-ring-width, 2px) solid var(--kj-focus-ring-color, var(--kj-primary));
|
|
48
|
+
outline-offset: 2px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.kj-action-sheet__item:disabled {
|
|
52
|
+
opacity: 0.5;
|
|
53
|
+
cursor: not-allowed;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.kj-action-sheet__item.is-destructive {
|
|
57
|
+
color: var(--kj-danger-fg, var(--kj-danger, #d92d20));
|
|
58
|
+
}
|
|
59
|
+
.kj-action-sheet__item.is-destructive:hover:not(:disabled) {
|
|
60
|
+
background: var(--kj-danger-bg-subtle, color-mix(in srgb, var(--kj-danger, #d92d20) 12%, transparent));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.kj-action-sheet__icon {
|
|
64
|
+
flex-shrink: 0;
|
|
65
|
+
width: 1.25rem;
|
|
66
|
+
height: 1.25rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.kj-action-sheet__label {
|
|
70
|
+
flex: 1;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.kj-action-sheet__cancel {
|
|
74
|
+
justify-content: center;
|
|
75
|
+
margin-top: var(--kj-space-sm);
|
|
76
|
+
font-weight: 600;
|
|
77
|
+
background: var(--kj-bg-muted, var(--kj-border-muted));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
@layer kj.component {
|
|
2
|
+
.kj-alert {
|
|
3
|
+
/* component knobs — themes/users override any of these */
|
|
4
|
+
--kj-alert-bg: var(--kj-bg-body);
|
|
5
|
+
--kj-alert-fg: var(--kj-fg-default);
|
|
6
|
+
--kj-alert-border-color: var(--kj-border-default);
|
|
7
|
+
--kj-alert-accent: var(--kj-fg-info);
|
|
8
|
+
--kj-alert-radius: var(--kj-radius-box, 0.5rem);
|
|
9
|
+
--kj-alert-padding-x: var(--kj-space-lg, 1rem);
|
|
10
|
+
--kj-alert-padding-y: var(--kj-space-md, 0.75rem);
|
|
11
|
+
--kj-alert-gap: var(--kj-space-md, 0.75rem);
|
|
12
|
+
--kj-alert-font-size: var(--kj-text-sm, 0.875rem);
|
|
13
|
+
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: flex-start;
|
|
16
|
+
gap: var(--kj-alert-gap);
|
|
17
|
+
background: var(--kj-alert-bg);
|
|
18
|
+
color: var(--kj-alert-fg);
|
|
19
|
+
border: var(--kj-border, 1px) solid var(--kj-alert-border-color);
|
|
20
|
+
border-left: 4px solid var(--kj-alert-accent);
|
|
21
|
+
border-radius: var(--kj-alert-radius);
|
|
22
|
+
padding: var(--kj-alert-padding-y) var(--kj-alert-padding-x);
|
|
23
|
+
font: var(--kj-alert-font-size) / 1.45 var(--kj-font-sans, sans-serif);
|
|
24
|
+
transition: opacity 200ms ease, transform 200ms ease;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.kj-alert[data-dismissed="true"] {
|
|
28
|
+
opacity: 0;
|
|
29
|
+
transform: translateY(-4px);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Severity variants — flip accent + (optionally) bg/fg. */
|
|
33
|
+
.kj-alert[data-variant="info"] { --kj-alert-accent: var(--kj-fg-info, #2563eb); }
|
|
34
|
+
.kj-alert[data-variant="success"] { --kj-alert-accent: var(--kj-fg-success, #16a34a); }
|
|
35
|
+
.kj-alert[data-variant="warning"] { --kj-alert-accent: var(--kj-fg-warning, #d97706); }
|
|
36
|
+
.kj-alert[data-variant="error"] { --kj-alert-accent: var(--kj-fg-danger, #dc2626); }
|
|
37
|
+
.kj-alert[data-variant="neutral"] { --kj-alert-accent: var(--kj-fg-muted, #6b7280); }
|
|
38
|
+
|
|
39
|
+
/* Static / banner mode — span full width, sticky-friendly chrome. */
|
|
40
|
+
.kj-alert[data-mode="static"] {
|
|
41
|
+
border-left-width: var(--kj-border, 1px);
|
|
42
|
+
border-top: 4px solid var(--kj-alert-accent);
|
|
43
|
+
border-radius: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Sizes */
|
|
47
|
+
.kj-alert[data-size="sm"] {
|
|
48
|
+
--kj-alert-padding-x: var(--kj-space-md, 0.75rem);
|
|
49
|
+
--kj-alert-padding-y: var(--kj-space-sm, 0.5rem);
|
|
50
|
+
--kj-alert-font-size: 0.8125rem;
|
|
51
|
+
}
|
|
52
|
+
.kj-alert[data-size="lg"] {
|
|
53
|
+
--kj-alert-padding-x: var(--kj-space-xl, 1.25rem);
|
|
54
|
+
--kj-alert-padding-y: var(--kj-space-lg, 1rem);
|
|
55
|
+
--kj-alert-font-size: 1rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* ── Body wrapper ─────────────────────────────────────────────── */
|
|
59
|
+
.kj-alert__body {
|
|
60
|
+
flex: 1 1 auto;
|
|
61
|
+
min-width: 0;
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
gap: 0.25rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* ── Title / Description ──────────────────────────────────────── */
|
|
68
|
+
.kj-alert__title {
|
|
69
|
+
margin: 0;
|
|
70
|
+
font-weight: 600;
|
|
71
|
+
font-size: 1em;
|
|
72
|
+
color: var(--kj-alert-accent);
|
|
73
|
+
line-height: 1.3;
|
|
74
|
+
}
|
|
75
|
+
.kj-alert__description {
|
|
76
|
+
margin: 0;
|
|
77
|
+
color: var(--kj-alert-fg);
|
|
78
|
+
opacity: 0.9;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* ── Icon ─────────────────────────────────────────────────────── */
|
|
82
|
+
.kj-alert__icon {
|
|
83
|
+
flex: 0 0 auto;
|
|
84
|
+
display: inline-flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
justify-content: center;
|
|
87
|
+
width: 1.25em;
|
|
88
|
+
height: 1.25em;
|
|
89
|
+
color: var(--kj-alert-accent);
|
|
90
|
+
margin-top: 0.1em;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* ── Actions ──────────────────────────────────────────────────── */
|
|
94
|
+
.kj-alert__actions {
|
|
95
|
+
flex: 0 0 auto;
|
|
96
|
+
display: inline-flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
gap: var(--kj-space-sm, 0.5rem);
|
|
99
|
+
margin-left: auto;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* ── Dismiss ──────────────────────────────────────────────────── */
|
|
103
|
+
.kj-alert__dismiss {
|
|
104
|
+
flex: 0 0 auto;
|
|
105
|
+
appearance: none;
|
|
106
|
+
background: transparent;
|
|
107
|
+
border: 0;
|
|
108
|
+
color: inherit;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
padding: 4px 8px;
|
|
111
|
+
border-radius: 4px;
|
|
112
|
+
line-height: 1;
|
|
113
|
+
font-size: 1.1rem;
|
|
114
|
+
opacity: 0.7;
|
|
115
|
+
margin-left: auto;
|
|
116
|
+
/* Touch-target floor (WCAG 2.5.5) */
|
|
117
|
+
min-width: 2.75rem;
|
|
118
|
+
min-height: 2.75rem;
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
justify-content: center;
|
|
122
|
+
}
|
|
123
|
+
.kj-alert__dismiss:hover { opacity: 1; background: rgb(0 0 0 / 0.06); }
|
|
124
|
+
.kj-alert__dismiss:focus-visible {
|
|
125
|
+
outline: 2px solid var(--kj-alert-accent);
|
|
126
|
+
outline-offset: 2px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* When actions and dismiss coexist, dismiss should not push actions away. */
|
|
130
|
+
.kj-alert__actions + .kj-alert__dismiss {
|
|
131
|
+
margin-left: 0;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
@layer kj.component {
|
|
2
|
+
.kj-avatar {
|
|
3
|
+
--kj-avatar-size: 2.5rem;
|
|
4
|
+
--kj-avatar-bg: var(--kj-bg-field);
|
|
5
|
+
--kj-avatar-fg: var(--kj-fg-default);
|
|
6
|
+
--kj-avatar-radius: 9999px;
|
|
7
|
+
|
|
8
|
+
position: relative;
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: center;
|
|
12
|
+
width: var(--kj-avatar-size);
|
|
13
|
+
height: var(--kj-avatar-size);
|
|
14
|
+
background: var(--kj-avatar-bg);
|
|
15
|
+
color: var(--kj-avatar-fg);
|
|
16
|
+
border-radius: var(--kj-avatar-radius);
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
font: 0.875rem / 1 var(--kj-font-sans);
|
|
19
|
+
font-weight: 600;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* `rounded` reads `--kj-radius-box-lg` (1rem default, declared in
|
|
23
|
+
`kj.base`) rather than `--kj-radius-box` because some themes (kouji,
|
|
24
|
+
bauhaus) set `--kj-radius-box` to 0 as a brutalist signature — falling
|
|
25
|
+
back to that would make `rounded` and `circle` look identical on those
|
|
26
|
+
themes. `--kj-radius-box-lg` stays unset by theme overrides, so the
|
|
27
|
+
toggle always produces a visible shape change. */
|
|
28
|
+
.kj-avatar[data-shape='rounded'] {
|
|
29
|
+
--kj-avatar-radius: var(--kj-radius-box-lg);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* The host's `[hidden]` attribute (written by the avatar-group when a
|
|
33
|
+
child overflows `kjMax`) needs an explicit `display: none` because the
|
|
34
|
+
`inline-flex` declaration above wins against the UA `[hidden] { display:
|
|
35
|
+
none }` rule via selector specificity. Without this, "hidden" overflow
|
|
36
|
+
avatars still render and `kjMax` looks broken. */
|
|
37
|
+
.kj-avatar[hidden] {
|
|
38
|
+
display: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* The "+N" chip is a native button wrapping the +N avatar: no chrome of
|
|
42
|
+
its own, the avatar paints; the open state tints the avatar. */
|
|
43
|
+
.kj-avatar-group-overflow-trigger {
|
|
44
|
+
display: inline-flex;
|
|
45
|
+
padding: 0;
|
|
46
|
+
border: 0;
|
|
47
|
+
background: none;
|
|
48
|
+
border-radius: 9999px;
|
|
49
|
+
}
|
|
50
|
+
.kj-avatar-group-overflow-trigger[aria-expanded='true'] .kj-avatar {
|
|
51
|
+
--kj-avatar-bg: var(--kj-bg-primary);
|
|
52
|
+
--kj-avatar-fg: var(--kj-fg-on-primary);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.kj-avatar[data-size='xs'] {
|
|
56
|
+
--kj-avatar-size: 1.5rem;
|
|
57
|
+
font-size: 0.6875rem;
|
|
58
|
+
}
|
|
59
|
+
.kj-avatar[data-size='sm'] {
|
|
60
|
+
--kj-avatar-size: 2rem;
|
|
61
|
+
font-size: 0.75rem;
|
|
62
|
+
}
|
|
63
|
+
.kj-avatar[data-size='lg'] {
|
|
64
|
+
--kj-avatar-size: 3rem;
|
|
65
|
+
font-size: 1rem;
|
|
66
|
+
}
|
|
67
|
+
.kj-avatar[data-size='xl'] {
|
|
68
|
+
--kj-avatar-size: 4rem;
|
|
69
|
+
font-size: 1.25rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.kj-avatar-image {
|
|
73
|
+
width: 100%;
|
|
74
|
+
height: 100%;
|
|
75
|
+
object-fit: cover;
|
|
76
|
+
display: block;
|
|
77
|
+
}
|
|
78
|
+
.kj-avatar-image:not([data-loaded]) {
|
|
79
|
+
opacity: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.kj-avatar-fallback {
|
|
83
|
+
position: absolute;
|
|
84
|
+
inset: 0;
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
}
|
|
89
|
+
.kj-avatar-fallback:not([data-visible]) {
|
|
90
|
+
opacity: 0;
|
|
91
|
+
pointer-events: none;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
@layer kj.component {
|
|
2
|
+
.kj-badge {
|
|
3
|
+
--kj-badge-bg: var(--kj-bg-primary);
|
|
4
|
+
--kj-badge-fg: var(--kj-fg-on-primary);
|
|
5
|
+
--kj-badge-border-color: transparent;
|
|
6
|
+
--kj-badge-radius: var(--kj-radius-selector);
|
|
7
|
+
--kj-badge-padding-x: var(--kj-space-sm);
|
|
8
|
+
--kj-badge-padding-y: 0.125rem;
|
|
9
|
+
--kj-badge-font-size: 0.75rem;
|
|
10
|
+
--kj-badge-dot-size: 0.375rem;
|
|
11
|
+
--kj-badge-dot-color: currentColor;
|
|
12
|
+
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: 0.25rem;
|
|
16
|
+
background: var(--kj-badge-bg);
|
|
17
|
+
color: var(--kj-badge-fg);
|
|
18
|
+
border: var(--kj-border) solid var(--kj-badge-border-color);
|
|
19
|
+
border-radius: var(--kj-badge-radius);
|
|
20
|
+
padding: var(--kj-badge-padding-y) var(--kj-badge-padding-x);
|
|
21
|
+
font: var(--kj-badge-font-size) / 1 var(--kj-font-sans);
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.kj-badge[data-dot]::before {
|
|
26
|
+
content: "";
|
|
27
|
+
flex: none;
|
|
28
|
+
width: var(--kj-badge-dot-size);
|
|
29
|
+
height: var(--kj-badge-dot-size);
|
|
30
|
+
border-radius: 50%;
|
|
31
|
+
background: var(--kj-badge-dot-color);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.kj-badge[data-variant="secondary"] {
|
|
35
|
+
--kj-badge-bg: var(--kj-bg-surface);
|
|
36
|
+
--kj-badge-fg: var(--kj-fg-default);
|
|
37
|
+
}
|
|
38
|
+
.kj-badge[data-variant="destructive"] {
|
|
39
|
+
--kj-badge-bg: var(--kj-bg-danger);
|
|
40
|
+
--kj-badge-fg: var(--kj-fg-on-danger);
|
|
41
|
+
}
|
|
42
|
+
.kj-badge[data-variant="outline"] {
|
|
43
|
+
--kj-badge-bg: transparent;
|
|
44
|
+
--kj-badge-fg: var(--kj-fg-default);
|
|
45
|
+
--kj-badge-border-color: var(--kj-border-default);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.kj-badge[data-size="xs"] {
|
|
49
|
+
--kj-badge-padding-x: 0.1875rem;
|
|
50
|
+
--kj-badge-padding-y: 0.03125rem;
|
|
51
|
+
--kj-badge-font-size: 0.5625rem;
|
|
52
|
+
}
|
|
53
|
+
.kj-badge[data-size="sm"] {
|
|
54
|
+
--kj-badge-padding-x: 0.375rem;
|
|
55
|
+
--kj-badge-padding-y: 0.125rem;
|
|
56
|
+
--kj-badge-font-size: 0.6875rem;
|
|
57
|
+
}
|
|
58
|
+
.kj-badge[data-size="lg"] { --kj-badge-padding-x: var(--kj-space-md); --kj-badge-font-size: 0.875rem; }
|
|
59
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/* ─────────────────────────────────────────────────────────────
|
|
2
|
+
.kj-breadcrumb — component-layer tokens + structural CSS
|
|
3
|
+
Tokens default to shared-layer values from @kouji-ui/themes.
|
|
4
|
+
The component owns its own gap, separator content, and per-cell
|
|
5
|
+
colours; the per-crumb anchor inherits Link's tokens by default.
|
|
6
|
+
──────────────────────────────────────────────────────────── */
|
|
7
|
+
|
|
8
|
+
@layer kj.component {
|
|
9
|
+
.kj-breadcrumb {
|
|
10
|
+
/* component knobs — themes / users can override any of these */
|
|
11
|
+
--kj-breadcrumb-gap: var(--kj-space-sm, 0.5rem);
|
|
12
|
+
--kj-breadcrumb-separator-content: '/';
|
|
13
|
+
--kj-breadcrumb-overflow-pad: 0.25rem;
|
|
14
|
+
--kj-color-breadcrumb-muted: var(--kj-fg-muted);
|
|
15
|
+
--kj-color-breadcrumb-current: var(--kj-fg-default);
|
|
16
|
+
|
|
17
|
+
display: block;
|
|
18
|
+
color: var(--kj-color-breadcrumb-muted);
|
|
19
|
+
font-size: 0.875rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* ── Sizes (root) ───────────────────────────────────────────── */
|
|
23
|
+
.kj-breadcrumb[data-size="sm"] { font-size: 0.8125rem; }
|
|
24
|
+
.kj-breadcrumb[data-size="md"] { font-size: 0.875rem; }
|
|
25
|
+
.kj-breadcrumb[data-size="lg"] { font-size: 1rem; }
|
|
26
|
+
|
|
27
|
+
/* ── Ordered list ───────────────────────────────────────────── */
|
|
28
|
+
.kj-breadcrumb-list {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
flex-wrap: nowrap;
|
|
32
|
+
gap: var(--kj-breadcrumb-gap);
|
|
33
|
+
margin: 0;
|
|
34
|
+
padding: 0;
|
|
35
|
+
list-style: none;
|
|
36
|
+
min-width: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.kj-breadcrumb-list[data-wrap="wrap"] { flex-wrap: wrap; }
|
|
40
|
+
.kj-breadcrumb-list[data-wrap="no-wrap"] { flex-wrap: nowrap; }
|
|
41
|
+
.kj-breadcrumb-list[data-wrap="truncate"] { flex-wrap: nowrap; }
|
|
42
|
+
|
|
43
|
+
/* ── Item ───────────────────────────────────────────────────── */
|
|
44
|
+
.kj-breadcrumb-item {
|
|
45
|
+
display: inline-flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: var(--kj-breadcrumb-gap);
|
|
48
|
+
min-width: 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.kj-breadcrumb-item[data-hidden] { display: none; }
|
|
52
|
+
|
|
53
|
+
/* ── Auto separator (CSS pseudo-element) ────────────────────── */
|
|
54
|
+
.kj-breadcrumb-list:not([data-explicit-separators]) > .kj-breadcrumb-item:not(:first-child)::before {
|
|
55
|
+
content: var(--kj-breadcrumb-separator-content, '/');
|
|
56
|
+
color: var(--kj-color-breadcrumb-muted);
|
|
57
|
+
opacity: 0.65;
|
|
58
|
+
user-select: none;
|
|
59
|
+
margin-inline-end: var(--kj-breadcrumb-gap);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* RTL mirroring: chevron-like glyphs flip; slashes stay. The data-attr
|
|
63
|
+
is set by the consumer when they want mirroring; we ship the rule. */
|
|
64
|
+
[dir="rtl"] .kj-breadcrumb-list:not([data-explicit-separators]) > .kj-breadcrumb-item:not(:first-child)::before {
|
|
65
|
+
/* No-op for '/'. For '›' / '→' the consumer adds [data-mirror-separator]. */
|
|
66
|
+
}
|
|
67
|
+
[dir="rtl"] .kj-breadcrumb[data-mirror-separator] .kj-breadcrumb-list:not([data-explicit-separators]) > .kj-breadcrumb-item:not(:first-child)::before {
|
|
68
|
+
display: inline-block;
|
|
69
|
+
transform: scaleX(-1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* ── Explicit separator ─────────────────────────────────────── */
|
|
73
|
+
.kj-breadcrumb-separator {
|
|
74
|
+
display: inline-flex;
|
|
75
|
+
align-items: center;
|
|
76
|
+
color: var(--kj-color-breadcrumb-muted);
|
|
77
|
+
opacity: 0.65;
|
|
78
|
+
user-select: none;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* ── Per-crumb link ─────────────────────────────────────────────
|
|
82
|
+
Owns its resting colour. The anchor carries `.kj-link`, but the
|
|
83
|
+
KjLink *component* (which ships link.css) may not be on the page,
|
|
84
|
+
so those rules aren't guaranteed to load — without an explicit
|
|
85
|
+
colour the anchor falls back to the UA default blue in every theme.
|
|
86
|
+
Retargeting the Link tokens keeps styling consistent when link.css
|
|
87
|
+
*is* present. */
|
|
88
|
+
.kj-breadcrumb-link {
|
|
89
|
+
--kj-link-fg: var(--kj-color-breadcrumb-muted);
|
|
90
|
+
--kj-link-hover-fg: var(--kj-color-breadcrumb-current);
|
|
91
|
+
color: var(--kj-link-fg);
|
|
92
|
+
text-decoration: none;
|
|
93
|
+
padding-block: 0.5rem; /* hit-area extension for WCAG 2.5.5 */
|
|
94
|
+
transition: color var(--kj-transition, 0.15s ease);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.kj-breadcrumb-link:hover {
|
|
98
|
+
color: var(--kj-link-hover-fg);
|
|
99
|
+
text-decoration: underline;
|
|
100
|
+
text-underline-offset: 3px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Self-contained focus ring — link.css may not be loaded (see above),
|
|
104
|
+
so don't depend on `.kj-link:focus-visible` for WCAG 2.4.7. */
|
|
105
|
+
.kj-breadcrumb-link:focus-visible {
|
|
106
|
+
outline: 2px solid var(--kj-fg-primary);
|
|
107
|
+
outline-offset: 2px;
|
|
108
|
+
border-radius: var(--kj-radius-field, 0.25rem);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* ── Current cell ───────────────────────────────────────────── */
|
|
112
|
+
.kj-breadcrumb-current {
|
|
113
|
+
color: var(--kj-color-breadcrumb-current);
|
|
114
|
+
font-weight: 500;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* ── Ellipsis cell ──────────────────────────────────────────── */
|
|
118
|
+
.kj-breadcrumb-ellipsis {
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
justify-content: center;
|
|
122
|
+
min-width: 1.5rem;
|
|
123
|
+
padding-inline: var(--kj-breadcrumb-overflow-pad);
|
|
124
|
+
color: var(--kj-color-breadcrumb-muted);
|
|
125
|
+
background: transparent;
|
|
126
|
+
border: 0;
|
|
127
|
+
cursor: default;
|
|
128
|
+
user-select: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.kj-breadcrumb-ellipsis[data-overflow="menu"] {
|
|
132
|
+
cursor: pointer;
|
|
133
|
+
border-radius: var(--kj-radius-field, 0.25rem);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.kj-breadcrumb-ellipsis[data-overflow="menu"]:hover {
|
|
137
|
+
background: var(--kj-bg-surface, transparent);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* ── Print: show the full breadcrumb ────────────────────────── */
|
|
141
|
+
@media print {
|
|
142
|
+
.kj-breadcrumb-item[data-hidden] { display: revert; }
|
|
143
|
+
.kj-breadcrumb-ellipsis { display: none; }
|
|
144
|
+
}
|
|
145
|
+
}
|