diff --git a/.cursor/rules/design-system-not-kitchen-sink.mdc b/.cursor/rules/design-system-not-kitchen-sink.mdc new file mode 100644 index 0000000000..01516e161a --- /dev/null +++ b/.cursor/rules/design-system-not-kitchen-sink.mdc @@ -0,0 +1,23 @@ +--- +description: Facelift and kitchen-sink work changes the Vibe design system itself — kitchen-sink is only a preview surface, never the source of design changes. +alwaysApply: true +--- + +# Design System Changes vs Kitchen Sink + +## Core rule + +**Every design change must be made on the Vibe design system itself**, not on the kitchen-sink instance that displays it. + +Kitchen-sink (`packages/kitchen-sink`) is a **preview / exploration surface** for reviewing components and variants. It exists so we can see the design system while we change it. It is **not** where design work lives. + +## What this means in practice + +- Change components, tokens, styles, and APIs in the real packages (`packages/core`, `packages/components/*`, `packages/style`, etc.). +- Use kitchen-sink to **show** those changes (gallery pages, screens, theme toggles). +- Do **not** “fix” a visual issue by restyling or forking behavior only inside kitchen-sink demos, sections, or gallery wrappers. +- If a kitchen-sink gallery or section needs an update, it should only reflect or exercise the design-system change — not replace it. + +## Why + +We are changing the **design system**, so consumers of `@vibe/core` (and related packages) get the new design. Kitchen-sink-only tweaks would leave the actual system unchanged. diff --git a/CLAUDE.md b/CLAUDE.md index 95eca3c8ae..76a40aeb61 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,6 +6,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co The **Vibe Design System** is monday.com's official React component library, managed as a Lerna monorepo with Yarn Workspaces. The main package `@vibe/core` provides the primary component library, while specialized packages handle icons, testing utilities, codemods, and more. +## Design System vs Kitchen Sink + +**Every design change must be made on the Vibe design system itself**, not on the kitchen-sink instance that displays it. + +- Change components, tokens, styles, and APIs in the real packages (`packages/core`, `packages/components/*`, `packages/style`, etc.). +- Use `packages/kitchen-sink` only as a **preview / exploration surface** to review variants while redesigning. +- Do **not** fix or redesign visuals only inside kitchen-sink demos, sections, or gallery wrappers — that leaves the actual design system unchanged for consumers of `@vibe/core`. + ## Development Commands ### Building and Testing diff --git a/packages/kitchen-sink/src/App.tsx b/packages/kitchen-sink/src/App.tsx index c61bf7ef2a..bafab2f82c 100644 --- a/packages/kitchen-sink/src/App.tsx +++ b/packages/kitchen-sink/src/App.tsx @@ -3,8 +3,7 @@ import { AppThemeShell } from "./components/AppThemeShell"; import { LeftPane } from "./components/LeftPane"; import { useKitchenSink } from "./context/KitchenSinkContext"; import { ComponentsView } from "./components/ComponentsView"; -import { DropdownGalleryView } from "./components/DropdownGalleryView"; -import { ToastGalleryView } from "./components/ToastGalleryView"; +import { componentGalleries, isComponentGalleryId } from "./components/componentGalleries"; import { CompareView } from "./components/CompareView"; import { ThemePanel } from "./components/ThemePanel"; import { ScreensView } from "./components/ScreensView"; @@ -13,6 +12,11 @@ export default function App() { const { view, componentSubPage } = useKitchenSink(); const [leftPaneCollapsed, setLeftPaneCollapsed] = useState(false); + const GalleryView = + view === "components" && isComponentGalleryId(componentSubPage) + ? componentGalleries[componentSubPage] + : null; + return (
{view === "components" && componentSubPage === "grid" && } - {view === "components" && componentSubPage === "toast" && } - {view === "components" && componentSubPage === "dropdown" && } + {GalleryView && } {view === "compare" && } {view === "theme" && } {view === "screens" && } diff --git a/packages/kitchen-sink/src/components/ButtonGalleryView.tsx b/packages/kitchen-sink/src/components/ButtonGalleryView.tsx new file mode 100644 index 0000000000..b98bef1f74 --- /dev/null +++ b/packages/kitchen-sink/src/components/ButtonGalleryView.tsx @@ -0,0 +1,108 @@ +import { Button } from "@vibe/core"; +import { Bolt, Calendar } from "@vibe/icons"; +import { ComponentGallery, type GalleryVariation } from "./ComponentGallery"; + +const buttonVariations: GalleryVariation[] = [ + { + id: "kind-primary", + label: "Kind — Primary", + render: () => , + }, + { + id: "kind-secondary", + label: "Kind — Secondary", + render: () => , + }, + { + id: "kind-tertiary", + label: "Kind — Tertiary", + render: () => , + }, + { + id: "size-large", + label: "Size — Large", + render: () => , + }, + { + id: "size-medium", + label: "Size — Medium", + render: () => , + }, + { + id: "size-small", + label: "Size — Small", + render: () => , + }, + { + id: "disabled-primary", + label: "Disabled — Primary", + render: () => , + }, + { + id: "disabled-secondary", + label: "Disabled — Secondary", + render: () => ( + + ), + }, + { + id: "disabled-tertiary", + label: "Disabled — Tertiary", + render: () => ( + + ), + }, + { + id: "state-active", + label: "State — Active", + render: () => , + }, + { + id: "color-positive", + label: "Color — Positive", + render: () => , + }, + { + id: "color-negative", + label: "Color — Negative", + render: () => , + }, + { + id: "icon-left", + label: "Icon — Left", + render: () => , + }, + { + id: "icon-right", + label: "Icon — Right", + render: () => , + }, + { + id: "icon-both", + label: "Icon — Both sides", + render: () => ( + + ), + }, + { + id: "loading", + label: "State — Loading", + render: () => , + }, +]; + +export function ButtonGalleryView() { + return ( + + ); +} diff --git a/packages/kitchen-sink/src/components/ButtonGroupGalleryView.tsx b/packages/kitchen-sink/src/components/ButtonGroupGalleryView.tsx new file mode 100644 index 0000000000..701cb2a800 --- /dev/null +++ b/packages/kitchen-sink/src/components/ButtonGroupGalleryView.tsx @@ -0,0 +1,80 @@ +import { ButtonGroup } from "@vibe/core"; +import { ComponentGallery, type GalleryVariation } from "./ComponentGallery"; + +const options = [ + { value: 1, text: "Alpha" }, + { value: 2, text: "Beta" }, + { value: 3, text: "Gamma" }, + { value: 4, text: "Delta" }, +]; + +const buttonGroupVariations: GalleryVariation[] = [ + { + id: "kind-secondary", + label: "Kind — Secondary (default)", + render: () => ( + + ), + }, + { + id: "kind-tertiary", + label: "Kind — Tertiary", + render: () => ( + + ), + }, + { + id: "size-medium", + label: "Size — Medium", + render: () => ( + + ), + }, + { + id: "size-small", + label: "Size — Small", + render: () => ( + + ), + }, + { + id: "disabled", + label: "State — Disabled", + render: () => , + }, + { + id: "disabled-single", + label: "State — Single option disabled", + render: () => ( + + ), + }, + { + id: "full-width", + label: "Layout — Full width", + render: () => ( +
+ +
+ ), + }, +]; + +export function ButtonGroupGalleryView() { + return ( + + ); +} diff --git a/packages/kitchen-sink/src/components/ChipGalleryView.tsx b/packages/kitchen-sink/src/components/ChipGalleryView.tsx new file mode 100644 index 0000000000..ca05311eab --- /dev/null +++ b/packages/kitchen-sink/src/components/ChipGalleryView.tsx @@ -0,0 +1,76 @@ +import { Chips } from "@vibe/core"; +import { Email } from "@vibe/icons"; +import { ComponentGallery, type GalleryVariation } from "./ComponentGallery"; + +const chipVariations: GalleryVariation[] = [ + { + id: "default", + label: "Default", + render: () => , + }, + { + id: "color-primary", + label: "Color — Primary", + render: () => , + }, + { + id: "color-positive", + label: "Color — Positive", + render: () => , + }, + { + id: "color-negative", + label: "Color — Negative", + render: () => , + }, + { + id: "color-warning", + label: "Color — Warning", + render: () => , + }, + { + id: "color-neutral", + label: "Color — Neutral", + render: () => , + }, + { + id: "readonly", + label: "State — Read only", + render: () => , + }, + { + id: "disabled", + label: "State — Disabled", + render: () => , + }, + { + id: "removable", + label: "Removable", + render: () => {}} />, + }, + { + id: "clickable", + label: "Clickable", + render: () => {}} />, + }, + { + id: "left-icon", + label: "With left icon", + render: () => , + }, + { + id: "right-icon", + label: "With right icon", + render: () => , + }, +]; + +export function ChipGalleryView() { + return ( + + ); +} diff --git a/packages/kitchen-sink/src/components/ComponentGallery.tsx b/packages/kitchen-sink/src/components/ComponentGallery.tsx new file mode 100644 index 0000000000..74fe11a0c8 --- /dev/null +++ b/packages/kitchen-sink/src/components/ComponentGallery.tsx @@ -0,0 +1,32 @@ +import type { ReactNode } from "react"; + +export type GalleryVariation = { + id: string; + label: string; + render: () => ReactNode; +}; + +type ComponentGalleryProps = { + title: string; + description: string; + variations: GalleryVariation[]; +}; + +export function ComponentGallery({ title, description, variations }: ComponentGalleryProps) { + return ( +
+
+

{title}

+

{description}

+
+
+ {variations.map(({ id, label, render }) => ( +
+

{label}

+
{render()}
+
+ ))} +
+
+ ); +} diff --git a/packages/kitchen-sink/src/components/IconButtonGalleryView.tsx b/packages/kitchen-sink/src/components/IconButtonGalleryView.tsx new file mode 100644 index 0000000000..e9e1325475 --- /dev/null +++ b/packages/kitchen-sink/src/components/IconButtonGalleryView.tsx @@ -0,0 +1,115 @@ +import { IconButton } from "@vibe/core"; +import { Add, Bolt, Doc, Robot } from "@vibe/icons"; +import { ComponentGallery, type GalleryVariation } from "./ComponentGallery"; + +const iconButtonVariations: GalleryVariation[] = [ + { + id: "kind-primary", + label: "Kind — Primary", + render: () => , + }, + { + id: "kind-secondary", + label: "Kind — Secondary", + render: () => , + }, + { + id: "kind-tertiary", + label: "Kind — Tertiary", + render: () => , + }, + { + id: "size-xxs", + label: "Size — XXS", + render: () => , + }, + { + id: "size-xs", + label: "Size — XS", + render: () => , + }, + { + id: "size-small", + label: "Size — Small", + render: () => , + }, + { + id: "size-medium", + label: "Size — Medium", + render: () => , + }, + { + id: "size-large", + label: "Size — Large", + render: () => , + }, + { + id: "active-primary", + label: "Active — Primary", + render: () => , + }, + { + id: "active-secondary", + label: "Active — Secondary", + render: () => , + }, + { + id: "active-tertiary", + label: "Active — Tertiary", + render: () => , + }, + { + id: "disabled-primary", + label: "Disabled — Primary", + render: () => ( + + ), + }, + { + id: "disabled-secondary", + label: "Disabled — Secondary", + render: () => ( + + ), + }, + { + id: "disabled-tertiary", + label: "Disabled — Tertiary", + render: () => ( + + ), + }, + { + id: "default-add", + label: "Default — Add", + render: () => {}} />, + }, +]; + +export function IconButtonGalleryView() { + return ( + + ); +} diff --git a/packages/kitchen-sink/src/components/LabelGalleryView.tsx b/packages/kitchen-sink/src/components/LabelGalleryView.tsx new file mode 100644 index 0000000000..4b9768e346 --- /dev/null +++ b/packages/kitchen-sink/src/components/LabelGalleryView.tsx @@ -0,0 +1,87 @@ +import { Label } from "@vibe/core"; +import { ComponentGallery, type GalleryVariation } from "./ComponentGallery"; + +const labelVariations: GalleryVariation[] = [ + { + id: "kind-fill", + label: "Kind — Fill", + render: () =>