Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .cursor/rules/design-system-not-kitchen-sink.mdc
Original file line number Diff line number Diff line change
@@ -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.
8 changes: 8 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 7 additions & 4 deletions packages/kitchen-sink/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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 (
<AppThemeShell>
<div
Expand All @@ -24,8 +28,7 @@ export default function App() {
/>
<main className={`main-area${view === "screens" ? " main-area--no-padding" : ""}`}>
{view === "components" && componentSubPage === "grid" && <ComponentsView />}
{view === "components" && componentSubPage === "toast" && <ToastGalleryView />}
{view === "components" && componentSubPage === "dropdown" && <DropdownGalleryView />}
{GalleryView && <GalleryView />}
{view === "compare" && <CompareView />}
{view === "theme" && <ThemePanel />}
{view === "screens" && <ScreensView />}
Expand Down
108 changes: 108 additions & 0 deletions packages/kitchen-sink/src/components/ButtonGalleryView.tsx
Original file line number Diff line number Diff line change
@@ -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: () => <Button kind="primary">Primary</Button>,
},
{
id: "kind-secondary",
label: "Kind — Secondary",
render: () => <Button kind="secondary">Secondary</Button>,
},
{
id: "kind-tertiary",
label: "Kind — Tertiary",
render: () => <Button kind="tertiary">Tertiary</Button>,
},
{
id: "size-large",
label: "Size — Large",
render: () => <Button size="large">Large</Button>,
},
{
id: "size-medium",
label: "Size — Medium",
render: () => <Button size="medium">Medium</Button>,
},
{
id: "size-small",
label: "Size — Small",
render: () => <Button size="small">Small</Button>,
},
{
id: "disabled-primary",
label: "Disabled — Primary",
render: () => <Button disabled>Primary</Button>,
},
{
id: "disabled-secondary",
label: "Disabled — Secondary",
render: () => (
<Button kind="secondary" disabled>
Secondary
</Button>
),
},
{
id: "disabled-tertiary",
label: "Disabled — Tertiary",
render: () => (
<Button kind="tertiary" disabled>
Tertiary
</Button>
),
},
{
id: "state-active",
label: "State — Active",
render: () => <Button active>Active</Button>,
},
{
id: "color-positive",
label: "Color — Positive",
render: () => <Button color="positive">Positive</Button>,
},
{
id: "color-negative",
label: "Color — Negative",
render: () => <Button color="negative">Negative</Button>,
},
{
id: "icon-left",
label: "Icon — Left",
render: () => <Button leftIcon={Calendar}>Left icon</Button>,
},
{
id: "icon-right",
label: "Icon — Right",
render: () => <Button rightIcon={Calendar}>Right icon</Button>,
},
{
id: "icon-both",
label: "Icon — Both sides",
render: () => (
<Button leftIcon={Bolt} rightIcon={Bolt}>
Both icons
</Button>
),
},
{
id: "loading",
label: "State — Loading",
render: () => <Button loading>Loading</Button>,
},
];

export function ButtonGalleryView() {
return (
<ComponentGallery
title="Button"
description="All button variations currently supported by the component."
variations={buttonVariations}
/>
);
}
80 changes: 80 additions & 0 deletions packages/kitchen-sink/src/components/ButtonGroupGalleryView.tsx
Original file line number Diff line number Diff line change
@@ -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: () => (
<ButtonGroup groupAriaLabel="Secondary button group" options={options} value={1} kind="secondary" />
),
},
{
id: "kind-tertiary",
label: "Kind — Tertiary",
render: () => (
<ButtonGroup groupAriaLabel="Tertiary button group" options={options} value={1} kind="tertiary" />
),
},
{
id: "size-medium",
label: "Size — Medium",
render: () => (
<ButtonGroup groupAriaLabel="Medium button group" options={options} value={1} size="medium" />
),
},
{
id: "size-small",
label: "Size — Small",
render: () => (
<ButtonGroup groupAriaLabel="Small button group" options={options} value={1} size="small" />
),
},
{
id: "disabled",
label: "State — Disabled",
render: () => <ButtonGroup groupAriaLabel="Disabled button group" options={options} disabled />,
},
{
id: "disabled-single",
label: "State — Single option disabled",
render: () => (
<ButtonGroup
groupAriaLabel="Button group with disabled option"
options={[
{ value: 1, text: "Alpha" },
{ value: 2, text: "Beta" },
{ value: 3, text: "Gamma" },
{ value: 4, text: "Delta", disabled: true, tooltipContent: "Unavailable option" },
]}
value={1}
/>
),
},
{
id: "full-width",
label: "Layout — Full width",
render: () => (
<div style={{ width: "100%" }}>
<ButtonGroup groupAriaLabel="Full width button group" options={options} value={1} fullWidth />
</div>
),
},
];

export function ButtonGroupGalleryView() {
return (
<ComponentGallery
title="Button Group"
description="All button group variations currently supported by the component."
variations={buttonGroupVariations}
/>
);
}
76 changes: 76 additions & 0 deletions packages/kitchen-sink/src/components/ChipGalleryView.tsx
Original file line number Diff line number Diff line change
@@ -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: () => <Chips label="This is a chip" readOnly />,
},
{
id: "color-primary",
label: "Color — Primary",
render: () => <Chips label="Primary" color="primary" readOnly />,
},
{
id: "color-positive",
label: "Color — Positive",
render: () => <Chips label="Positive" color="positive" readOnly />,
},
{
id: "color-negative",
label: "Color — Negative",
render: () => <Chips label="Negative" color="negative" readOnly />,
},
{
id: "color-warning",
label: "Color — Warning",
render: () => <Chips label="Warning" color="warning" readOnly />,
},
{
id: "color-neutral",
label: "Color — Neutral",
render: () => <Chips label="Neutral" color="neutral" readOnly />,
},
{
id: "readonly",
label: "State — Read only",
render: () => <Chips label="Read only chip" readOnly />,
},
{
id: "disabled",
label: "State — Disabled",
render: () => <Chips label="Disabled" disabled />,
},
{
id: "removable",
label: "Removable",
render: () => <Chips label="Removable chip" onDelete={() => {}} />,
},
{
id: "clickable",
label: "Clickable",
render: () => <Chips label="Clickable chip" readOnly onClick={() => {}} />,
},
{
id: "left-icon",
label: "With left icon",
render: () => <Chips label="Left icon" leftIcon={Email} readOnly />,
},
{
id: "right-icon",
label: "With right icon",
render: () => <Chips label="Right icon" rightIcon={Email} readOnly />,
},
];

export function ChipGalleryView() {
return (
<ComponentGallery
title="Chip"
description="All chip variations currently supported by the component."
variations={chipVariations}
/>
);
}
32 changes: 32 additions & 0 deletions packages/kitchen-sink/src/components/ComponentGallery.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="component-gallery">
<header className="component-gallery-header">
<h1 className="component-gallery-title">{title}</h1>
<p className="component-gallery-description">{description}</p>
</header>
<div className="component-gallery-grid">
{variations.map(({ id, label, render }) => (
<article key={id} className="component-gallery-item">
<h2 className="component-gallery-item-label">{label}</h2>
<div className="component-gallery-item-preview">{render()}</div>
</article>
))}
</div>
</div>
);
}
Loading