@cosxai/ui 0.25.0 → 1.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +577 -0
  2. package/NOTICE +11 -0
  3. package/README.md +52 -0
  4. package/package.json +33 -7
  5. package/src/fonts.css +20 -0
  6. package/src/index.ts +8 -25
  7. package/src/lib/cn.ts +23 -6
  8. package/src/styles.css +17 -0
  9. package/src/theme.css +132 -0
  10. package/src/tokens/colors.css +112 -0
  11. package/src/tokens/compat.css +36 -0
  12. package/src/tokens/elevation.css +14 -0
  13. package/src/tokens/motion.css +42 -0
  14. package/src/tokens/spacing.css +55 -0
  15. package/src/tokens/typography-cjk.css +42 -0
  16. package/src/tokens/typography.css +81 -0
  17. package/src/actionbar/ActionBar.tsx +0 -837
  18. package/src/actionbar/ActionBarButton.tsx +0 -111
  19. package/src/actionbar/ActionBarMenuGroup.tsx +0 -116
  20. package/src/actionbar/ActionBarModeHandle.tsx +0 -171
  21. package/src/actionbar/ActionBarProvider.tsx +0 -91
  22. package/src/actionbar/actionbar-context.ts +0 -45
  23. package/src/actionbar/index.ts +0 -28
  24. package/src/actionbar/types.ts +0 -147
  25. package/src/actionbar/useActionBarItems.ts +0 -60
  26. package/src/actionbar/useActionBarMode.ts +0 -144
  27. package/src/actionbar/useActionBarPanel.ts +0 -56
  28. package/src/actionbar/useActionBarStatusDot.ts +0 -49
  29. package/src/actionbar/useActionBarToast.ts +0 -33
  30. package/src/ambient/AmbientBackdrop.tsx +0 -74
  31. package/src/ambient/CommandInput.tsx +0 -107
  32. package/src/ambient/SuperbarStrip.tsx +0 -36
  33. package/src/ambient/index.ts +0 -6
  34. package/src/bento/BentoCell.tsx +0 -66
  35. package/src/bento/BentoGrid.tsx +0 -42
  36. package/src/bento/index.ts +0 -2
  37. package/src/command/CommandPalette.tsx +0 -329
  38. package/src/command/CommandProvider.tsx +0 -57
  39. package/src/command/command-context.ts +0 -12
  40. package/src/command/index.ts +0 -6
  41. package/src/command/rank.ts +0 -50
  42. package/src/command/types.ts +0 -37
  43. package/src/command/useCommandSource.ts +0 -37
  44. package/src/dialogs/DialogsProvider.tsx +0 -216
  45. package/src/dialogs/Modal.tsx +0 -260
  46. package/src/dialogs/Toast.tsx +0 -85
  47. package/src/dialogs/dialogs-context.ts +0 -6
  48. package/src/dialogs/index.ts +0 -10
  49. package/src/dialogs/types.ts +0 -37
  50. package/src/dialogs/useDialogs.ts +0 -8
  51. package/src/editorial/EditorialSpotlight.tsx +0 -63
  52. package/src/editorial/Folio.tsx +0 -52
  53. package/src/editorial/PlateMarker.tsx +0 -33
  54. package/src/editorial/RomanSection.tsx +0 -65
  55. package/src/editorial/RunningMarginalia.tsx +0 -65
  56. package/src/editorial/index.ts +0 -10
  57. package/src/hooks/index.ts +0 -5
  58. package/src/hooks/useKeyboardHotkey.ts +0 -93
  59. package/src/hooks/useReducedMotion.ts +0 -20
  60. package/src/hooks/useViewport.ts +0 -61
  61. package/src/layout/Breadcrumb.tsx +0 -74
  62. package/src/layout/LeftNavRail.tsx +0 -139
  63. package/src/layout/MobileTabBar.tsx +0 -101
  64. package/src/layout/NavItem.tsx +0 -128
  65. package/src/layout/NavSearchTrigger.tsx +0 -88
  66. package/src/layout/NavSection.tsx +0 -40
  67. package/src/layout/RightSidebarPanel.tsx +0 -111
  68. package/src/layout/Shell.tsx +0 -91
  69. package/src/layout/SidePanel.tsx +0 -316
  70. package/src/layout/StickyBanner.tsx +0 -83
  71. package/src/layout/Topbar.tsx +0 -68
  72. package/src/layout/index.ts +0 -24
  73. package/src/layout/useNavRailState.ts +0 -69
  74. package/src/lib/time-utils.ts +0 -44
  75. package/src/neobrutalism/Marquee.tsx +0 -81
  76. package/src/neobrutalism/Sticker.tsx +0 -71
  77. package/src/neobrutalism/index.ts +0 -4
  78. package/src/primitives/Avatar.tsx +0 -53
  79. package/src/primitives/Button.tsx +0 -67
  80. package/src/primitives/Card.tsx +0 -41
  81. package/src/primitives/Checkbox.tsx +0 -87
  82. package/src/primitives/Chip.tsx +0 -191
  83. package/src/primitives/Combobox.tsx +0 -507
  84. package/src/primitives/CopyField.tsx +0 -139
  85. package/src/primitives/CountBadge.tsx +0 -50
  86. package/src/primitives/Input.tsx +0 -204
  87. package/src/primitives/Kbd.tsx +0 -45
  88. package/src/primitives/MentionCombobox.tsx +0 -612
  89. package/src/primitives/MultiCombobox.tsx +0 -327
  90. package/src/primitives/PageHeader.tsx +0 -77
  91. package/src/primitives/Radio.tsx +0 -131
  92. package/src/primitives/SegmentedControl.tsx +0 -135
  93. package/src/primitives/Select.tsx +0 -779
  94. package/src/primitives/SignaturePad.tsx +0 -461
  95. package/src/primitives/Tag.tsx +0 -56
  96. package/src/primitives/Textarea.tsx +0 -62
  97. package/src/primitives/ToggleSwitch.tsx +0 -79
  98. package/src/primitives/Tooltip.tsx +0 -213
  99. package/src/primitives/index.ts +0 -53
  100. package/src/pwa/InstallPromptBanner.tsx +0 -132
  101. package/src/pwa/index.ts +0 -4
  102. package/src/pwa/manifest.template.json +0 -20
  103. package/src/pwa/registerSW.ts +0 -55
  104. package/src/riso/Halftone.tsx +0 -85
  105. package/src/riso/Misregister.tsx +0 -63
  106. package/src/riso/RisoStamp.tsx +0 -76
  107. package/src/riso/index.ts +0 -3
  108. package/src/sketch/HandUnderline.tsx +0 -53
  109. package/src/sketch/RoughArrow.tsx +0 -91
  110. package/src/sketch/RoughBox.tsx +0 -73
  111. package/src/sketch/StickyNote.tsx +0 -56
  112. package/src/sketch/index.ts +0 -4
  113. package/src/styles/base.css +0 -186
  114. package/src/styles/chrome-ambient.css +0 -235
  115. package/src/styles/chrome-bento.css +0 -192
  116. package/src/styles/chrome-editorial.css +0 -168
  117. package/src/styles/chrome-neobrutalism.css +0 -326
  118. package/src/styles/chrome-riso.css +0 -339
  119. package/src/styles/chrome-sketch.css +0 -362
  120. package/src/styles/chrome-swiss.css +0 -265
  121. package/src/styles/chrome-terminal.css +0 -272
  122. package/src/styles/fonts.css +0 -1034
  123. package/src/styles/index.css +0 -343
  124. package/src/styles/tokens.css +0 -941
  125. package/src/terminal/AsciiBox.tsx +0 -65
  126. package/src/terminal/BrailleSpinner.tsx +0 -46
  127. package/src/terminal/index.ts +0 -4
  128. package/src/theme/ThemeProvider.tsx +0 -99
  129. package/src/theme/index.ts +0 -6
  130. package/src/theme/inline-script.ts +0 -40
  131. package/src/theme/theme-context.ts +0 -7
  132. package/src/theme/types.ts +0 -39
  133. package/src/theme/useTheme.ts +0 -8
