@rebasepro/app 0.17.3 → 0.18.1

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 (185) hide show
  1. package/README.md +4 -1
  2. package/dist/components/index.d.ts +0 -3
  3. package/dist/contexts/AuthControllerContext.d.ts +2 -1
  4. package/dist/contexts/CustomizationControllerContext.d.ts +2 -1
  5. package/dist/contexts/DialogsProvider.d.ts +2 -1
  6. package/dist/contexts/RebaseDataContext.d.ts +10 -1
  7. package/dist/contexts/StorageSourceContext.d.ts +11 -1
  8. package/dist/core/RebaseProps.d.ts +2 -12
  9. package/dist/debug/index.d.ts +19 -0
  10. package/dist/debug.js +3631 -0
  11. package/dist/hooks/data/delete.d.ts +16 -7
  12. package/dist/hooks/data/save.d.ts +18 -4
  13. package/dist/hooks/index.d.ts +1 -0
  14. package/dist/hooks/useAdminModeController.d.ts +5 -4
  15. package/dist/hooks/useNavigationGroupLabel.d.ts +17 -0
  16. package/dist/hooks/useStudioBridge.d.ts +33 -0
  17. package/dist/index.es.js +2599 -6980
  18. package/dist/index.es.js.map +1 -1
  19. package/dist/vitePlugin.d.ts +22 -0
  20. package/dist/vitePlugin.js +40 -1
  21. package/package.json +42 -31
  22. package/src/auth/api.ts +0 -134
  23. package/src/auth/index.ts +0 -26
  24. package/src/auth/types.ts +0 -115
  25. package/src/auth/useRebaseAuthController.ts +0 -345
  26. package/src/collections/collection_view_config.ts +0 -76
  27. package/src/collections/entity-display-cache.ts +0 -195
  28. package/src/collections/entity-display.ts +0 -77
  29. package/src/collections/entity_image_preview.ts +0 -61
  30. package/src/collections/filter-operator-resolution.ts +0 -119
  31. package/src/collections/form-layout.ts +0 -394
  32. package/src/collections/index.ts +0 -13
  33. package/src/collections/navigation_from_path.ts +0 -123
  34. package/src/collections/navigation_utils.ts +0 -171
  35. package/src/collections/parent_references_from_path.ts +0 -59
  36. package/src/collections/property-path.ts +0 -30
  37. package/src/collections/property_presentation.ts +0 -264
  38. package/src/collections/summary-property.ts +0 -114
  39. package/src/collections/title-property.ts +0 -312
  40. package/src/components/AIIcon.tsx +0 -47
  41. package/src/components/AuthSimulationMenu.tsx +0 -0
  42. package/src/components/ConfirmationDialog.tsx +0 -48
  43. package/src/components/Debug/UIReferenceView.tsx +0 -1053
  44. package/src/components/Debug/UIStyleGuide.tsx +0 -159
  45. package/src/components/Debug/collection-views/CardViewDemo.tsx +0 -87
  46. package/src/components/Debug/collection-views/CollectionTableDemo.tsx +0 -107
  47. package/src/components/Debug/collection-views/KanbanBoardDemo.tsx +0 -89
  48. package/src/components/Debug/collection-views/index.ts +0 -3
  49. package/src/components/Debug/collection-views/sample_data.ts +0 -44
  50. package/src/components/Debug/crm-dashboard/CalendarWidget.tsx +0 -387
  51. package/src/components/Debug/crm-dashboard/CrmDashboardDemo.tsx +0 -1100
  52. package/src/components/Debug/crm-dashboard/DashboardMetrics.tsx +0 -131
  53. package/src/components/Debug/crm-dashboard/PipelineOverview.tsx +0 -288
  54. package/src/components/Debug/crm-dashboard/RecentActivity.tsx +0 -213
  55. package/src/components/Debug/crm-dashboard/TaskFilters.tsx +0 -182
  56. package/src/components/Debug/crm-dashboard/TaskTable.tsx +0 -425
  57. package/src/components/Debug/crm-dashboard/TasksView.tsx +0 -234
  58. package/src/components/ErrorTooltip.tsx +0 -12
  59. package/src/components/ErrorView.tsx +0 -94
  60. package/src/components/LanguageToggle.tsx +0 -59
  61. package/src/components/LoginView/LoginView.tsx +0 -1235
  62. package/src/components/LoginView/index.ts +0 -2
  63. package/src/components/LoginView/oauth-redirect-flow.ts +0 -184
  64. package/src/components/NotFoundPage.tsx +0 -27
  65. package/src/components/RebaseAuth.tsx +0 -27
  66. package/src/components/RebaseLogo.tsx +0 -88
  67. package/src/components/SchemaDriftBanner.tsx +0 -102
  68. package/src/components/UnsavedChangesDialog.tsx +0 -46
  69. package/src/components/UserDisplay.tsx +0 -54
  70. package/src/components/UserSelectPopover.tsx +0 -399
  71. package/src/components/UserSettingsView.tsx +0 -318
  72. package/src/components/common/index.ts +0 -6
  73. package/src/components/common/table_height.tsx +0 -21
  74. package/src/components/common/types.tsx +0 -66
  75. package/src/components/common/useColumnsIds.tsx +0 -261
  76. package/src/components/common/useDataTableController.tsx +0 -571
  77. package/src/components/common/useDebouncedData.ts +0 -49
  78. package/src/components/common/useScrollRestoration.tsx +0 -68
  79. package/src/components/index.tsx +0 -26
  80. package/src/contexts/AdminModeController.tsx +0 -11
  81. package/src/contexts/AnalyticsContext.tsx +0 -4
  82. package/src/contexts/AuthControllerContext.tsx +0 -4
  83. package/src/contexts/CollectionResolverContext.tsx +0 -24
  84. package/src/contexts/CollectionScopeContext.tsx +0 -68
  85. package/src/contexts/ComponentOverrideContext.tsx +0 -81
  86. package/src/contexts/CustomizationControllerContext.tsx +0 -4
  87. package/src/contexts/DataDriverContext.tsx +0 -4
  88. package/src/contexts/DataSourcesContext.tsx +0 -36
  89. package/src/contexts/DatabaseAdminContext.tsx +0 -4
  90. package/src/contexts/DialogsProvider.tsx +0 -56
  91. package/src/contexts/EffectiveRoleController.tsx +0 -12
  92. package/src/contexts/ModeController.tsx +0 -11
  93. package/src/contexts/RebaseClientInstanceContext.tsx +0 -7
  94. package/src/contexts/RebaseDataContext.tsx +0 -4
  95. package/src/contexts/SnackbarProvider.tsx +0 -15
  96. package/src/contexts/StorageSourceContext.tsx +0 -4
  97. package/src/contexts/StorageSourcesContext.tsx +0 -30
  98. package/src/contexts/UserConfigurationPersistenceContext.tsx +0 -4
  99. package/src/contexts/index.ts +0 -18
  100. package/src/core/PluginLifecycleManager.tsx +0 -96
  101. package/src/core/PluginProviderStack.tsx +0 -40
  102. package/src/core/Rebase.tsx +0 -488
  103. package/src/core/RebaseProps.tsx +0 -333
  104. package/src/core/RebaseRouter.tsx +0 -18
  105. package/src/core/RebaseRoutes.tsx +0 -24
  106. package/src/core/index.tsx +0 -5
  107. package/src/hooks/ApiConfigContext.tsx +0 -83
  108. package/src/hooks/data/collectionQuery.ts +0 -55
  109. package/src/hooks/data/delete.ts +0 -56
  110. package/src/hooks/data/save.ts +0 -78
  111. package/src/hooks/data/useCollection.tsx +0 -183
  112. package/src/hooks/data/useData.tsx +0 -18
  113. package/src/hooks/data/useDataOrder.ts +0 -26
  114. package/src/hooks/data/useFetch.tsx +0 -156
  115. package/src/hooks/data/useRelationSelector.tsx +0 -280
  116. package/src/hooks/index.tsx +0 -45
  117. package/src/hooks/useAdminModeController.tsx +0 -23
  118. package/src/hooks/useAnalyticsController.tsx +0 -8
  119. package/src/hooks/useAuthController.tsx +0 -15
  120. package/src/hooks/useAuthSubscription.ts +0 -130
  121. package/src/hooks/useBackendStorageSource.ts +0 -295
  122. package/src/hooks/useBridgeRegistration.tsx +0 -32
  123. package/src/hooks/useBrowserTitleAndIcon.tsx +0 -23
  124. package/src/hooks/useBuildAdminModeController.tsx +0 -29
  125. package/src/hooks/useBuildEffectiveRoleController.tsx +0 -30
  126. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +0 -83
  127. package/src/hooks/useBuildModeController.tsx +0 -73
  128. package/src/hooks/useClipboard.tsx +0 -158
  129. package/src/hooks/useCollapsedGroups.ts +0 -116
  130. package/src/hooks/useComponentOverride.tsx +0 -59
  131. package/src/hooks/useCustomizationController.tsx +0 -14
  132. package/src/hooks/useDialogsController.tsx +0 -15
  133. package/src/hooks/useEffectiveRoleController.tsx +0 -10
  134. package/src/hooks/useLargeLayout.tsx +0 -65
  135. package/src/hooks/useModeController.tsx +0 -23
  136. package/src/hooks/useNavigationBlocker.tsx +0 -108
  137. package/src/hooks/usePermissions.ts +0 -45
  138. package/src/hooks/useRebaseClient.tsx +0 -10
  139. package/src/hooks/useRebaseContext.tsx +0 -84
  140. package/src/hooks/useRebaseRegistry.tsx +0 -91
  141. package/src/hooks/useResolvedComponent.tsx +0 -195
  142. package/src/hooks/useSlot.tsx +0 -64
  143. package/src/hooks/useSnackbarController.tsx +0 -80
  144. package/src/hooks/useStorageSource.tsx +0 -11
  145. package/src/hooks/useStudioBridge.tsx +0 -258
  146. package/src/hooks/useTranslation.ts +0 -38
  147. package/src/hooks/useUnsavedChangesDialog.tsx +0 -67
  148. package/src/hooks/useUserConfigurationPersistence.tsx +0 -11
  149. package/src/i18n/RebaseI18nProvider.tsx +0 -159
  150. package/src/index.ts +0 -32
  151. package/src/internal/common.tsx +0 -28
  152. package/src/internal/useRestoreScroll.tsx +0 -69
  153. package/src/locales/de.ts +0 -941
  154. package/src/locales/en.ts +0 -1021
  155. package/src/locales/es.ts +0 -962
  156. package/src/locales/fr.ts +0 -941
  157. package/src/locales/hi.ts +0 -941
  158. package/src/locales/it.ts +0 -941
  159. package/src/locales/pt.ts +0 -949
  160. package/src/util/constants.ts +0 -7
  161. package/src/util/createFormexStub.tsx +0 -66
  162. package/src/util/entity_cache.ts +0 -242
  163. package/src/util/enums.ts +0 -34
  164. package/src/util/icon_list.ts +0 -22
  165. package/src/util/icons.tsx +0 -129
  166. package/src/util/index.ts +0 -13
  167. package/src/util/local_storage.ts +0 -66
  168. package/src/util/previews.ts +0 -127
  169. package/src/util/useStorageUploadController.tsx +0 -354
  170. package/src/vitePlugin.ts +0 -215
  171. /package/dist/{components/Debug → debug}/UIReferenceView.d.ts +0 -0
  172. /package/dist/{components/Debug → debug}/UIStyleGuide.d.ts +0 -0
  173. /package/dist/{components/Debug → debug}/collection-views/CardViewDemo.d.ts +0 -0
  174. /package/dist/{components/Debug → debug}/collection-views/CollectionTableDemo.d.ts +0 -0
  175. /package/dist/{components/Debug → debug}/collection-views/KanbanBoardDemo.d.ts +0 -0
  176. /package/dist/{components/Debug → debug}/collection-views/index.d.ts +0 -0
  177. /package/dist/{components/Debug → debug}/collection-views/sample_data.d.ts +0 -0
  178. /package/dist/{components/Debug → debug}/crm-dashboard/CalendarWidget.d.ts +0 -0
  179. /package/dist/{components/Debug → debug}/crm-dashboard/CrmDashboardDemo.d.ts +0 -0
  180. /package/dist/{components/Debug → debug}/crm-dashboard/DashboardMetrics.d.ts +0 -0
  181. /package/dist/{components/Debug → debug}/crm-dashboard/PipelineOverview.d.ts +0 -0
  182. /package/dist/{components/Debug → debug}/crm-dashboard/RecentActivity.d.ts +0 -0
  183. /package/dist/{components/Debug → debug}/crm-dashboard/TaskFilters.d.ts +0 -0
  184. /package/dist/{components/Debug → debug}/crm-dashboard/TaskTable.d.ts +0 -0
  185. /package/dist/{components/Debug → debug}/crm-dashboard/TasksView.d.ts +0 -0
