@rebasepro/cli 0.6.0 → 0.6.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.
- package/dist/commands/init.d.ts +13 -0
- package/dist/index.es.js +64 -48
- package/dist/index.es.js.map +1 -1
- package/package.json +7 -8
- package/skills/rebase-admin/SKILL.md +710 -0
- package/skills/rebase-collections/SKILL.md +1 -1
- package/skills/rebase-deployment/SKILL.md +315 -13
- package/skills/rebase-design-language/SKILL.md +96 -68
- package/skills/rebase-ui-components/SKILL.md +77 -0
- package/dist/index.cjs +0 -1948
- package/dist/index.cjs.map +0 -1
|
@@ -12,9 +12,9 @@ This document is the single source of truth for the visual design language used
|
|
|
12
12
|
|
|
13
13
|
## 1. Foundational Principle
|
|
14
14
|
|
|
15
|
-
> **
|
|
15
|
+
> **Near-zero chrome — the UI disappears so content is the interface.**
|
|
16
16
|
|
|
17
|
-
Rebase applications render inside the Rebase Shell — an admin panel with a sidebar, top bar, and content area. Custom views must feel like a native part of this panel. They must **not** look like a marketing website, a Dribbble concept, or a standalone SaaS dashboard.
|
|
17
|
+
Rebase applications render inside the Rebase Shell — an admin panel with a sidebar, top bar, and content area. Custom views must feel like a native part of this panel. The design is Attio-inspired: data-dense, quiet, and monochromatic. Every element exists to serve the data, not to decorate. They must **not** look like a marketing website, a Dribbble concept, or a standalone SaaS dashboard.
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
// Utilities
|
|
52
52
|
cls, defaultBorderMixin, cardMixin, cardClickableMixin, paperMixin,
|
|
53
53
|
// Icons (all from @rebasepro/ui)
|
|
54
|
-
|
|
54
|
+
AddIcon, DeleteIcon
|
|
55
55
|
} from "@rebasepro/ui";
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -108,7 +108,7 @@ The surface scale goes from `50` (lightest) to `950` (darkest):
|
|
|
108
108
|
Used for subtle interactive backgrounds and input fields. Full 50–950 range:
|
|
109
109
|
|
|
110
110
|
| Token | Value | Usage |
|
|
111
|
-
|
|
111
|
+
|---------------------------|-------------|-------------------------------------|
|
|
112
112
|
| `surface-accent-50` | `#f8fafc` | Lightest accent background |
|
|
113
113
|
| `surface-accent-100` | `#f1f5f9` | Hover backgrounds (light) |
|
|
114
114
|
| `surface-accent-200` | `#e2e8f0` | Field backgrounds (light) |
|
|
@@ -149,22 +149,24 @@ Used for subtle interactive backgrounds and input fields. Full 50–950 range:
|
|
|
149
149
|
|
|
150
150
|
### Variant Scale
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
|
155
|
-
|
|
156
|
-
| `
|
|
157
|
-
| `
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
152
|
+
The typography scale is compact and uses semibold weights for headings — designed for high content density.
|
|
153
|
+
|
|
154
|
+
| Variant | CSS Class | Rendered Element | Specs |
|
|
155
|
+
|--------------|-----------------------|------------------|---------------------------------------------------------|
|
|
156
|
+
| `h1` | `typography-h1` | `<h1>` | 4xl, font-semibold, tracking-tight |
|
|
157
|
+
| `h2` | `typography-h2` | `<h2>` | 3xl, font-semibold, tracking-tight |
|
|
158
|
+
| `h3` | `typography-h3` | `<h3>` | 2xl, font-semibold, tracking-tight |
|
|
159
|
+
| `h4` | `typography-h4` | `<h4>` | xl, font-semibold, tracking-[-0.01em] |
|
|
160
|
+
| `h5` | `typography-h5` | `<h5>` | lg, font-semibold, tracking-[-0.01em] |
|
|
161
|
+
| `h6` | `typography-h6` | `<h6>` | base, font-semibold, tracking-[-0.01em] |
|
|
162
|
+
| `subtitle1` | `typography-subtitle1`| `<h6>` | sm, font-semibold, tracking-[-0.01em] |
|
|
163
|
+
| `subtitle2` | `typography-subtitle2`| `<h6>` | sm, font-medium |
|
|
164
|
+
| `body1` | `typography-body1` | `<p>` | sm |
|
|
165
|
+
| `body2` | `typography-body2` | `<p>` | xs |
|
|
166
|
+
| `caption` | `typography-caption` | `<p>` | [11px], leading-[1.4] |
|
|
167
|
+
| `label` | `typography-label` | `<label>` | xs, font-medium, tracking-wide |
|
|
168
|
+
| `inherit` | `typography-inherit` | `<p>` | text-inherit (inherits parent sizing) |
|
|
169
|
+
| `button` | `typography-button` | `<span>` | xs, font-semibold, tracking-wide |
|
|
168
170
|
|
|
169
171
|
### Color Prop
|
|
170
172
|
|
|
@@ -180,7 +182,7 @@ Used for subtle interactive backgrounds and input fields. Full 50–950 range:
|
|
|
180
182
|
### Typography Usage Examples
|
|
181
183
|
|
|
182
184
|
```tsx
|
|
183
|
-
// Page title — use h4 or h5
|
|
185
|
+
// Page title — use h4 or h5 (the scale is compact; h1-h3 are reserved for hero contexts)
|
|
184
186
|
<Typography variant="h4">Dashboard</Typography>
|
|
185
187
|
|
|
186
188
|
// Section title
|
|
@@ -264,8 +266,8 @@ The `Card` component from `@rebasepro/ui` automatically applies `cardMixin` and,
|
|
|
264
266
|
|
|
265
267
|
```tsx
|
|
266
268
|
// Style mixins applied by Card:
|
|
267
|
-
// cardMixin = "bg-white dark:bg-surface-900 rounded-
|
|
268
|
-
// cardClickableMixin = "hover:bg-surface-
|
|
269
|
+
// cardMixin = "bg-white dark:bg-surface-900 rounded-lg border border-surface-200 dark:border-surface-700"
|
|
270
|
+
// cardClickableMixin = "hover:bg-surface-50 dark:hover:bg-surface-800 cursor-pointer transition-colors duration-150"
|
|
269
271
|
```
|
|
270
272
|
|
|
271
273
|
```tsx
|
|
@@ -288,12 +290,13 @@ The `Card` component from `@rebasepro/ui` automatically applies `cardMixin` and,
|
|
|
288
290
|
|
|
289
291
|
| ❌ Don't | ✅ Do |
|
|
290
292
|
|---------------------------------------------------|-----------------------------------------------|
|
|
291
|
-
| `rounded-2xl` | Let `Card` use `rounded-
|
|
292
|
-
| `shadow-lg shadow-blue-500/20` |
|
|
293
|
+
| `rounded-2xl` | Let `Card` use `rounded-lg` |
|
|
294
|
+
| `shadow-lg shadow-blue-500/20` | No shadows — hover uses `bg-surface-50` only |
|
|
293
295
|
| `hover:-translate-y-1` | Don't lift cards on hover |
|
|
294
296
|
| `hover:scale-110` on icons | Use subtle `transition-colors` at most |
|
|
295
|
-
| `bg-gradient-to-br from-blue-500 to-indigo-600` | Use
|
|
297
|
+
| `bg-gradient-to-br from-blue-500 to-indigo-600` | Use plain surface colors |
|
|
296
298
|
| `glass-card`, `glass-panel`, backdrop-blur | Use `Card` or `Paper` component |
|
|
299
|
+
| `hover:shadow-md`, `hover:ring-1` | Use `hover:bg-surface-50 dark:hover:bg-surface-800` |
|
|
297
300
|
|
|
298
301
|
### NavigationCard Reference Pattern
|
|
299
302
|
|
|
@@ -301,30 +304,36 @@ This is the gold standard for how a card should look:
|
|
|
301
304
|
|
|
302
305
|
```tsx
|
|
303
306
|
<Card className={cls(
|
|
304
|
-
"group h-full p-4 cursor-pointer transition-
|
|
305
|
-
"
|
|
306
|
-
"hover:shadow-md hover:shadow-black/[0.04]",
|
|
307
|
-
"hover:border-surface-300 dark:hover:border-primary/20"
|
|
307
|
+
"group h-full p-4 cursor-pointer transition-colors duration-150 ease-in-out",
|
|
308
|
+
"hover:bg-surface-50 dark:hover:bg-surface-800"
|
|
308
309
|
)}>
|
|
309
310
|
<div className="flex flex-col h-full">
|
|
310
|
-
{/*
|
|
311
|
-
<div className="flex items-center
|
|
312
|
-
|
|
311
|
+
{/* Header: icon + title left, actions right */}
|
|
312
|
+
<div className="flex items-center w-full justify-between mb-1">
|
|
313
|
+
<div className="flex items-center gap-3">
|
|
314
|
+
{/* Icon: plain muted color, no background pill */}
|
|
315
|
+
<div className="flex items-center justify-center w-5 h-5 text-surface-400 dark:text-surface-500">
|
|
316
|
+
{icon}
|
|
317
|
+
</div>
|
|
318
|
+
<Typography variant="subtitle1" component="h2">{name}</Typography>
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
{/* Description indented to align with title */}
|
|
322
|
+
<div className="grow pl-8">
|
|
323
|
+
<Typography variant="caption" color="secondary">
|
|
324
|
+
<Markdown source={description} size="small" />
|
|
325
|
+
</Typography>
|
|
313
326
|
</div>
|
|
314
|
-
{/* Title */}
|
|
315
|
-
<Typography variant="subtitle1" component="h2">{name}</Typography>
|
|
316
|
-
{/* Description */}
|
|
317
|
-
<Typography variant="caption" color="secondary">
|
|
318
|
-
<Markdown source={description} size="small" />
|
|
319
|
-
</Typography>
|
|
320
327
|
</div>
|
|
321
328
|
</Card>
|
|
322
329
|
```
|
|
323
330
|
|
|
324
331
|
**Key observations from NavigationCard:**
|
|
325
|
-
- Icons
|
|
326
|
-
- Hover
|
|
327
|
-
- The card transitions
|
|
332
|
+
- Icons are **plain muted color** (`text-surface-400 dark:text-surface-500`) — no background pill, no gradient, no primary tint.
|
|
333
|
+
- Hover effect is a **single background color change** — `hover:bg-surface-50 dark:hover:bg-surface-800`. No shadows, no border changes, no rings.
|
|
334
|
+
- The card transitions use `transition-colors duration-150` — fast and minimal.
|
|
335
|
+
- No arrow icon or decorative footer — the card is the affordance.
|
|
336
|
+
- Description is offset with `pl-8` to align with the title (past the icon).
|
|
328
337
|
|
|
329
338
|
---
|
|
330
339
|
|
|
@@ -336,10 +345,10 @@ Always import and use these mixins rather than hardcoding equivalent classes:
|
|
|
336
345
|
|
|
337
346
|
| Mixin | Classes |
|
|
338
347
|
|------------------------------|------------------------------------------------------------------------------------------------------|
|
|
339
|
-
| `defaultBorderMixin` | `border-surface-200
|
|
340
|
-
| `paperMixin` | `bg-white rounded-
|
|
341
|
-
| `cardMixin` | `bg-white dark:bg-surface-900 rounded-
|
|
342
|
-
| `cardClickableMixin` | hover:bg
|
|
348
|
+
| `defaultBorderMixin` | `border-surface-200 dark:border-surface-700` |
|
|
349
|
+
| `paperMixin` | `bg-white rounded-lg dark:bg-surface-800 border border-surface-200 dark:border-surface-700` |
|
|
350
|
+
| `cardMixin` | `bg-white dark:bg-surface-900 rounded-lg border border-surface-200 dark:border-surface-700` |
|
|
351
|
+
| `cardClickableMixin` | `hover:bg-surface-50 dark:hover:bg-surface-800 cursor-pointer transition-colors duration-150` |
|
|
343
352
|
| `cardSelectedMixin` | `bg-primary-bg/30 dark:bg-primary-bg/10 ring-1 ring-primary/75` |
|
|
344
353
|
|
|
345
354
|
### Field & Focus Mixins
|
|
@@ -374,7 +383,7 @@ The mixin applies a subtle primary-tinted background and a `ring-1` primary bord
|
|
|
374
383
|
|
|
375
384
|
### Valid Button Variants
|
|
376
385
|
|
|
377
|
-
The `Button` component accepts these variants and colors
|
|
386
|
+
The `Button` component accepts these variants and colors. Buttons use `rounded-lg`, `transition-colors`, and no active scale effect.
|
|
378
387
|
|
|
379
388
|
```tsx
|
|
380
389
|
<Button variant="filled" color="primary">Primary Action</Button>
|
|
@@ -389,6 +398,13 @@ The `Button` component accepts these variants and colors:
|
|
|
389
398
|
| `color` | `"primary"`, `"secondary"`, `"text"`, `"error"`, `"neutral"` |
|
|
390
399
|
| `size` | `"small"`, `"medium"`, `"large"`, `"xl"`, `"2xl"` |
|
|
391
400
|
|
|
401
|
+
### Button Styling Details
|
|
402
|
+
|
|
403
|
+
- Base shape: `rounded-lg` (not `rounded-md`)
|
|
404
|
+
- Transitions: `transition-colors` (not `transition-all`)
|
|
405
|
+
- Filled hover: `hover:brightness-105` (subtle, not `hover:brightness-110`)
|
|
406
|
+
- No `shadow-sm`, no `hover:shadow-md`, no `active:scale-[0.98]`
|
|
407
|
+
|
|
392
408
|
### Button Anti-Patterns
|
|
393
409
|
|
|
394
410
|
```tsx
|
|
@@ -401,6 +417,9 @@ The `Button` component accepts these variants and colors:
|
|
|
401
417
|
// ❌ NEVER: Custom shadow styling
|
|
402
418
|
<Button className="shadow-lg shadow-violet-500/20 hover:shadow-xl">
|
|
403
419
|
|
|
420
|
+
// ❌ NEVER: Active scale effect
|
|
421
|
+
<Button className="active:scale-[0.98]">
|
|
422
|
+
|
|
404
423
|
// ✅ CORRECT: Use proper variant and color
|
|
405
424
|
<Button variant="filled" color="primary">Submit</Button>
|
|
406
425
|
<Button variant="outlined" color="primary">Cancel</Button>
|
|
@@ -446,7 +465,7 @@ Follow the `NavigationGroup` pattern — section headers are **small, uppercase,
|
|
|
446
465
|
variant="caption"
|
|
447
466
|
component="h2"
|
|
448
467
|
color="secondary"
|
|
449
|
-
className="px-4 py-1 rounded font-
|
|
468
|
+
className="px-4 py-1 rounded font-medium text-[10px] uppercase tracking-[0.08em] text-surface-400 dark:text-surface-500"
|
|
450
469
|
>
|
|
451
470
|
Pipeline Stages
|
|
452
471
|
</Typography>
|
|
@@ -470,14 +489,14 @@ For panel-level titles (inside a Card or Paper), use `subtitle1`:
|
|
|
470
489
|
|
|
471
490
|
## 11. Metric / KPI Cards
|
|
472
491
|
|
|
473
|
-
When displaying numeric KPIs,
|
|
492
|
+
When displaying numeric KPIs, use plain muted icons (matching NavigationCard) — no background pill:
|
|
474
493
|
|
|
475
494
|
```tsx
|
|
476
495
|
<Card className="p-4">
|
|
477
|
-
<div className="flex items-center gap-
|
|
478
|
-
{/* Icon:
|
|
479
|
-
<div className="flex items-center justify-center w-
|
|
480
|
-
<UsersIcon className="h-
|
|
496
|
+
<div className="flex items-center gap-3">
|
|
497
|
+
{/* Icon: plain muted color, no background */}
|
|
498
|
+
<div className="flex items-center justify-center w-5 h-5 text-surface-400 dark:text-surface-500">
|
|
499
|
+
<UsersIcon className="h-4 w-4" />
|
|
481
500
|
</div>
|
|
482
501
|
<div>
|
|
483
502
|
<Typography variant="caption" color="secondary">Active Leads</Typography>
|
|
@@ -493,6 +512,9 @@ When displaying numeric KPIs, follow the NavigationCard icon pattern:
|
|
|
493
512
|
// ❌ NEVER: Gradient icon backgrounds
|
|
494
513
|
<div className="p-4 bg-gradient-to-br from-blue-500 to-indigo-600 text-white rounded-2xl shadow-lg shadow-blue-500/20">
|
|
495
514
|
|
|
515
|
+
// ❌ NEVER: Primary-tinted icon pill (old pattern)
|
|
516
|
+
<div className="w-10 h-10 rounded-lg bg-primary/8 dark:bg-primary/10 text-primary/70">
|
|
517
|
+
|
|
496
518
|
// ❌ NEVER: Oversized rounded corners
|
|
497
519
|
<div className="rounded-2xl">
|
|
498
520
|
|
|
@@ -508,9 +530,10 @@ When displaying numeric KPIs, follow the NavigationCard icon pattern:
|
|
|
508
530
|
## 12. Icons
|
|
509
531
|
|
|
510
532
|
- Import icons from `lucide-react` for functional/semantic icons.
|
|
511
|
-
- Import icons from `@rebasepro/ui` for navigation icons (`
|
|
512
|
-
- **Icon
|
|
513
|
-
- Icon size: typically `h-
|
|
533
|
+
- Import icons from `@rebasepro/ui` for navigation icons (`AddIcon`, `DeleteIcon`, etc.)
|
|
534
|
+
- **Icon treatment**: plain muted color (`text-surface-400 dark:text-surface-500`). **No** background pill, **no** primary tint, **no** gradients.
|
|
535
|
+
- Icon size: typically `h-4 w-4` or `h-5 w-5`.
|
|
536
|
+
- No decorative arrow icons on cards — the card itself is the affordance.
|
|
514
537
|
|
|
515
538
|
---
|
|
516
539
|
|
|
@@ -588,7 +611,7 @@ Ensure `@fontsource/rubik` and `@fontsource/jetbrains-mono` are imported in the
|
|
|
588
611
|
- Standard dark mode backgrounds:
|
|
589
612
|
- Page: `dark:bg-surface-800`
|
|
590
613
|
- Cards: `dark:bg-surface-900`
|
|
591
|
-
- Borders: `dark:border-surface-700
|
|
614
|
+
- Borders: `dark:border-surface-700`
|
|
592
615
|
|
|
593
616
|
---
|
|
594
617
|
|
|
@@ -626,17 +649,22 @@ Before submitting UI code, verify you have NONE of these:
|
|
|
626
649
|
| 4 | Template literal class concatenation | Use `cls()` from `@rebasepro/ui` |
|
|
627
650
|
| 5 | Gradient text on headings | Remove gradient, use `Typography` color prop |
|
|
628
651
|
| 6 | Glassmorphism (`backdrop-blur`, translucent bg) | Use `Card`, `Paper`, or solid backgrounds |
|
|
629
|
-
| 7 | `rounded-2xl` on cards/panels | Use `Card`/`Paper` which use `rounded-
|
|
630
|
-
| 8 | Colored gradient icon backgrounds
|
|
631
|
-
| 9 | `hover:-translate-y-1` or `hover:scale-110` |
|
|
632
|
-
| 10| Custom shadow colors (`shadow-blue-500/20`) |
|
|
652
|
+
| 7 | `rounded-2xl` on cards/panels | Use `Card`/`Paper` which use `rounded-lg` |
|
|
653
|
+
| 8 | Colored gradient or primary-tinted icon backgrounds | Use plain `text-surface-400 dark:text-surface-500` |
|
|
654
|
+
| 9 | `hover:-translate-y-1` or `hover:scale-110` | Don't lift or scale on hover |
|
|
655
|
+
| 10| Custom shadow colors (`shadow-blue-500/20`) | No shadows on hover — use `hover:bg-surface-50` only |
|
|
633
656
|
| 11| `animate-bounce`, `animate-pulse` on alerts | Use static `Alert` component |
|
|
634
657
|
| 12| Custom CSS classes like `glass-card`, `shimmer-shine` | Remove and use standard UI kit patterns |
|
|
635
658
|
| 13| `font-extrabold` overrides on Typography | Let the variant handle font weight |
|
|
636
659
|
| 14| `text-[10px]`, `tracking-widest` custom overrides | Use `Typography variant="caption"` |
|
|
637
|
-
| 15| Per-card colored themes (blue card, green card, etc.) | Use uniform `Card`
|
|
660
|
+
| 15| Per-card colored themes (blue card, green card, etc.) | Use uniform `Card` with plain muted icons |
|
|
638
661
|
| 16| `dark:bg-surface-950` for page background | Use `dark:bg-surface-800` |
|
|
639
662
|
| 17| Arbitrary Tailwind colors (`text-violet-600`, etc.) | Use design token colors |
|
|
663
|
+
| 18| `hover:shadow-md`, `hover:ring-1` on cards | Use `hover:bg-surface-50 dark:hover:bg-surface-800` |
|
|
664
|
+
| 19| `active:scale-[0.98]` on buttons | Buttons don't scale — use `transition-colors` only |
|
|
665
|
+
| 20| `border-*/60` opacity on borders | Use solid borders via `defaultBorderMixin` |
|
|
666
|
+
| 21| `bg-primary/8` icon background pills | Icons are plain color, no background container |
|
|
667
|
+
| 22| Decorative arrow icons on cards | Cards are the affordance — no `ArrowRightIcon` needed |
|
|
640
668
|
|
|
641
669
|
> **IMPORTANT FOR AGENTS:** The internal `EntityCard` component (used for card-view in collection grids) uses `hover:-translate-y-0.5` and `hover:shadow-lg`, and the Studio home page uses per-section colored icons. These are **intentional exceptions** in Rebase's own codebase for specific contexts (rich media cards with thumbnails and the Studio admin landing page). **Do NOT copy these patterns** into custom views, home pages, or dashboard cards — they are reserved for these specific internal components.
|
|
642
670
|
|
|
@@ -648,7 +676,7 @@ When building new views, always reference these existing implementations:
|
|
|
648
676
|
|
|
649
677
|
| Component | Location | What it demonstrates |
|
|
650
678
|
|----------------------|-------------------------------------------------------------------|--------------------------------|
|
|
651
|
-
| `NavigationCard` | `packages/admin/src/components/HomePage/NavigationCard.tsx` | Card pattern, icon treatment
|
|
679
|
+
| `NavigationCard` | `packages/admin/src/components/HomePage/NavigationCard.tsx` | Card pattern, plain icon treatment |
|
|
652
680
|
| `SmallNavigationCard`| `packages/admin/src/components/HomePage/SmallNavigationCard.tsx` | Compact card with mixins |
|
|
653
681
|
| `ContentHomePage` | `packages/admin/src/components/HomePage/ContentHomePage.tsx` | Page layout, Container usage |
|
|
654
682
|
| `NavigationGroup` | `packages/admin/src/components/HomePage/NavigationGroup.tsx` | Section headers, grouping |
|
|
@@ -657,8 +685,8 @@ When building new views, always reference these existing implementations:
|
|
|
657
685
|
|
|
658
686
|
## 21. Summary: The Design Philosophy
|
|
659
687
|
|
|
660
|
-
1. **
|
|
661
|
-
2. **
|
|
662
|
-
3. **
|
|
663
|
-
4. **
|
|
664
|
-
5. **
|
|
688
|
+
1. **Near-zero chrome.** The UI disappears so content is the interface. No decorative elements, no visual noise — only what serves the data.
|
|
689
|
+
2. **Data-first.** Every element exists to present or interact with data. If it doesn't serve the data, remove it.
|
|
690
|
+
3. **Quiet sophistication.** Hierarchy comes from subtle weight and size differentiation (semibold headings, medium subtitles, regular body) rather than dramatic size jumps or color contrasts.
|
|
691
|
+
4. **Monochromatic hierarchy.** One accent color (`primary` blue) used sparingly at low opacity. Icons are plain muted grays. No rainbow gradients, no per-card color themes.
|
|
692
|
+
5. **Content density.** Smaller type, tighter spacing, more data per viewport. The compressed typography scale (`sm` body text, `xs` captions, `[11px]` fine print) maximizes information density without sacrificing readability.
|
|
@@ -1397,6 +1397,83 @@ export function DashboardView() {
|
|
|
1397
1397
|
}
|
|
1398
1398
|
```
|
|
1399
1399
|
|
|
1400
|
+
## Rich Text Editor (`RichTextEditor`)
|
|
1401
|
+
|
|
1402
|
+
> **IMPORTANT:** `RichTextEditor` lives in `@rebasepro/admin`, NOT in `@rebasepro/ui`. It is a separate heavy entry point (~300 KB) because it bundles ProseMirror.
|
|
1403
|
+
|
|
1404
|
+
A full-featured, block-based WYSIWYG editor with slash commands, bubble menus, image uploads, tables, AI autocomplete, drag-and-drop reordering, and a raw Markdown toggle. Outputs **Markdown**, **JSON** (ProseMirror document tree), and **HTML**.
|
|
1405
|
+
|
|
1406
|
+
### Import
|
|
1407
|
+
|
|
1408
|
+
```ts
|
|
1409
|
+
// The component (heavy — code-split / lazy-load when possible)
|
|
1410
|
+
import { RichTextEditor } from "@rebasepro/admin/editor";
|
|
1411
|
+
|
|
1412
|
+
// Types only (lightweight — from the main entry point)
|
|
1413
|
+
import type { RichTextEditorProps, JSONContent, EditorAIController } from "@rebasepro/admin";
|
|
1414
|
+
```
|
|
1415
|
+
|
|
1416
|
+
> **Note:** The previous export name `RebaseEditor` still works but is deprecated. Always use `RichTextEditor`.
|
|
1417
|
+
|
|
1418
|
+
### Props
|
|
1419
|
+
|
|
1420
|
+
| Prop | Type | Default | Description |
|
|
1421
|
+
|------|------|---------|-------------|
|
|
1422
|
+
| `content` | `JSONContent \| string` | — | Initial content. Pass a markdown string or a ProseMirror JSON document. |
|
|
1423
|
+
| `onMarkdownContentChange` | `(md: string) => void` | — | Called with serialized Markdown on edits |
|
|
1424
|
+
| `onJsonContentChange` | `(json: JSONContent \| null) => void` | — | Called with ProseMirror JSON on edits |
|
|
1425
|
+
| `onHtmlContentChange` | `(html: string) => void` | — | Called with HTML string on edits |
|
|
1426
|
+
| `handleImageUpload` | `(file: File) => Promise<string>` | **required** | Upload handler that returns the image URL |
|
|
1427
|
+
| `version` | `number` | — | Bump to force-reset editor content (e.g. on form discard) |
|
|
1428
|
+
| `textSize` | `"sm" \| "base" \| "lg"` | `"base"` | Prose typography scale |
|
|
1429
|
+
| `highlight` | `{ from: number, to: number }` | — | Highlight a character range (used by AI autocomplete) |
|
|
1430
|
+
| `aiController` | `EditorAIController` | — | AI autocomplete controller |
|
|
1431
|
+
| `disabled` | `boolean` | `false` | Read-only mode |
|
|
1432
|
+
| `markdownConfig` | `MarkdownEditorConfig` | — | Markdown parser options (`html`, `transformPastedText`) |
|
|
1433
|
+
|
|
1434
|
+
### Usage Example
|
|
1435
|
+
|
|
1436
|
+
```tsx
|
|
1437
|
+
import { RichTextEditor } from "@rebasepro/admin/editor";
|
|
1438
|
+
|
|
1439
|
+
function MyEditor() {
|
|
1440
|
+
const [markdown, setMarkdown] = useState("");
|
|
1441
|
+
|
|
1442
|
+
return (
|
|
1443
|
+
<RichTextEditor
|
|
1444
|
+
content={markdown}
|
|
1445
|
+
onMarkdownContentChange={setMarkdown}
|
|
1446
|
+
handleImageUpload={async (file) => {
|
|
1447
|
+
const url = await uploadToStorage(file);
|
|
1448
|
+
return url;
|
|
1449
|
+
}}
|
|
1450
|
+
textSize="base"
|
|
1451
|
+
/>
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1454
|
+
```
|
|
1455
|
+
|
|
1456
|
+
### Lazy Loading
|
|
1457
|
+
|
|
1458
|
+
Because the editor is ~300 KB, lazy-load it when it's not immediately visible:
|
|
1459
|
+
|
|
1460
|
+
```tsx
|
|
1461
|
+
import { lazy, Suspense } from "react";
|
|
1462
|
+
import { Skeleton } from "@rebasepro/ui";
|
|
1463
|
+
|
|
1464
|
+
const RichTextEditor = lazy(() =>
|
|
1465
|
+
import("@rebasepro/admin/editor").then(m => ({ default: m.RichTextEditor }))
|
|
1466
|
+
);
|
|
1467
|
+
|
|
1468
|
+
function LazyEditor(props) {
|
|
1469
|
+
return (
|
|
1470
|
+
<Suspense fallback={<Skeleton height={200} className="w-full rounded-md" />}>
|
|
1471
|
+
<RichTextEditor {...props} />
|
|
1472
|
+
</Suspense>
|
|
1473
|
+
);
|
|
1474
|
+
}
|
|
1475
|
+
```
|
|
1476
|
+
|
|
1400
1477
|
## Tailwind CSS v4
|
|
1401
1478
|
|
|
1402
1479
|
Rebase uses Tailwind CSS v4 with CSS-first configuration:
|