@@ -1,139 +0,0 @@
1
- import { useEffect, type ReactNode, type CSSProperties } from "react";
2
-
3
- // Fixed-left vertical nav rail. Three slots — brand (top), children
4
- // (the nav body, scrollable), footer (avatar / collapse toggle).
5
- //
6
- // Owns the CSS var --ck-leftnav-width. Page content reads this var
7
- // to inset itself, so layouts react to the rail width changing
8
- // without prop-drilling.
9
- //
10
- // Stateless visually: collapsed is a boolean prop. State management
11
- // lives in useNavRailState(), which the parent owns; this keeps the
12
- // component pure and testable.
13
-
14
- export interface LeftNavRailProps {
15
- brand?: ReactNode;
16
- children: ReactNode;
17
- footer?: ReactNode;
18
- /**
19
- * footerTop — a block pinned BETWEEN the scrolling nav area and the
20
- * footer rule: always visible, above the divider, immune to a long
21
- * menu (the nav list scrolls above it). The agent drawer's trigger
22
- * is the motivating case.
23
- */
24
- footerTop?: ReactNode;
25
- collapsed?: boolean;
26
- // Expanded / collapsed widths in px. Defaults 256 / 56.
27
- widthExpanded?: number;
28
- widthCollapsed?: number;
29
- className?: string;
30
- // Hide entirely (e.g. on phone). When true, sets --ck-leftnav-width: 0.
31
- hidden?: boolean;
32
- }
33
-
34
- export function LeftNavRail({
35
- brand,
36
- children,
37
- footer,
38
- footerTop,
39
- collapsed = false,
40
- widthExpanded = 256,
41
- widthCollapsed = 56,
42
- className,
43
- hidden = false,
44
- }: LeftNavRailProps) {
45
- const width = hidden ? 0 : collapsed ? widthCollapsed : widthExpanded;
46
-
47
- // Stamp --ck-leftnav-width on documentElement so page-level
48
- // layouts (Shell's marginLeft, fixed AgentRail, ActionBar's right
49
- // inset) can read it without a context.
50
- useEffect(() => {
51
- document.documentElement.style.setProperty("--ck-leftnav-width", `${width}px`);
52
- return () => {
53
- // On unmount, clear to 0 so consumers without a rail don't inherit
54
- // a stale inset.
55
- document.documentElement.style.setProperty("--ck-leftnav-width", "0px");
56
- };
57
- }, [width]);
58
-
59
- if (hidden) return null;
60
-
61
- return (
62
- <aside
63
- data-ck-leftnav
64
- className={className}
65
- style={
66
- {
67
- position: "fixed",
68
- left: 0,
69
- top: 0,
70
- bottom: 0,
71
- width,
72
- // Default to --ck-bg-surface so the rail blends seamlessly
73
- // with the topbar + cards. Consumers wanting a tinted rail
74
- // override via --ck-bg-sidebar in their own stylesheet or
75
- // pass a className that sets background.
76
- background: "var(--ck-bg-surface)",
77
- borderRight: "1px solid var(--ck-border-subtle)",
78
- display: "flex",
79
- flexDirection: "column",
80
- fontFamily: "var(--ck-font-sans)",
81
- color: "var(--ck-text-primary)",
82
- transition: "width var(--ck-dur-fast) var(--ck-ease), background-color 200ms var(--ck-ease)",
83
- zIndex: 30,
84
- } as CSSProperties
85
- }
86
- >
87
- {brand && (
88
- <div
89
- style={{
90
- // Match the topbar's height (Topbar stamps
91
- // --ck-breadcrumb-height; default 64 px). Logo +
92
- // crumbs sit on the same horizontal axis and the
93
- // brand-area bottom rule aligns with the topbar's
94
- // bottom rule — no per-app tuning.
95
- height: "var(--ck-breadcrumb-height, 64px)",
96
- padding: collapsed ? "0 4px" : "0 12px",
97
- display: "flex",
98
- alignItems: "center",
99
- // Logo is brand mark, not nav item — centre it in both
100
- // collapsed and expanded states so the visual anchor stays
101
- // put across the width transition. Matches the centred
102
- // favicon position when the rail is collapsed.
103
- justifyContent: "center",
104
- borderBottom: "1px solid var(--ck-border-subtle)",
105
- transition: "padding var(--ck-dur-fast) var(--ck-ease)",
106
- flexShrink: 0,
107
- }}
108
- >
109
- {brand}
110
- </div>
111
- )}
112
- <div
113
- style={{
114
- flex: 1,
115
- minHeight: 0,
116
- overflowY: "auto",
117
- padding: collapsed ? "8px 4px" : "12px 8px",
118
- }}
119
- >
120
- {children}
121
- </div>
122
- {footerTop && (
123
- <div style={{ padding: collapsed ? "4px 4px 8px" : "4px 8px 12px", flexShrink: 0 }}>
124
- {footerTop}
125
- </div>
126
- )}
127
- {footer && (
128
- <div
129
- style={{
130
- padding: collapsed ? "8px 4px" : "12px 8px",
131
- borderTop: "1px solid var(--ck-border-subtle)",
132
- }}
133
- >
134
- {footer}
135
- </div>
136
- )}
137
- </aside>
138
- );
139
- }
@@ -1,101 +0,0 @@
1
- import { useEffect, type ReactNode, type CSSProperties } from "react";
2
-
3
- // Fixed-bottom tab bar for phones. Sits above the home-indicator
4
- // safe area on iOS, exposes --ck-tabbar-height so the GlobalActionBar
5
- // and any sticky bottom UI can lift to clear it.
6
- //
7
- // Tab list is fully configurable — caller supplies items with an
8
- // active match function so the bar can highlight the right one for
9
- // the current pathname. No router coupling.
10
-
11
- export interface MobileTab {
12
- key: string;
13
- label: string;
14
- icon: ReactNode;
15
- // Called when the tab is tapped. Caller handles navigation.
16
- onSelect: () => void;
17
- // Whether this tab represents the current route. Caller derives
18
- // from their router (e.g. `pathname.startsWith("/shares")`).
19
- active: boolean;
20
- }
21
-
22
- export interface MobileTabBarProps {
23
- tabs: MobileTab[];
24
- // Height of the bar (content area; safe-area inset added on top).
25
- // Default 56 px.
26
- height?: number;
27
- className?: string;
28
- }
29
-
30
- export function MobileTabBar({
31
- tabs,
32
- height = 56,
33
- className,
34
- }: MobileTabBarProps) {
35
- // Stamp --ck-tabbar-height. Includes safe-area inset so consumers
36
- // (e.g. floating action bar) can lift cleanly above the home
37
- // indicator. iOS env() works in calc() inside :root vars.
38
- useEffect(() => {
39
- document.documentElement.style.setProperty(
40
- "--ck-tabbar-height",
41
- `calc(${height}px + env(safe-area-inset-bottom, 0px))`,
42
- );
43
- return () => {
44
- document.documentElement.style.setProperty("--ck-tabbar-height", "0px");
45
- };
46
- }, [height]);
47
-
48
- return (
49
- <nav
50
- data-ck-tabbar
51
- aria-label="Primary"
52
- className={className}
53
- style={
54
- {
55
- position: "fixed",
56
- left: 0,
57
- right: 0,
58
- bottom: 0,
59
- height: "var(--ck-tabbar-height)",
60
- paddingBottom: "env(safe-area-inset-bottom, 0px)",
61
- background: "var(--ck-bg-surface)",
62
- borderTop: "1px solid var(--ck-border-subtle)",
63
- display: "flex",
64
- justifyContent: "space-around",
65
- alignItems: "stretch",
66
- zIndex: 50,
67
- fontFamily: "var(--ck-font-sans)",
68
- } as CSSProperties
69
- }
70
- >
71
- {tabs.map((t) => (
72
- <button
73
- key={t.key}
74
- type="button"
75
- onClick={t.onSelect}
76
- aria-current={t.active ? "page" : undefined}
77
- style={{
78
- flex: 1,
79
- display: "flex",
80
- flexDirection: "column",
81
- alignItems: "center",
82
- justifyContent: "center",
83
- gap: 2,
84
- padding: "6px 8px",
85
- border: "none",
86
- background: "transparent",
87
- color: t.active ? "var(--ck-accent)" : "var(--ck-text-tertiary)",
88
- cursor: "pointer",
89
- font: "500 11px/1 var(--ck-font-sans)",
90
- transition: "color var(--ck-dur-fast) var(--ck-ease)",
91
- }}
92
- >
93
- <span style={{ fontSize: 18, lineHeight: 1, display: "inline-flex" }}>
94
- {t.icon}
95
- </span>
96
- <span>{t.label}</span>
97
- </button>
98
- ))}
99
- </nav>
100
- );
101
- }
@@ -1,128 +0,0 @@
1
- import type { ReactNode, CSSProperties } from "react";
2
- import { CountBadge } from "../primitives/CountBadge";
3
-
4
- // Single nav row inside <LeftNavRail>. Router-agnostic — pass your
5
- // own router's link primitive via the `as` prop, or fall back to a
6
- // plain anchor. Collapsed mode renders icon-only with the label as
7
- // a tooltip.
8
- //
9
- // Use with NavLink-style render-prop routers by wrapping NavItem
10
- // with your router's link and forwarding `active`:
11
- //
12
- // <NavLink to="/x">
13
- // {({ isActive }) =>
14
- // <NavItem active={isActive} icon={<X/>} label="X" />
15
- // }
16
- // </NavLink>
17
-
18
- export interface NavItemProps {
19
- // Visible label (also used as tooltip when collapsed).
20
- label: string;
21
- icon: ReactNode;
22
- active?: boolean;
23
- // Optional notification count badge — renders nothing for 0.
24
- badge?: number;
25
- collapsed?: boolean;
26
- onClick?: () => void;
27
- // Render as an anchor with this href. When omitted, renders as
28
- // a button (use onClick).
29
- href?: string;
30
- // Optional custom render — escape hatch for router-link wrappers
31
- // that need to spread their own props on the element. Receives
32
- // the rendered children + the inline style.
33
- className?: string;
34
- style?: CSSProperties;
35
- }
36
-
37
- export function NavItem({
38
- label,
39
- icon,
40
- active,
41
- badge,
42
- collapsed,
43
- onClick,
44
- href,
45
- className,
46
- style,
47
- }: NavItemProps) {
48
- const showBadge = badge !== undefined && badge > 0;
49
- const baseStyle: CSSProperties = {
50
- position: "relative",
51
- display: "flex",
52
- alignItems: "center",
53
- borderRadius: "var(--ck-radius-md)",
54
- transition: "background var(--ck-dur-fast) var(--ck-ease), color var(--ck-dur-fast) var(--ck-ease)",
55
- background: active ? "var(--ck-accent-muted)" : "transparent",
56
- color: active ? "var(--ck-accent)" : "var(--ck-text-secondary)",
57
- font: "400 13px/1 var(--ck-font-sans)",
58
- fontWeight: active ? 500 : 400,
59
- cursor: "pointer",
60
- textDecoration: "none",
61
- border: "none",
62
- ...(collapsed
63
- ? {
64
- justifyContent: "center",
65
- width: 40,
66
- height: 40,
67
- }
68
- : {
69
- justifyContent: "space-between",
70
- padding: "8px 12px",
71
- }),
72
- ...style,
73
- };
74
-
75
- const content = collapsed ? (
76
- <>
77
- <span style={{ display: "inline-flex" }}>{icon}</span>
78
- {showBadge && (
79
- <span style={{ position: "absolute", top: 2, right: 2 }}>
80
- <CountBadge count={badge} size="sm" tone="critical" />
81
- </span>
82
- )}
83
- </>
84
- ) : (
85
- <>
86
- <span style={{ display: "inline-flex", alignItems: "center", gap: 10 }}>
87
- {icon}
88
- <span>{label}</span>
89
- </span>
90
- {showBadge && <CountBadge count={badge} size="sm" tone="critical" />}
91
- </>
92
- );
93
-
94
- // data-ck-navitem + data-active are escape hatches for chrome
95
- // CSS to override the inline visual state (e.g. neobrutalism
96
- // wants a fully different chunky look on the active item).
97
- const dataAttrs = {
98
- "data-ck-navitem": "",
99
- "data-active": active ? "true" : undefined,
100
- };
101
-
102
- if (href !== undefined) {
103
- return (
104
- <a
105
- href={href}
106
- title={collapsed ? label : undefined}
107
- className={className}
108
- style={baseStyle}
109
- {...dataAttrs}
110
- >
111
- {content}
112
- </a>
113
- );
114
- }
115
-
116
- return (
117
- <button
118
- type="button"
119
- onClick={onClick}
120
- title={collapsed ? label : undefined}
121
- className={className}
122
- style={baseStyle}
123
- {...dataAttrs}
124
- >
125
- {content}
126
- </button>
127
- );
128
- }
@@ -1,88 +0,0 @@
1
- import { Kbd } from "../primitives/Kbd";
2
-
3
- // Search-style command-palette opener for the left rail. Wide
4
- // click target, search icon on the left, kbd hint on the right.
5
- // Hidden in collapsed mode — the palette is still reachable via
6
- // ⌘K, no need for a dedicated trigger when there's no label space.
7
-
8
- export interface NavSearchTriggerProps {
9
- onClick: () => void;
10
- placeholder?: string;
11
- hotkey?: string;
12
- collapsed?: boolean;
13
- }
14
-
15
- export function NavSearchTrigger({
16
- onClick,
17
- placeholder = "Search",
18
- hotkey = "K",
19
- collapsed,
20
- }: NavSearchTriggerProps) {
21
- if (collapsed) return null;
22
- return (
23
- <button
24
- type="button"
25
- onClick={onClick}
26
- aria-label="Open command palette"
27
- title="Open command palette"
28
- data-ck-search-trigger
29
- style={{
30
- position: "relative",
31
- width: "100%",
32
- height: 34,
33
- padding: "0 8px 0 32px",
34
- background: "var(--ck-bg-muted)",
35
- border: "1px solid transparent",
36
- borderRadius: "var(--ck-radius-sm)",
37
- cursor: "pointer",
38
- display: "flex",
39
- alignItems: "center",
40
- justifyContent: "space-between",
41
- textAlign: "left",
42
- transition: "background var(--ck-dur-fast) var(--ck-ease), border-color var(--ck-dur-fast) var(--ck-ease)",
43
- }}
44
- onMouseEnter={(e) => {
45
- e.currentTarget.style.borderColor = "var(--ck-border-strong)";
46
- }}
47
- onMouseLeave={(e) => {
48
- e.currentTarget.style.borderColor = "transparent";
49
- }}
50
- >
51
- <svg
52
- width="14"
53
- height="14"
54
- viewBox="0 0 24 24"
55
- fill="none"
56
- stroke="currentColor"
57
- strokeWidth="2"
58
- strokeLinecap="round"
59
- strokeLinejoin="round"
60
- style={{
61
- position: "absolute",
62
- left: 10,
63
- top: "50%",
64
- transform: "translateY(-50%)",
65
- color: "var(--ck-text-tertiary)",
66
- pointerEvents: "none",
67
- }}
68
- aria-hidden
69
- >
70
- <circle cx="11" cy="11" r="7" />
71
- <line x1="21" y1="21" x2="16.65" y2="16.65" />
72
- </svg>
73
- <span
74
- style={{
75
- flex: 1,
76
- font: "400 12px/1 var(--ck-font-sans)",
77
- color: "var(--ck-text-tertiary)",
78
- }}
79
- >
80
- {placeholder}
81
- </span>
82
- <span style={{ display: "inline-flex", gap: 2 }}>
83
- <Kbd>Mod</Kbd>
84
- <Kbd>{hotkey}</Kbd>
85
- </span>
86
- </button>
87
- );
88
- }
@@ -1,40 +0,0 @@
1
- import type { ReactNode } from "react";
2
-
3
- // Section header inside <LeftNavRail>. Mono uppercase eyebrow above
4
- // a group of <NavItem>s. Hides its own label in collapsed mode —
5
- // icons are self-explanatory at 56 px and the cluster delimiters
6
- // become visual noise.
7
-
8
- export interface NavSectionProps {
9
- label: string;
10
- collapsed?: boolean;
11
- children: ReactNode;
12
- }
13
-
14
- export function NavSection({ label, collapsed, children }: NavSectionProps) {
15
- return (
16
- <div style={{ marginBottom: 16 }}>
17
- {!collapsed && (
18
- <div
19
- className="ck-tag"
20
- style={{
21
- padding: "0 12px",
22
- marginBottom: 6,
23
- }}
24
- >
25
- {label}
26
- </div>
27
- )}
28
- <div
29
- style={{
30
- display: "flex",
31
- flexDirection: "column",
32
- gap: collapsed ? 4 : 1,
33
- alignItems: collapsed ? "center" : "stretch",
34
- }}
35
- >
36
- {children}
37
- </div>
38
- </div>
39
- );
40
- }
@@ -1,111 +0,0 @@
1
- import type { ReactNode, CSSProperties } from "react";
2
-
3
- // Floating right-side panel. Used for ephemeral side surfaces —
4
- // comments, signing management, review-link list, etc. Unlike the
5
- // always-on AgentRail-style right rail, this is summoned by user
6
- // action and dismissed via the close button or Esc.
7
- //
8
- // Sticks below the topbar (reads --ck-breadcrumb-height), max-height
9
- // leaves room for any bottom-fixed UI (--ck-tabbar-height).
10
- // Caller owns the open/close state.
11
-
12
- export interface RightSidebarPanelProps {
13
- open: boolean;
14
- onClose: () => void;
15
- // Required — small uppercase eyebrow above the title slot.
16
- eyebrow: string;
17
- title?: ReactNode;
18
- // Right-side header slot (e.g. filter dropdown). Sits beside the
19
- // close button.
20
- headerExtras?: ReactNode;
21
- children: ReactNode;
22
- // px. Default 320.
23
- width?: number;
24
- // px offset from viewport edges. Default 12.
25
- edgeOffset?: number;
26
- className?: string;
27
- }
28
-
29
- export function RightSidebarPanel({
30
- open,
31
- onClose,
32
- eyebrow,
33
- title,
34
- headerExtras,
35
- children,
36
- width = 320,
37
- edgeOffset = 12,
38
- className,
39
- }: RightSidebarPanelProps) {
40
- if (!open) return null;
41
- const topOffset = `calc(var(--ck-breadcrumb-height, 64px) + ${edgeOffset}px)`;
42
- const bottomOffset = `calc(var(--ck-tabbar-height, 0px) + ${edgeOffset}px)`;
43
- return (
44
- <aside
45
- role="complementary"
46
- className={className}
47
- style={
48
- {
49
- position: "fixed",
50
- top: topOffset,
51
- right: edgeOffset,
52
- width,
53
- maxHeight: `calc(100vh - ${topOffset} - ${bottomOffset})`,
54
- background: "var(--ck-bg-surface)",
55
- border: "1px solid var(--ck-border-subtle)",
56
- borderRadius: "var(--ck-radius-md)",
57
- boxShadow: "var(--ck-shadow-2)",
58
- display: "flex",
59
- flexDirection: "column",
60
- zIndex: 60,
61
- fontFamily: "var(--ck-font-sans)",
62
- } as CSSProperties
63
- }
64
- >
65
- <div
66
- style={{
67
- padding: "14px 16px",
68
- borderBottom: "1px solid var(--ck-border-subtle)",
69
- display: "flex",
70
- alignItems: "flex-start",
71
- gap: 8,
72
- }}
73
- >
74
- <div style={{ flex: 1, minWidth: 0 }}>
75
- <div className="ck-eyebrow" style={{ marginBottom: title ? 4 : 0 }}>
76
- {eyebrow}
77
- </div>
78
- {title && (
79
- <div
80
- style={{
81
- font: "500 14px/1.3 var(--ck-font-sans)",
82
- color: "var(--ck-text-primary)",
83
- }}
84
- >
85
- {title}
86
- </div>
87
- )}
88
- </div>
89
- {headerExtras}
90
- <button
91
- type="button"
92
- onClick={onClose}
93
- aria-label="Close"
94
- style={{
95
- border: "none",
96
- background: "transparent",
97
- color: "var(--ck-text-tertiary)",
98
- cursor: "pointer",
99
- fontSize: 18,
100
- lineHeight: 1,
101
- padding: 2,
102
- marginLeft: 4,
103
- }}
104
- >
105
- ×
106
- </button>
107
- </div>
108
- <div style={{ flex: 1, minHeight: 0, overflowY: "auto" }}>{children}</div>
109
- </aside>
110
- );
111
- }
@@ -1,91 +0,0 @@
1
- import type { ReactNode, CSSProperties } from "react";
2
-
3
- // Layout shell. The kit is unopinionated about WHICH navigation
4
- // primitives sit in each slot — pass <LeftNavRail>, <Topbar>,
5
- // <MobileTabBar> etc. (or your own equivalents) and Shell composes
6
- // them into the standard layout:
7
- //
8
- // ┌──────────────────────────────────────────┐
9
- // │ topbar (full width, fixed) │
10
- // ├────────┬─────────────────────────┬───────┤
11
- // │ │ │ │
12
- // │ left │ main (children) │ right │
13
- // │ nav │ │ rail │
14
- // │ (fix) │ insets via CSS vars │ (fix) │
15
- // │ │ │ │
16
- // └────────┴─────────────────────────┴───────┘
17
- //
18
- // All three rails are position:fixed and stamp their widths/heights
19
- // as CSS vars (--ck-leftnav-width, --ck-rightrail-width,
20
- // --ck-tabbar-height). Shell reads those vars to inset the main
21
- // region. No prop drilling.
22
-
23
- export interface ShellProps {
24
- // Drop <LeftNavRail> here. Shell renders it as-is; the rail itself
25
- // handles fixed positioning.
26
- leftRail?: ReactNode;
27
- // <Topbar>. Sticky at the top of the main column.
28
- topbar?: ReactNode;
29
- // Page body.
30
- children: ReactNode;
31
- // Right rail (e.g. agent panel, comments panel) — rendered as-is.
32
- rightRail?: ReactNode;
33
- // Mobile bottom tab bar — rendered as-is.
34
- tabBar?: ReactNode;
35
- // Inline style overrides for the main region (useful for setting
36
- // background per route).
37
- mainStyle?: CSSProperties;
38
- className?: string;
39
- }
40
-
41
- export function Shell({
42
- leftRail,
43
- topbar,
44
- children,
45
- rightRail,
46
- tabBar,
47
- mainStyle,
48
- className,
49
- }: ShellProps) {
50
- return (
51
- <div
52
- data-ck-shell
53
- className={className}
54
- style={{
55
- minHeight: "100vh",
56
- background: "var(--ck-bg-canvas)",
57
- color: "var(--ck-text-primary)",
58
- }}
59
- >
60
- {leftRail}
61
- {rightRail}
62
- {tabBar}
63
- <div
64
- style={
65
- {
66
- marginLeft: "var(--ck-leftnav-width, 0px)",
67
- marginRight: "var(--ck-rightrail-width, 0px)",
68
- paddingBottom: "var(--ck-tabbar-height, 0px)",
69
- minHeight: "100vh",
70
- display: "flex",
71
- flexDirection: "column",
72
- transition: "margin var(--ck-dur-fast) var(--ck-ease)",
73
- } as CSSProperties
74
- }
75
- >
76
- {topbar && (
77
- <div
78
- style={{
79
- position: "sticky",
80
- top: 0,
81
- zIndex: 20,
82
- }}
83
- >
84
- {topbar}
85
- </div>
86
- )}
87
- <main style={{ flex: 1, minHeight: 0, ...mainStyle }}>{children}</main>
88
- </div>
89
- </div>
90
- );
91
- }