@repraze/kernelkit 0.1.0-alpha.2 → 0.1.0-alpha.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/README.md +17 -0
- package/dist/components/alert.d.ts.map +1 -1
- package/dist/components/alert.js +4 -6
- package/dist/components/alert.js.map +1 -1
- package/dist/components/avatar.js +1 -1
- package/dist/components/avatar.js.map +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/badge.js.map +1 -1
- package/dist/components/breadcrumb.d.ts +1 -0
- package/dist/components/breadcrumb.d.ts.map +1 -1
- package/dist/components/breadcrumb.js +7 -6
- package/dist/components/breadcrumb.js.map +1 -1
- package/dist/components/callout.d.ts +8 -4
- package/dist/components/callout.d.ts.map +1 -1
- package/dist/components/callout.js +22 -12
- package/dist/components/callout.js.map +1 -1
- package/dist/components/chart.js +2 -2
- package/dist/components/chart.js.map +1 -1
- package/dist/components/code-block.js +1 -1
- package/dist/components/code-block.js.map +1 -1
- package/dist/components/command.js +1 -1
- package/dist/components/command.js.map +1 -1
- package/dist/components/data-table/elements/data-table-info-row.js +1 -1
- package/dist/components/data-table/elements/data-table-info-row.js.map +1 -1
- package/dist/components/dropdown-menu.d.ts +1 -1
- package/dist/components/dropdown-menu.d.ts.map +1 -1
- package/dist/components/dropdown-menu.js +1 -1
- package/dist/components/dropdown-menu.js.map +1 -1
- package/dist/components/kbd.d.ts.map +1 -1
- package/dist/components/kbd.js +2 -4
- package/dist/components/kbd.js.map +1 -1
- package/dist/components/message.js +2 -2
- package/dist/components/message.js.map +1 -1
- package/dist/components/meter.js +1 -1
- package/dist/components/meter.js.map +1 -1
- package/dist/components/progress.js +1 -1
- package/dist/components/progress.js.map +1 -1
- package/dist/components/questionnaire.js +1 -1
- package/dist/components/questionnaire.js.map +1 -1
- package/dist/components/search-dialog.d.ts +6 -1
- package/dist/components/search-dialog.d.ts.map +1 -1
- package/dist/components/search-dialog.js +13 -1
- package/dist/components/search-dialog.js.map +1 -1
- package/dist/components/search-trigger.d.ts +1 -1
- package/dist/components/search-trigger.d.ts.map +1 -1
- package/dist/components/search-trigger.js +2 -2
- package/dist/components/search-trigger.js.map +1 -1
- package/dist/components/section.js +1 -1
- package/dist/components/section.js.map +1 -1
- package/dist/components/sidebar.js +1 -1
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/site-footer.js +1 -1
- package/dist/components/site-footer.js.map +1 -1
- package/dist/components/site-header.js +2 -2
- package/dist/components/site-header.js.map +1 -1
- package/dist/components/stat.js +2 -2
- package/dist/components/stat.js.map +1 -1
- package/dist/components/tabs.d.ts +4 -2
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +13 -7
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/theme-menu.js +1 -1
- package/dist/components/theme-menu.js.map +1 -1
- package/dist/components/toc.js +1 -1
- package/dist/components/toc.js.map +1 -1
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +5 -2
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/trace.js +1 -1
- package/dist/components/trace.js.map +1 -1
- package/dist/docs/doc-kit.d.ts +72 -0
- package/dist/docs/doc-kit.d.ts.map +1 -0
- package/dist/docs/doc-kit.js +45 -0
- package/dist/docs/doc-kit.js.map +1 -0
- package/dist/docs/doc-page.d.ts +27 -0
- package/dist/docs/doc-page.d.ts.map +1 -0
- package/dist/docs/doc-page.js +33 -0
- package/dist/docs/doc-page.js.map +1 -0
- package/dist/docs/docs-index.d.ts +60 -0
- package/dist/docs/docs-index.d.ts.map +1 -0
- package/dist/docs/docs-index.js +45 -0
- package/dist/docs/docs-index.js.map +1 -0
- package/dist/docs/docs-nav.d.ts +13 -0
- package/dist/docs/docs-nav.d.ts.map +1 -0
- package/dist/docs/docs-nav.js +8 -0
- package/dist/docs/docs-nav.js.map +1 -0
- package/dist/docs/docs-search.d.ts +19 -0
- package/dist/docs/docs-search.d.ts.map +1 -0
- package/dist/docs/docs-search.js +33 -0
- package/dist/docs/docs-search.js.map +1 -0
- package/dist/docs/index.d.ts +7 -0
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +7 -0
- package/dist/docs/index.js.map +1 -0
- package/dist/docs/review-matrix.d.ts +25 -0
- package/dist/docs/review-matrix.d.ts.map +1 -0
- package/dist/docs/review-matrix.js +31 -0
- package/dist/docs/review-matrix.js.map +1 -0
- package/dist/hooks/use-theme-palette.d.ts +8 -0
- package/dist/hooks/use-theme-palette.d.ts.map +1 -0
- package/dist/hooks/use-theme-palette.js +24 -0
- package/dist/hooks/use-theme-palette.js.map +1 -0
- package/dist/lib/recipes.d.ts +10 -0
- package/dist/lib/recipes.d.ts.map +1 -1
- package/dist/lib/recipes.js +12 -0
- package/dist/lib/recipes.js.map +1 -1
- package/dist/provider/theme-provider.d.ts +10 -1
- package/dist/provider/theme-provider.d.ts.map +1 -1
- package/dist/provider/theme-provider.js +23 -8
- package/dist/provider/theme-provider.js.map +1 -1
- package/dist/site/brand.d.ts +20 -0
- package/dist/site/brand.d.ts.map +1 -0
- package/dist/site/brand.js +17 -0
- package/dist/site/brand.js.map +1 -0
- package/dist/site/github-icon.d.ts +4 -0
- package/dist/site/github-icon.d.ts.map +1 -0
- package/dist/site/github-icon.js +6 -0
- package/dist/site/github-icon.js.map +1 -0
- package/dist/site/index.d.ts +6 -0
- package/dist/site/index.d.ts.map +1 -0
- package/dist/site/index.js +6 -0
- package/dist/site/index.js.map +1 -0
- package/dist/site/suite-footer.d.ts +24 -0
- package/dist/site/suite-footer.d.ts.map +1 -0
- package/dist/site/suite-footer.js +19 -0
- package/dist/site/suite-footer.js.map +1 -0
- package/dist/site/suite-header.d.ts +40 -0
- package/dist/site/suite-header.d.ts.map +1 -0
- package/dist/site/suite-header.js +19 -0
- package/dist/site/suite-header.js.map +1 -0
- package/dist/site/use-page-title.d.ts +3 -0
- package/dist/site/use-page-title.d.ts.map +1 -0
- package/dist/site/use-page-title.js +8 -0
- package/dist/site/use-page-title.js.map +1 -0
- package/dist/vite/index.d.ts +65 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +242 -0
- package/dist/vite/index.js.map +1 -0
- package/package.json +39 -3
- package/src/components/alert.tsx +4 -6
- package/src/components/avatar.tsx +1 -1
- package/src/components/badge.tsx +1 -1
- package/src/components/breadcrumb.tsx +8 -7
- package/src/components/callout.tsx +27 -12
- package/src/components/chart.tsx +2 -2
- package/src/components/code-block.tsx +1 -1
- package/src/components/command.tsx +1 -1
- package/src/components/data-table/elements/data-table-info-row.tsx +1 -1
- package/src/components/dropdown-menu.tsx +1 -1
- package/src/components/kbd.tsx +2 -4
- package/src/components/message.tsx +2 -2
- package/src/components/meter.tsx +1 -1
- package/src/components/progress.tsx +1 -1
- package/src/components/questionnaire.tsx +1 -1
- package/src/components/search-dialog.tsx +14 -1
- package/src/components/search-trigger.tsx +2 -3
- package/src/components/section.tsx +1 -1
- package/src/components/sidebar.tsx +1 -1
- package/src/components/site-footer.tsx +1 -1
- package/src/components/site-header.tsx +2 -2
- package/src/components/stat.tsx +2 -2
- package/src/components/tabs.tsx +17 -9
- package/src/components/theme-menu.tsx +1 -1
- package/src/components/toc.tsx +1 -1
- package/src/components/tooltip.tsx +15 -3
- package/src/components/trace.tsx +1 -1
- package/src/docs/doc-kit.tsx +176 -0
- package/src/docs/doc-page.tsx +126 -0
- package/src/docs/docs-index.ts +108 -0
- package/src/docs/docs-nav.tsx +47 -0
- package/src/docs/docs-search.tsx +88 -0
- package/src/docs/index.ts +6 -0
- package/src/docs/review-matrix.tsx +67 -0
- package/src/hooks/use-theme-palette.ts +25 -0
- package/src/lib/recipes.ts +14 -0
- package/src/provider/theme-provider.tsx +34 -9
- package/src/site/brand.tsx +41 -0
- package/src/site/github-icon.tsx +10 -0
- package/src/site/index.ts +5 -0
- package/src/site/suite-footer.tsx +68 -0
- package/src/site/suite-header.tsx +114 -0
- package/src/site/use-page-title.ts +8 -0
- package/src/styles/kernelkit.css +6 -0
- package/src/styles/site.css +15 -0
- package/src/vite/client.d.ts +11 -0
- package/src/vite/index.ts +298 -0
|
@@ -65,7 +65,7 @@ function MessageHeader({className, ...props}: React.ComponentProps<"div">) {
|
|
|
65
65
|
<div
|
|
66
66
|
data-slot="message-header"
|
|
67
67
|
className={cn(
|
|
68
|
-
"flex max-w-full min-w-0 items-center gap-1.5 px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 [&_time]:font-
|
|
68
|
+
"flex max-w-full min-w-0 items-center gap-1.5 px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 [&_time]:font-alt [&_time]:font-normal [&_time]:tabular-nums",
|
|
69
69
|
className,
|
|
70
70
|
)}
|
|
71
71
|
{...props}
|
|
@@ -78,7 +78,7 @@ function MessageFooter({className, ...props}: React.ComponentProps<"div">) {
|
|
|
78
78
|
<div
|
|
79
79
|
data-slot="message-footer"
|
|
80
80
|
className={cn(
|
|
81
|
-
"flex max-w-full min-w-0 items-center gap-1 px-3 text-xs text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 [&_time]:font-
|
|
81
|
+
"flex max-w-full min-w-0 items-center gap-1 px-3 text-xs text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 [&_time]:font-alt [&_time]:tabular-nums",
|
|
82
82
|
className,
|
|
83
83
|
)}
|
|
84
84
|
{...props}
|
package/src/components/meter.tsx
CHANGED
|
@@ -59,7 +59,7 @@ function MeterValue({className, ...props}: MeterPrimitive.Value.Props) {
|
|
|
59
59
|
return (
|
|
60
60
|
<MeterPrimitive.Value
|
|
61
61
|
data-slot="meter-value"
|
|
62
|
-
className={cn("ms-auto font-
|
|
62
|
+
className={cn("ms-auto font-alt text-xs text-muted-foreground tabular-nums", className)}
|
|
63
63
|
{...props}
|
|
64
64
|
/>
|
|
65
65
|
);
|
|
@@ -86,7 +86,7 @@ function ProgressValue({className, ...props}: ProgressPrimitive.Value.Props) {
|
|
|
86
86
|
return (
|
|
87
87
|
<ProgressPrimitive.Value
|
|
88
88
|
data-slot="progress-value"
|
|
89
|
-
className={cn("ms-auto font-
|
|
89
|
+
className={cn("ms-auto font-alt text-xs text-muted-foreground tabular-nums", className)}
|
|
90
90
|
{...props}
|
|
91
91
|
/>
|
|
92
92
|
);
|
|
@@ -122,7 +122,7 @@ function QuestionnaireChoice({
|
|
|
122
122
|
</QuestionnairePrimitive.ChoiceLabel>
|
|
123
123
|
<QuestionnairePrimitive.ChoiceShortcut
|
|
124
124
|
data-slot="questionnaire-choice-shortcut"
|
|
125
|
-
className="pointer-events-none ms-auto hidden size-5 shrink-0 translate-y-[--spacing(0.45)] items-center justify-center rounded-sm border border-border bg-muted font-
|
|
125
|
+
className="pointer-events-none ms-auto hidden size-5 shrink-0 translate-y-[--spacing(0.45)] items-center justify-center rounded-sm border border-border bg-muted font-alt text-[0.625rem] leading-none font-medium text-muted-foreground group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 group-data-[shortcut]/questionnaire-choice:inline-flex"
|
|
126
126
|
/>
|
|
127
127
|
</QuestionnairePrimitive.Choice>
|
|
128
128
|
);
|
|
@@ -84,4 +84,17 @@ function SearchFooter({className, ...props}: React.ComponentProps<"div">) {
|
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
/**
|
|
88
|
+
* The suite's search filter for `<Command filter={substringFilter}>`: a plain substring match (prefix
|
|
89
|
+
* matches rank first). cmdk's default fuzzy match finds "t…a…b" in nearly every title.
|
|
90
|
+
*/
|
|
91
|
+
function substringFilter(value: string, search: string, keywords?: string[]) {
|
|
92
|
+
const haystack = [value, ...(keywords ?? [])].join(" ").toLowerCase();
|
|
93
|
+
const needle = search.trim().toLowerCase();
|
|
94
|
+
if (haystack.startsWith(needle)) {
|
|
95
|
+
return 1;
|
|
96
|
+
}
|
|
97
|
+
return haystack.includes(needle) ? 0.5 : 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export {SearchDialog, SearchFooter, SearchItem, substringFilter};
|
|
@@ -51,16 +51,15 @@ interface SearchTriggerProps extends React.ComponentProps<typeof Button> {
|
|
|
51
51
|
children?: React.ReactNode;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/** Header search button: icon, placeholder, OS-aware shortcut. Open your dialog in `onClick`. */
|
|
54
|
+
/** Header search button: icon, placeholder, OS-aware shortcut. Same 32px height as the header's icon buttons. Open your dialog in `onClick`. */
|
|
55
55
|
function SearchTrigger({children = "Search…", className, ...props}: SearchTriggerProps) {
|
|
56
56
|
const mod = useModKey();
|
|
57
57
|
return (
|
|
58
58
|
<Button
|
|
59
59
|
variant="outline"
|
|
60
|
-
size="sm"
|
|
61
60
|
aria-label="Search"
|
|
62
61
|
data-slot="search-trigger"
|
|
63
|
-
className={cn("w-
|
|
62
|
+
className={cn("w-8 justify-start px-0 text-muted-foreground sm:w-48 sm:px-2.5 md:w-56", className)}
|
|
64
63
|
{...props}
|
|
65
64
|
>
|
|
66
65
|
<SearchIcon data-icon="inline-start" className="mx-auto sm:mx-0" />
|
|
@@ -50,7 +50,7 @@ function SectionEyebrow({className, render, ...props}: useRender.ComponentProps<
|
|
|
50
50
|
return useRender({
|
|
51
51
|
defaultTagName: "div",
|
|
52
52
|
props: mergeProps<"div">(
|
|
53
|
-
{className: cn("font-
|
|
53
|
+
{className: cn("font-alt text-xs font-medium text-primary-text uppercase sm:col-start-1", className)},
|
|
54
54
|
props,
|
|
55
55
|
),
|
|
56
56
|
render,
|
|
@@ -592,7 +592,7 @@ function SidebarMenuBadge({className, ...props}: React.ComponentProps<"div">) {
|
|
|
592
592
|
data-slot="sidebar-menu-badge"
|
|
593
593
|
data-sidebar="menu-badge"
|
|
594
594
|
className={cn(
|
|
595
|
-
"pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-sm px-1 font-
|
|
595
|
+
"pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-sm px-1 font-alt text-xs font-medium text-muted-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 peer-data-active/menu-button:text-sidebar-accent-foreground",
|
|
596
596
|
className,
|
|
597
597
|
)}
|
|
598
598
|
{...props}
|
|
@@ -22,7 +22,7 @@ import type * as React from "react";
|
|
|
22
22
|
function SiteFooter({className, children, ...props}: React.ComponentProps<"footer">) {
|
|
23
23
|
return (
|
|
24
24
|
<footer data-slot="site-footer" className={cn("border-t border-border", className)} {...props}>
|
|
25
|
-
<div className="mx-auto flex w-full max-w-(--kk-site-width) flex-col gap-3 px-4 py-6 font-
|
|
25
|
+
<div className="mx-auto flex w-full max-w-(--kk-site-width) flex-col gap-3 px-4 py-6 font-alt text-xs text-muted-foreground sm:flex-row sm:items-center sm:justify-between md:px-6">
|
|
26
26
|
{children}
|
|
27
27
|
</div>
|
|
28
28
|
</footer>
|
|
@@ -66,7 +66,7 @@ function SiteHeaderBrand({className, render, ...props}: useRender.ComponentProps
|
|
|
66
66
|
props: mergeProps<"a">(
|
|
67
67
|
{
|
|
68
68
|
className: cn(
|
|
69
|
-
"flex shrink-0 items-center gap-2 rounded-md font-
|
|
69
|
+
"flex shrink-0 items-center gap-2 rounded-md font-alt text-sm font-semibold tracking-tight",
|
|
70
70
|
focusRing,
|
|
71
71
|
"[&_svg]:shrink-0",
|
|
72
72
|
className,
|
|
@@ -105,7 +105,7 @@ function SiteNavLink({className, render, ...props}: useRender.ComponentProps<"a"
|
|
|
105
105
|
props: mergeProps<"a">(
|
|
106
106
|
{
|
|
107
107
|
className: cn(
|
|
108
|
-
"relative flex h-8 items-center rounded-md px-2.5 font-
|
|
108
|
+
"relative flex h-8 items-center rounded-md px-2.5 font-alt text-sm text-muted-foreground transition-colors hover:bg-hover hover:text-foreground motion-reduce:transition-none",
|
|
109
109
|
focusRing,
|
|
110
110
|
// indicator: left edge by default, bottom edge inside SiteNav
|
|
111
111
|
"after:pointer-events-none after:absolute after:top-1.5 after:bottom-1.5 after:left-0 after:w-0.5 after:rounded-pill after:bg-primary-text after:opacity-0",
|
package/src/components/stat.tsx
CHANGED
|
@@ -51,7 +51,7 @@ function StatValue({className, ...props}: React.ComponentProps<"div">) {
|
|
|
51
51
|
<div
|
|
52
52
|
data-slot="stat-value"
|
|
53
53
|
className={cn(
|
|
54
|
-
"col-start-1 flex items-baseline gap-1 font-
|
|
54
|
+
"col-start-1 flex items-baseline gap-1 font-alt text-2xl leading-tight font-medium tracking-tight text-foreground tabular-nums",
|
|
55
55
|
"group-data-[size=sm]/stat:text-xl group-data-[size=lg]/stat:text-3xl",
|
|
56
56
|
className,
|
|
57
57
|
)}
|
|
@@ -74,7 +74,7 @@ function StatUnit({className, ...props}: React.ComponentProps<"span">) {
|
|
|
74
74
|
type StatTrend = "up" | "down" | "flat";
|
|
75
75
|
|
|
76
76
|
const statDeltaVariants = cva(
|
|
77
|
-
"col-start-1 inline-flex w-fit items-center gap-1 font-
|
|
77
|
+
"col-start-1 inline-flex w-fit items-center gap-1 font-alt text-xs font-medium tabular-nums [&_svg]:size-3.5 [&_svg]:shrink-0",
|
|
78
78
|
{
|
|
79
79
|
variants: {
|
|
80
80
|
intent: {
|
package/src/components/tabs.tsx
CHANGED
|
@@ -18,8 +18,10 @@ function Tabs({className, orientation = "horizontal", ...props}: TabsPrimitive.R
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* `default`: a
|
|
22
|
-
*
|
|
21
|
+
* `default`: a track with the active tab tinted with the accent and marked by a 2px pill along its bottom
|
|
22
|
+
* edge, like a current nav link. Track border + padding = `--radius-xs` (lg − md), so the `rounded-md` chips
|
|
23
|
+
* stay concentric with the `rounded-lg` track at every radius. `line`: a baseline with the same 2px pill
|
|
24
|
+
* on it under the active tab.
|
|
23
25
|
* Sizes follow the control table (GUIDELINES §4) so a tabs list lines up with buttons and inputs.
|
|
24
26
|
*/
|
|
25
27
|
const tabsListVariants = cva(
|
|
@@ -27,7 +29,8 @@ const tabsListVariants = cva(
|
|
|
27
29
|
{
|
|
28
30
|
variants: {
|
|
29
31
|
variant: {
|
|
30
|
-
default:
|
|
32
|
+
default:
|
|
33
|
+
"rounded-lg border border-transparent bg-muted p-[max(0px,calc(var(--radius-xs)-1px))] data-vertical:gap-0.5 hc:border-border",
|
|
31
34
|
line: "gap-1 rounded-none border-border bg-transparent data-horizontal:border-b data-horizontal:py-[3px] data-vertical:border-r data-vertical:px-[3px]",
|
|
32
35
|
},
|
|
33
36
|
size: {
|
|
@@ -73,13 +76,18 @@ const tabsTriggerClass = cn(
|
|
|
73
76
|
"group-data-[size=lg]/tabs-list:gap-2 group-data-[size=lg]/tabs-list:px-2.5",
|
|
74
77
|
// vertical: full-width rows
|
|
75
78
|
"data-vertical:w-full data-vertical:flex-none data-vertical:justify-start data-vertical:py-1",
|
|
76
|
-
//
|
|
79
|
+
// active: foreground text and a 2px primary-text pill; default adds the accent tint (nav link look)
|
|
77
80
|
"data-active:text-foreground",
|
|
78
|
-
"group-data-[variant=default]/tabs-list:data-active:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"data-horizontal:after:inset-x-
|
|
82
|
-
|
|
81
|
+
"group-data-[variant=default]/tabs-list:data-active:bg-accent group-data-[variant=default]/tabs-list:data-active:text-accent-foreground",
|
|
82
|
+
"after:pointer-events-none after:absolute after:rounded-pill after:bg-primary-text after:opacity-0 after:transition-opacity data-active:after:opacity-100",
|
|
83
|
+
// default: the pill sits inside the chip on its bottom edge (vertical: its start edge, like sidebar rows)
|
|
84
|
+
"group-data-[variant=default]/tabs-list:data-horizontal:after:inset-x-2 group-data-[variant=default]/tabs-list:data-horizontal:after:-bottom-px group-data-[variant=default]/tabs-list:data-horizontal:after:h-0.5",
|
|
85
|
+
// the pill spans the label: inset = the trigger's padding per size
|
|
86
|
+
"group-data-[size=sm]/tabs-list:group-data-[variant=default]/tabs-list:data-horizontal:after:inset-x-1.5 group-data-[size=lg]/tabs-list:group-data-[variant=default]/tabs-list:data-horizontal:after:inset-x-2.5",
|
|
87
|
+
"group-data-[variant=default]/tabs-list:data-vertical:after:inset-y-1.5 group-data-[variant=default]/tabs-list:data-vertical:after:-left-px group-data-[variant=default]/tabs-list:data-vertical:after:w-0.5",
|
|
88
|
+
// line: the pill sits on the list's baseline
|
|
89
|
+
"group-data-[variant=line]/tabs-list:data-horizontal:after:inset-x-1 group-data-[variant=line]/tabs-list:data-horizontal:after:-bottom-1 group-data-[variant=line]/tabs-list:data-horizontal:after:h-0.5",
|
|
90
|
+
"group-data-[variant=line]/tabs-list:data-vertical:after:inset-y-1 group-data-[variant=line]/tabs-list:data-vertical:after:-right-1 group-data-[variant=line]/tabs-list:data-vertical:after:w-0.5",
|
|
83
91
|
);
|
|
84
92
|
|
|
85
93
|
function TabsTrigger({className, ...props}: TabsPrimitive.Tab.Props) {
|
|
@@ -116,7 +116,7 @@ function ThemeRadiusPicker({className}: {className?: string}) {
|
|
|
116
116
|
className={cn("w-full", className)}
|
|
117
117
|
>
|
|
118
118
|
{RADII.map((radius) => (
|
|
119
|
-
<ToggleGroupItem key={radius} value={radius} className="flex-1 font-
|
|
119
|
+
<ToggleGroupItem key={radius} value={radius} className="flex-1 font-alt">
|
|
120
120
|
{radius}
|
|
121
121
|
</ToggleGroupItem>
|
|
122
122
|
))}
|
package/src/components/toc.tsx
CHANGED
|
@@ -35,7 +35,7 @@ function TocTitle({className, render, ...props}: useRender.ComponentProps<"p">)
|
|
|
35
35
|
return useRender({
|
|
36
36
|
defaultTagName: "p",
|
|
37
37
|
props: mergeProps<"p">(
|
|
38
|
-
{className: cn("font-
|
|
38
|
+
{className: cn("font-alt text-xs font-medium text-muted-foreground uppercase", className)},
|
|
39
39
|
props,
|
|
40
40
|
),
|
|
41
41
|
render,
|
|
@@ -39,15 +39,27 @@ function TooltipContent({
|
|
|
39
39
|
<TooltipPrimitive.Popup
|
|
40
40
|
data-slot="tooltip-content"
|
|
41
41
|
className={cn(
|
|
42
|
-
//
|
|
42
|
+
// Popover-coloured chip: the popup surface and border, small mono text.
|
|
43
43
|
popupMotion,
|
|
44
|
-
"z-50 inline-flex min-h-6 w-fit max-w-xs items-center gap-1.5 rounded-md bg-
|
|
44
|
+
"z-50 inline-flex min-h-6 w-fit max-w-xs items-center gap-1.5 rounded-md border border-border bg-popover px-2 py-1 font-alt text-xs text-popover-foreground shadow-md shadow-(color:--shadow-color) has-data-[slot=kbd]:pr-1 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:h-4 **:data-[slot=kbd]:min-w-4 **:data-[slot=kbd]:rounded-xs",
|
|
45
45
|
className,
|
|
46
46
|
)}
|
|
47
47
|
{...props}
|
|
48
48
|
>
|
|
49
49
|
{children}
|
|
50
|
-
<TooltipPrimitive.Arrow
|
|
50
|
+
<TooltipPrimitive.Arrow
|
|
51
|
+
className={cn(
|
|
52
|
+
// A rotated square in the popup colours; the border sits on the two edges that face out,
|
|
53
|
+
// centred on the popup's border line so the outline runs on without a seam.
|
|
54
|
+
"z-50 size-2.5 rotate-45 rounded-xs border-border bg-popover",
|
|
55
|
+
"data-[side=top]:-bottom-1.25 data-[side=top]:border-r data-[side=top]:border-b",
|
|
56
|
+
"data-[side=bottom]:-top-1.25 data-[side=bottom]:border-t data-[side=bottom]:border-l",
|
|
57
|
+
"data-[side=left]:top-1/2! data-[side=left]:-right-1.25 data-[side=left]:-translate-y-1/2 data-[side=left]:border-t data-[side=left]:border-r",
|
|
58
|
+
"data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1.25 data-[side=inline-start]:-translate-y-1/2 data-[side=inline-start]:border-t data-[side=inline-start]:border-r",
|
|
59
|
+
"data-[side=right]:top-1/2! data-[side=right]:-left-1.25 data-[side=right]:-translate-y-1/2 data-[side=right]:border-b data-[side=right]:border-l",
|
|
60
|
+
"data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1.25 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-end]:border-b data-[side=inline-end]:border-l",
|
|
61
|
+
)}
|
|
62
|
+
/>
|
|
51
63
|
</TooltipPrimitive.Popup>
|
|
52
64
|
</TooltipPrimitive.Positioner>
|
|
53
65
|
</TooltipPrimitive.Portal>
|
package/src/components/trace.tsx
CHANGED
|
@@ -67,7 +67,7 @@ function TraceDescription({className, ...props}: React.ComponentProps<"span">) {
|
|
|
67
67
|
return (
|
|
68
68
|
<span
|
|
69
69
|
data-slot="trace-description"
|
|
70
|
-
className={cn("shrink-0 font-
|
|
70
|
+
className={cn("shrink-0 font-alt text-xs text-muted-foreground tabular-nums", className)}
|
|
71
71
|
{...props}
|
|
72
72
|
/>
|
|
73
73
|
);
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CodeBlock,
|
|
5
|
+
CodeBlockActions,
|
|
6
|
+
CodeBlockContent,
|
|
7
|
+
CodeBlockCopyButton,
|
|
8
|
+
CodeBlockHeader,
|
|
9
|
+
CodeBlockTitle,
|
|
10
|
+
} from "@repraze/kernelkit/components/code-block";
|
|
11
|
+
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@repraze/kernelkit/components/table";
|
|
12
|
+
import {Tabs, TabsContent, TabsList, TabsTrigger} from "@repraze/kernelkit/components/tabs";
|
|
13
|
+
import {useHighlightedCode} from "@repraze/kernelkit/hooks/use-highlighted-code";
|
|
14
|
+
import {cn} from "cn";
|
|
15
|
+
import type * as React from "react";
|
|
16
|
+
|
|
17
|
+
export interface PropRow {
|
|
18
|
+
name: string;
|
|
19
|
+
type: string;
|
|
20
|
+
default?: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DemoDef {
|
|
25
|
+
title: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
component: React.ComponentType;
|
|
28
|
+
/** Preview frame: "center" (default), "start" (top-left), "full" (no padding), "tall". */
|
|
29
|
+
layout?: "center" | "start" | "full" | "tall";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** A docs page: one `defineDoc({...})` per file in the site's docs folder (read statically by docsMetaPlugin). */
|
|
33
|
+
export interface DocDef<Category extends string = string> {
|
|
34
|
+
title: string;
|
|
35
|
+
category: Category;
|
|
36
|
+
description: string;
|
|
37
|
+
/** A link badge after the category in the page header: the primitive it wraps, the source file it documents. */
|
|
38
|
+
source?: {label: string; href: string};
|
|
39
|
+
demos: DemoDef[];
|
|
40
|
+
props?: {component: string; rows: PropRow[]}[];
|
|
41
|
+
/** Freeform content after the demos. */
|
|
42
|
+
notes?: React.ComponentType;
|
|
43
|
+
/** The notes' own h2 sections (`id` on each), listed in the table of contents after the demos. */
|
|
44
|
+
sections?: {id: string; title: string}[];
|
|
45
|
+
/** Sort order inside the category (lower first, default 50). */
|
|
46
|
+
order?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface DocEntry<Category extends string = string> extends DocDef<Category> {
|
|
50
|
+
slug: string;
|
|
51
|
+
/** Source of each demo's own function, by demo index. */
|
|
52
|
+
demoSources: string[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Declare a docs page. The site narrows the categories once:
|
|
57
|
+
*
|
|
58
|
+
* ```ts
|
|
59
|
+
* export const CATEGORIES = ["Foundations", "Components"] as const;
|
|
60
|
+
* export const defineDoc = (doc: DocDef<(typeof CATEGORIES)[number]>) => doc;
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function defineDoc<Category extends string>(doc: DocDef<Category>): DocDef<Category> {
|
|
64
|
+
return doc;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function slugify(text: string) {
|
|
68
|
+
return text
|
|
69
|
+
.toLowerCase()
|
|
70
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
71
|
+
.replace(/^-|-$/g, "");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** A highlighted, copyable code sample (the kit's CodeBlock), titled with its language by default. */
|
|
75
|
+
export function Code({
|
|
76
|
+
code,
|
|
77
|
+
language = "tsx",
|
|
78
|
+
title,
|
|
79
|
+
className,
|
|
80
|
+
}: {
|
|
81
|
+
code: string;
|
|
82
|
+
language?: string;
|
|
83
|
+
title?: string;
|
|
84
|
+
className?: string;
|
|
85
|
+
}) {
|
|
86
|
+
const lines = useHighlightedCode(code, language);
|
|
87
|
+
return (
|
|
88
|
+
<CodeBlock className={className}>
|
|
89
|
+
<CodeBlockHeader>
|
|
90
|
+
<CodeBlockTitle>{title ?? language}</CodeBlockTitle>
|
|
91
|
+
<CodeBlockActions>
|
|
92
|
+
<CodeBlockCopyButton value={code} />
|
|
93
|
+
</CodeBlockActions>
|
|
94
|
+
</CodeBlockHeader>
|
|
95
|
+
<CodeBlockContent className="max-h-[480px] text-[13px]">
|
|
96
|
+
{lines.map((line, i) => (
|
|
97
|
+
<span key={i} className="block min-h-lh">
|
|
98
|
+
{line}
|
|
99
|
+
</span>
|
|
100
|
+
))}
|
|
101
|
+
</CodeBlockContent>
|
|
102
|
+
</CodeBlock>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const layoutClass: Record<NonNullable<DemoDef["layout"]>, string> = {
|
|
107
|
+
center: "flex min-h-56 items-center justify-center p-8",
|
|
108
|
+
start: "flex min-h-56 items-start justify-start p-8",
|
|
109
|
+
full: "overflow-hidden",
|
|
110
|
+
tall: "flex min-h-[28rem] items-center justify-center p-8",
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/** One demo: its title and description, then Preview and Code tabs. The section's id is the slugified title. */
|
|
114
|
+
export function Demo({demo, code}: {demo: DemoDef; code: string}) {
|
|
115
|
+
const Component = demo.component;
|
|
116
|
+
return (
|
|
117
|
+
<section className="flex scroll-mt-24 flex-col gap-3" id={slugify(demo.title)}>
|
|
118
|
+
<div className="flex flex-col gap-1">
|
|
119
|
+
<h3 className="font-mono text-sm font-medium">{demo.title}</h3>
|
|
120
|
+
{demo.description ? <p className="text-sm text-muted-foreground">{demo.description}</p> : null}
|
|
121
|
+
</div>
|
|
122
|
+
<Tabs defaultValue="preview">
|
|
123
|
+
<TabsList>
|
|
124
|
+
<TabsTrigger value="preview">Preview</TabsTrigger>
|
|
125
|
+
<TabsTrigger value="code">Code</TabsTrigger>
|
|
126
|
+
</TabsList>
|
|
127
|
+
<TabsContent value="preview">
|
|
128
|
+
<div
|
|
129
|
+
data-slot="demo-frame"
|
|
130
|
+
className={cn("rounded-xl border bg-card", layoutClass[demo.layout ?? "center"])}
|
|
131
|
+
>
|
|
132
|
+
<Component />
|
|
133
|
+
</div>
|
|
134
|
+
</TabsContent>
|
|
135
|
+
<TabsContent value="code">
|
|
136
|
+
<Code code={code} />
|
|
137
|
+
</TabsContent>
|
|
138
|
+
</Tabs>
|
|
139
|
+
</section>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** A component's props: name, type, default and description. */
|
|
144
|
+
export function PropsTable({component, rows}: {component: string; rows: PropRow[]}) {
|
|
145
|
+
return (
|
|
146
|
+
<section className="flex flex-col gap-3">
|
|
147
|
+
<h3 className="font-mono text-sm font-medium">{component}</h3>
|
|
148
|
+
<div className="overflow-hidden rounded-xl border bg-card">
|
|
149
|
+
<Table>
|
|
150
|
+
<TableHeader>
|
|
151
|
+
<TableRow>
|
|
152
|
+
<TableHead>Prop</TableHead>
|
|
153
|
+
<TableHead>Type</TableHead>
|
|
154
|
+
<TableHead>Default</TableHead>
|
|
155
|
+
<TableHead>Description</TableHead>
|
|
156
|
+
</TableRow>
|
|
157
|
+
</TableHeader>
|
|
158
|
+
<TableBody>
|
|
159
|
+
{rows.map((row) => (
|
|
160
|
+
<TableRow key={row.name}>
|
|
161
|
+
<TableCell className="font-mono text-xs text-primary-text">{row.name}</TableCell>
|
|
162
|
+
<TableCell className="font-mono text-xs whitespace-normal">{row.type}</TableCell>
|
|
163
|
+
<TableCell className="font-mono text-xs text-muted-foreground">
|
|
164
|
+
{row.default ?? "-"}
|
|
165
|
+
</TableCell>
|
|
166
|
+
<TableCell className="text-sm whitespace-normal text-muted-foreground">
|
|
167
|
+
{row.description}
|
|
168
|
+
</TableCell>
|
|
169
|
+
</TableRow>
|
|
170
|
+
))}
|
|
171
|
+
</TableBody>
|
|
172
|
+
</Table>
|
|
173
|
+
</div>
|
|
174
|
+
</section>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {Badge} from "@repraze/kernelkit/components/badge";
|
|
4
|
+
import {
|
|
5
|
+
PageHeader,
|
|
6
|
+
PageHeaderDescription,
|
|
7
|
+
PageHeaderEyebrow,
|
|
8
|
+
PageHeaderTitle,
|
|
9
|
+
} from "@repraze/kernelkit/components/page-header";
|
|
10
|
+
import {Pager, PagerLink} from "@repraze/kernelkit/components/pager";
|
|
11
|
+
import {SiteAside, SiteLayout, SiteMain, SiteSidebar} from "@repraze/kernelkit/components/site-layout";
|
|
12
|
+
import {Toc, TocItem, TocList, TocTitle, useTocActive} from "@repraze/kernelkit/components/toc";
|
|
13
|
+
import {ExternalLinkIcon} from "lucide-react";
|
|
14
|
+
import type * as React from "react";
|
|
15
|
+
|
|
16
|
+
import {Demo, type DocEntry, PropsTable, slugify} from "./doc-kit";
|
|
17
|
+
import type {DocsIndex} from "./docs-index";
|
|
18
|
+
|
|
19
|
+
/** A router link to a docs page, used as a `render` element: `(slug) => <Link to="/docs/$slug" params={{slug}} />`. */
|
|
20
|
+
export type DocLinkFor = (slug: string) => React.ReactElement;
|
|
21
|
+
|
|
22
|
+
/** The table of contents of a page: its demos, the notes' sections, then the API. */
|
|
23
|
+
export function docToc(doc: DocEntry): {id: string; title: string}[] {
|
|
24
|
+
return [
|
|
25
|
+
...doc.demos.map((demo) => ({id: slugify(demo.title), title: demo.title})),
|
|
26
|
+
...(doc.sections ?? []),
|
|
27
|
+
...(doc.props?.length ? [{id: "api", title: "API"}] : []),
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface DocPageProps<Category extends string = string> {
|
|
32
|
+
/** The loaded page (`index.loadDoc(slug)`, usually from the route's loader). */
|
|
33
|
+
doc: DocEntry<Category>;
|
|
34
|
+
index: DocsIndex<Category>;
|
|
35
|
+
linkFor: DocLinkFor;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A docs page in the suite's layout (GUIDELINES §7b): PageHeader (category, source badge, title,
|
|
40
|
+
* description), the demos, the notes, the API tables and the Pager in SiteMain; the Toc in SiteAside.
|
|
41
|
+
*/
|
|
42
|
+
export function DocPage<Category extends string>({doc, index, linkFor}: DocPageProps<Category>) {
|
|
43
|
+
const {prev, next} = index.neighbours(doc.slug);
|
|
44
|
+
const Notes = doc.notes;
|
|
45
|
+
const sections = docToc(doc);
|
|
46
|
+
const active = useTocActive(sections.map((s) => s.id));
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
<SiteMain>
|
|
51
|
+
<PageHeader>
|
|
52
|
+
<PageHeaderEyebrow>
|
|
53
|
+
<Badge variant="outline">{doc.category}</Badge>
|
|
54
|
+
{doc.source ? (
|
|
55
|
+
<Badge
|
|
56
|
+
variant="secondary"
|
|
57
|
+
className="font-mono"
|
|
58
|
+
render={<a href={doc.source.href} target="_blank" rel="noreferrer" />}
|
|
59
|
+
>
|
|
60
|
+
{doc.source.label} <ExternalLinkIcon />
|
|
61
|
+
</Badge>
|
|
62
|
+
) : null}
|
|
63
|
+
</PageHeaderEyebrow>
|
|
64
|
+
<PageHeaderTitle>{doc.title}</PageHeaderTitle>
|
|
65
|
+
<PageHeaderDescription>{doc.description}</PageHeaderDescription>
|
|
66
|
+
</PageHeader>
|
|
67
|
+
|
|
68
|
+
{doc.demos.map((demo, i) => (
|
|
69
|
+
<Demo key={demo.title} demo={demo} code={doc.demoSources[i] ?? ""} />
|
|
70
|
+
))}
|
|
71
|
+
|
|
72
|
+
{Notes ? (
|
|
73
|
+
<div className="flex flex-col gap-4">
|
|
74
|
+
<Notes />
|
|
75
|
+
</div>
|
|
76
|
+
) : null}
|
|
77
|
+
|
|
78
|
+
{doc.props?.length ? (
|
|
79
|
+
<section id="api" className="flex scroll-mt-24 flex-col gap-6">
|
|
80
|
+
<h2 className="font-heading text-xl font-semibold">API</h2>
|
|
81
|
+
{doc.props.map((p) => (
|
|
82
|
+
<PropsTable key={p.component} {...p} />
|
|
83
|
+
))}
|
|
84
|
+
</section>
|
|
85
|
+
) : null}
|
|
86
|
+
|
|
87
|
+
<Pager>
|
|
88
|
+
{prev ? (
|
|
89
|
+
<PagerLink direction="previous" render={linkFor(prev.slug)}>
|
|
90
|
+
{prev.title}
|
|
91
|
+
</PagerLink>
|
|
92
|
+
) : null}
|
|
93
|
+
{next ? (
|
|
94
|
+
<PagerLink direction="next" render={linkFor(next.slug)}>
|
|
95
|
+
{next.title}
|
|
96
|
+
</PagerLink>
|
|
97
|
+
) : null}
|
|
98
|
+
</Pager>
|
|
99
|
+
</SiteMain>
|
|
100
|
+
{sections.length > 1 ? (
|
|
101
|
+
<SiteAside>
|
|
102
|
+
<Toc>
|
|
103
|
+
<TocTitle>On this page</TocTitle>
|
|
104
|
+
<TocList>
|
|
105
|
+
{sections.map((s) => (
|
|
106
|
+
<TocItem key={s.id} href={`#${s.id}`} active={s.id === active}>
|
|
107
|
+
{s.title}
|
|
108
|
+
</TocItem>
|
|
109
|
+
))}
|
|
110
|
+
</TocList>
|
|
111
|
+
</Toc>
|
|
112
|
+
</SiteAside>
|
|
113
|
+
) : null}
|
|
114
|
+
</>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The suite's docs layout: SiteLayout with the docs nav in a sticky SiteSidebar, then the page (which adds its Toc). */
|
|
119
|
+
export function DocsLayout({nav, children}: {nav: React.ReactNode; children: React.ReactNode}) {
|
|
120
|
+
return (
|
|
121
|
+
<SiteLayout>
|
|
122
|
+
<SiteSidebar>{nav}</SiteSidebar>
|
|
123
|
+
{children}
|
|
124
|
+
</SiteLayout>
|
|
125
|
+
);
|
|
126
|
+
}
|