From 6e3157ab47d3fefd4e1737989eb8920fb14cee11 Mon Sep 17 00:00:00 2001 From: Carla Goncalves Date: Thu, 19 Mar 2026 12:14:41 +0000 Subject: [PATCH 1/3] Add takeover component Add takeover mdx file Add interactive examples --- .../design-system/components/meta.json | 1 + .../design-system/components/takeover.mdx | 515 ++++++++++++++++++ .../interactive-examples.tsx | 290 ++++++++++ packages/eclipse/src/components/index.ts | 10 + packages/eclipse/src/components/takeover.tsx | 133 +++++ 5 files changed, 949 insertions(+) create mode 100644 apps/eclipse/content/design-system/components/takeover.mdx create mode 100644 apps/eclipse/src/components/takeover-examples/interactive-examples.tsx create mode 100644 packages/eclipse/src/components/takeover.tsx diff --git a/apps/eclipse/content/design-system/components/meta.json b/apps/eclipse/content/design-system/components/meta.json index 5d0d142b60..4d4b1f2602 100644 --- a/apps/eclipse/content/design-system/components/meta.json +++ b/apps/eclipse/content/design-system/components/meta.json @@ -34,6 +34,7 @@ "switch", "table", "tabs", + "takeover", "textarea", "tooltip", "typetable" diff --git a/apps/eclipse/content/design-system/components/takeover.mdx b/apps/eclipse/content/design-system/components/takeover.mdx new file mode 100644 index 0000000000..17fc15780d --- /dev/null +++ b/apps/eclipse/content/design-system/components/takeover.mdx @@ -0,0 +1,515 @@ +--- +title: Takeover +description: A component for displaying Takeover states with icons, titles, descriptions, and call-to-action buttons. Perfect for showing when no data is available or guiding users to take action. +--- + +import { + Takeover, + TakeoverMenu, + TakeoverContent, + TakeoverDescription, + TakeoverHeader, + TakeoverFooter, + TakeoverTitle, + Button, + Avatar, + Input, +} from "@prisma/eclipse"; +import { TakeoverMenuExample, WizardTakeoverExample, SimpleTakeoverMenuExample, TakeoverWithFooterAndHeaderExample, TakeoverWithFooterOnlyExample, TakeoverWithHeaderOnlyExample, WizardWithFooterExample } from "@/components/takeover-examples/interactive-examples"; + +### Usage + +**With TakeoverMenu (Interactive)** + +Use TakeoverMenu for navigation controls with back and close buttons: + +**Live Example:** + +
+

Live Example:

+ +
+ +**Wizard Pattern with TakeoverMenu** + +Create multi-step wizards with custom navigation: + +**Live Example:** + +
+

Live Example:

+ +
+ +**Simple TakeoverMenu Example** + +Basic usage of TakeoverMenu with default controls: + +**Live Example:** + +
+

Live Example:

+ +
+ +**Default Variant: With Footer and Header** + +Complete takeover with menu, header, content, and footer: + +```tsx +import { + Takeover, + TakeoverMenu, + TakeoverHeader, + TakeoverTitle, + TakeoverDescription, + TakeoverContent, + TakeoverFooter, + Button, +} from "@prisma/eclipse"; + +export function TakeoverWithFooterAndHeader() { + return ( + <> + + {}} onClose={() => {}} /> + + Complete Layout + + This shows a full takeover with header, content, and footer. + + + + + + +

+ Additional information or secondary actions +

+
+
+ + ); +} +``` + +**Live Example:** + +
+

Live Example:

+ +
+ +**Default Variant: With Footer Only** + +Takeover with footer but no header: + +```tsx +import { + Takeover, + TakeoverMenu, + TakeoverContent, + TakeoverFooter, + Button, +} from "@prisma/eclipse"; + +export function TakeoverWithFooterOnly() { + return ( + <> + + {}} onClose={() => {}} /> + +
+

Quick Action

+

+ Perform an action without additional header information. +

+ +
+
+ +
+ + +
+
+
+ + ); +} +``` + +**Live Example:** + +
+

