@olwiba/ui 0.2.25 → 0.2.27
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/content/docs/app/app-shell.mdx +71 -0
- package/content/docs/app/auth-section.mdx +73 -0
- package/content/docs/app/billing-panel.mdx +38 -0
- package/content/docs/app/empty-state.mdx +47 -0
- package/content/docs/app/error-page.mdx +31 -0
- package/content/docs/app/index.mdx +13 -0
- package/content/docs/app/meta.json +4 -0
- package/content/docs/app/onboarding-wizard.mdx +41 -0
- package/content/docs/app/settings-section.mdx +37 -0
- package/content/docs/app/team-members-panel.mdx +35 -0
- package/content/docs/app/update-banner.mdx +43 -0
- package/content/docs/components/activity-feed.mdx +42 -0
- package/content/docs/components/chart.mdx +47 -0
- package/content/docs/components/command-menu.mdx +41 -0
- package/content/docs/components/confirm-dialog.mdx +26 -0
- package/content/docs/components/context-menu.mdx +26 -0
- package/content/docs/components/data-table.mdx +40 -0
- package/content/docs/components/dock.mdx +26 -0
- package/content/docs/components/feature-card.mdx +26 -0
- package/content/docs/components/file-upload.mdx +35 -0
- package/content/docs/components/full-page-spinner.mdx +44 -0
- package/content/docs/components/glass-card.mdx +26 -0
- package/content/docs/components/image-card.mdx +26 -0
- package/content/docs/components/index.mdx +49 -0
- package/content/docs/components/load-more.mdx +34 -0
- package/content/docs/components/meta.json +35 -0
- package/content/docs/components/notifications-popover.mdx +34 -0
- package/content/docs/components/notify.mdx +40 -0
- package/content/docs/components/olwiba-ui-context.mdx +69 -0
- package/content/docs/components/page-header.mdx +42 -0
- package/content/docs/components/pricing-card.mdx +26 -0
- package/content/docs/components/register-hotkeys.mdx +50 -0
- package/content/docs/components/root-error-fallback.mdx +39 -0
- package/content/docs/components/spotlight.mdx +26 -0
- package/content/docs/components/stat-card.mdx +26 -0
- package/content/docs/components/suspensed.mdx +42 -0
- package/content/docs/components/testimonial-card.mdx +26 -0
- package/content/docs/components/theme-color-updater.mdx +40 -0
- package/content/docs/components/theme-switch-minimal.mdx +32 -0
- package/content/docs/components/version-banner.mdx +44 -0
- package/content/docs/email/action-email.mdx +62 -0
- package/content/docs/email/email-layout.mdx +58 -0
- package/content/docs/email/email-link-fallback.mdx +46 -0
- package/content/docs/email/index.mdx +32 -0
- package/content/docs/email/meta.json +10 -0
- package/content/docs/email/notice-email.mdx +51 -0
- package/content/docs/hooks/index.mdx +21 -0
- package/content/docs/hooks/meta.json +16 -0
- package/content/docs/hooks/use-confirm.mdx +81 -0
- package/content/docs/hooks/use-controlled-open.mdx +53 -0
- package/content/docs/hooks/use-copy-to-clipboard.mdx +26 -0
- package/content/docs/hooks/use-debounce.mdx +26 -0
- package/content/docs/hooks/use-intersection-observer.mdx +26 -0
- package/content/docs/hooks/use-local-storage.mdx +26 -0
- package/content/docs/hooks/use-media-query.mdx +26 -0
- package/content/docs/hooks/use-mounted.mdx +39 -0
- package/content/docs/hooks/use-pagination.mdx +26 -0
- package/content/docs/hooks/use-scrolled-past.mdx +44 -0
- package/content/docs/index.mdx +68 -0
- package/content/docs/marketing/contact-section.mdx +16 -0
- package/content/docs/marketing/cta-section.mdx +31 -0
- package/content/docs/marketing/faq-section.mdx +16 -0
- package/content/docs/marketing/features-section.mdx +23 -0
- package/content/docs/marketing/footer.mdx +16 -0
- package/content/docs/marketing/hero-section.mdx +16 -0
- package/content/docs/marketing/index.mdx +22 -0
- package/content/docs/marketing/meta.json +20 -0
- package/content/docs/marketing/navbar.mdx +16 -0
- package/content/docs/marketing/newsletter-section.mdx +16 -0
- package/content/docs/marketing/post-list.mdx +32 -0
- package/content/docs/marketing/pricing-section.mdx +16 -0
- package/content/docs/marketing/stats-section.mdx +16 -0
- package/content/docs/marketing/steps-section.mdx +60 -0
- package/content/docs/marketing/team-section.mdx +16 -0
- package/content/docs/marketing/testimonials-section.mdx +16 -0
- package/content/docs/mechanics/carousel.mdx +42 -0
- package/content/docs/mechanics/index.mdx +11 -0
- package/content/docs/mechanics/meta.json +4 -0
- package/content/docs/mechanics/sortable.mdx +44 -0
- package/content/docs/meta.json +4 -0
- package/content/docs/motion/animated-swap.mdx +75 -0
- package/content/docs/motion/count-up.mdx +31 -0
- package/content/docs/motion/fade-in.mdx +34 -0
- package/content/docs/motion/index.mdx +12 -0
- package/content/docs/motion/meta.json +4 -0
- package/content/docs/motion/page-transition.mdx +29 -0
- package/content/docs/motion/stagger-children.mdx +31 -0
- package/content/docs/overlays/index.mdx +9 -0
- package/content/docs/overlays/meta.json +4 -0
- package/content/docs/overlays/overlay.mdx +60 -0
- package/content/docs/overlays/underlay.mdx +56 -0
- package/dist/email/index.d.ts +8 -1
- package/dist/email/index.js +3 -3
- package/dist/email/index.js.map +1 -1
- package/docs-manifest.json +253 -0
- package/package.json +18 -9
- package/site/demos/action-email.tsx +6 -0
- package/site/demos/activity-feed.tsx +42 -0
- package/site/demos/animated-swap.tsx +42 -0
- package/site/demos/app-shell.tsx +47 -0
- package/site/demos/app-ui-page.tsx +9 -0
- package/site/demos/application-sidebar-block.tsx +9 -0
- package/site/demos/auth-section.tsx +15 -0
- package/site/demos/auth-split-block.tsx +9 -0
- package/site/demos/billing-page.tsx +157 -0
- package/site/demos/billing-panel.tsx +26 -0
- package/site/demos/carousel.tsx +34 -0
- package/site/demos/chart.tsx +55 -0
- package/site/demos/command-menu.tsx +39 -0
- package/site/demos/confirm-dialog.tsx +27 -0
- package/site/demos/contact-form-block.tsx +3 -0
- package/site/demos/contact-section.tsx +2 -0
- package/site/demos/context-menu.tsx +30 -0
- package/site/demos/count-up.tsx +23 -0
- package/site/demos/cta-section.tsx +6 -0
- package/site/demos/dashboard-overview-block.tsx +9 -0
- package/site/demos/dashboard-shell-block.tsx +10 -0
- package/site/demos/data-table.tsx +47 -0
- package/site/demos/demo-brand.tsx +23 -0
- package/site/demos/dock.tsx +20 -0
- package/site/demos/document-sidebar-block.tsx +9 -0
- package/site/demos/email-examples.tsx +58 -0
- package/site/demos/email-frame.tsx +50 -0
- package/site/demos/email-layout.tsx +6 -0
- package/site/demos/email-link-fallback.tsx +6 -0
- package/site/demos/email-previews.generated.ts +11 -0
- package/site/demos/empty-state-block.tsx +3 -0
- package/site/demos/empty-state.tsx +23 -0
- package/site/demos/error-page.tsx +5 -0
- package/site/demos/fade-in.tsx +18 -0
- package/site/demos/faq-section.tsx +6 -0
- package/site/demos/feature-card.tsx +13 -0
- package/site/demos/features-section.tsx +6 -0
- package/site/demos/file-upload.tsx +16 -0
- package/site/demos/footer.tsx +42 -0
- package/site/demos/full-page-spinner.tsx +9 -0
- package/site/demos/glass-card.tsx +14 -0
- package/site/demos/glow-effect.tsx +3 -0
- package/site/demos/gradient-background.tsx +3 -0
- package/site/demos/grid-pattern.tsx +3 -0
- package/site/demos/hero-section.tsx +6 -0
- package/site/demos/image-card.tsx +17 -0
- package/site/demos/login-block.tsx +9 -0
- package/site/demos/marketing-cta-block.tsx +3 -0
- package/site/demos/marketing-demo-data.tsx +114 -0
- package/site/demos/marketing-faq-block.tsx +3 -0
- package/site/demos/marketing-features-block.tsx +3 -0
- package/site/demos/marketing-footer-block.tsx +3 -0
- package/site/demos/marketing-hero-block.tsx +10 -0
- package/site/demos/marketing-nav-block.tsx +3 -0
- package/site/demos/marketing-newsletter-block.tsx +3 -0
- package/site/demos/marketing-page.tsx +52 -0
- package/site/demos/marketing-pricing-block.tsx +3 -0
- package/site/demos/marketing-stats-block.tsx +3 -0
- package/site/demos/marketing-team-block.tsx +3 -0
- package/site/demos/marketing-testimonials-block.tsx +3 -0
- package/site/demos/navbar.tsx +32 -0
- package/site/demos/newsletter-section.tsx +2 -0
- package/site/demos/noise-overlay.tsx +3 -0
- package/site/demos/not-found-block.tsx +3 -0
- package/site/demos/notice-email.tsx +6 -0
- package/site/demos/notifications-popover.tsx +27 -0
- package/site/demos/notify.tsx +44 -0
- package/site/demos/olwiba-ui-context.tsx +51 -0
- package/site/demos/onboarding-block.tsx +3 -0
- package/site/demos/onboarding-wizard.tsx +43 -0
- package/site/demos/overlay.tsx +72 -0
- package/site/demos/page-header.tsx +15 -0
- package/site/demos/page-transition.tsx +34 -0
- package/site/demos/post-list.tsx +24 -0
- package/site/demos/pricing-card.tsx +27 -0
- package/site/demos/pricing-section.tsx +6 -0
- package/site/demos/register-hotkeys.tsx +39 -0
- package/site/demos/root-error-fallback.tsx +28 -0
- package/site/demos/settings-layout-block.tsx +3 -0
- package/site/demos/settings-section.tsx +22 -0
- package/site/demos/sign-in-page.tsx +10 -0
- package/site/demos/sortable.tsx +30 -0
- package/site/demos/spotlight.tsx +29 -0
- package/site/demos/stagger-children.tsx +16 -0
- package/site/demos/stat-card.tsx +12 -0
- package/site/demos/stats-section.tsx +6 -0
- package/site/demos/steps-section.tsx +66 -0
- package/site/demos/suspensed.tsx +31 -0
- package/site/demos/team-members-panel.tsx +26 -0
- package/site/demos/team-section.tsx +2 -0
- package/site/demos/testimonial-card.tsx +17 -0
- package/site/demos/testimonials-section.tsx +6 -0
- package/site/demos/theme-color-updater.tsx +32 -0
- package/site/demos/theme-switch-minimal.tsx +10 -0
- package/site/demos/underlay.tsx +74 -0
- package/site/demos/update-banner.tsx +31 -0
- package/site/demos/use-copy-to-clipboard.tsx +21 -0
- package/site/demos/use-debounce.tsx +25 -0
- package/site/demos/use-intersection-observer.tsx +32 -0
- package/site/demos/use-local-storage.tsx +22 -0
- package/site/demos/use-media-query.tsx +31 -0
- package/site/demos/use-pagination.tsx +31 -0
- package/site/demos/user-profile-block.tsx +3 -0
- package/site/demos/version-banner.tsx +27 -0
- package/site/lib/sandboxes.ts +1647 -0
- package/src/email/EmailLinkFallback.tsx +7 -1
- package/src/email/index.ts +3 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AppShell
|
|
3
|
+
description: Full-page sidebar shell with collapsible nav, user menu, and header. Pass your nav items, brand, and user; get a consistent shell across every route.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="app-shell" shellPreview />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { AppShell } from "@olwiba/ui";
|
|
22
|
+
import { LayoutDashboard, Plus, UserRound } from "lucide-react";
|
|
23
|
+
import { Link } from "your-router"; // TanStack, Next.js, etc.
|
|
24
|
+
|
|
25
|
+
export function AppLayout({ children }) {
|
|
26
|
+
return (
|
|
27
|
+
<AppShell
|
|
28
|
+
brand={{ name: "My App", href: "/" }}
|
|
29
|
+
navItems={[
|
|
30
|
+
{ icon: LayoutDashboard, label: "Dashboard", href: "/dashboard", isActive: true },
|
|
31
|
+
]}
|
|
32
|
+
action={{ icon: Plus, label: "New item", href: "/new" }}
|
|
33
|
+
user={{
|
|
34
|
+
email: "user@example.com",
|
|
35
|
+
plan: "free",
|
|
36
|
+
avatarFallback: <UserRound aria-hidden className="size-5" />,
|
|
37
|
+
onSignOut: () => signOut(),
|
|
38
|
+
}}
|
|
39
|
+
pageTitle="Dashboard"
|
|
40
|
+
renderLink={({ href, children }) => <Link to={href}>{children}</Link>}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</AppShell>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Use `sidebarPosition="contained"` in docs sandboxes or embedded previews so the shell fits its parent rather than filling the viewport:
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<AppShell sidebarPosition="contained" />
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API Reference
|
|
55
|
+
|
|
56
|
+
<APIReference name="AppShell" props={[
|
|
57
|
+
{ name: "brand", type: "AppShellBrand", description: "App name, logo, and href for the sidebar header." },
|
|
58
|
+
{ name: "navItems", type: "AppNavItem[]", description: "Primary navigation links rendered in the sidebar." },
|
|
59
|
+
{ name: "action", type: "AppShellAction", description: "CTA button above nav items (e.g. New item, Quick create)." },
|
|
60
|
+
{ name: "user", type: "AppShellUser", description: "User info and callbacks shown in the sidebar footer dropdown." },
|
|
61
|
+
{ name: "pageTitle", type: "string", default: '"Dashboard"', description: "Title shown in the top header bar." },
|
|
62
|
+
{ name: "headerStart", type: "ReactNode | ((controls: AppShellHeaderControls) => ReactNode)", description: "Header-start content. Its render form can expand the shell without importing the private sidebar context." },
|
|
63
|
+
{ name: "sidebarFooterStart", type: "ReactNode", description: "Product chrome rendered above the user menu in the sidebar footer." },
|
|
64
|
+
{ name: "sidebarContentKey", type: "string", description: "Remount key for animated sidebar identity or navigation-mode changes." },
|
|
65
|
+
{ name: "sidebarContentClassName", type: "string", description: "Classes applied to the sidebar header, content, and footer." },
|
|
66
|
+
{ name: "renderLink", type: "AppShellRenderLink", description: "Override link rendering for SPA navigation. Default: native <a>." },
|
|
67
|
+
{ name: "collapsible", type: '"icon" | "offcanvas" | "none"', default: '"icon"', description: 'Sidebar collapse behaviour.' },
|
|
68
|
+
{ name: "sidebarPosition", type: '"viewport" | "contained"', default: '"viewport"', description: 'Use "contained" for docs sandboxes or embedded previews; "viewport" for full-page app shells.' },
|
|
69
|
+
{ name: "side", type: '"left" | "right"', default: '"left"', description: "Which side the sidebar sits on." },
|
|
70
|
+
{ name: "children", type: "ReactNode", description: "Page content rendered in the main area." },
|
|
71
|
+
]} />
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AuthSection
|
|
3
|
+
description: Sign in, sign up, forgot/reset password, and code verification — one form, five modes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="auth-section" shellPreview />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { AuthSection } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
// Centered (default)
|
|
24
|
+
<AuthSection
|
|
25
|
+
onSubmit={(e) => { e.preventDefault(); signIn() }}
|
|
26
|
+
onSso={() => signInWithSso()}
|
|
27
|
+
signUpHref="/register"
|
|
28
|
+
forgotPasswordHref="/forgot-password"
|
|
29
|
+
/>
|
|
30
|
+
|
|
31
|
+
// Split layout with decorative panel
|
|
32
|
+
<AuthSection
|
|
33
|
+
layout="split"
|
|
34
|
+
onSubmit={(e) => { e.preventDefault(); signIn() }}
|
|
35
|
+
/>
|
|
36
|
+
|
|
37
|
+
// Custom form
|
|
38
|
+
<AuthSection layout="split">
|
|
39
|
+
<MyCustomForm />
|
|
40
|
+
</AuthSection>
|
|
41
|
+
|
|
42
|
+
// Forgot password
|
|
43
|
+
<AuthSection mode="forgot-password" signInHref="/sign-in" onSubmit={handleForgotPassword} success={sent ? "Check your inbox for a reset link." : undefined} />
|
|
44
|
+
|
|
45
|
+
// Reset password (reached via the emailed link)
|
|
46
|
+
<AuthSection mode="reset-password" signInHref="/sign-in" onSubmit={handleResetPassword} />
|
|
47
|
+
|
|
48
|
+
// Verify code (email verification or 2FA)
|
|
49
|
+
<AuthSection mode="verify" destination={email} onSubmit={handleVerify} onResend={handleResend} />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Every mode shares the same `AuthSection`/`DefaultForm` — swap `mode` rather than reaching for a separate screen component per auth step.
|
|
53
|
+
|
|
54
|
+
## API Reference
|
|
55
|
+
|
|
56
|
+
<APIReference name="AuthSection" props={[
|
|
57
|
+
{ name: "mode", type: '"signin" | "signup" | "forgot-password" | "reset-password" | "verify"', default: '"signin"', description: "Controls form title, fields, and footer text." },
|
|
58
|
+
{ name: "layout", type: '"centered" | "split"', default: '"centered"', description: "Visual layout of the auth screen." },
|
|
59
|
+
{ name: "children", type: "ReactNode", description: "Custom form content. Defaults to the built-in form." },
|
|
60
|
+
{ name: "panel", type: "ReactNode", description: "Split layout only — custom content for the left decorative panel." },
|
|
61
|
+
{ name: "onSubmit", type: "(e: FormEvent) => void", description: "Form submit handler." },
|
|
62
|
+
{ name: "onSso", type: "() => void", description: "Shows a SSO button when provided (signin only)." },
|
|
63
|
+
{ name: "signUpHref", type: "string", default: '"#"', description: "Link for the sign-up prompt (signin)." },
|
|
64
|
+
{ name: "signInHref", type: "string", default: '"#"', description: "Link back to sign-in (signup / forgot-password / reset-password / verify)." },
|
|
65
|
+
{ name: "forgotPasswordHref", type: "string", default: '"#"', description: "Link for the forgot password prompt (signin)." },
|
|
66
|
+
{ name: "onResend", type: "() => void", description: "Re-sends the one-time code (verify)." },
|
|
67
|
+
{ name: "destination", type: "string", description: "Address the code was sent to (verify)." },
|
|
68
|
+
{ name: "codeLength", type: "number", default: "6", description: "Number of digits in the code (verify)." },
|
|
69
|
+
{ name: "brand", type: "ReactNode", description: "Logo or brand mark shown above the form title." },
|
|
70
|
+
{ name: "error", type: "string", description: "Error message shown below the form fields." },
|
|
71
|
+
{ name: "success", type: "string", description: "Positive confirmation message shown below the form fields." },
|
|
72
|
+
{ name: "className", type: "string", description: "Class applied to the outer wrapper." },
|
|
73
|
+
]} />
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: BillingPanel
|
|
3
|
+
description: In-app billing summary — current plan, usage, payment method, and invoice history.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="billing-panel" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { BillingPanel } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
<BillingPanel
|
|
24
|
+
planName="Pro"
|
|
25
|
+
planPrice="$29/mo"
|
|
26
|
+
renewalDate="March 12, 2026"
|
|
27
|
+
usage={[{ label: "Seats", used: 6, limit: 10 }]}
|
|
28
|
+
paymentMethod={{ brand: "Visa", last4: "4242", expiry: "08/27" }}
|
|
29
|
+
invoices={invoices}
|
|
30
|
+
onManagePlan={() => openPlanDialog()}
|
|
31
|
+
/>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This is the account-side billing view — for marketing plan comparisons, use `PricingSection`/`UpgradePrompt` instead.
|
|
35
|
+
|
|
36
|
+
## API Reference
|
|
37
|
+
|
|
38
|
+
<APIReference name="BillingPanel" props={[]} />
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: EmptyState
|
|
3
|
+
description: Zero-content placeholder with icon, heading, description, and an optional CTA button.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<ComponentPreview name="empty-state" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { EmptyState } from "@olwiba/ui";
|
|
22
|
+
import { FolderOpen } from "lucide-react";
|
|
23
|
+
|
|
24
|
+
<EmptyState
|
|
25
|
+
icon={FolderOpen}
|
|
26
|
+
title="No projects yet"
|
|
27
|
+
description="Create your first project to get started."
|
|
28
|
+
variant="card"
|
|
29
|
+
action={<Button>New project</Button>}
|
|
30
|
+
secondaryAction={<Button variant="ghost">Learn more</Button>}
|
|
31
|
+
/>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## API Reference
|
|
35
|
+
|
|
36
|
+
<APIReference name="EmptyState" props={[
|
|
37
|
+
{ name: "icon", type: "LucideIcon", description: "Icon rendered above the heading." },
|
|
38
|
+
{ name: "title", type: "string", description: "Primary heading." },
|
|
39
|
+
{ name: "description", type: "ReactNode", description: "Supporting content below the heading." },
|
|
40
|
+
{ name: "eyebrow", type: "ReactNode", description: "Optional compact label above the heading." },
|
|
41
|
+
{ name: "action", type: "ReactNode", description: "Primary action." },
|
|
42
|
+
{ name: "secondaryAction", type: "ReactNode", description: "Secondary action rendered alongside the primary action." },
|
|
43
|
+
{ name: "variant", type: '"plain" | "card"', default: '"plain"', description: "Use card for route-level product empty states." },
|
|
44
|
+
{ name: "compact", type: "boolean", default: "false", description: "Reduces the card presentation's height and padding." },
|
|
45
|
+
{ name: "fill", type: "boolean", default: "false", description: "Fills a flex-sized parent." },
|
|
46
|
+
{ name: "className", type: "string", description: "Class applied to the root element." },
|
|
47
|
+
]} />
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: ErrorPage
|
|
3
|
+
description: Full-page 404 / error fallback with navigation actions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<ComponentPreview name="error-page" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { ErrorPage } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
// In a TanStack Router not-found route
|
|
24
|
+
export const Route = createFileRoute("/404")({
|
|
25
|
+
component: () => <ErrorPage />,
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API Reference
|
|
30
|
+
|
|
31
|
+
`ErrorPage` takes no props — it renders a self-contained 404 screen with a Go back and Take me home action.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: App UI
|
|
3
|
+
description: Shells and screens for application UIs — sidebar shell, auth, empty states, and error pages.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
App UI components are the structural building blocks of a product interface. They're configured once and used across every route.
|
|
7
|
+
|
|
8
|
+
| Component | Description |
|
|
9
|
+
|-----------|-------------|
|
|
10
|
+
| `AppShell` | Full-page sidebar shell with nav, user menu, and header |
|
|
11
|
+
| `AuthSection` | Sign-in screen — centered or split layout |
|
|
12
|
+
| `EmptyState` | Zero-content placeholder with icon, copy, and CTA |
|
|
13
|
+
| `ErrorPage` | 404 / error fallback page |
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: OnboardingWizard
|
|
3
|
+
description: Stateful multi-step onboarding flow.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="onboarding-wizard" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { OnboardingWizard } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
<OnboardingWizard
|
|
24
|
+
onComplete={() => router.push("/dashboard")}
|
|
25
|
+
steps={[
|
|
26
|
+
{ id: "welcome", title: "Welcome", content: <WelcomeStep /> },
|
|
27
|
+
{
|
|
28
|
+
id: "workspace",
|
|
29
|
+
title: "Name your workspace",
|
|
30
|
+
content: <WorkspaceNameStep />,
|
|
31
|
+
onNext: () => (name.trim() ? true : "Give your workspace a name to continue."),
|
|
32
|
+
},
|
|
33
|
+
]}
|
|
34
|
+
/>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
One component driven by a `steps` array — swap the array to reshape the flow rather than hand-building a new wizard per feature. `onNext` can return `false` or an error string to block advancing.
|
|
38
|
+
|
|
39
|
+
## API Reference
|
|
40
|
+
|
|
41
|
+
<APIReference name="OnboardingWizard" props={[]} />
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: SettingsSection
|
|
3
|
+
description: One title/description/content row for building a settings page.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="settings-section" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { SettingsSection } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
<div className="divide-y divide-border">
|
|
24
|
+
<SettingsSection title="Profile" description="This appears on your public profile.">
|
|
25
|
+
<MyProfileForm />
|
|
26
|
+
</SettingsSection>
|
|
27
|
+
<SettingsSection title="Delete workspace" description="This cannot be undone." danger>
|
|
28
|
+
<Button variant="destructive">Delete workspace</Button>
|
|
29
|
+
</SettingsSection>
|
|
30
|
+
</div>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Stack a few inside a `divide-y` wrapper to build a full settings page — one block reused per row, rather than a bespoke layout each time.
|
|
34
|
+
|
|
35
|
+
## API Reference
|
|
36
|
+
|
|
37
|
+
<APIReference name="SettingsSection" props={[]} />
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TeamMembersPanel
|
|
3
|
+
description: Member list with role management and an invite dialog.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="team-members-panel" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { TeamMembersPanel } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
<TeamMembersPanel
|
|
24
|
+
members={members}
|
|
25
|
+
onInvite={(email, role) => inviteMember(email, role)}
|
|
26
|
+
onRoleChange={(id, role) => updateRole(id, role)}
|
|
27
|
+
onRemove={(id) => removeMember(id)}
|
|
28
|
+
/>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Built on top of `DataTable` — pass `roles` to customize the options offered in the invite dialog and per-row role menu.
|
|
32
|
+
|
|
33
|
+
## API Reference
|
|
34
|
+
|
|
35
|
+
<APIReference name="TeamMembersPanel" props={[]} />
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: UpdateBanner
|
|
3
|
+
description: Slide-in banner that tells users a new deploy shipped and their tab is stale — poll a version endpoint, offer one-click refresh.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="update-banner" />
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
Bake a build version into the client bundle (e.g. vite `define` with the git SHA), expose the same value from a `/api/version` endpoint, and mount the banner once in the root layout:
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { UpdateBanner } from "@olwiba/ui";
|
|
18
|
+
|
|
19
|
+
declare const __BUILD_VERSION__: string;
|
|
20
|
+
|
|
21
|
+
<UpdateBanner
|
|
22
|
+
currentVersion={__BUILD_VERSION__}
|
|
23
|
+
fetchVersion={async () => {
|
|
24
|
+
const res = await fetch("/api/version", { cache: "no-store" });
|
|
25
|
+
return res.json();
|
|
26
|
+
}}
|
|
27
|
+
/>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
When a new deploy goes live, open tabs still run the old bundle; the next poll sees a different server version and the banner slides in. Refresh defaults to a full reload — pass `onRefresh` to hook a celebration or custom flow first.
|
|
31
|
+
|
|
32
|
+
## API Reference
|
|
33
|
+
|
|
34
|
+
<APIReference name="UpdateBanner" props={[
|
|
35
|
+
{ name: "currentVersion", type: "string", description: "Version baked into the running bundle at build time." },
|
|
36
|
+
{ name: "fetchVersion", type: "() => Promise<{ version: string }>", description: "Fetch the deployed version — the host app wires its own endpoint." },
|
|
37
|
+
{ name: "intervalMs", type: "number", default: "300000", description: "Poll interval in ms." },
|
|
38
|
+
{ name: "forceShow", type: "boolean", default: "false", description: "Force the banner visible (demos/testing)." },
|
|
39
|
+
{ name: "onRefresh", type: "() => void", description: "Refresh click handler; defaults to window.location.reload()." },
|
|
40
|
+
{ name: "message", type: "ReactNode", description: "Banner copy." },
|
|
41
|
+
{ name: "buttonLabel", type: "string", default: '"Refresh now"', description: "Refresh button label." },
|
|
42
|
+
{ name: "className", type: "string", description: "Class applied to the banner card." },
|
|
43
|
+
]} />
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: ActivityFeed
|
|
3
|
+
description: Vertical activity timeline with avatar or icon markers connected by a rail.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="activity-feed" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { ActivityFeed } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
<ActivityFeed
|
|
24
|
+
items={[
|
|
25
|
+
{
|
|
26
|
+
id: "1",
|
|
27
|
+
title: <><b>Ana</b> deployed to production</>,
|
|
28
|
+
description: "v0.1.16 · 12 commits",
|
|
29
|
+
timestamp: "2h ago",
|
|
30
|
+
avatar: "/avatars/ana.png",
|
|
31
|
+
initials: "AS",
|
|
32
|
+
},
|
|
33
|
+
{ id: "2", title: "Subscription renewed", timestamp: "Yesterday", icon: <CreditCard /> },
|
|
34
|
+
]}
|
|
35
|
+
/>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Presentation-only: pass pre-formatted timestamps and rich `title` nodes from your own data layer. Items with `avatar` render an avatar marker; otherwise `icon` (or a default) renders in a bordered circle.
|
|
39
|
+
|
|
40
|
+
## API Reference
|
|
41
|
+
|
|
42
|
+
<APIReference name="ActivityFeed" props={[]} />
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Chart
|
|
3
|
+
description: Theme-aware line, area, bar, and donut charts — one component, type switches the form.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="chart" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { Chart } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
<Chart
|
|
24
|
+
type="line"
|
|
25
|
+
data={revenue}
|
|
26
|
+
xKey="month"
|
|
27
|
+
series={[
|
|
28
|
+
{ key: "mrr", label: "MRR" },
|
|
29
|
+
{ key: "costs", label: "Costs" },
|
|
30
|
+
]}
|
|
31
|
+
valueFormatter={(v) => `$${v.toLocaleString()}`}
|
|
32
|
+
/>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Pick the form by the data's job: `line`/`area` for change over time, `bar` for magnitude comparison, `donut` for part-of-whole. Colors come from the `--chart-1..5` theme tokens in fixed order — series keep their color when others are filtered out. Override per series with `color`.
|
|
36
|
+
|
|
37
|
+
Donut uses `xKey` for slice labels and `series[0].key` for values. More than 5 slices: fold the tail into an "Other" row in your data rather than adding hues.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
<Chart type="donut" data={plans} xKey="plan" series={[{ key: "users" }]} />
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
A legend renders automatically for multiple series (and donuts); a single named series doesn't need one. Tooltips are always on.
|
|
44
|
+
|
|
45
|
+
## API Reference
|
|
46
|
+
|
|
47
|
+
<APIReference name="Chart" props={[]} />
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CommandMenu
|
|
3
|
+
description: Global Cmd+K / Ctrl+K search palette.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="command-menu" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { CommandMenu } from "@olwiba/ui";
|
|
22
|
+
import { LayoutDashboard, Settings } from "lucide-react";
|
|
23
|
+
|
|
24
|
+
<CommandMenu
|
|
25
|
+
groups={[
|
|
26
|
+
{
|
|
27
|
+
heading: "Navigate",
|
|
28
|
+
items: [
|
|
29
|
+
{ id: "dashboard", label: "Dashboard", icon: LayoutDashboard, onSelect: () => router.push("/dashboard") },
|
|
30
|
+
{ id: "settings", label: "Settings", icon: Settings, onSelect: () => router.push("/settings") },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
]}
|
|
34
|
+
/>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Registers the Cmd+K (mac) / Ctrl+K (win) hotkey by default — pass `hotkey={false}` and your own `open`/`onOpenChange` if you'd rather trigger it from a button.
|
|
38
|
+
|
|
39
|
+
## API Reference
|
|
40
|
+
|
|
41
|
+
<APIReference name="CommandMenu" props={[]} />
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: ConfirmDialog
|
|
3
|
+
description: Modal confirmation dialog — UI shell for the useConfirm hook.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="confirm-dialog" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { ConfirmDialog } from "@olwiba/ui";
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## API Reference
|
|
25
|
+
|
|
26
|
+
<APIReference name="ConfirmDialog" props={[]} />
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: ContextMenu
|
|
3
|
+
description: Right-click context menu with animated entry.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="context-menu" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { ContextMenu } from "@olwiba/ui";
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## API Reference
|
|
25
|
+
|
|
26
|
+
<APIReference name="ContextMenu" props={[]} />
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: DataTable
|
|
3
|
+
description: Sortable, paginated, optionally-selectable data table built on TanStack Table.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<div className="flex flex-col md:flex-row items-center justify-start gap-2 mb-2">
|
|
7
|
+
<CopyCommandButton command="bun add @olwiba/ui" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<Sandbox id="data-table" />
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
bun add @olwiba/ui
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { DataTable, type DataTableColumn } from "@olwiba/ui";
|
|
22
|
+
|
|
23
|
+
const columns: DataTableColumn<Project>[] = [
|
|
24
|
+
{ accessorKey: "name", header: "Project" },
|
|
25
|
+
{ accessorKey: "status", header: "Status" },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
<DataTable
|
|
29
|
+
columns={columns}
|
|
30
|
+
data={projects}
|
|
31
|
+
searchKey="name"
|
|
32
|
+
toolbar={<Button size="sm">New project</Button>}
|
|
33
|
+
/>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
One component — toggle `searchKey`, `selectable`, and `pageSize` rather than reaching for a different table per use case. Columns are standard TanStack Table `ColumnDef`s, so sorting, custom cells, and accessors all work as usual.
|
|
37
|
+
|
|
38
|
+
## API Reference
|
|
39
|
+
|
|
40
|
+
<APIReference name="DataTable" props={[]} />
|