Skip to content
Merged
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
2 changes: 1 addition & 1 deletion packages/propel/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function getAbsolutePath(value: string) {
}
const config: StorybookConfig = {
stories: ["../src/**/*.stories.@(ts|tsx)"],
addons: [],
addons: ["@storybook/addon-designs", "@storybook/addon-docs"],
framework: {
name: getAbsolutePath("@storybook/react-vite"),
options: {},
Expand Down
14 changes: 14 additions & 0 deletions packages/propel/.storybook/manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { addons } from "storybook/manager-api";
import { create } from "storybook/theming";

const planeTheme = create({
base: "dark",
brandTitle: "Plane UI",
brandUrl: "https://plane.so",
brandImage: "plane-lockup-light.svg",
brandTarget: "_self",
});

addons.setConfig({
theme: planeTheme,
});
13 changes: 8 additions & 5 deletions packages/propel/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { Preview } from "@storybook/react-vite";
import "@plane/tailwind-config/global.css";

const preview: Preview = {
parameters: {
controls: {
matchers: {},
},
const parameters: Preview["parameters"] = {
controls: {
matchers: {},
},
};

const preview: Preview = {
parameters,
tags: ["autodocs"],
};
export default preview;
8 changes: 5 additions & 3 deletions packages/propel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@
"@plane/eslint-config": "workspace:*",
"@plane/tailwind-config": "workspace:*",
"@plane/typescript-config": "workspace:*",
"@storybook/react-vite": "^9.1.2",
"@storybook/addon-designs": "10.0.2",
"@storybook/addon-docs": "9.1.2",
"@storybook/react-vite": "9.1.2",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"eslint-plugin-storybook": "^9.1.2",
"storybook": "^9.1.2",
"eslint-plugin-storybook": "9.1.2",
"storybook": "9.1.2",
"tsdown": "catalog:",
"typescript": "catalog:"
}
Expand Down
16 changes: 16 additions & 0 deletions packages/propel/public/plane-lockup-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
103 changes: 68 additions & 35 deletions packages/propel/src/tabs/tabs.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,97 @@
import { Fragment } from "react";
import { ComponentProps } from "react";
import type { Meta, StoryObj } from "@storybook/react-vite";
import { Tabs } from "./tabs";

const meta: Meta<typeof Tabs> = {
type TabOption = {
label: string;
value: string;
};

const tabOptions: TabOption[] = [
{ label: "Account", value: "account" },
{ label: "Password", value: "password" },
];

interface StoryProps extends ComponentProps<typeof Tabs> {
options: TabOption[];
}

const meta: Meta<StoryProps> = {
title: "Components/Tabs",
component: Tabs,
parameters: {
layout: "centered",
},
args: {
defaultValue: "account",
options: tabOptions,
},
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Basic: Story = {
render: () => (
<div className="w-[400px]">
<Tabs defaultValue="account">
<Tabs.List>
<Tabs.Trigger value="account">Overview</Tabs.Trigger>
<Tabs.Trigger value="password">Settings</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="account" className="p-4">
Overview settings go here
</Tabs.Content>
<Tabs.Content value="password" className="p-4">
Settings settings go here
</Tabs.Content>
</Tabs>
</div>
),
args: {
options: [
{
label: "Account",
value: "account",
},
{
label: "Password",
value: "password",
},
],
},

render: ({ defaultValue, options }) => {
const safeDefault = options?.some((o) => o.value === defaultValue) ? defaultValue : options?.[0]?.value;
return (
<div className="w-[400px]">
<Tabs defaultValue={safeDefault}>
<Tabs.List>
{options.map((option) => (
<Tabs.Trigger key={option.value} value={option.value}>
{option.label}
</Tabs.Trigger>
))}
<Tabs.Indicator />
</Tabs.List>
{options.map((option) => (
<Tabs.Content key={option.value} value={option.value} className="p-4">
{option.label} content goes here
</Tabs.Content>
))}
</Tabs>
</div>
);
},
};

export const Sizes: Story = {
render: () => {
render: ({ defaultValue, options }) => {
const sizes = ["sm", "md", "lg"] as const;
const labels = {
const sizeLabels: Record<(typeof sizes)[number], string> = {
sm: "Small",
md: "Medium",
lg: "Large",
};

return (
<div className="w-[400px]">
{sizes.map((size, index) => (
<Fragment key={size}>
{index > 0 && <div className="h-4" />}
<div className="text-lg">{labels[size]}</div>
<Tabs defaultValue="overview">
<div className="w-[400px] grid gap-4">
{sizes.map((size) => (
<div key={size} className="flex flex-col gap-2">
<div className="text-lg">{sizeLabels[size]}</div>
<Tabs defaultValue={defaultValue}>
<Tabs.List>
<Tabs.Trigger value="overview" size={size}>
Overview
</Tabs.Trigger>
<Tabs.Trigger value="settings" size={size}>
Settings
</Tabs.Trigger>
{options.map((option) => (
<Tabs.Trigger key={option.value} value={option.value} size={size}>
{option.label}
</Tabs.Trigger>
))}
</Tabs.List>
</Tabs>
</Fragment>
</div>
))}
</div>
);
Expand Down
Loading
Loading