Live Example:

+ +
+ +**Default Variant: With Header Only** + +Takeover with header but no footer: + +```tsx +import { + Takeover, + TakeoverMenu, + TakeoverHeader, + TakeoverTitle, + TakeoverDescription, + TakeoverContent, + Button, +} from "@prisma/eclipse"; + +export function TakeoverWithHeaderOnly() { + return ( + <> + + {}} onClose={() => {}} /> + + Header Only Layout + + This layout includes a header and content, but no footer. + + + +
+ + +
+
+
+ + ); +} +``` + +**Live Example:** + +
+

Live Example:

+ +
+ +**Wizard Variant: With Footer and Header** + +Wizard pattern with footer for step navigation: + +```tsx +import { + Takeover, + TakeoverMenu, + TakeoverHeader, + TakeoverTitle, + TakeoverDescription, + TakeoverContent, + TakeoverFooter, + Button, +} from "@prisma/eclipse"; + +export function WizardWithFooter() { + const [step, setStep] = React.useState(1); + + return ( + + +
+ Step {step} of 3 +
+
+ + Wizard Step {step} + + Complete this step to continue the process. + + + +
+ Step content goes here... +
+
+ +
+ + +
+
+
+ ); +} +``` + +**Live Example:** + +
+

Live Example:

+ +
+ +### API Reference + +#### Takeover + +The main container component for the Takeover state. Wraps the `TakeoverHeader` and `TakeoverContent` components. + +**Props:** +- `className` - Additional CSS classes (string, optional) +- All standard HTML div attributes + +```tsx + + + + +``` + +#### TakeoverMenu + +Navigation controls for the takeover with back and close buttons. + +**Props:** +- `variant` - Visual variant ("default" | "wizard", default: "default") + - `"default"` - Shows back and close buttons + - `"wizard"` - Custom layout for wizard patterns +- `onBack` - Callback when back button is clicked (() => void, optional) +- `onClose` - Callback when close button is clicked (() => void, optional) +- `className` - Additional CSS classes (string, optional) +- All standard HTML div attributes + +```tsx + previousStep()} + onClose={() => closeTakeover()} +/> + +// Wizard variant with custom content + +
+ + +
+
+``` + +#### TakeoverHeader + +Container for the Takeover state header, including the media, title, and description. + +**Props:** +- `className` - Additional CSS classes (string, optional) +- All standard HTML div attributes + +```tsx + + + + +``` + +#### TakeoverTitle + +Displays the title of the Takeover state. + +**Props:** +- `className` - Additional CSS classes (string, optional) +- All standard HTML div attributes + +```tsx +No data +``` + +#### TakeoverDescription + +Displays the description text of the Takeover state. Supports links with automatic styling. + +**Props:** +- `className` - Additional CSS classes (string, optional) +- All standard HTML p attributes + +```tsx + + You do not have any notifications. + Learn more + +``` + +#### TakeoverContent + +Container for action elements like buttons, inputs, or links in the Takeover state. + +**Props:** +- `className` - Additional CSS classes (string, optional) +- All standard HTML div attributes + +```tsx + + + +``` + +#### TakeoverFooter + +Footer section for additional actions or information at the bottom of the takeover. + +**Props:** +- `className` - Additional CSS classes (string, optional) +- All standard HTML div attributes + +```tsx + +
+ + +
+
+``` + +### Features + +- ✅ Flexible composition with semantic components +- ✅ TakeoverMenu with default and wizard variants +- ✅ TakeoverFooter for navigation and actions +- ✅ Two media variants (default and icon) +- ✅ Responsive design with proper spacing +- ✅ Automatic link styling in descriptions +- ✅ Centered text alignment +- ✅ Balanced text layout for readability +- ✅ Dashed border container +- ✅ Supports custom backgrounds and borders +- ✅ Icon sizing optimization +- ✅ Fully typed with TypeScript +- ✅ Customizable with className props + +### Best Practices + +- Use clear, action-oriented titles that describe the Takeover state +- Provide helpful descriptions that guide users on what to do next +- Always include at least one call-to-action button when possible +- Use appropriate icons that represent the context (e.g., folder for files, bell for notifications) +- Keep descriptions concise but informative +- Use the `icon` variant for small icons, `default` for larger visuals +- Consider adding a border or background for better visual separation +- Ensure Takeover states are accessible with proper semantic HTML +- Test Takeover states in different contexts (search, filters, first-time use) +- Provide multiple action options when relevant (create, import, learn more) + +### Accessibility + +The Takeover component follows accessibility best practices: + +- Uses semantic HTML structure with proper div hierarchy +- Supports keyboard navigation for interactive elements +- Link styling with proper contrast ratios +- Underlined links for clarity +- Readable text sizes (text-sm) +- Proper spacing for touch targets +- Works with screen readers +- Maintains proper focus order +- All interactive elements are keyboard accessible + +### Common Use Cases + +The Takeover component is perfect for: + +- **No data states** - When lists or tables have no items +- **Search results** - When searches return no matches +- **Filtered views** - When filters exclude all items +- **Notifications** - When there are no notifications +- **First-time use** - Onboarding new users to features +- **File uploads** - Takeover file storage or folders +- **Team invites** - No team members yet +- **404 pages** - Page not found errors +- **Completed tasks** - All items processed or cleared +- **Settings** - Features not yet configured +- **Archives** - Takeover archived content + +### Styling + +The Takeover component uses design tokens and can be customized: + +- **Container**: Dashed border, rounded corners, padding, centered content +- **Header**: Vertical layout with gap spacing +- **Media (icon variant)**: Muted background, size-8, rounded-lg +- **Media (default variant)**: Transparent background for custom sizing +- **Title**: Small font, medium weight, tracking-tight +- **Description**: Small relaxed line height, muted foreground color +- **Links**: Underlined with hover effects to primary color +- **Content**: Flexible column layout with gap spacing + +Customize by passing `className` props: + +```tsx + + + Custom Styled + + +``` + +### Design Patterns + +**Progressive Disclosure:** +```tsx + + + Get Started + + Create your first item to begin. + + + + +
+ Advanced options +
Additional setup information...
+
+
+
+``` + +**Error Recovery:** +```tsx + + + Connection Error + + Unable to load data. Check your connection and try again. + + + + + + +``` + +**Loading to Takeover Transition:** +```tsx +{isLoading ? ( + +) : items.length === 0 ? ( + + + No Items + Add your first item to get started. + + + + + +) : ( + +)} +``` diff --git a/apps/eclipse/src/components/takeover-examples/interactive-examples.tsx b/apps/eclipse/src/components/takeover-examples/interactive-examples.tsx new file mode 100644 index 0000000000..43502527de --- /dev/null +++ b/apps/eclipse/src/components/takeover-examples/interactive-examples.tsx @@ -0,0 +1,290 @@ +"use client"; + +import { useState } from "react"; +import { + Takeover, + TakeoverMenu, + TakeoverHeader, + TakeoverTitle, + TakeoverDescription, + TakeoverContent, + TakeoverFooter, + Button, +} from "@prisma/eclipse"; + +export function TakeoverMenuExample() { + const [isOpen, setIsOpen] = useState(true); + const [step, setStep] = useState(1); + + const handleBack = () => { + if (step > 1) { + setStep(step - 1); + } + }; + + const handleClose = () => { + setIsOpen(false); + }; + + const handleReset = () => { + setIsOpen(true); + setStep(1); + }; + + if (!isOpen) { + return ( +
+

+ Takeover closed. Click below to reopen. +

+ +
+ ); + } + + return ( +
+ + + + Step {step} of 3 + + {step === 1 && "Welcome! This is the first step of the process."} + {step === 2 && "Great! You're on the second step now."} + {step === 3 && "Final step! Almost done."} + + + + {step < 3 ? ( + + ) : ( + + )} + + +
+ ); +} + +export function WizardTakeoverExample() { + const [currentStep, setCurrentStep] = useState(1); + const totalSteps = 4; + + const handleNext = () => { + if (currentStep < totalSteps) { + setCurrentStep(currentStep + 1); + } + }; + + const handlePrevious = () => { + if (currentStep > 1) { + setCurrentStep(currentStep - 1); + } + }; + + const handleReset = () => { + setCurrentStep(1); + }; + + return ( +
+ + +
+ + + Step {currentStep} of {totalSteps} + + +
+
+ + + {currentStep === 1 && "Getting Started"} + {currentStep === 2 && "Configuration"} + {currentStep === 3 && "Team Setup"} + {currentStep === 4 && "All Set!"} + + + {currentStep === 1 && "Let's begin by setting up your account."} + {currentStep === 2 && "Configure your preferences and settings."} + {currentStep === 3 && "Invite your team members to collaborate."} + {currentStep === 4 && "You're ready to start using the platform!"} + + + +
+ Progress: {Math.round((currentStep / totalSteps) * 100)}% +
+
+
+
+ ); +} + +export function SimpleTakeoverMenuExample() { + const [showMenu, setShowMenu] = useState(true); + + return ( +
+ + {showMenu && ( + alert("Back clicked!")} + onClose={() => setShowMenu(false)} + /> + )} + {!showMenu && ( +
+

Menu hidden.

+ +
+ )} + + Interactive Takeover + + This takeover has navigation controls. Try clicking the back or + close buttons in the menu above. + + + + + +
+
+ ); +} + +export function TakeoverWithFooterAndHeaderExample() { + return ( +
+ + {}} onClose={() => {}} /> + + Complete Layout + + This shows a full takeover with header, content, and footer. + + + + + + +

+ Additional information or secondary actions +

+
+
+
+ ); +} + +export function TakeoverWithFooterOnlyExample() { + return ( +
+ + {}} onClose={() => {}} /> + +
+

Quick Action

+

+ Perform an action without additional header information. +

+ +
+
+ +
+ + +
+
+
+
+ ); +} + +export function TakeoverWithHeaderOnlyExample() { + return ( +
+ + {}} onClose={() => {}} /> + + Header Only Layout + + This layout includes a header and content, but no footer. + + + +
+ + +
+
+
+
+ ); +} + +export function WizardWithFooterExample() { + const [step, setStep] = useState(1); + + return ( +
+ + +
+ Step {step} of 3 +
+
+ + Wizard Step {step} + + Complete this step to continue the process. + + + +
+ Step content goes here... +
+
+ +
+ + +
+
+
+
+ ); +} diff --git a/packages/eclipse/src/components/index.ts b/packages/eclipse/src/components/index.ts index fa034f917b..47b371e621 100644 --- a/packages/eclipse/src/components/index.ts +++ b/packages/eclipse/src/components/index.ts @@ -178,3 +178,13 @@ export { EmptyContent, EmptyMedia, } from "./empty"; + +export { + Takeover, + TakeoverMenu, + TakeoverHeader, + TakeoverTitle, + TakeoverDescription, + TakeoverContent, + TakeoverFooter, +} from "./takeover"; diff --git a/packages/eclipse/src/components/takeover.tsx b/packages/eclipse/src/components/takeover.tsx new file mode 100644 index 0000000000..4c798fb570 --- /dev/null +++ b/packages/eclipse/src/components/takeover.tsx @@ -0,0 +1,133 @@ +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "../lib/cn"; +import { Button } from "./button"; + +function Takeover({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ); +} + +const takeoverMenuVariants = cva("p-6 w-full", { + variants: { + variant: { + default: "flex justify-between align-center", + wizard: "", + }, + }, + defaultVariants: { + variant: "default", + }, +}); + +function TakeoverMenu({ + className, + variant = "default", + onBack, + onClose, + ...props +}: React.ComponentProps<"div"> & + VariantProps & { + onBack?: () => void; + onClose?: () => void; + }) { + return ( +
+ {variant === "default" ? ( + <> +
onBack?.()}> + +
+
onClose?.()}> + +
+ + ) : ( + props.children + )} +
+ ); +} + +function TakeoverHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ); +} + +function TakeoverTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ); +} + +function TakeoverDescription({ + className, + ...props +}: React.ComponentProps<"p">) { + return ( +
a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary mb-11! mt-0!", + className, + )} + {...props} + /> + ); +} + +function TakeoverContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ); +} +function TakeoverFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ); +} + +export { + Takeover, + TakeoverMenu, + TakeoverHeader, + TakeoverTitle, + TakeoverDescription, + TakeoverContent, + TakeoverFooter, +}; From a6132003419f52f95f72f0b5ea23d56a74137ba4 Mon Sep 17 00:00:00 2001 From: Carla Goncalves Date: Thu, 19 Mar 2026 12:17:56 +0000 Subject: [PATCH 2/3] Update takeover --- apps/eclipse/content/design-system/components/takeover.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/eclipse/content/design-system/components/takeover.mdx b/apps/eclipse/content/design-system/components/takeover.mdx index 17fc15780d..4f1865456a 100644 --- a/apps/eclipse/content/design-system/components/takeover.mdx +++ b/apps/eclipse/content/design-system/components/takeover.mdx @@ -1,8 +1,9 @@ --- title: Takeover -description: A component for displaying Takeover states with icons, titles, descriptions, and call-to-action buttons. Perfect for showing when no data is available or guiding users to take action. +description: A takeover component that displays full-width guided experiences with menu navigation, headers, content, and footers. Perfect for multi-step wizards, onboarding flows, and focused user journeys. --- + import { Takeover, TakeoverMenu, From e8515ab3c3a6e85dfe557e1865e9269278fbc2dc Mon Sep 17 00:00:00 2001 From: Carla Goncalves Date: Mon, 20 Apr 2026 13:26:58 +0100 Subject: [PATCH 3/3] Update vertical align --- packages/eclipse/src/components/takeover.tsx | 18 +++++++++++++----- packages/ui/src/components/navigation-menu.tsx | 10 +++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/eclipse/src/components/takeover.tsx b/packages/eclipse/src/components/takeover.tsx index 4c798fb570..e04914dadb 100644 --- a/packages/eclipse/src/components/takeover.tsx +++ b/packages/eclipse/src/components/takeover.tsx @@ -19,7 +19,7 @@ function Takeover({ className, ...props }: React.ComponentProps<"div">) { const takeoverMenuVariants = cva("p-6 w-full", { variants: { variant: { - default: "flex justify-between align-center", + default: "flex justify-between items-center", wizard: "", }, }, @@ -47,12 +47,20 @@ function TakeoverMenu({ > {variant === "default" ? ( <> -
onBack?.()}> +
-
onClose?.()}> + +
+ ) : ( props.children diff --git a/packages/ui/src/components/navigation-menu.tsx b/packages/ui/src/components/navigation-menu.tsx index 4074dc9716..7600a7898b 100644 --- a/packages/ui/src/components/navigation-menu.tsx +++ b/packages/ui/src/components/navigation-menu.tsx @@ -275,7 +275,7 @@ function Socials({ return (
{(include === "all" || include?.includes("discord")) && ( - + )} {(include === "all" || include?.includes("twitter")) && ( - + )} {(include === "all" || include?.includes("youtube")) && ( - + )} {(include === "all" || include?.includes("linkedin")) && ( - +