Update stories to match new component organization

This commit is contained in:
adilallo
2026-02-05 22:46:16 -07:00
parent 6f178e934f
commit aef04c525a
51 changed files with 111 additions and 111 deletions
+258
View File
@@ -0,0 +1,258 @@
import React from "react";
import Checkbox from "../../app/components/controls/Checkbox";
import { within, userEvent } from "@storybook/test";
import { expect } from "@storybook/test";
// Interaction functions for Storybook play functions
const DefaultInteraction = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const checkbox = canvas.getByRole("checkbox");
expect(checkbox).toHaveAttribute("aria-checked", "false");
await userEvent.click(checkbox);
expect(checkbox).toHaveAttribute("aria-checked", "true");
await userEvent.click(checkbox);
expect(checkbox).toHaveAttribute("aria-checked", "false");
},
};
const CheckedInteraction = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const checkbox = canvas.getByRole("checkbox");
expect(checkbox).toHaveAttribute("aria-checked", "true");
await userEvent.click(checkbox);
expect(checkbox).toHaveAttribute("aria-checked", "false");
},
};
export default {
title: "Components/Controls/Checkbox",
component: Checkbox,
parameters: {
layout: "centered",
backgrounds: {
default: "dark",
values: [
{ name: "light", value: "#ffffff" },
{ name: "dark", value: "#000000" },
],
},
},
argTypes: {
checked: {
control: "boolean",
description: "Whether the checkbox is checked",
},
mode: {
control: "select",
options: ["standard", "inverse", "Standard", "Inverse"],
description: "Visual mode of the checkbox (case-insensitive: accepts both lowercase and PascalCase)",
},
state: {
control: "select",
options: ["default", "hover", "focus", "Default", "Hover", "Focus"],
description: "Interaction state for static display (case-insensitive: accepts both lowercase and PascalCase)",
},
disabled: {
control: "boolean",
description: "Whether the checkbox is disabled",
},
label: {
control: "text",
description: "Label text for the checkbox",
},
},
};
export const Default = {
args: {
checked: false,
mode: "standard",
state: "default",
disabled: false,
label: "Default checkbox",
},
play: DefaultInteraction.play,
render: (args) => {
const [checked, setChecked] = React.useState(args.checked);
return (
<Checkbox
{...args}
checked={checked}
onChange={({ checked: newChecked }) => setChecked(newChecked)}
/>
);
},
};
export const Checked = {
args: {
checked: true,
mode: "standard",
state: "default",
disabled: false,
label: "Checked checkbox",
},
play: CheckedInteraction.play,
render: (args) => {
const [checked, setChecked] = React.useState(args.checked);
return (
<Checkbox
{...args}
checked={checked}
onChange={({ checked: newChecked }) => setChecked(newChecked)}
/>
);
},
};
export const Standard = {
render: () => {
const [checked, setChecked] = React.useState(false);
return (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-white font-medium">Standard Mode</h3>
<div className="flex flex-col gap-2">
<Checkbox
label="Standard Checkbox"
checked={checked}
mode="standard"
onChange={({ checked: newChecked }) => setChecked(newChecked)}
/>
</div>
</div>
</div>
);
},
};
export const Inverse = {
render: () => {
const [checked, setChecked] = React.useState(false);
return (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-white font-medium">Inverse Mode</h3>
<div className="flex flex-col gap-2">
<Checkbox
label="Inverse Checkbox"
checked={checked}
mode="inverse"
onChange={({ checked: newChecked }) => setChecked(newChecked)}
/>
</div>
</div>
</div>
);
},
};
export const Disabled = {
args: {
checked: false,
mode: "standard",
state: "default",
disabled: true,
label: "Disabled checkbox",
},
render: (args) => <Checkbox {...args} />,
};
export const DisabledChecked = {
args: {
checked: true,
mode: "standard",
state: "default",
disabled: true,
label: "Disabled checked checkbox",
},
render: (args) => <Checkbox {...args} />,
};
// All modes comparison
export const AllModes = () => {
const [standardChecked, setStandardChecked] = React.useState(false);
const [inverseChecked, setInverseChecked] = React.useState(false);
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Standard Mode</h3>
<div className="space-y-4">
<Checkbox
label="Standard Checkbox"
checked={standardChecked}
mode="standard"
onChange={({ checked }) => setStandardChecked(checked)}
/>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Inverse Mode</h3>
<div className="space-y-4">
<Checkbox
label="Inverse Checkbox"
checked={inverseChecked}
mode="inverse"
onChange={({ checked }) => setInverseChecked(checked)}
/>
</div>
</div>
</div>
);
};
// Test PascalCase props from Figma
export const FigmaPascalCase = () => {
const [standardChecked, setStandardChecked] = React.useState(false);
const [inverseChecked, setInverseChecked] = React.useState(false);
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Figma PascalCase Props (Standard/Inverse)</h3>
<p className="text-sm text-gray-400 mb-4">
These components accept both PascalCase (from Figma) and lowercase (from codebase) prop values.
</p>
<div className="space-y-4">
<Checkbox
label="Standard Mode (PascalCase)"
checked={standardChecked}
mode="Standard"
state="Default"
onChange={({ checked }) => setStandardChecked(checked)}
/>
<Checkbox
label="Inverse Mode (PascalCase)"
checked={inverseChecked}
mode="Inverse"
state="Default"
onChange={({ checked }) => setInverseChecked(checked)}
/>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Mixed Case (backward compatibility)</h3>
<div className="space-y-4">
<Checkbox
label="Standard mode (lowercase) - still works"
checked={false}
mode="standard"
state="default"
/>
<Checkbox
label="Inverse Mode (mixed) - still works"
checked={false}
mode="inverse"
state="Default"
/>
</div>
</div>
</div>
);
};
+172
View File
@@ -0,0 +1,172 @@
import React from "react";
import CheckboxGroup from "../../app/components/controls/CheckboxGroup";
export default {
title: "Components/Controls/CheckboxGroup",
component: CheckboxGroup,
parameters: {
layout: "centered",
backgrounds: {
default: "dark",
values: [
{ name: "light", value: "#ffffff" },
{ name: "dark", value: "#000000" },
],
},
},
argTypes: {
mode: {
control: "select",
options: ["standard", "inverse"],
description: "Visual mode of the checkbox group",
},
disabled: {
control: "boolean",
description: "Whether the checkbox group is disabled",
},
},
};
export const Default = {
render: () => {
const [value, setValue] = React.useState([]);
return (
<CheckboxGroup
name="default-checkbox-group"
value={value}
onChange={({ value: newValue }) => setValue(newValue)}
mode="standard"
options={[
{ value: "option1", label: "Checkbox label" },
{ value: "option2", label: "Checkbox label" },
]}
/>
);
},
};
export const WithSubtext = {
render: () => {
const [value, setValue] = React.useState([]);
return (
<CheckboxGroup
name="subtext-checkbox-group"
value={value}
onChange={({ value: newValue }) => setValue(newValue)}
mode="standard"
options={[
{ value: "option1", label: "Checkbox label" },
{
value: "option2",
label: "Checkbox label",
subtext: "Nunc sed hendrerit consequat.",
},
]}
/>
);
},
};
export const Inverse = {
render: () => {
const [value, setValue] = React.useState([]);
return (
<CheckboxGroup
name="inverse-checkbox-group"
value={value}
onChange={({ value: newValue }) => setValue(newValue)}
mode="inverse"
options={[
{ value: "option1", label: "Checkbox label" },
{ value: "option2", label: "Checkbox label" },
]}
/>
);
},
};
export const InverseWithSubtext = {
render: () => {
const [value, setValue] = React.useState([]);
return (
<CheckboxGroup
name="inverse-subtext-checkbox-group"
value={value}
onChange={({ value: newValue }) => setValue(newValue)}
mode="inverse"
options={[
{ value: "option1", label: "Checkbox label" },
{
value: "option2",
label: "Checkbox label",
subtext: "Nunc sed hendrerit consequat.",
},
]}
/>
);
},
};
export const Disabled = {
render: () => (
<CheckboxGroup
name="disabled-checkbox-group"
value={[]}
mode="standard"
disabled
options={[
{ value: "option1", label: "Checkbox label" },
{ value: "option2", label: "Checkbox label" },
]}
/>
),
};
export const AllModes = () => {
const [standardValue, setStandardValue] = React.useState([]);
const [inverseValue, setInverseValue] = React.useState([]);
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Standard Mode</h3>
<CheckboxGroup
name="standard-all-checkbox-group"
value={standardValue}
onChange={({ value }) => setStandardValue(value)}
mode="standard"
options={[
{ value: "option1", label: "Checkbox label" },
{
value: "option2",
label: "Checkbox label",
subtext: "Nunc sed hendrerit consequat.",
},
]}
/>
</div>
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Inverse Mode</h3>
<CheckboxGroup
name="inverse-all-checkbox-group"
value={inverseValue}
onChange={({ value }) => setInverseValue(value)}
mode="inverse"
options={[
{ value: "option3", label: "Checkbox label" },
{
value: "option4",
label: "Checkbox label",
subtext: "Nunc sed hendrerit consequat.",
},
]}
/>
</div>
</div>
);
};
+299
View File
@@ -0,0 +1,299 @@
import React from "react";
import RadioButton from "../../app/components/controls/RadioButton";
export default {
title: "Components/Controls/RadioButton",
component: RadioButton,
parameters: {
layout: "centered",
backgrounds: {
default: "dark",
values: [
{ name: "light", value: "#ffffff" },
{ name: "dark", value: "#000000" },
],
},
},
argTypes: {
checked: {
control: "boolean",
description: "Whether the radio button is checked",
},
mode: {
control: "select",
options: ["standard", "inverse", "Standard", "Inverse"],
description: "Visual mode of the radio button (case-insensitive: accepts both lowercase and PascalCase)",
},
state: {
control: "select",
options: ["default", "hover", "focus", "selected", "Default", "Hover", "Focus", "Selected"],
description: "Interaction state for static display (case-insensitive: accepts both lowercase and PascalCase)",
},
disabled: {
control: "boolean",
description: "Whether the radio button is disabled",
},
label: {
control: "text",
description: "Label text for the radio button",
},
},
};
export const Default = {
args: {
checked: false,
mode: "standard",
state: "default",
disabled: false,
label: "Default radio button",
},
render: (args) => {
const [checked, setChecked] = React.useState(args.checked);
return (
<RadioButton
{...args}
checked={checked}
onChange={({ checked: newChecked }) => setChecked(newChecked)}
/>
);
},
};
export const Checked = {
args: {
checked: true,
mode: "standard",
state: "default",
disabled: false,
label: "Checked radio button",
},
render: (args) => {
const [checked, setChecked] = React.useState(args.checked);
return (
<RadioButton
{...args}
checked={checked}
onChange={({ checked: newChecked }) => setChecked(newChecked)}
/>
);
},
};
export const Standard = {
render: () => {
const [checked, setChecked] = React.useState(false);
return (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-white font-medium">Standard Mode</h3>
<div className="flex flex-col gap-2">
<RadioButton
label="Standard Radio Button"
checked={checked}
mode="standard"
onChange={({ checked: newChecked }) => setChecked(newChecked)}
/>
</div>
</div>
</div>
);
},
};
export const Inverse = {
render: () => {
const [checked, setChecked] = React.useState(false);
return (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-white font-medium">Inverse Mode</h3>
<div className="flex flex-col gap-2">
<RadioButton
label="Inverse Radio Button"
checked={checked}
mode="inverse"
onChange={({ checked: newChecked }) => setChecked(newChecked)}
/>
</div>
</div>
</div>
);
},
};
export const Disabled = {
args: {
checked: false,
mode: "standard",
state: "default",
disabled: true,
label: "Disabled radio button",
},
render: (args) => <RadioButton {...args} />,
};
export const DisabledChecked = {
args: {
checked: true,
mode: "standard",
state: "default",
disabled: true,
label: "Disabled checked radio button",
},
render: (args) => <RadioButton {...args} />,
};
// All modes comparison
export const AllModes = () => {
const [standardChecked, setStandardChecked] = React.useState(false);
const [inverseChecked, setInverseChecked] = React.useState(false);
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Standard Mode</h3>
<div className="space-y-4">
<RadioButton
label="Standard Radio Button"
checked={standardChecked}
mode="standard"
onChange={({ checked }) => setStandardChecked(checked)}
/>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Inverse Mode</h3>
<div className="space-y-4">
<RadioButton
label="Inverse Radio Button"
checked={inverseChecked}
mode="inverse"
onChange={({ checked }) => setInverseChecked(checked)}
/>
</div>
</div>
</div>
);
};
// All states for standard mode
export const StandardAllStates = () => {
const [unchecked, setUnchecked] = React.useState(false);
const [checked, setChecked] = React.useState(true);
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Standard Mode - Unselected</h3>
<div className="space-y-4">
<RadioButton
label="Unselected (default, hover, focus)"
checked={unchecked}
mode="standard"
onChange={({ checked }) => setUnchecked(checked)}
/>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Standard Mode - Selected</h3>
<div className="space-y-4">
<RadioButton
label="Selected (default, hover, focus)"
checked={checked}
mode="standard"
onChange={({ checked }) => setChecked(checked)}
/>
</div>
</div>
</div>
);
};
// All states for inverse mode
export const InverseAllStates = () => {
const [unchecked, setUnchecked] = React.useState(false);
const [checked, setChecked] = React.useState(true);
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Inverse Mode - Unselected</h3>
<div className="space-y-4">
<RadioButton
label="Unselected (default, hover, focus)"
checked={unchecked}
mode="inverse"
onChange={({ checked }) => setUnchecked(checked)}
/>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Inverse Mode - Selected</h3>
<div className="space-y-4">
<RadioButton
label="Selected (default, hover, focus)"
checked={checked}
mode="inverse"
onChange={({ checked }) => setChecked(checked)}
/>
</div>
</div>
</div>
);
};
// Test PascalCase props from Figma
export const FigmaPascalCase = () => {
const [standardChecked, setStandardChecked] = React.useState(false);
const [inverseChecked, setInverseChecked] = React.useState(false);
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Figma PascalCase Props (Standard/Inverse)</h3>
<p className="text-sm text-gray-400 mb-4">
These components accept both PascalCase (from Figma) and lowercase (from codebase) prop values.
</p>
<div className="space-y-4">
<RadioButton
label="Standard Mode (PascalCase)"
checked={standardChecked}
mode="Standard"
state="Default"
onChange={({ checked }) => setStandardChecked(checked)}
/>
<RadioButton
label="Inverse Mode (PascalCase)"
checked={inverseChecked}
mode="Inverse"
state="Default"
onChange={({ checked }) => setInverseChecked(checked)}
/>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Mixed Case (backward compatibility)</h3>
<div className="space-y-4">
<RadioButton
label="Standard mode (lowercase) - still works"
checked={false}
mode="standard"
state="default"
/>
<RadioButton
label="Inverse Mode (mixed) - still works"
checked={false}
mode="inverse"
state="Default"
/>
</div>
</div>
</div>
);
};
+175
View File
@@ -0,0 +1,175 @@
import React from "react";
import RadioGroup from "../../app/components/controls/RadioGroup";
export default {
title: "Components/Controls/RadioGroup",
component: RadioGroup,
parameters: {
layout: "centered",
backgrounds: {
default: "dark",
values: [
{ name: "light", value: "#ffffff" },
{ name: "dark", value: "#000000" },
],
},
},
argTypes: {
mode: {
control: "select",
options: ["standard", "inverse"],
description: "Visual mode of the radio group",
},
disabled: {
control: "boolean",
description: "Whether the radio group is disabled",
},
},
};
export const Default = {
render: () => {
const [value, setValue] = React.useState("");
return (
<RadioGroup
name="default-radio-group"
value={value}
onChange={({ value: newValue }) => setValue(newValue)}
mode="standard"
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
);
},
};
export const WithSubtext = {
render: () => {
const [value, setValue] = React.useState("");
return (
<RadioGroup
name="subtext-radio-group"
value={value}
onChange={({ value: newValue }) => setValue(newValue)}
mode="standard"
options={[
{ value: "option1", label: "Option 1" },
{
value: "option2",
label: "Option 2",
subtext: "Lorem ipsum dolor sit amet consectetur",
},
]}
/>
);
},
};
export const Inverse = {
render: () => {
const [value, setValue] = React.useState("");
return (
<RadioGroup
name="inverse-radio-group"
value={value}
onChange={({ value: newValue }) => setValue(newValue)}
mode="inverse"
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
);
},
};
export const InverseWithSubtext = {
render: () => {
const [value, setValue] = React.useState("");
return (
<RadioGroup
name="inverse-subtext-radio-group"
value={value}
onChange={({ value: newValue }) => setValue(newValue)}
mode="inverse"
options={[
{ value: "option1", label: "Option 1" },
{
value: "option2",
label: "Option 2",
subtext: "Lorem ipsum dolor sit amet consectetur",
},
]}
/>
);
},
};
export const Disabled = {
render: () => (
<RadioGroup
name="disabled-radio-group"
value=""
mode="standard"
disabled
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
),
};
export const AllModes = () => {
const [standardValue, setStandardValue] = React.useState("");
const [inverseValue, setInverseValue] = React.useState("");
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Standard Mode</h3>
<RadioGroup
name="standard-all-radio-group"
value={standardValue}
onChange={({ value }) => setStandardValue(value)}
mode="standard"
options={[
{ value: "option1", label: "Option 1" },
{
value: "option2",
label: "Option 2",
subtext: "Lorem ipsum dolor sit amet consectetur",
},
]}
/>
</div>
<div>
<h3 className="text-lg font-semibold mb-4 text-white">Inverse Mode</h3>
<RadioGroup
name="inverse-all-radio-group"
value={inverseValue}
onChange={({ value }) => setInverseValue(value)}
mode="inverse"
options={[
{ value: "option3", label: "Option 1" },
{
value: "option4",
label: "Option 2",
subtext: "Lorem ipsum dolor sit amet consectetur",
},
]}
/>
</div>
</div>
);
};
+172
View File
@@ -0,0 +1,172 @@
import React, { useState } from "react";
import SelectInput from "../../app/components/controls/SelectInput";
export default {
title: "Components/Controls/SelectInput",
component: SelectInput,
parameters: {
layout: "centered",
},
argTypes: {
state: {
control: { type: "select" },
options: ["default", "active", "focus"],
},
disabled: {
control: { type: "boolean" },
},
error: {
control: { type: "boolean" },
},
placeholder: {
control: { type: "text" },
},
label: {
control: { type: "text" },
},
},
};
const Template = (args) => {
const [value, setValue] = useState("");
return (
<SelectInput
{...args}
value={value}
onChange={(data) => setValue(data.target.value)}
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
);
};
// Default story
export const Default = Template.bind({});
Default.args = {
label: "Default Select Input",
placeholder: "Choose an option",
state: "default",
};
// States
export const Active = Template.bind({});
Active.args = {
label: "Active State",
placeholder: "Choose an option",
state: "active",
};
export const Focus = Template.bind({});
Focus.args = {
label: "Focus State",
placeholder: "Choose an option",
state: "focus",
};
export const Error = Template.bind({});
Error.args = {
label: "Error State",
placeholder: "Choose an option",
error: true,
};
export const Disabled = Template.bind({});
Disabled.args = {
label: "Disabled State",
placeholder: "Choose an option",
disabled: true,
};
// Interactive example
export const Interactive = (args) => {
const [value, setValue] = useState("");
return (
<div className="space-y-4">
<SelectInput
{...args}
value={value}
onChange={(data) => setValue(data.target.value)}
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
<p className="text-sm text-gray-600">Current value: "{value}"</p>
</div>
);
};
Interactive.args = {
label: "Interactive Select Input",
placeholder: "Choose an option",
state: "default",
};
// All states comparison
export const AllStates = () => (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4">Select Input States</h3>
<div className="space-y-4">
<SelectInput
label="Default State"
placeholder="Choose an option"
value=""
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
<SelectInput
label="Active State"
placeholder="Choose an option"
state="active"
value=""
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
<SelectInput
label="Focus State"
placeholder="Choose an option"
state="focus"
value=""
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
<SelectInput
label="Error State"
placeholder="Choose an option"
error={true}
value=""
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
<SelectInput
label="Disabled State"
placeholder="Choose an option"
disabled={true}
value=""
options={[
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
]}
/>
</div>
</div>
</div>
);
+128
View File
@@ -0,0 +1,128 @@
import React from "react";
import Switch from "../../app/components/controls/Switch";
export default {
title: "Components/Controls/Switch",
component: Switch,
parameters: {
layout: "centered",
},
argTypes: {
checked: {
control: "boolean",
description: "Whether the switch is checked (on) or not (off)",
},
state: {
control: "select",
options: ["default", "focus"],
description: "Visual state of the switch",
},
label: {
control: "text",
description: "Label text displayed next to the switch",
},
onChange: {
action: "changed",
description: "Callback fired when the switch is toggled",
},
onFocus: {
action: "focused",
description: "Callback fired when the switch receives focus",
},
onBlur: {
action: "blurred",
description: "Callback fired when the switch loses focus",
},
},
};
const Template = (args) => <Switch {...args} />;
export const Default = Template.bind({});
Default.args = {
checked: false,
label: "Switch label",
};
export const Checked = Template.bind({});
Checked.args = {
checked: true,
label: "Switch label",
};
export const Focus = Template.bind({});
Focus.args = {
checked: false,
state: "focus",
label: "Switch label",
};
export const FocusChecked = Template.bind({});
FocusChecked.args = {
checked: true,
state: "focus",
label: "Switch label",
};
export const States = () => (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-lg font-semibold">Switch States</h3>
<div className="space-y-4">
<Switch checked={false} label="Switch label" />
<Switch checked={true} label="Switch label" />
<Switch checked={false} state="focus" label="Switch label" />
<Switch checked={true} state="focus" label="Switch label" />
</div>
</div>
</div>
);
export const Interactive = () => {
const [checked, setChecked] = React.useState(false);
const [state, setState] = React.useState("default");
return (
<div className="space-y-6">
<div className="space-y-4">
<h3 className="text-lg font-semibold">Interactive Switch</h3>
<Switch
checked={checked}
state={state}
onChange={() => setChecked(!checked)}
label="Enable notifications"
/>
</div>
<div className="space-y-4">
<h4 className="text-md font-semibold">Controls</h4>
<div className="space-y-2">
<div>
<label className="block text-sm font-medium mb-1">State:</label>
<select
value={state}
onChange={(e) => setState(e.target.value)}
className="px-3 py-1 border border-gray-300 rounded"
>
<option value="default">Default</option>
<option value="focus">Focus</option>
</select>
</div>
</div>
</div>
</div>
);
};
export const WithText = () => (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-lg font-semibold">Switch with Different Labels</h3>
<div className="space-y-4">
<Switch checked={false} label="Enable notifications" />
<Switch checked={true} label="Auto-save documents" />
<Switch checked={false} label="Dark mode" />
<Switch checked={true} label="Email updates" />
</div>
</div>
</div>
);
+286
View File
@@ -0,0 +1,286 @@
import React from "react";
import TextArea from "../../app/components/controls/TextArea";
export default {
title: "Components/Controls/TextArea",
component: TextArea,
parameters: {
layout: "centered",
},
argTypes: {
size: {
control: { type: "select" },
options: ["small", "medium", "large"],
},
labelVariant: {
control: { type: "select" },
options: ["default", "horizontal"],
},
state: {
control: { type: "select" },
options: ["default", "active", "hover", "focus", "error"],
},
disabled: {
control: { type: "boolean" },
},
error: {
control: { type: "boolean" },
},
},
};
const Template = (args) => <TextArea {...args} />;
export const Default = Template.bind({});
Default.args = {
label: "Text Area",
placeholder: "Enter text...",
value: "",
};
export const WithValue = Template.bind({});
WithValue.args = {
label: "Text Area",
placeholder: "Enter text...",
value:
"This is some sample text content that demonstrates how the text area looks with content.",
};
export const Small = Template.bind({});
Small.args = {
size: "small",
label: "Small Text Area",
placeholder: "Enter text...",
value: "",
};
export const Medium = Template.bind({});
Medium.args = {
size: "medium",
label: "Medium Text Area",
placeholder: "Enter text...",
value: "",
};
export const Large = Template.bind({});
Large.args = {
size: "large",
label: "Large Text Area",
placeholder: "Enter text...",
value: "",
};
export const HorizontalLabel = Template.bind({});
HorizontalLabel.args = {
labelVariant: "horizontal",
label: "Horizontal Label",
placeholder: "Enter text...",
value: "",
};
export const AllSizes = () => (
<div className="space-y-6">
<div className="space-y-4">
<h3 className="text-lg font-semibold">Default Label Variant</h3>
<div className="space-y-4">
<TextArea
size="small"
label="Small Text Area"
placeholder="Enter text..."
value=""
/>
<TextArea
size="medium"
label="Medium Text Area"
placeholder="Enter text..."
value=""
/>
<TextArea
size="large"
label="Large Text Area"
placeholder="Enter text..."
value=""
/>
</div>
</div>
<div className="space-y-4">
<h3 className="text-lg font-semibold">Horizontal Label Variant</h3>
<div className="space-y-4">
<TextArea
size="small"
labelVariant="horizontal"
label="Small Text Area"
placeholder="Enter text..."
value=""
/>
<TextArea
size="medium"
labelVariant="horizontal"
label="Medium Text Area"
placeholder="Enter text..."
value=""
/>
<TextArea
size="large"
labelVariant="horizontal"
label="Large Text Area"
placeholder="Enter text..."
value=""
/>
</div>
</div>
</div>
);
export const States = () => (
<div className="space-y-6">
<div className="space-y-4">
<h3 className="text-lg font-semibold">Default Label Variant</h3>
<div className="space-y-4">
<TextArea label="Default State" placeholder="Enter text..." value="" />
<TextArea
label="Active State"
placeholder="Enter text..."
value=""
state="active"
/>
<TextArea
label="Hover State"
placeholder="Enter text..."
value=""
state="hover"
/>
<TextArea
label="Focus State"
placeholder="Enter text..."
value=""
state="focus"
/>
<TextArea
label="Error State"
placeholder="Enter text..."
value=""
error
/>
<TextArea
label="Disabled State"
placeholder="Enter text..."
value=""
disabled
/>
</div>
</div>
<div className="space-y-4">
<h3 className="text-lg font-semibold">Horizontal Label Variant</h3>
<div className="space-y-4">
<TextArea
labelVariant="horizontal"
label="Default State"
placeholder="Enter text..."
value=""
/>
<TextArea
labelVariant="horizontal"
label="Active State"
placeholder="Enter text..."
value=""
state="active"
/>
<TextArea
labelVariant="horizontal"
label="Hover State"
placeholder="Enter text..."
value=""
state="hover"
/>
<TextArea
labelVariant="horizontal"
label="Focus State"
placeholder="Enter text..."
value=""
state="focus"
/>
<TextArea
labelVariant="horizontal"
label="Error State"
placeholder="Enter text..."
value=""
error
/>
<TextArea
labelVariant="horizontal"
label="Disabled State"
placeholder="Enter text..."
value=""
disabled
/>
</div>
</div>
</div>
);
export const Interactive = () => {
const [value, setValue] = React.useState("");
const [state, setState] = React.useState("default");
const [disabled, setDisabled] = React.useState(false);
const [error, setError] = React.useState(false);
return (
<div className="space-y-6">
<div className="space-y-4">
<h3 className="text-lg font-semibold">Interactive TextArea</h3>
<div className="space-y-4">
<TextArea
label="Interactive Text Area"
placeholder="Type something..."
value={value}
onChange={(e) => setValue(e.target.value)}
state={state}
disabled={disabled}
error={error}
/>
</div>
</div>
<div className="space-y-4">
<h4 className="text-md font-semibold">Controls</h4>
<div className="space-y-2">
<div>
<label className="block text-sm font-medium mb-1">State:</label>
<select
value={state}
onChange={(e) => setState(e.target.value)}
className="px-3 py-1 border border-gray-300 rounded"
>
<option value="default">Default</option>
<option value="active">Active</option>
<option value="hover">Hover</option>
<option value="focus">Focus</option>
</select>
</div>
<div className="flex items-center space-x-2">
<input
type="checkbox"
id="disabled"
checked={disabled}
onChange={(e) => setDisabled(e.target.checked)}
/>
<label htmlFor="disabled" className="text-sm">
Disabled
</label>
</div>
<div className="flex items-center space-x-2">
<input
type="checkbox"
id="error"
checked={error}
onChange={(e) => setError(e.target.checked)}
/>
<label htmlFor="error" className="text-sm">
Error
</label>
</div>
</div>
</div>
</div>
);
};
+269
View File
@@ -0,0 +1,269 @@
import React from "react";
import TextInput from "../../app/components/controls/TextInput";
export default {
title: "Components/Controls/TextInput",
component: TextInput,
parameters: {
layout: "centered",
},
argTypes: {
size: {
control: { type: "select" },
options: ["small", "medium", "large"],
},
labelVariant: {
control: { type: "select" },
options: ["default", "horizontal"],
},
state: {
control: { type: "select" },
options: ["default", "active", "hover", "focus", "error", "disabled"],
},
disabled: {
control: { type: "boolean" },
},
error: {
control: { type: "boolean" },
},
label: {
control: { type: "text" },
},
placeholder: {
control: { type: "text" },
},
value: {
control: { type: "text" },
},
},
};
const Template = (args) => <TextInput {...args} />;
// Default story
export const Default = Template.bind({});
Default.args = {
label: "Default Text Input",
placeholder: "Enter text...",
size: "medium",
labelVariant: "default",
state: "default",
};
// Size variants
export const Small = Template.bind({});
Small.args = {
label: "Small Text Input",
placeholder: "Small size",
size: "small",
labelVariant: "default",
state: "default",
};
export const Medium = Template.bind({});
Medium.args = {
label: "Medium Text Input",
placeholder: "Medium size",
size: "medium",
labelVariant: "default",
state: "default",
};
export const Large = Template.bind({});
Large.args = {
label: "Large Text Input",
placeholder: "Large size",
size: "large",
labelVariant: "default",
state: "default",
};
// Label variants
export const DefaultLabel = Template.bind({});
DefaultLabel.args = {
label: "Default Label (Top)",
placeholder: "Top label",
size: "medium",
labelVariant: "default",
state: "default",
};
export const HorizontalLabel = Template.bind({});
HorizontalLabel.args = {
label: "Horizontal Label",
placeholder: "Left label",
size: "medium",
labelVariant: "horizontal",
state: "default",
};
// States
export const Active = Template.bind({});
Active.args = {
label: "Active State",
placeholder: "Active input",
size: "medium",
labelVariant: "default",
state: "active",
};
export const Hover = Template.bind({});
Hover.args = {
label: "Hover State",
placeholder: "Hover input",
size: "medium",
labelVariant: "default",
state: "hover",
};
export const Focus = Template.bind({});
Focus.args = {
label: "Focus State",
placeholder: "Focused input",
size: "medium",
labelVariant: "default",
state: "focus",
};
export const Error = Template.bind({});
Error.args = {
label: "Error State",
placeholder: "Error input",
size: "medium",
labelVariant: "default",
state: "default",
error: true,
};
export const Disabled = Template.bind({});
Disabled.args = {
label: "Disabled State",
placeholder: "Disabled input",
size: "medium",
labelVariant: "default",
state: "default",
disabled: true,
};
// Interactive example
export const Interactive = (args) => {
const [value, setValue] = React.useState("");
return (
<div className="space-y-4">
<TextInput
{...args}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<p className="text-sm text-gray-600">Current value: "{value}"</p>
</div>
);
};
Interactive.args = {
label: "Interactive Text Input",
placeholder: "Type something...",
size: "medium",
labelVariant: "default",
state: "default",
};
// All sizes comparison
export const AllSizes = () => (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4">Small Size</h3>
<div className="space-y-4">
<TextInput
label="Small Default"
placeholder="Small with top label"
size="small"
labelVariant="default"
/>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4">Medium Size</h3>
<div className="space-y-4">
<TextInput
label="Medium Default"
placeholder="Medium with top label"
size="medium"
labelVariant="default"
/>
<TextInput
label="Medium Horizontal"
placeholder="Medium with left label"
size="medium"
labelVariant="horizontal"
/>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4">Large Size</h3>
<div className="space-y-4">
<TextInput
label="Large Default"
placeholder="Large with top label"
size="large"
labelVariant="default"
/>
<TextInput
label="Large Horizontal"
placeholder="Large with left label"
size="large"
labelVariant="horizontal"
/>
</div>
</div>
</div>
);
// All states comparison
export const AllStates = () => (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold mb-4">Text Input States</h3>
<div className="space-y-4">
<TextInput
label="Default State"
placeholder="Default input"
size="medium"
state="default"
/>
<TextInput
label="Active State"
placeholder="Active input"
size="medium"
state="active"
/>
<TextInput
label="Hover State"
placeholder="Hover input"
size="medium"
state="hover"
/>
<TextInput
label="Focus State"
placeholder="Focused input"
size="medium"
state="focus"
/>
<TextInput
label="Error State"
placeholder="Error input"
size="medium"
error={true}
/>
<TextInput
label="Disabled State"
placeholder="Disabled input"
size="medium"
disabled={true}
/>
</div>
</div>
</div>
);
+122
View File
@@ -0,0 +1,122 @@
import React from "react";
import Toggle from "../../app/components/controls/Toggle";
export default {
title: "Components/Controls/Toggle",
component: Toggle,
parameters: {
layout: "centered",
},
argTypes: {
state: {
control: { type: "select" },
options: ["default", "hover", "focus"],
},
disabled: {
control: { type: "boolean" },
},
checked: {
control: { type: "boolean" },
},
showIcon: {
control: { type: "boolean" },
},
showText: {
control: { type: "boolean" },
},
},
};
const Template = (args) => <Toggle {...args} />;
export const States = () => (
<div className="space-y-6">
<div className="space-y-4">
<h3 className="text-lg font-semibold">Toggle States</h3>
<div className="space-y-4">
<Toggle label="Default State" checked={false} />
<Toggle label="Hover State" checked={false} state="hover" />
<Toggle label="Selected State" checked={true} />
<Toggle label="Focus State" checked={false} state="focus" />
<Toggle label="Disabled State" checked={false} disabled />
</div>
</div>
</div>
);
export const WithText = Template.bind({});
WithText.args = {
label: "Text Toggle",
checked: false,
showText: true,
text: "Toggle",
};
export const WithIcon = Template.bind({});
WithIcon.args = {
label: "Icon Toggle",
checked: false,
showIcon: true,
icon: "I",
};
export const Interactive = () => {
const [checked, setChecked] = React.useState(false);
const [state, setState] = React.useState("default");
const [disabled, setDisabled] = React.useState(false);
return (
<div className="space-y-6">
<div className="space-y-4">
<h3 className="text-lg font-semibold">Interactive Toggle</h3>
<div className="space-y-4">
<Toggle
label="Interactive Toggle"
checked={checked}
onChange={() => setChecked(!checked)}
state={state}
disabled={disabled}
/>
</div>
</div>
<div className="space-y-4">
<h4 className="text-md font-semibold">Controls</h4>
<div className="space-y-2">
<div className="flex items-center space-x-2">
<input
type="checkbox"
id="checked"
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
/>
<label htmlFor="checked" className="text-sm">
Checked
</label>
</div>
<div>
<label className="block text-sm font-medium mb-1">State:</label>
<select
value={state}
onChange={(e) => setState(e.target.value)}
className="px-3 py-1 border border-gray-300 rounded"
>
<option value="default">Default</option>
<option value="focus">Focus</option>
</select>
</div>
<div className="flex items-center space-x-2">
<input
type="checkbox"
id="disabled"
checked={disabled}
onChange={(e) => setDisabled(e.target.checked)}
/>
<label htmlFor="disabled" className="text-sm">
Disabled
</label>
</div>
</div>
</div>
</div>
);
};
+210
View File
@@ -0,0 +1,210 @@
import React from "react";
import ToggleGroup from "../../app/components/controls/ToggleGroup";
export default {
title: "Components/Controls/ToggleGroup",
component: ToggleGroup,
parameters: {
layout: "centered",
},
argTypes: {
position: {
control: { type: "select" },
options: ["left", "middle", "right"],
},
state: {
control: { type: "select" },
options: ["default", "hover", "focus", "selected"],
},
showText: {
control: { type: "boolean" },
},
},
};
const Template = (args) => <ToggleGroup {...args}>Toggle Item</ToggleGroup>;
export const Default = Template.bind({});
Default.args = {
position: "left",
state: "default",
showText: true,
};
export const Middle = Template.bind({});
Middle.args = {
position: "middle",
state: "default",
showText: true,
};
export const Right = Template.bind({});
Right.args = {
position: "right",
state: "default",
showText: true,
};
export const States = () => (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-lg font-semibold">Toggle Group States</h3>
<div className="flex space-x-4">
<ToggleGroup position="left" state="default">
Default
</ToggleGroup>
<ToggleGroup position="middle" state="hover">
Hover
</ToggleGroup>
<ToggleGroup position="middle" state="focus">
Focus
</ToggleGroup>
<ToggleGroup position="right" state="selected">
Selected
</ToggleGroup>
</div>
</div>
</div>
);
export const Positions = () => (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-lg font-semibold">Toggle Group Positions</h3>
<div className="flex">
<ToggleGroup position="left" state="default">
Left
</ToggleGroup>
<ToggleGroup position="middle" state="default">
Middle
</ToggleGroup>
<ToggleGroup position="middle" state="default">
Middle
</ToggleGroup>
<ToggleGroup position="right" state="default">
Right
</ToggleGroup>
</div>
</div>
</div>
);
export const WithText = Template.bind({});
WithText.args = {
position: "left",
state: "default",
showText: true,
children: "Active Deals",
};
export const WithoutText = Template.bind({});
WithoutText.args = {
position: "left",
state: "default",
showText: false,
children: "☰",
};
export const WithIcons = () => (
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-lg font-semibold">Toggle Group with Icons</h3>
<div className="flex">
<ToggleGroup
position="left"
state="default"
showText={false}
ariaLabel="Menu"
>
</ToggleGroup>
<ToggleGroup
position="middle"
state="selected"
showText={false}
ariaLabel="Menu"
>
</ToggleGroup>
<ToggleGroup
position="right"
state="default"
showText={false}
ariaLabel="Menu"
>
</ToggleGroup>
</div>
</div>
</div>
);
export const Interactive = () => {
const [selectedPosition, setSelectedPosition] = React.useState("left");
const [state, setState] = React.useState("default");
const [showText, setShowText] = React.useState(true);
return (
<div className="space-y-6">
<div className="space-y-4">
<h3 className="text-lg font-semibold">Interactive Toggle Group</h3>
<div className="flex">
<ToggleGroup
position="left"
state={selectedPosition === "left" ? "selected" : state}
showText={showText}
onChange={() => setSelectedPosition("left")}
ariaLabel={!showText ? "Active Deals" : undefined}
>
{showText ? "Active Deals" : "☰"}
</ToggleGroup>
<ToggleGroup
position="middle"
state={selectedPosition === "middle" ? "selected" : state}
showText={showText}
onChange={() => setSelectedPosition("middle")}
ariaLabel={!showText ? "Inactive Deals" : undefined}
>
{showText ? "Inactive Deals" : "☰"}
</ToggleGroup>
<ToggleGroup
position="right"
state={selectedPosition === "right" ? "selected" : state}
showText={showText}
onChange={() => setSelectedPosition("right")}
ariaLabel={!showText ? "Pending Deals" : undefined}
>
{showText ? "Pending Deals" : "☰"}
</ToggleGroup>
</div>
</div>
<div className="space-y-4">
<h4 className="text-md font-semibold">Controls</h4>
<div className="space-y-2">
<div>
<label className="block text-sm font-medium mb-1">State:</label>
<select
value={state}
onChange={(e) => setState(e.target.value)}
className="px-3 py-1 border border-gray-300 rounded"
>
<option value="default">Default</option>
<option value="focus">Focus</option>
</select>
</div>
<div className="flex items-center space-x-2">
<input
type="checkbox"
id="showText"
checked={showText}
onChange={(e) => setShowText(e.target.checked)}
/>
<label htmlFor="showText" className="text-sm">
Show Text
</label>
</div>
</div>
</div>
</div>
);
};