@@ -1,1053 +0,0 @@
1
-
2
- /**
3
- * UIReferenceView — hidden debug route at /debug/ui
4
- *
5
- * This file is a STATIC reference of the real UI patterns used across the app.
6
- * Markup / styles are copied from source files where a section mirrors a real
7
- * screen. DO NOT add invented styles — copy from actual source files, or from
8
- * the components in @rebasepro/ui.
9
- *
10
- * Sections named after a component mirror that component. Sections named after
11
- * a pattern (e.g. "Management Screen", "Form Dialog") are illustrative
12
- * compositions of kit components and are not tied to a specific screen.
13
- *
14
- * Do not cite source line numbers here — they rot silently. Name the file only.
15
- *
16
- * Sources:
17
- * DefaultDrawer.tsx, DefaultAppBar.tsx, DrawerNavigationItem.tsx,
18
- * DrawerNavigationGroup.tsx
19
- */
20
- import React, { useState } from "react";
21
- import {
22
- Alert,
23
- AlertCircleIcon,
24
- Avatar,
25
- AppWindow,
26
- BooleanSwitch,
27
- Button,
28
- Checkbox,
29
- ChevronDownIcon,
30
- ChevronsLeftIcon,
31
- ChevronsRightIcon,
32
- Chip,
33
- CircleUserIcon,
34
- CircularProgress,
35
- cls,
36
- ColumnsIcon,
37
- defaultBorderMixin,
38
- FileIcon,
39
- FileTextIcon,
40
- FilterChip,
41
- FilterIcon,
42
- FolderIcon,
43
- IconButton,
44
- iconSize,
45
- KanbanIcon,
46
- LayoutGridIcon,
47
- ListIcon,
48
- LoadingButton,
49
- LogOutIcon,
50
- Menu,
51
- MenuItem,
52
- MoonIcon,
53
- MultiSelect,
54
- MultiSelectItem,
55
- PanelLeftIcon,
56
- PencilIcon,
57
- PlusIcon,
58
- SearchBar,
59
- Select,
60
- SelectItem,
61
- Separator,
62
- SettingsIcon,
63
- Skeleton,
64
- SunIcon,
65
- SunMoonIcon,
66
- Tab,
67
- Table,
68
- TableBody,
69
- TableCell,
70
- TableHeader,
71
- TableRow,
72
- Tabs,
73
- TagIcon,
74
- TextField,
75
- Tooltip,
76
- Trash2Icon,
77
- TypeIcon,
78
- Typography,
79
- UserIcon
80
- } from "@rebasepro/ui";
81
- import { RebaseLogo } from "../RebaseLogo";
82
- import { CrmDashboardDemo } from "./crm-dashboard/CrmDashboardDemo";
83
- import { CollectionTableDemo, CardViewDemo, KanbanBoardDemo } from "./collection-views";
84
-
85
- const SECTIONS = [
86
- { id: "drawer", label: "Drawer", icon: PanelLeftIcon },
87
- { id: "appbar", label: "App Bar", icon: AppWindow },
88
- { id: "tabs", label: "Tabs", icon: ListIcon },
89
- { id: "editor-sidebar", label: "Editor Sidebar", icon: ColumnsIcon },
90
- { id: "empty-states", label: "Empty States", icon: FileIcon },
91
- { id: "typography", label: "Typography", icon: TypeIcon },
92
- { id: "buttons", label: "Buttons", icon: PlusIcon },
93
- { id: "inputs", label: "Form Inputs", icon: FileTextIcon },
94
- { id: "chips-alerts", label: "Chips & Alerts", icon: AlertCircleIcon },
95
- { id: "users", label: "Management", icon: UserIcon },
96
- { id: "user-dialog", label: "Form Dialog", icon: CircleUserIcon },
97
- { id: "crm-dashboard", label: "CRM Dashboard", icon: LayoutGridIcon },
98
- { id: "collection-table", label: "Collection Table", icon: ListIcon },
99
- { id: "card-view", label: "Card View", icon: LayoutGridIcon },
100
- { id: "kanban-board", label: "Kanban Board", icon: KanbanIcon }
101
- ];
102
-
103
- export function UIReferenceView() {
104
- const [activeSection, setActiveSection] = useState("drawer");
105
- const scrollContainerRef = React.useRef<HTMLDivElement>(null);
106
-
107
- const scrollTo = (id: string) => {
108
- const el = document.getElementById(id);
109
- const container = scrollContainerRef.current;
110
- if (el && container) {
111
- const offsetTop = el.offsetTop - container.offsetTop;
112
- container.scrollTo({ top: offsetTop, behavior: "smooth" });
113
- }
114
- setActiveSection(id);
115
- };
116
-
117
- return (
118
- <div className="flex w-full">
119
-
120
- {/* ── Sidebar nav (same structure as DefaultDrawer) ─────────────── */}
121
- {/* 232px, not 200px. The icon rail is 56px and the label is uppercase
122
- at 12px, which left ~128px — one character short of "COLLECTION
123
- TABLE", so the longest entry in the list rendered as
124
- "COLLECTION TA…". This is the reference's own nav, not the shared
125
- DefaultDrawer, so widening it costs no copy-fidelity. */}
126
- <div className={cls("flex flex-col sticky top-0 h-screen grow-0 shrink-0 w-[232px] border-r", defaultBorderMixin)}>
127
- {/* DrawerLogo */}
128
- <div className="flex flex-row items-center shrink-0 pt-4 pb-2 px-2">
129
- <div className="shrink-0 flex items-center justify-center w-[56px] h-[40px]">
130
- <RebaseLogo width="28px" height="28px"/>
131
- </div>
132
- <Typography variant="subtitle1" noWrap className="truncate">UI Ref</Typography>
133
- </div>
134
-
135
- {/* Nav entries */}
136
- <div className="mt-3 flex-grow overflow-scroll no-scrollbar">
137
- <div className="my-2 mx-2 flex flex-col">
138
- {/* Group header — from DrawerNavigationGroup */}
139
- <div className={cls("pl-4 pr-2 py-1 flex flex-row items-center transition-colors cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-700/50 rounded-t-lg bg-surface-50 dark:bg-surface-950/30")}>
140
- <ChevronDownIcon size={iconSize.smallest} className="text-surface-500 dark:text-surface-400 transition-transform duration-200 mr-1"/>
141
- <Typography variant="caption" color="secondary" className="font-medium flex-grow line-clamp-1">
142
- SECTIONS
143
- </Typography>
144
- </div>
145
- {/* Nav items — from DrawerNavigationItem */}
146
- <div className="overflow-hidden bg-surface-50 dark:bg-surface-950/30 rounded-b-lg">
147
- {SECTIONS.map(s => {
148
- const IconComponent = s.icon;
149
- return (
150
- <div key={s.id}>
151
- <div
152
- onClick={() => scrollTo(s.id)}
153
- className={cls(
154
- "rounded-lg truncate group/nav",
155
- "hover:bg-primary/5 dark:hover:bg-primary/5 text-text-primary dark:text-surface-200 hover:text-surface-900 dark:hover:text-white",
156
- "flex flex-row items-center",
157
- "pr-4 h-10",
158
- "font-medium text-xs cursor-pointer",
159
- activeSection === s.id ? "bg-primary/8 dark:bg-primary/10 text-primary dark:text-primary" : ""
160
- )}
161
- >
162
- <div className={cls("shrink-0 flex items-center justify-center w-[56px] h-[40px] text-surface-500 dark:text-text-secondary-dark transition-colors duration-150 group-hover/nav:text-primary", activeSection === s.id && "text-primary dark:text-primary")}>
163
- <IconComponent size={iconSize.small}/>
164
- </div>
165
- <div className="text-text-primary dark:text-surface-200 opacity-100 font-inherit truncate space-x-2">
166
- {s.label.toUpperCase()}
167
- </div>
168
- </div>
169
- </div>
170
- );
171
- })}
172
- </div>
173
- </div>
174
- </div>
175
-
176
- {/* DrawerToggle — from DefaultDrawer */}
177
- <div className={cls("shrink-0 mt-auto border-t px-2 py-2", defaultBorderMixin)}>
178
- <div className={cls(
179
- "flex flex-row items-center rounded-lg cursor-pointer",
180
- "hover:bg-surface-accent-100 dark:hover:bg-surface-800",
181
- "transition-colors duration-150",
182
- "py-2"
183
- )}>
184
- <div className="shrink-0 flex items-center justify-center w-[56px] h-[24px] text-surface-500 dark:text-surface-400">
185
- <ChevronsLeftIcon size={iconSize.small}/>
186
- </div>
187
- <Typography variant="body2" className="text-surface-500 dark:text-surface-400 select-none whitespace-nowrap">
188
- Collapse
189
- </Typography>
190
- </div>
191
- </div>
192
- </div>
193
-
194
- {/* ── Main content area ───────────────────────────────────────────── */}
195
- {/* `min-w-0` is required, not cosmetic. A flex item defaults to
196
- `min-width: auto`, so this column sized itself to its widest
197
- descendant — the 1451px CRM dashboard — and pushed the whole page
198
- past the viewport, cutting the collection table's last columns
199
- off screen. With `min-w-0` the column can shrink to the space
200
- available and the `overflow-x-auto` on the wide mocks actually
201
- engages instead of being overruled from above. */}
202
- <div ref={scrollContainerRef} className="flex-1 min-w-0">
203
-
204
- {/* ═══════════════════════════════════════════════
205
- SECTION: Drawer
206
- ═══════════════════════════════════════════════ */}
207
- <SectionBlock id="drawer" title="Drawer — DefaultDrawer.tsx">
208
- <Typography variant="body2" color="secondary" className="mb-4">
209
- The drawer wraps <code className="font-mono text-xs">DrawerLogo</code>, scrollable <code className="font-mono text-xs">DrawerNavigationGroup</code>s,
210
- and <code className="font-mono text-xs">DrawerToggle</code>. Two visual states: collapsed (icon only, 72px) and expanded (280px).
211
- </Typography>
212
- <div className="flex gap-6 flex-wrap">
213
-
214
- {/* Collapsed — exact markup from DefaultDrawer + DrawerNavigationItem */}
215
- <div>
216
- <Typography variant="caption" color="secondary" className="block mb-1">Collapsed (72px)</Typography>
217
- <div className={cls("flex flex-col h-72 relative w-[72px] border rounded-lg overflow-hidden bg-white dark:bg-surface-900", defaultBorderMixin)}>
218
- <div className="flex flex-row items-center shrink-0 pt-4 pb-2 px-2">
219
- <div className="shrink-0 flex items-center justify-center w-[56px] h-[40px]">
220
- <RebaseLogo width="28px" height="28px"/>
221
- </div>
222
- </div>
223
- <div className="mt-3 flex-grow overflow-hidden">
224
- <div className="my-2 mx-2 flex flex-col">
225
- <div className="overflow-hidden rounded-lg bg-surface-50 dark:bg-surface-950/30">
226
- {[<FolderIcon key="folder" size={iconSize.small}/>, <UserIcon key="user" size={iconSize.small}/>, <TagIcon key="tag" size={iconSize.small}/>].map((icon, i) => (
227
- <div key={i} className="rounded-lg truncate hover:bg-primary/5 dark:hover:bg-primary/5 flex flex-row items-center h-10">
228
- <div className="shrink-0 flex items-center justify-center w-[56px] h-[40px] text-text-secondary dark:text-text-secondary-dark">
229
- {icon}
230
- </div>
231
- </div>
232
- ))}
233
- </div>
234
- </div>
235
- </div>
236
- <div className={cls("shrink-0 mt-auto border-t px-2 py-2", defaultBorderMixin)}>
237
- <div className="flex flex-row items-center rounded-lg cursor-pointer hover:bg-surface-accent-100 dark:hover:bg-surface-800 transition-colors duration-150 py-2">
238
- <div className="shrink-0 flex items-center justify-center w-[56px] h-[24px] text-surface-500 dark:text-surface-400">
239
- <ChevronsRightIcon size={iconSize.small}/>
240
- </div>
241
- </div>
242
- </div>
243
- </div>
244
- </div>
245
-
246
- {/* Expanded — exact markup from DefaultDrawer + DrawerNavigationGroup + DrawerNavigationItem */}
247
- <div>
248
- <Typography variant="caption" color="secondary" className="block mb-1">Expanded (280px)</Typography>
249
- <div className={cls("flex flex-col h-72 relative w-[280px] border rounded-lg overflow-hidden bg-white dark:bg-surface-900", defaultBorderMixin)}>
250
- {/* DrawerLogo */}
251
- <div className="flex flex-row items-center shrink-0 pt-4 pb-2 px-2">
252
- <div className="shrink-0 flex items-center justify-center w-[56px] h-[40px]">
253
- <RebaseLogo width="28px" height="28px"/>
254
- </div>
255
- <div className="flex flex-row items-center overflow-hidden transition-all duration-200 ease-in-out opacity-100 w-full ml-1">
256
- <Typography variant="subtitle1" noWrap className="truncate">Rebase</Typography>
257
- </div>
258
- </div>
259
- {/* DrawerNavigationGroup */}
260
- <div className="mt-3 flex-grow overflow-hidden">
261
- <div className="my-2 mx-2 flex flex-col">
262
- <div className="pl-4 pr-2 py-1 flex flex-row items-center transition-colors cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-700/50 rounded-t-lg bg-surface-50 dark:bg-surface-950/30">
263
- <ChevronDownIcon size={iconSize.smallest} className="text-surface-500 dark:text-surface-400 mr-1"/>
264
- <Typography variant="caption" color="secondary" className="font-medium flex-grow line-clamp-1">CONTENT</Typography>
265
- </div>
266
- <div className="overflow-hidden bg-surface-50 dark:bg-surface-950/30 rounded-b-lg">
267
- {[
268
- { label: "Posts",
269
- icon: <FolderIcon size={iconSize.small}/>,
270
- active: true },
271
- { label: "Authors",
272
- icon: <UserIcon size={iconSize.small}/>,
273
- active: false },
274
- { label: "Tags",
275
- icon: <TagIcon size={iconSize.small}/>,
276
- active: false }
277
- ].map(({ label, icon, active }) => (
278
- <div key={label} className={cls(
279
- "rounded-lg truncate hover:bg-primary/5 dark:hover:bg-primary/5 text-text-primary dark:text-surface-200 hover:text-surface-900 dark:hover:text-white flex flex-row items-center pr-4 h-10 font-medium text-xs cursor-pointer",
280
- active ? "bg-primary/8 dark:bg-primary/10 text-primary dark:text-primary" : ""
281
- )}>
282
- <div className={cls("shrink-0 flex items-center justify-center w-[56px] h-[40px] transition-colors duration-150", active ? "text-primary dark:text-primary" : "text-surface-500 dark:text-text-secondary-dark")}>
283
- {icon}
284
- </div>
285
- <div className="text-text-primary dark:text-surface-200 font-inherit truncate">
286
- {label.toUpperCase()}
287
- </div>
288
- </div>
289
- ))}
290
- </div>
291
- </div>
292
- </div>
293
- {/* DrawerToggle */}
294
- <div className={cls("shrink-0 mt-auto border-t px-2 py-2", defaultBorderMixin)}>
295
- <div className="flex flex-row items-center rounded-lg cursor-pointer hover:bg-surface-accent-100 dark:hover:bg-surface-800 transition-colors duration-150 py-2">
296
- <div className="shrink-0 flex items-center justify-center w-[56px] h-[24px] text-surface-500 dark:text-surface-400">
297
- <ChevronsLeftIcon size={iconSize.small}/>
298
- </div>
299
- <div className="overflow-hidden transition-all duration-200 ease-in-out opacity-100 w-auto">
300
- <Typography variant="body2" className="text-surface-500 dark:text-surface-400 select-none whitespace-nowrap">
301
- Collapse
302
- </Typography>
303
- </div>
304
- </div>
305
- </div>
306
- </div>
307
- </div>
308
- </div>
309
- </SectionBlock>
310
-
311
- {/* ═══════════════════════════════════════════════
312
- SECTION: AppBar
313
- ═══════════════════════════════════════════════ */}
314
- <SectionBlock id="appbar" title="App Bar — DefaultAppBar.tsx">
315
- <Typography variant="body2" color="secondary" className="mb-4">
316
- Fixed at top (<code className="font-mono text-xs">h-16 absolute top-0</code>). Contains breadcrumbs (caption + body2), Content/Studio pill toggle,
317
- theme menu, and user avatar menu via <code className="font-mono text-xs">Menu</code>.
318
- </Typography>
319
- {/* Exact classes from DefaultAppBar */}
320
- <div className={cls("w-full h-16 flex flex-row gap-2 px-4 items-center border rounded-lg relative", defaultBorderMixin)}>
321
- {/* Breadcrumbs — from DefaultAppBar */}
322
- <div className="mr-8 hidden lg:block">
323
- <div className="flex flex-row gap-2 items-center">
324
- <Typography variant="caption" color="secondary">/</Typography>
325
- <div className="flex flex-row items-center gap-2 whitespace-nowrap">
326
- <Typography variant="body2">Posts</Typography>
327
- <span className="text-xs text-surface-accent-500 dark:text-surface-accent-400 bg-surface-100 dark:bg-surface-700 px-1 py-0 rounded">42</span>
328
- </div>
329
- <Typography variant="caption" color="secondary">/</Typography>
330
- <div className="flex flex-row items-center gap-2 whitespace-nowrap">
331
- <Typography variant="body2">My Post</Typography>
332
- </div>
333
- </div>
334
- </div>
335
- <div className="grow"/>
336
- {/* Content/Studio toggle — from DefaultAppBar */}
337
- <div className={cls("mr-2 hidden sm:flex bg-surface-100 dark:bg-surface-950 rounded-lg p-0.5 border", defaultBorderMixin)}>
338
- <button className={cls("px-3 py-1 text-xs font-semibold rounded-md transition-all", "bg-white dark:bg-surface-900 shadow-sm text-primary dark:text-primary-400")}>
339
- Content
340
- </button>
341
- <button className={cls("px-3 py-1 text-xs font-semibold rounded-md transition-all", "text-surface-500 hover:text-surface-900 dark:hover:text-white")}>
342
- Studio
343
- </button>
344
- </div>
345
- {/* Theme menu — from DefaultAppBar */}
346
- <Menu trigger={
347
- <IconButton color="inherit">
348
- <MoonIcon/>
349
- </IconButton>
350
- }>
351
- <MenuItem><MoonIcon size={iconSize.smallest}/> Dark</MenuItem>
352
- <MenuItem><SunIcon size={iconSize.smallest}/> Light</MenuItem>
353
- <MenuItem><SunMoonIcon size={iconSize.smallest}/> System</MenuItem>
354
- </Menu>
355
- {/* Avatar menu — from DefaultAppBar */}
356
- <Menu trigger={<Avatar>A</Avatar>}>
357
- <div className="px-4 py-2 mb-2">
358
- <Typography variant="body1" color="secondary">Alice Johnson</Typography>
359
- <Typography variant="body2" color="secondary">alice@example.com</Typography>
360
- </div>
361
- <MenuItem><SettingsIcon/> Account Settings</MenuItem>
362
- <MenuItem><LogOutIcon/> Log Out</MenuItem>
363
- </Menu>
364
- </div>
365
- </SectionBlock>
366
-
367
- {/* ═══════════════════════════════════════════════
368
- SECTION: Tabs
369
- ═══════════════════════════════════════════════ */}
370
- <SectionBlock id="tabs" title="Tabs — Tabs.tsx">
371
- <Typography variant="body2" color="secondary" className="mb-4">
372
- All editor components use <code className="font-mono text-xs">variant=&quot;boxy&quot;</code> tabs for sidebar navigation.
373
- The boxy variant provides a segmented, flat tab bar that integrates tightly with editor chrome.
374
- </Typography>
375
-
376
- <div className="flex flex-col gap-6">
377
- {/* Default variant */}
378
- <div>
379
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">variant=&quot;default&quot;</Typography>
380
- <Tabs value="tab1" onValueChange={() => {}}>
381
- <Tab value="tab1">Schema</Tab>
382
- <Tab value="tab2">Snippets</Tab>
383
- <Tab value="tab3">History</Tab>
384
- </Tabs>
385
- </div>
386
-
387
- {/* Boxy variant — exact pattern from SQLEditorSidebar, JSEditorSidebar, RLSEditor */}
388
- <div>
389
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">variant=&quot;boxy&quot; (Editor Standard)</Typography>
390
- <div className={cls("border rounded-lg overflow-hidden w-[320px]", defaultBorderMixin)}>
391
- <Tabs value="schema" onValueChange={() => {}} variant="boxy" className="border-b border-surface-200 dark:border-surface-950">
392
- <Tab value="schema">Schema</Tab>
393
- <Tab value="snippets">Snippets</Tab>
394
- <Tab value="history">History</Tab>
395
- </Tabs>
396
- {/* Section header pattern — used in all editor sidebars */}
397
- <div className={cls("p-3 border-b flex justify-between items-center bg-surface-50 dark:bg-surface-900", defaultBorderMixin)}>
398
- <Typography variant="caption" className="font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark">TABLES</Typography>
399
- <IconButton size="small">
400
- <SettingsIcon size={iconSize.smallest}/>
401
- </IconButton>
402
- </div>
403
- <div className="p-2 h-24">
404
- <Typography variant="caption" className="text-text-disabled dark:text-text-disabled-dark italic p-2">Tab content area…</Typography>
405
- </div>
406
- </div>
407
- </div>
408
-
409
- {/* Toolbar tabs — from SQLEditor/JSEditor main toolbar */}
410
- <div>
411
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">Toolbar Tabs (boxy, inline with controls)</Typography>
412
- <div className={cls("border rounded-lg overflow-hidden flex items-center justify-between pr-2 bg-white dark:bg-surface-950", defaultBorderMixin)}>
413
- <div className="flex items-center">
414
- <Tabs value="query1" onValueChange={() => {}} variant="boxy" className="w-[unset] flex-shrink-0">
415
- <Tab value="query1" className="flex items-center gap-1.5">
416
- <svg className="w-3.5 h-3.5 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"/></svg>
417
- Query 1
418
- </Tab>
419
- <Tab value="query2" className="flex items-center gap-1.5">
420
- <svg className="w-3.5 h-3.5 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"/></svg>
421
- Query 2
422
- </Tab>
423
- </Tabs>
424
- <IconButton size="small" className="ml-2 flex-shrink-0">
425
- <PlusIcon/>
426
- </IconButton>
427
- </div>
428
- <div className="flex items-center gap-1.5">
429
- <Button variant="text" size="small">Explain</Button>
430
- <div className="h-4 w-px bg-surface-200 dark:bg-surface-950"/>
431
- <Button size="small" color="primary">Run</Button>
432
- </div>
433
- </div>
434
- </div>
435
- </div>
436
- </SectionBlock>
437
-
438
- {/* ═══════════════════════════════════════════════
439
- SECTION: Editor Sidebar
440
- ═══════════════════════════════════════════════ */}
441
- <SectionBlock id="editor-sidebar" title="Editor Sidebar — Harmonized Pattern">
442
- <Typography variant="body2" color="secondary" className="mb-4">
443
- All studio editor components (SQL, JS, RLS, Collection) share the same underlying sidebar foundation:
444
- <code className="font-mono text-xs">Tabs variant=&quot;boxy&quot;</code> at top (optional) → section header with uppercase label → scrollable list.
445
- While SQL/JS/RLS use dense tree entries, the Collection Schema Editor uses larger items (<code className="font-mono text-xs">px-3 py-2</code>, <code className="font-mono text-xs">text-sm</code>) suitable for primary navigation.
446
- </Typography>
447
-
448
- <div className="flex gap-6 flex-wrap">
449
- {/* SQL Editor Sidebar replica */}
450
- <div>
451
- <Typography variant="caption" color="secondary" className="block mb-1">SQL Editor Sidebar</Typography>
452
- <div className={cls("flex flex-col h-72 w-[240px] border rounded-lg overflow-hidden", defaultBorderMixin)}>
453
- <Tabs value="schema" onValueChange={() => {}} variant="boxy" className="border-b border-surface-200 dark:border-surface-950">
454
- <Tab value="schema">Schema</Tab>
455
- <Tab value="snippets">Snippets</Tab>
456
- <Tab value="history">History</Tab>
457
- </Tabs>
458
- <div className={cls("p-3 border-b flex justify-between items-center bg-surface-50 dark:bg-surface-900", defaultBorderMixin)}>
459
- <Typography variant="caption" className="font-semibold uppercase tracking-wider text-text-secondary dark:text-text-secondary-dark">TABLES</Typography>
460
- <IconButton size="small">
461
- <SettingsIcon size={iconSize.smallest}/>
462
- </IconButton>
463
- </div>
464
- <div className="flex-grow overflow-y-auto no-scrollbar p-1">
465
- {/* Schema tree items — from SchemaBrowser */}
466
- <div className="mb-2">
467
- <div className="flex items-center p-1 cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-900 rounded transition-colors">
468
- <svg className="w-3 h-3 mr-1 rotate-90" fill="currentColor" viewBox="0 0 20 20"><path d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"/></svg>
469
- <Typography variant="body2" className="text-text-primary dark:text-text-primary-dark font-medium text-xs">public</Typography>
470
- </div>
471
- <div className="ml-3 mt-1 space-y-1">
472
- {["users", "posts", "comments"].map(t => (
473
- <div key={t} className="flex items-center p-1 cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-900 rounded transition-colors group">
474
- <svg className="w-3.5 h-3.5 mr-1 shrink-0 text-text-disabled dark:text-text-disabled-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg>
475
- <Typography variant="body2" className="text-text-secondary dark:text-text-secondary-dark text-xs truncate">{t}</Typography>
476
- </div>
477
- ))}
478
- </div>
479
- </div>
480
- </div>
481
- </div>
482
- </div>
483
-
484
- {/* RLS Editor Sidebar replica */}
485
- <div>
486
- <Typography variant="caption" color="secondary" className="block mb-1">RLS Editor Sidebar</Typography>
487
- <div className={cls("flex flex-col h-72 w-[240px] border rounded-lg overflow-hidden", defaultBorderMixin)}>
488
- <Tabs value="tables" onValueChange={() => {}} variant="boxy" className="border-b border-surface-200 dark:border-surface-950">
489
- <Tab value="tables">Tables</Tab>
490
- <Tab value="info">Info</Tab>
491
- </Tabs>
492
- <div className={cls("p-3 border-b flex justify-between items-center bg-surface-50 dark:bg-surface-900", defaultBorderMixin)}>
493
- <Typography variant="caption" className="font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark">RLS</Typography>
494
- <IconButton size="small">
495
- <SettingsIcon size={iconSize.smallest}/>
496
- </IconButton>
497
- </div>
498
- <div className="flex-grow overflow-y-auto no-scrollbar p-1">
499
- <div className="mb-2">
500
- <div className="flex items-center p-1 cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-900 rounded transition-colors">
501
- <svg className="w-3 h-3 mr-1 rotate-90" fill="currentColor" viewBox="0 0 20 20"><path d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"/></svg>
502
- <Typography variant="body2" className="text-text-primary dark:text-text-primary-dark font-medium text-xs">public</Typography>
503
- </div>
504
- <div className="ml-3 mt-1 space-y-0.5">
505
- {[{ name: "users",
506
- enabled: true }, { name: "posts",
507
- enabled: true }, { name: "sessions",
508
- enabled: false }].map(t => (
509
- <div key={t.name} className={cls("flex items-center p-1 cursor-pointer rounded transition-colors", t.name === "users" ? "bg-primary/10 text-primary dark:bg-primary/20" : "hover:bg-surface-100 dark:hover:bg-surface-900 text-text-secondary")}>
510
- <svg className="w-3.5 h-3.5 mr-1 shrink-0 text-text-disabled" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg>
511
- <Typography variant="body2" className="text-xs truncate flex-1">{t.name}</Typography>
512
- <div className={cls("w-1.5 h-1.5 rounded-full shrink-0", t.enabled ? "bg-green-500" : "bg-orange-400 opacity-50")}/>
513
- </div>
514
- ))}
515
- </div>
516
- </div>
517
- </div>
518
- </div>
519
- </div>
520
-
521
- {/* Collection Editor Sidebar replica */}
522
- <div>
523
- <Typography variant="caption" color="secondary" className="block mb-1">Collection Editor Sidebar</Typography>
524
- <div className={cls("flex flex-col h-72 w-[240px] border rounded-lg overflow-hidden bg-white dark:bg-surface-950", defaultBorderMixin)}>
525
- <div className={cls("p-3 border-b flex justify-between items-center bg-surface-50 dark:bg-surface-900", defaultBorderMixin)}>
526
- <Typography variant="caption" className="font-semibold uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark">COLLECTIONS</Typography>
527
- <IconButton size="small">
528
- <PlusIcon size={iconSize.smallest}/>
529
- </IconButton>
530
- </div>
531
- <div className="flex-grow overflow-y-auto no-scrollbar p-2 space-y-0.5">
532
- {[{ name: "Authors" }, { name: "Posts",
533
- selected: true }, { name: "Tags" }].map(c => (
534
- <div key={c.name} className={cls("flex items-center gap-3 px-3 py-2 cursor-pointer rounded-md text-sm transition-colors", c.selected ? "bg-primary/10 text-primary dark:bg-primary/20 dark:text-primary-light" : "hover:bg-surface-100 dark:hover:bg-surface-900 text-text-secondary dark:text-text-secondary-dark")}>
535
- <FolderIcon size={iconSize.small} className={cls(c.selected ? "text-primary dark:text-primary-light" : "text-text-secondary dark:text-text-secondary-dark")}/>
536
- <span className="truncate flex-1">{c.name}</span>
537
- </div>
538
- ))}
539
- </div>
540
- </div>
541
- </div>
542
- </div>
543
- </SectionBlock>
544
-
545
- {/* ═══════════════════════════════════════════════
546
- SECTION: Empty States
547
- ═══════════════════════════════════════════════ */}
548
- <SectionBlock id="empty-states" title="Empty States — Canonical Pattern">
549
- <Typography variant="body2" color="secondary" className="mb-4">
550
- All empty / placeholder states share the same layout: a centered <code className="font-mono text-xs">flex-col</code> container
551
- with <code className="font-mono text-xs">Typography variant=&quot;label&quot;</code> for the message and a <code className="font-mono text-xs">Button</code> with <code className="font-mono text-xs">AddIcon</code> for the primary action.
552
- Sources: <code className="font-mono text-xs">CollectionPropertiesEditorForm</code>, <code className="font-mono text-xs">CollectionsStudioView</code>, <code className="font-mono text-xs">CollectionStudioView</code>.
553
- </Typography>
554
-
555
- <div className="flex gap-6 flex-wrap">
556
- {/* Property editor empty state */}
557
- <div>
558
- <Typography variant="caption" color="secondary" className="block mb-1">Property Editor (no selection)</Typography>
559
- <div className={cls("flex flex-col items-center justify-center h-48 w-[320px] border rounded-lg", defaultBorderMixin)}>
560
- <div className="flex flex-col items-center justify-center h-full gap-4">
561
- <Typography variant="label" className="text-center px-4">
562
- Select a property to edit it
563
- </Typography>
564
- <Button>
565
- <PlusIcon/>
566
- Add new property
567
- </Button>
568
- </div>
569
- </div>
570
- </div>
571
-
572
- {/* Property editor empty collection state */}
573
- <div>
574
- <Typography variant="caption" color="secondary" className="block mb-1">Property Editor (empty collection)</Typography>
575
- <div className={cls("flex flex-col items-center justify-center h-48 w-[320px] border rounded-lg", defaultBorderMixin)}>
576
- <div className="flex flex-col items-center justify-center h-full gap-4">
577
- <Typography variant="label" className="text-center px-4">
578
- Now you can add your first property
579
- </Typography>
580
- <Button>
581
- <PlusIcon/>
582
- Add new property
583
- </Button>
584
- </div>
585
- </div>
586
- </div>
587
-
588
- {/* Collection list empty state */}
589
- <div>
590
- <Typography variant="caption" color="secondary" className="block mb-1">Collection ListIcon (no selection)</Typography>
591
- <div className={cls("flex flex-col items-center justify-center h-48 w-[320px] border rounded-lg", defaultBorderMixin)}>
592
- <div className="flex flex-col items-center justify-center h-full gap-4">
593
- <Typography variant="label" className="text-center px-4">
594
- Select a collection or create a new one to start editing
595
- </Typography>
596
- <Button>
597
- <PlusIcon/>
598
- Add new collection
599
- </Button>
600
- </div>
601
- </div>
602
- </div>
603
- </div>
604
- </SectionBlock>
605
-
606
- {/* ═══════════════════════════════════════════════
607
- SECTION: Typography
608
- ═══════════════════════════════════════════════ */}
609
- <SectionBlock id="typography" title="Typography">
610
- <Typography variant="body2" color="secondary" className="mb-4">
611
- All variants from <code className="font-mono text-xs">Typography</code>. Colors: primary (default), secondary, disabled, error.
612
- </Typography>
613
- <div className="flex flex-col gap-3">
614
- {(["h1", "h2", "h3", "h4", "h5", "h6", "lead", "subtitle1", "subtitle2", "body1", "body2", "caption", "label", "button"] as const).map(v => (
615
- <div key={v} className={cls("flex items-baseline gap-4 border-b pb-3 last:border-0", defaultBorderMixin)}>
616
- <span className="w-24 shrink-0 text-xs text-surface-400 font-mono">{v}</span>
617
- {/* `component="p"` keeps the variant's styling but not its
618
- element. Rendering the specimen with its native tag put a
619
- real <h1> — "The quick brown fox jumps over the lazy dog" —
620
- plus h2-h6 into the document outline of every page that
621
- embeds this view, including the public rebase.pro/ui gallery,
622
- where it competed with the page's actual heading. The class
623
- carries the type, so this renders identically. */}
624
- <Typography variant={v} component="p">The quick brown fox jumps over the lazy dog</Typography>
625
- </div>
626
- ))}
627
- </div>
628
- <div className="flex gap-4 flex-wrap mt-4">
629
- {(["primary", "secondary", "disabled", "error"] as const).map(c => (
630
- <Typography key={c} color={c}>color=&quot;{c}&quot;</Typography>
631
- ))}
632
- </div>
633
-
634
- {/* The data tiers are shown with real content rather than the
635
- pangram above: `micro` is always one or two words naming the
636
- value beneath it, and `mono` is always a measurement. A
637
- specimen reading "The quick brown fox" would demonstrate the
638
- size and misrepresent the purpose. */}
639
- <div className={cls("mt-8 pt-6 border-t", defaultBorderMixin)}>
640
- <Typography variant="subtitle2" className="block mb-1">Data tiers</Typography>
641
- <Typography variant="body2" color="secondary" className="block mb-5 max-w-[65ch]">
642
- For values that are looked up rather than read: a field name, a measurement,
643
- a headline figure. <code className="font-mono text-xs">mono</code> and{" "}
644
- <code className="font-mono text-xs">stat</code> both carry{" "}
645
- <code className="font-mono text-xs">tabular-nums</code>, so a column of them
646
- keeps its decimal points aligned and a live counter does not jitter as its
647
- digits change width.
648
- </Typography>
649
-
650
- <div className="flex flex-wrap items-start gap-x-12 gap-y-5">
651
- {([
652
- ["Region", "europe-west1"],
653
- ["Took", "32.2s"],
654
- ["Last run", "16/08/2026, 05:30:32"]
655
- ] as const).map(([label, value]) => (
656
- <div key={label}>
657
- <Typography variant="micro" component="div" color="secondary" className="block">
658
- {label}
659
- </Typography>
660
- <Typography variant="mono" component="div" className="block mt-1 text-sm">
661
- {value}
662
- </Typography>
663
- </div>
664
- ))}
665
- </div>
666
-
667
- <div className="mt-6">
668
- <span className="text-xs text-surface-400 font-mono">stat</span>
669
- <Typography variant="stat" component="div" className="block mt-1">1,284</Typography>
670
- </div>
671
- </div>
672
- </SectionBlock>
673
-
674
- {/* ═══════════════════════════════════════════════
675
- SECTION: Buttons
676
- ═══════════════════════════════════════════════ */}
677
- <SectionBlock id="buttons" title="Buttons">
678
- <div className="flex flex-col gap-6">
679
- {(["filled", "text"] as const).map(variant => (
680
- <div key={variant}>
681
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">variant=&quot;{variant}&quot;</Typography>
682
- <div className="flex flex-wrap gap-3 items-center">
683
- {(["primary", "secondary", "text", "error", "neutral"] as const).map(color => (
684
- <Button key={color} variant={variant} color={color}>{color.charAt(0).toUpperCase() + color.slice(1)}</Button>
685
- ))}
686
- <Button variant={variant} disabled>Disabled</Button>
687
- </div>
688
- </div>
689
- ))}
690
- <div>
691
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">sizes</Typography>
692
- <div className="flex flex-wrap items-end gap-3">
693
- {(["small", "medium", "large", "xl", "2xl"] as const).map(s => (
694
- <Button key={s} size={s}>{s.charAt(0).toUpperCase() + s.slice(1)}</Button>
695
- ))}
696
- </div>
697
- </div>
698
- <div>
699
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">IconButton — sizes</Typography>
700
- {/* `items-end`, matching the Button size ramp above.
701
- Each entry is a column of button-over-label, and the
702
- buttons step 28→32→40→48px. Centring the columns
703
- against each other scattered the captions across a
704
- 10px band, so a row meant to read as an even ramp
705
- read as ragged. Aligning the ends puts every caption
706
- on one baseline and lets the size difference show in
707
- the buttons, which is the point of the row. */}
708
- <div className="flex flex-wrap gap-3 items-end">
709
- {([
710
- { s: "smallest" as const, icon: <PencilIcon size={14}/> },
711
- { s: "small" as const, icon: <PencilIcon size={16}/> },
712
- { s: "medium" as const, icon: <PencilIcon size={20}/> },
713
- { s: "large" as const, icon: <PencilIcon size={24}/> }
714
- ]).map(({ s, icon }) => (
715
- <div key={s} className="flex flex-col items-center gap-1">
716
- <IconButton size={s}>{icon}</IconButton>
717
- <Typography variant="caption" color="secondary">{s.charAt(0).toUpperCase() + s.slice(1)}</Typography>
718
- </div>
719
- ))}
720
- <div className="flex flex-col items-center gap-1">
721
- <IconButton disabled><Trash2Icon size={20}/></IconButton>
722
- <Typography variant="caption" color="secondary">Disabled</Typography>
723
- </div>
724
- <div className="flex flex-col items-center gap-1">
725
- <IconButton variant="filled"><PlusIcon size={20}/></IconButton>
726
- <Typography variant="caption" color="secondary">Filled</Typography>
727
- </div>
728
- <div className="flex flex-col items-center gap-1">
729
- <IconButton shape="square"><SettingsIcon size={20}/></IconButton>
730
- <Typography variant="caption" color="secondary">Square</Typography>
731
- </div>
732
- </div>
733
- </div>
734
- <div>
735
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">LoadingButton</Typography>
736
- <div className="flex flex-wrap gap-3">
737
- <LoadingButton loading={true}>Saving…</LoadingButton>
738
- <LoadingButton loading={false}>Idle</LoadingButton>
739
- </div>
740
- </div>
741
- </div>
742
- </SectionBlock>
743
-
744
- {/* ═══════════════════════════════════════════════
745
- SECTION: Form Inputs
746
- ═══════════════════════════════════════════════ */}
747
- <SectionBlock id="inputs" title="Form Inputs">
748
- <div className="grid grid-cols-12 gap-4">
749
- <div className="col-span-12 sm:col-span-6">
750
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">TextField</Typography>
751
- <div className="flex flex-col gap-3">
752
- <TextField label="Default" placeholder="Type something…"/>
753
- <TextField label="With value" value="Filled value" onChange={() => {}}/>
754
- <TextField label="Error state" error value="Bad value" onChange={() => {}}/>
755
- <TextField label="Disabled" disabled value="Read only" onChange={() => {}}/>
756
- {/* The smaller sizes are the ones dialogs use, and they
757
- were absent here — which is how a labelled `small`
758
- field shipped with its label sitting on top of its
759
- placeholder. Keep all four so the collision is
760
- visible on this page rather than in a modal. */}
761
- <TextField size="medium" label="Medium" placeholder="Placeholder under the label"/>
762
- <TextField size="small" label="Small" placeholder="Placeholder under the label"/>
763
- <TextField size="smallest" label="Smallest" value="Filled value" onChange={() => {}}/>
764
- </div>
765
- </div>
766
- <div className="col-span-12 sm:col-span-6 flex flex-col gap-4">
767
- <div>
768
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">Select</Typography>
769
- <Select label="Status" value="published" onValueChange={() => {}}>
770
- <SelectItem value="draft">Draft</SelectItem>
771
- <SelectItem value="published">Published</SelectItem>
772
- <SelectItem value="archived">Archived</SelectItem>
773
- </Select>
774
- </div>
775
- <div>
776
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">MultiSelect</Typography>
777
- <MultiSelect label="Roles" value={["admin", "editor"]} onValueChange={() => {}}>
778
- <MultiSelectItem value="admin">Admin</MultiSelectItem>
779
- <MultiSelectItem value="editor">Editor</MultiSelectItem>
780
- <MultiSelectItem value="viewer">Viewer</MultiSelectItem>
781
- </MultiSelect>
782
- </div>
783
- </div>
784
- <div className="col-span-12 sm:col-span-6 flex flex-col gap-3">
785
- <Typography variant="caption" color="secondary" className="block font-mono">Checkbox</Typography>
786
- <label className="flex items-center gap-2 cursor-pointer"><Checkbox checked={true} onCheckedChange={() => {}}/><span>Checked</span></label>
787
- <label className="flex items-center gap-2 cursor-pointer"><Checkbox checked={false} onCheckedChange={() => {}}/><span>Unchecked</span></label>
788
- <label className="flex items-center gap-2"><Checkbox checked={true} disabled/><span>Disabled</span></label>
789
- </div>
790
- <div className="col-span-12 sm:col-span-6 flex flex-col gap-3">
791
- <Typography variant="caption" color="secondary" className="block font-mono">BooleanSwitch</Typography>
792
- <div className="flex items-center gap-2"><BooleanSwitch value={true} onValueChange={() => {}}/><span>On</span></div>
793
- <div className="flex items-center gap-2"><BooleanSwitch value={false} onValueChange={() => {}}/><span>Off</span></div>
794
- </div>
795
- <div className="col-span-12">
796
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">SearchBar</Typography>
797
- <SearchBar placeholder="Search entities…"/>
798
- </div>
799
- <div className="col-span-12">
800
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">Skeleton</Typography>
801
- <div className="flex gap-4 items-center flex-wrap">
802
- <Skeleton className="w-10 h-10 rounded-full"/>
803
- <Skeleton className="w-48 h-4 rounded"/>
804
- <Skeleton className="w-32 h-8 rounded-md"/>
805
- </div>
806
- </div>
807
- </div>
808
- </SectionBlock>
809
-
810
- {/* ═══════════════════════════════════════════════
811
- SECTION: Chips & Alerts
812
- ═══════════════════════════════════════════════ */}
813
- <SectionBlock id="chips-alerts" title="Chips & Alerts">
814
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">Chip — colorScheme</Typography>
815
- <div className="flex flex-wrap gap-2 mb-4">
816
- {(["blue", "teal", "red", "green", "yellow", "orange", "purple", "pink", "cyan", "indigo", "violet", "fuchsia", "rose", "emerald", "gray"] as const).map(s => (
817
- <Chip key={s} colorScheme={s}>{s}</Chip>
818
- ))}
819
- </div>
820
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">Chip — sizes</Typography>
821
- <div className="flex flex-wrap gap-2 items-center mb-4">
822
- {(["smallest", "small", "medium", "large"] as const).map(sz => (
823
- <Chip key={sz} colorScheme="blue" size={sz}>{sz}</Chip>
824
- ))}
825
- </div>
826
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">Chip — outlined, error, clickable, icon</Typography>
827
- <div className="flex flex-wrap gap-2 items-center mb-4">
828
- <Chip colorScheme="red" outlined>Outlined Red</Chip>
829
- <Chip colorScheme="blue" outlined>Outlined Blue</Chip>
830
- <Chip error>Error</Chip>
831
- <Chip error outlined>Error Outlined</Chip>
832
- <Chip onClick={() => {}}>Clickable</Chip>
833
- <Chip icon={<TagIcon size={12}/>} colorScheme="teal">With Icon</Chip>
834
- <Chip>Default (no scheme)</Chip>
835
- <Chip outlined>Default Outlined</Chip>
836
- </div>
837
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">FilterChip</Typography>
838
- <div className="flex flex-wrap gap-2 items-center mb-6">
839
- <FilterChip active>Active</FilterChip>
840
- <FilterChip>Inactive</FilterChip>
841
- <FilterChip icon={<FilterIcon size={12}/>} active>With Icon</FilterChip>
842
- <FilterChip size="small">Small</FilterChip>
843
- <FilterChip disabled>Disabled</FilterChip>
844
- </div>
845
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">Alert — color variants</Typography>
846
- <div className="flex flex-col gap-2">
847
- <Alert color="info">Info — informational message</Alert>
848
- <Alert color="success">Success — operation completed</Alert>
849
- <Alert color="warning">Warning — attention required</Alert>
850
- <Alert color="error">Error — something went wrong</Alert>
851
- </div>
852
- <div className="mt-4">
853
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">Separator</Typography>
854
- <div>Above</div>
855
- <Separator orientation="horizontal"/>
856
- <div>Below</div>
857
- </div>
858
- <div className="mt-4">
859
- <Typography variant="caption" color="secondary" className="block mb-2 font-mono">CircularProgress</Typography>
860
- <div className="flex gap-6 items-center">
861
- {(["small", "medium", "large"] as const).map(s => (
862
- <div key={s} className="flex flex-col items-center gap-1">
863
- <CircularProgress size={s}/>
864
- <Typography variant="caption" color="secondary">{s}</Typography>
865
- </div>
866
- ))}
867
- </div>
868
- </div>
869
- </SectionBlock>
870
-
871
- {/* ═══════════════════════════════════════════════
872
- SECTION: Management Screen
873
- ═══════════════════════════════════════════════ */}
874
- <SectionBlock id="users" title="Management Screen — Alert + Table + Chip">
875
- <Typography variant="body2" color="secondary" className="mb-4">
876
- Canonical layout for an admin management screen: an <code className="font-mono text-xs">Alert</code> with an <code className="font-mono text-xs">action</code>, a header row, and a plain <code className="font-mono text-xs">Table</code> with <code className="font-mono text-xs">Chip</code>s. Illustrative mock — not tied to a specific screen.
877
- </Typography>
878
- {/* Alert with an action button */}
879
- <Alert color="warning"
880
- outerClassName="mb-4"
881
- action={<Button>Make me admin</Button>}>
882
- No admin users exist. You can make yourself an admin.
883
- </Alert>
884
- {/* Header row: title + primary action */}
885
- <div className="flex items-center mt-12">
886
- <Typography gutterBottom variant="h4" className="grow" component="h4">Users</Typography>
887
- <Button startIcon={<PlusIcon/>}>Add user</Button>
888
- </div>
889
- {/* Table */}
890
- <div className="overflow-auto">
891
- <Table className="w-full">
892
- <TableHeader>
893
- <TableCell header className="truncate w-16"></TableCell>
894
- <TableCell header>Email</TableCell>
895
- <TableCell header>Name</TableCell>
896
- <TableCell header>Roles</TableCell>
897
- </TableHeader>
898
- <TableBody>
899
- {[
900
- { uid: "1",
901
- email: "alice@example.com",
902
- displayName: "Alice Johnson",
903
- roles: [{ id: "admin",
904
- name: "Admin",
905
- isAdmin: true }] },
906
- { uid: "2",
907
- email: "bob@example.com",
908
- displayName: "Bob Smith",
909
- roles: [{ id: "editor",
910
- name: "Editor",
911
- isAdmin: false }] },
912
- { uid: "3",
913
- email: "carol@example.com",
914
- displayName: "Carol White",
915
- roles: [] }
916
- ].map(user => (
917
- <TableRow key={user.uid}>
918
- <TableCell style={{ width: "64px" }}>
919
- <Tooltip asChild title="Delete this user">
920
- <IconButton size="small"><Trash2Icon/></IconButton>
921
- </Tooltip>
922
- </TableCell>
923
- <TableCell>{user.email}</TableCell>
924
- <TableCell className="font-medium">{user.displayName}</TableCell>
925
- <TableCell>
926
- <div className="flex flex-wrap gap-2">
927
- {user.roles.map(role => (
928
- <Chip key={role.id} colorScheme={role.isAdmin ? "purple" : "blue"} size="small">
929
- {role.name}
930
- </Chip>
931
- ))}
932
- </div>
933
- </TableCell>
934
- </TableRow>
935
- ))}
936
- </TableBody>
937
- </Table>
938
- </div>
939
- </SectionBlock>
940
-
941
- {/* ═══════════════════════════════════════════════
942
- SECTION: Form Dialog
943
- ═══════════════════════════════════════════════ */}
944
- <SectionBlock id="user-dialog" title="Form Dialog — grid + MultiSelect + LoadingButton">
945
- <Typography variant="body2" color="secondary" className="mb-4">
946
- Canonical form-in-a-card layout: <code className="font-mono text-xs">grid grid-cols-12 gap-4</code> for the fields, a <code className="font-mono text-xs">MultiSelect</code>, and a <code className="font-mono text-xs">LoadingButton</code> to submit. Illustrative mock — not tied to a specific screen.
947
- </Typography>
948
- <div className={`rounded-lg border w-full max-w-xl ${defaultBorderMixin}`}>
949
- <div className="px-6 pt-6 pb-2">
950
- <Typography variant="h4">User</Typography>
951
- </div>
952
- <div className="px-6 py-4">
953
- <div className="grid grid-cols-12 gap-4">
954
- <div className="col-span-12">
955
- <TextField name="displayName" required value="Alice Johnson" onChange={() => {}} label="Name"/>
956
- </div>
957
- <div className="col-span-12">
958
- <TextField required name="email" value="alice@example.com" onChange={() => {}} label="Email" disabled/>
959
- </div>
960
- <div className="col-span-12">
961
- <MultiSelect className="w-full" label="Roles" value={["admin"]} onValueChange={() => {}}>
962
- <MultiSelectItem value="admin">Admin</MultiSelectItem>
963
- <MultiSelectItem value="editor">Editor</MultiSelectItem>
964
- <MultiSelectItem value="viewer">Viewer</MultiSelectItem>
965
- </MultiSelect>
966
- </div>
967
- </div>
968
- </div>
969
- <div className="flex items-center justify-end gap-2 px-6 pb-6">
970
- <Button variant="text">Cancel</Button>
971
- <LoadingButton variant="filled" loading={false}>Update</LoadingButton>
972
- </div>
973
- </div>
974
- </SectionBlock>
975
-
976
- {/* ═══════════════════════════════════════════════
977
- SECTION: CRM Dashboard
978
- ═══════════════════════════════════════════════ */}
979
- <SectionBlock wide id="crm-dashboard" title="CRM Dashboard — CrmDashboardDemo">
980
- <Typography variant="body2" color="secondary" className="mb-4">
981
- A real-world showcase of a complex dashboard home page incorporating Rebase design language.
982
- </Typography>
983
- {/* The dashboard is intrinsically ~1483px wide — wider than the
984
- content column at any laptop size. Scrolling it inside its
985
- own container is what stops it pushing the section, and is
986
- the same rule wide tables follow everywhere else. */}
987
- <div className="w-full overflow-x-auto">
988
- <CrmDashboardDemo />
989
- </div>
990
- </SectionBlock>
991
-
992
- {/* ═══════════════════════════════════════════════
993
- SECTION: Collection Table
994
- ═══════════════════════════════════════════════ */}
995
- <SectionBlock wide id="collection-table" title="Collection Table">
996
- <Typography variant="body2" color="secondary" className="mb-4">
997
- Sample data collection rendered as a sortable, searchable, filterable table with row selection.
998
- Uses <code className="font-mono text-xs">Table</code>, <code className="font-mono text-xs">Chip</code>,{" "}
999
- <code className="font-mono text-xs">SearchBar</code>, <code className="font-mono text-xs">Select</code>,{" "}
1000
- <code className="font-mono text-xs">Checkbox</code>.
1001
- </Typography>
1002
- <div className="w-full"><CollectionTableDemo /></div>
1003
- </SectionBlock>
1004
-
1005
- {/* ═══════════════════════════════════════════════
1006
- SECTION: Card View
1007
- ═══════════════════════════════════════════════ */}
1008
- <SectionBlock wide id="card-view" title="Card View">
1009
- <Typography variant="body2" color="secondary" className="mb-4">
1010
- Grid of entity cards with thumbnail area, progress bar, status/priority chips, and assignee.
1011
- Uses <code className="font-mono text-xs">Card</code>, <code className="font-mono text-xs">Chip</code>,{" "}
1012
- <code className="font-mono text-xs">ToggleButtonGroup</code>, <code className="font-mono text-xs">SearchBar</code>.
1013
- </Typography>
1014
- <div className="w-full"><CardViewDemo /></div>
1015
- </SectionBlock>
1016
-
1017
- {/* ═══════════════════════════════════════════════
1018
- SECTION: Kanban Board
1019
- ═══════════════════════════════════════════════ */}
1020
- <SectionBlock wide id="kanban-board" title="Kanban Board">
1021
- <Typography variant="body2" color="secondary" className="mb-4">
1022
- Drag-and-drop kanban board with four status columns.
1023
- Uses <code className="font-mono text-xs">KanbanView</code>, <code className="font-mono text-xs">BoardItem</code>,{" "}
1024
- <code className="font-mono text-xs">BoardItemViewProps</code>.
1025
- </Typography>
1026
- <div className="w-full overflow-x-auto"><KanbanBoardDemo /></div>
1027
- </SectionBlock>
1028
- </div>
1029
- </div>
1030
- );
1031
- }
1032
-
1033
- function SectionBlock({ id, title, wide, children }: { id: string; title: string; wide?: boolean; children: React.ReactNode }) {
1034
- return (
1035
- // `max-w-5xl` and `border-b` used to share this element, and they cannot.
1036
- // Several mocks here are app-scale and intrinsically wider than 64rem
1037
- // (the CRM dashboard reaches 1483px), so the section's own rule stopped
1038
- // at 1264px while its content ran past it — every such section read as a
1039
- // broken edge.
1040
- //
1041
- // Split instead: the SECTION spans the column, so its rule always
1042
- // reaches its own edges; the CONTENT keeps a measure, so a form column
1043
- // never stretches to 700px on a wide monitor. `wide` opts the app-scale
1044
- // mocks out of the measure — they pair it with `overflow-x-auto` so they
1045
- // scroll inside themselves rather than pushing the page.
1046
- <section id={id} className={cls("px-6 py-8 border-b scroll-mt-0", defaultBorderMixin)}>
1047
- <div className={wide ? undefined : "max-w-5xl"}>
1048
- <Typography variant="h5" className="mb-1">{title}</Typography>
1049
- <div className="mt-4">{children}</div>
1050
- </div>
1051
- </section>
1052
- );
1053
- }