@ctrl-ui/react 0.9.4 → 0.9.5
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/README.md +27 -0
- package/dist/blocks/coding-agent.js +1 -4
- package/dist/blocks/file-explorer.js +14 -16
- package/dist/lib/cn.d.ts +2 -0
- package/dist/lib/cn.js +29 -24
- package/dist/styles/recipes/button-states.css +12 -0
- package/dist/styles/recipes/button.css +1 -1
- package/dist/styles/recipes/chat-composer-attachment.css +7 -0
- package/dist/styles/recipes/color-picker-details.css +7 -0
- package/dist/styles/recipes/field.css +7 -0
- package/dist/styles/recipes/inline-attachment.css +7 -0
- package/dist/styles/recipes/kbd.css +7 -0
- package/dist/styles/recipes/pagination.css +8 -1
- package/dist/styles/recipes/scroll-area.css +1 -3
- package/dist/styles/recipes/tabs.css +12 -0
- package/dist/styles/type-scale.css +2 -1
- package/dist/ui/sidebar.js +1 -1
- package/dist/ui/typography.d.ts +2 -0
- package/dist/ui/typography.js +2 -0
- package/lint/no-raw-type-classes.grit +7 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -26,6 +26,33 @@ import { Button } from "@ctrl-ui/react/ui/button";
|
|
|
26
26
|
|
|
27
27
|
Import paths mirror the registry tree. To ship less CSS, import `styles/theme.css` and only the recipes and effects your components use.
|
|
28
28
|
|
|
29
|
+
## Text and class names
|
|
30
|
+
|
|
31
|
+
Render text with `Text` and `Heading`. Size, tone, and weight are props; `className` carries layout only:
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { Text } from "@ctrl-ui/react/ui/typography";
|
|
35
|
+
|
|
36
|
+
<Text size="caption" tone="muted">Saved</Text>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Merge class names with the package's `cn`. A bare `twMerge` reads `text-micro` as a text color and silently drops it next to `text-muted-foreground`. Add your own type rungs on top of `withControlUiMerge` instead of starting a second merger:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { withControlUiMerge } from "@ctrl-ui/react/lib/cn";
|
|
43
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
44
|
+
|
|
45
|
+
const twMerge = extendTailwindMerge({ extend: { classGroups: { "font-size": [{ text: ["hero"] }] } } }, withControlUiMerge);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Controls size their own text: pick the control's `size`, or set its `--cui-*-font-size` knob in your theme, rather than wrapping the label in a `text-*` span.
|
|
49
|
+
|
|
50
|
+
With Biome, the shipped GritQL plugin warns on type rungs in `className`:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{ "plugins": ["./node_modules/@ctrl-ui/react/lint/no-raw-type-classes.grit"] }
|
|
54
|
+
```
|
|
55
|
+
|
|
29
56
|
## Customize
|
|
30
57
|
|
|
31
58
|
Your application owns its theme. Override the library's neutral defaults in your CSS:
|
|
@@ -182,10 +182,7 @@ function CodingAgentSidebar({ appName, brand, sidebarTop, navigation, projects,
|
|
|
182
182
|
}, project.id))
|
|
183
183
|
})]
|
|
184
184
|
})] }),
|
|
185
|
-
sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, {
|
|
186
|
-
className: "border-t border-sidebar-border",
|
|
187
|
-
children: sidebarFooter
|
|
188
|
-
}) : null,
|
|
185
|
+
sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, { children: sidebarFooter }) : null,
|
|
189
186
|
/* @__PURE__ */ jsx(SidebarRail, {})
|
|
190
187
|
]
|
|
191
188
|
});
|
|
@@ -147,7 +147,7 @@ function FileExplorerSidebar({ locations, activeLocationId, sidebarTop, sidebarF
|
|
|
147
147
|
collapsible: "offcanvas",
|
|
148
148
|
children: [
|
|
149
149
|
sidebarTop ? /* @__PURE__ */ jsx(SidebarHeader, {
|
|
150
|
-
className: "min-h-11 justify-center
|
|
150
|
+
className: "min-h-11 justify-center px-3",
|
|
151
151
|
children: sidebarTop
|
|
152
152
|
}) : null,
|
|
153
153
|
/* @__PURE__ */ jsx(SidebarContent, { children: groups.map((group) => /* @__PURE__ */ jsxs(SidebarGroup, { children: [group.label ? /* @__PURE__ */ jsx(SidebarGroupLabel, { children: group.label }) : null, /* @__PURE__ */ jsx(SidebarMenu, { children: group.items.map((location) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(SidebarMenuButton, {
|
|
@@ -159,24 +159,22 @@ function FileExplorerSidebar({ locations, activeLocationId, sidebarTop, sidebarF
|
|
|
159
159
|
},
|
|
160
160
|
children: [location.icon ?? /* @__PURE__ */ jsx(FolderIcon, {}), /* @__PURE__ */ jsx("span", { children: location.label })]
|
|
161
161
|
}) }, location.id)) })] }, group.label || "locations")) }),
|
|
162
|
-
sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, {
|
|
163
|
-
className: "border-t border-sidebar-border",
|
|
164
|
-
children: sidebarFooter
|
|
165
|
-
}) : null,
|
|
162
|
+
sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, { children: sidebarFooter }) : null,
|
|
166
163
|
/* @__PURE__ */ jsx(SidebarRail, {})
|
|
167
164
|
]
|
|
168
165
|
});
|
|
169
166
|
}
|
|
170
167
|
function FileExplorerHeader({ location, headingLevel, breadcrumbs, query, searchPlaceholder, searchLabel, clearSearchLabel, backLabel, moreActionsLabel, canGoBack, headerActions, headerMenuItems, onBack, onBreadcrumbSelect, onQueryChange }) {
|
|
171
168
|
return /* @__PURE__ */ jsxs("header", {
|
|
172
|
-
className: "shrink-0 border-b border-border/70
|
|
169
|
+
className: "shrink-0 border-b border-border/70",
|
|
173
170
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
174
171
|
className: "flex h-12 items-center gap-2 px-3",
|
|
175
172
|
children: [
|
|
176
|
-
/* @__PURE__ */ jsx(SidebarTrigger, { size: "
|
|
173
|
+
/* @__PURE__ */ jsx(SidebarTrigger, { size: "sm" }),
|
|
177
174
|
/* @__PURE__ */ jsx(Button, {
|
|
178
175
|
variant: "ghost",
|
|
179
|
-
size: "
|
|
176
|
+
size: "sm",
|
|
177
|
+
iconOnly: true,
|
|
180
178
|
className: "hidden @xl/explorer:inline-flex",
|
|
181
179
|
disabled: !canGoBack,
|
|
182
180
|
"aria-label": backLabel,
|
|
@@ -200,7 +198,7 @@ function FileExplorerHeader({ location, headingLevel, breadcrumbs, query, search
|
|
|
200
198
|
}) : null,
|
|
201
199
|
headerMenuItems ? /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
202
200
|
variant: "ghost",
|
|
203
|
-
size: "
|
|
201
|
+
size: "sm",
|
|
204
202
|
iconOnly: true,
|
|
205
203
|
"aria-label": moreActionsLabel,
|
|
206
204
|
className: headerActions ? "@2xl/explorer:hidden" : void 0,
|
|
@@ -214,7 +212,7 @@ function FileExplorerHeader({ location, headingLevel, breadcrumbs, query, search
|
|
|
214
212
|
})] }) : null,
|
|
215
213
|
searchPlaceholder ? /* @__PURE__ */ jsxs(InputGroup, {
|
|
216
214
|
size: "sm",
|
|
217
|
-
className: "flex-[0_1_9rem]
|
|
215
|
+
className: "flex-[0_1_9rem] @xl/explorer:flex-[0_0_12rem]",
|
|
218
216
|
children: [
|
|
219
217
|
/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
220
218
|
className: "ps-2",
|
|
@@ -408,7 +406,7 @@ function FileExplorerColumns({ columns, selectedEntry, selectedPath, headingLeve
|
|
|
408
406
|
})
|
|
409
407
|
}) }) : null })] })]
|
|
410
408
|
}), /* @__PURE__ */ jsx("div", {
|
|
411
|
-
className: "min-h-0 flex-1
|
|
409
|
+
className: "min-h-0 flex-1",
|
|
412
410
|
children: activeColumn ? renderColumn(activeColumn, activeIndex, "narrow") : null
|
|
413
411
|
})] }) : null
|
|
414
412
|
}), /* @__PURE__ */ jsx("div", {
|
|
@@ -416,7 +414,7 @@ function FileExplorerColumns({ columns, selectedEntry, selectedPath, headingLeve
|
|
|
416
414
|
className: "hidden h-full min-h-0 @xl/explorer:block",
|
|
417
415
|
children: wideDisplayed ? /* @__PURE__ */ jsxs(ResizablePanelGroup, {
|
|
418
416
|
orientation: "horizontal",
|
|
419
|
-
|
|
417
|
+
variant: "nested",
|
|
420
418
|
children: [columns.map((column, columnIndex) => /* @__PURE__ */ jsx(FileExplorerPanel, {
|
|
421
419
|
defaultSize: columnSize,
|
|
422
420
|
minSize: "16%",
|
|
@@ -531,7 +529,7 @@ function FileExplorerColumnView({ column, optionRef, onSelect, onOpen, onOptionK
|
|
|
531
529
|
}
|
|
532
530
|
function FileExplorerPreview({ entry, headingLevel }) {
|
|
533
531
|
if (!entry) return /* @__PURE__ */ jsx(Empty, {
|
|
534
|
-
className: "h-full rounded-none
|
|
532
|
+
className: "h-full rounded-none",
|
|
535
533
|
children: /* @__PURE__ */ jsxs(EmptyHeader, { children: [
|
|
536
534
|
/* @__PURE__ */ jsx(EmptyMedia, { children: /* @__PURE__ */ jsx(FileIcon, {}) }),
|
|
537
535
|
/* @__PURE__ */ jsx(EmptyTitle, { children: "Select an item" }),
|
|
@@ -539,7 +537,7 @@ function FileExplorerPreview({ entry, headingLevel }) {
|
|
|
539
537
|
] })
|
|
540
538
|
});
|
|
541
539
|
return /* @__PURE__ */ jsx(ScrollArea, {
|
|
542
|
-
className: "h-full
|
|
540
|
+
className: "h-full",
|
|
543
541
|
lockAxis: "x",
|
|
544
542
|
children: /* @__PURE__ */ jsx(FileExplorerPreviewContent, {
|
|
545
543
|
entry,
|
|
@@ -681,7 +679,7 @@ function FileExplorerStatusBar({ breadcrumbs, selectedEntry }) {
|
|
|
681
679
|
const itemCount = selectedEntry?.children?.length ?? 0;
|
|
682
680
|
const itemLabel = itemCount === 1 ? "1 item" : `${itemCount} items`;
|
|
683
681
|
return /* @__PURE__ */ jsxs("footer", {
|
|
684
|
-
className: "flex h-8 shrink-0 items-center gap-3 border-t border-border/70
|
|
682
|
+
className: "flex h-8 shrink-0 items-center gap-3 border-t border-border/70 px-3 text-micro text-muted-foreground",
|
|
685
683
|
children: [/* @__PURE__ */ jsx("span", {
|
|
686
684
|
className: "min-w-0 flex-1 truncate",
|
|
687
685
|
title: path,
|
|
@@ -695,7 +693,7 @@ function FileExplorerStatusBar({ breadcrumbs, selectedEntry }) {
|
|
|
695
693
|
function FileExplorerAddressBar({ breadcrumbs, onSelect }) {
|
|
696
694
|
return /* @__PURE__ */ jsx(Breadcrumb, {
|
|
697
695
|
"aria-label": "Current folder",
|
|
698
|
-
className: "min-w-0 overflow-hidden
|
|
696
|
+
className: "min-w-0 overflow-hidden px-1",
|
|
699
697
|
children: /* @__PURE__ */ jsx(BreadcrumbList, {
|
|
700
698
|
className: "min-w-0 flex-nowrap overflow-hidden",
|
|
701
699
|
children: breadcrumbs.map((breadcrumb, index) => {
|
package/dist/lib/cn.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ClassValue } from "clsx";
|
|
2
|
+
import { Config } from "tailwind-merge";
|
|
2
3
|
//#region src/lib/cn.d.ts
|
|
4
|
+
export declare function withControlUiMerge(config: Config<string, string>): Config<string, string>;
|
|
3
5
|
export declare function cn(...inputs: ClassValue[]): string;
|
|
4
6
|
//#endregion
|
package/dist/lib/cn.js
CHANGED
|
@@ -1,30 +1,35 @@
|
|
|
1
1
|
import { clsx } from "clsx";
|
|
2
|
-
import { extendTailwindMerge } from "tailwind-merge";
|
|
2
|
+
import { extendTailwindMerge, mergeConfigs } from "tailwind-merge";
|
|
3
3
|
//#region src/lib/cn.ts
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
4
|
+
const textScale = [
|
|
5
|
+
"micro",
|
|
6
|
+
"caption",
|
|
7
|
+
"label",
|
|
8
|
+
"body",
|
|
9
|
+
"body-lg",
|
|
10
|
+
"heading-1",
|
|
11
|
+
"heading-2",
|
|
12
|
+
"heading-3",
|
|
13
|
+
"heading-4",
|
|
14
|
+
"display"
|
|
15
|
+
];
|
|
16
|
+
const shadowScale = [
|
|
17
|
+
"pop",
|
|
18
|
+
"soft",
|
|
19
|
+
"modal"
|
|
20
|
+
];
|
|
21
|
+
function withControlUiMerge(config) {
|
|
22
|
+
return mergeConfigs(config, {
|
|
23
|
+
extend: { classGroups: {
|
|
24
|
+
"font-size": [{ text: textScale }],
|
|
25
|
+
shadow: [{ shadow: shadowScale }]
|
|
26
|
+
} },
|
|
27
|
+
override: { conflictingClassGroups: { "font-size": [] } }
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const twMerge = extendTailwindMerge(withControlUiMerge);
|
|
26
31
|
function cn(...inputs) {
|
|
27
32
|
return twMerge(clsx(inputs));
|
|
28
33
|
}
|
|
29
34
|
//#endregion
|
|
30
|
-
export { cn };
|
|
35
|
+
export { cn, withControlUiMerge };
|
|
@@ -63,4 +63,16 @@
|
|
|
63
63
|
cursor: not-allowed;
|
|
64
64
|
opacity: var(--disabled-opacity);
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
@media (forced-colors: active) {
|
|
68
|
+
:where([data-control-family="button"][data-control="true"]:not(:focus-visible, :has(:focus-visible))) {
|
|
69
|
+
outline: 1px solid currentColor;
|
|
70
|
+
outline-offset: -1px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:where([data-control-family="button"][data-control="true"][data-active="true"]:not(:focus-visible, :has(:focus-visible))) {
|
|
74
|
+
outline: var(--focus-ring-width) solid Highlight;
|
|
75
|
+
outline-offset: calc(var(--focus-ring-width) * -1);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
66
78
|
}
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
--cui-button-shadow: inset 0 0 0 var(--control-rim-width) var(--control-rim), var(--shadow-sm);
|
|
165
165
|
--cui-button-active-background: oklch(from var(--primary) l c h / 0.08);
|
|
166
166
|
--cui-button-active-foreground: var(--primary-text);
|
|
167
|
-
--cui-button-active-shadow: inset 0 0 0
|
|
167
|
+
--cui-button-active-shadow: inset 0 0 0 var(--control-rim-width) oklch(from var(--primary) l c h / 0.6), var(--shadow-sm);
|
|
168
168
|
--cui-button-active-hover-background: oklch(from var(--primary) l c h / 0.1);
|
|
169
169
|
}
|
|
170
170
|
|
|
@@ -25,6 +25,13 @@
|
|
|
25
25
|
transition-timing-function: var(--ease-standard);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
@media (forced-colors: active) {
|
|
29
|
+
:where([data-control-family="chat-composer-attachment"][data-slot="root"][data-variant]:not(:focus-visible, :has(:focus-visible))) {
|
|
30
|
+
outline: 1px solid CanvasText;
|
|
31
|
+
outline-offset: -1px;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
:where([data-control-family="chat-composer-attachment"][data-slot="list"]) {
|
|
29
36
|
gap: calc(var(--spacing) * 2);
|
|
30
37
|
padding: var(--cui-chat-composer-attachment-list-padding);
|
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
box-shadow: var(--cui-color-picker-trigger-shadow);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
@media (forced-colors: active) {
|
|
9
|
+
:where([data-control-family="color-picker"][data-slot="trigger-color"]) {
|
|
10
|
+
outline: 1px solid CanvasText;
|
|
11
|
+
outline-offset: -1px;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
:where([data-control-family="color-picker"][data-slot="trigger"]) {
|
|
9
16
|
border-radius: var(--cui-color-picker-trigger-radius);
|
|
10
17
|
transition-property: transform, translate, scale, rotate;
|
|
@@ -25,6 +25,13 @@
|
|
|
25
25
|
backdrop-filter: var(--cui-field-backdrop-filter);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
@media (forced-colors: active) {
|
|
29
|
+
:where([data-control-family="field"][data-control="true"]:not(:focus-visible, :has(:focus-visible))) {
|
|
30
|
+
outline: 1px solid CanvasText;
|
|
31
|
+
outline-offset: -1px;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
:where(
|
|
29
36
|
[data-control-family="field"][data-control="true"]:not([data-control-family="field"][data-field-kind="autocomplete"]):not(
|
|
30
37
|
[data-control-family="field"][data-field-kind="combobox"]
|
|
@@ -52,6 +52,13 @@
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
@media (forced-colors: active) {
|
|
56
|
+
:where([data-control-family="inline-attachment"][data-slot="root"]:not(:focus-visible)) {
|
|
57
|
+
outline: 1px solid CanvasText;
|
|
58
|
+
outline-offset: -1px;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
55
62
|
:where([data-control-family="inline-attachment"][data-slot="image"]) {
|
|
56
63
|
border-radius: inherit;
|
|
57
64
|
}
|
|
@@ -28,6 +28,13 @@
|
|
|
28
28
|
--cui-kbd-shadow: 0 0 transparent;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
@media (forced-colors: active) {
|
|
32
|
+
:where([data-control-family="kbd"][data-slot="root"]:not([data-variant="ghost"])) {
|
|
33
|
+
outline: 1px solid CanvasText;
|
|
34
|
+
outline-offset: -1px;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
:where([data-control-family="kbd"][data-slot="group"]) {
|
|
32
39
|
gap: calc(var(--spacing) * 1);
|
|
33
40
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
border-radius: var(--cui-pagination-link-radius);
|
|
18
18
|
background: var(--cui-pagination-link-background);
|
|
19
19
|
box-shadow:
|
|
20
|
-
inset 0 0 0
|
|
20
|
+
inset 0 0 0 var(--control-rim-width) var(--_pagination-link-border-color),
|
|
21
21
|
var(--cui-pagination-link-shadow);
|
|
22
22
|
color: var(--cui-pagination-link-foreground);
|
|
23
23
|
font-variant-numeric: tabular-nums;
|
|
@@ -39,6 +39,13 @@
|
|
|
39
39
|
opacity: var(--disabled-opacity);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
@media (forced-colors: active) {
|
|
43
|
+
:where([data-control-family="pagination"][data-slot="link"][data-active="true"]:not(:focus-visible)) {
|
|
44
|
+
outline: var(--focus-ring-width) solid Highlight;
|
|
45
|
+
outline-offset: calc(var(--focus-ring-width) * -1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
:where([data-control-family="pagination"][data-slot="link"]:has(> svg:first-child)) {
|
|
43
50
|
padding-inline-start: calc(var(--spacing) * 2);
|
|
44
51
|
}
|
|
@@ -39,14 +39,12 @@
|
|
|
39
39
|
:where(
|
|
40
40
|
[data-control-family="scroll-area"][data-slot="root"][data-scrollbar-gutter="stable"]
|
|
41
41
|
> [data-slot="scrollbar"][data-orientation="vertical"]:not([data-has-overflow-y])
|
|
42
|
-
> [data-slot="thumb"]
|
|
43
42
|
),
|
|
44
43
|
:where(
|
|
45
44
|
[data-control-family="scroll-area"][data-slot="root"][data-scrollbar-gutter="stable"]
|
|
46
45
|
> [data-slot="scrollbar"][data-orientation="horizontal"]:not([data-has-overflow-x])
|
|
47
|
-
> [data-slot="thumb"]
|
|
48
46
|
) {
|
|
49
|
-
|
|
47
|
+
visibility: hidden;
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
@supports (corner-shape: squircle) {
|
|
@@ -114,6 +114,18 @@
|
|
|
114
114
|
opacity: var(--disabled-opacity);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
@media (forced-colors: active) {
|
|
118
|
+
:where([data-control-family="tabs"][data-slot="list"]:not([data-variant="browser"], [data-single="true"])) {
|
|
119
|
+
outline: 1px solid CanvasText;
|
|
120
|
+
outline-offset: -1px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
:where([data-control-family="tabs"][data-slot="list"]:not([data-variant="browser"]) [data-slot="indicator"]) {
|
|
124
|
+
outline: var(--focus-ring-width) solid Highlight;
|
|
125
|
+
outline-offset: calc(var(--focus-ring-width) * -1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
117
129
|
:where([data-control-family="tabs"][data-slot="list"][data-variant="browser"]) {
|
|
118
130
|
--_tabs-browser-corner-double: calc(var(--_tabs-trigger-radius-fit) + var(--_tabs-trigger-radius-fit));
|
|
119
131
|
--_tabs-browser-inset: calc(var(--_tabs-trigger-radius-fit) + var(--cui-tabs-surface-radius));
|
|
@@ -65,7 +65,8 @@
|
|
|
65
65
|
|
|
66
66
|
/*
|
|
67
67
|
* History: fixed 3 competing type systems (Tailwind defaults + named rungs + raw text-[Npx]) into one rung/role; 14px = body.
|
|
68
|
-
* Usage:
|
|
68
|
+
* Usage: React text goes through <Text>/<Heading> (ui/typography): size, tone and weight are props, className stays layout-only.
|
|
69
|
+
* A bare rung is for markup React doesn't render as components (MDX, markdown, email HTML), e.g. text-heading-1 on <h1>.
|
|
69
70
|
* Heading LEVEL is the document outline; the RUNG is the look. They are decoupled on purpose: an <h3> may wear text-heading-2.
|
|
70
71
|
* Control chrome text is sized by its recipe (`--cui-button-font-size`, `--cui-field-font-size`), not by these utilities.
|
|
71
72
|
*/
|
package/dist/ui/sidebar.js
CHANGED
|
@@ -309,7 +309,7 @@ function SidebarContent({ className, children, ...props }) {
|
|
|
309
309
|
className: cn("min-h-0 flex-1 group-data-[collapsible=icon]:overflow-hidden", className),
|
|
310
310
|
lockAxis: "x",
|
|
311
311
|
scrollbarGutter: iconOnly ? "auto" : void 0,
|
|
312
|
-
viewportClassName: "overscroll-y-contain",
|
|
312
|
+
viewportClassName: "data-has-overflow-y:overscroll-y-contain",
|
|
313
313
|
...props,
|
|
314
314
|
children: /* @__PURE__ */ jsx("div", {
|
|
315
315
|
"data-control-ui": "sidebar",
|
package/dist/ui/typography.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ declare const toneClassNames: {
|
|
|
17
17
|
readonly foreground: "text-foreground";
|
|
18
18
|
readonly muted: "text-muted-foreground";
|
|
19
19
|
readonly primary: "text-primary-text";
|
|
20
|
+
readonly success: "text-success-text";
|
|
21
|
+
readonly warning: "text-warning-text";
|
|
20
22
|
readonly destructive: "text-destructive-text";
|
|
21
23
|
};
|
|
22
24
|
declare const weightClassNames: {
|
package/dist/ui/typography.js
CHANGED
|
@@ -18,6 +18,8 @@ const toneClassNames = {
|
|
|
18
18
|
foreground: "text-foreground",
|
|
19
19
|
muted: "text-muted-foreground",
|
|
20
20
|
primary: "text-primary-text",
|
|
21
|
+
success: "text-success-text",
|
|
22
|
+
warning: "text-warning-text",
|
|
21
23
|
destructive: "text-destructive-text"
|
|
22
24
|
};
|
|
23
25
|
const weightClassNames = {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
language js(typescript, jsx)
|
|
2
|
+
|
|
3
|
+
JsxAttribute(name=$name, initializer=$value) as $attr where {
|
|
4
|
+
$name <: `className`,
|
|
5
|
+
$value <: contains r".*\btext-(?:micro|caption|label|body|body-lg|heading-[1-4]|display)\b.*",
|
|
6
|
+
register_diagnostic(span=$attr, message="Type rung in className: render text through <Text>/<Heading>, or size the control with its size prop or --cui-*-font-size knob.", severity="warn")
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ctrl-ui/react",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "100+ React components for Tailwind CSS and shadcn/ui: pickers, trees, editors, canvases, app templates, and AI chat surfaces, with neutral defaults and consumer-owned themes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"**/*.css"
|
|
33
33
|
],
|
|
34
34
|
"files": [
|
|
35
|
-
"dist"
|
|
35
|
+
"dist",
|
|
36
|
+
"lint/*.grit"
|
|
36
37
|
],
|
|
37
38
|
"publishConfig": {
|
|
38
39
|
"access": "public"
|