Select and Context Menu component with storybook and testing

This commit is contained in:
adilallo
2025-10-10 12:07:13 -06:00
parent 2bc5fcdf45
commit 9c72afdc52
20 changed files with 3827 additions and 88 deletions
+138
View File
@@ -0,0 +1,138 @@
import React, { useState } from "react";
import ContextMenu from "../app/components/ContextMenu";
import ContextMenuItem from "../app/components/ContextMenuItem";
import ContextMenuSection from "../app/components/ContextMenuSection";
import ContextMenuDivider from "../app/components/ContextMenuDivider";
export default {
title: "Forms/ContextMenu",
component: ContextMenu,
argTypes: {
className: {
control: { type: "text" },
},
},
};
const Template = (args) => (
<ContextMenu {...args}>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
<ContextMenuItem hasSubmenu>Context Menu Item</ContextMenuItem>
<ContextMenuItem hasSubmenu>Context Menu Item</ContextMenuItem>
<ContextMenuDivider />
<ContextMenuItem selected>Context Menu Item</ContextMenuItem>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
<ContextMenuDivider />
<ContextMenuSection title="Section Title">
<ContextMenuItem>Context Menu Item</ContextMenuItem>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
</ContextMenuSection>
</ContextMenu>
);
export const Default = Template.bind({});
export const WithCustomStyling = Template.bind({});
WithCustomStyling.args = {
className: "min-w-[250px]",
};
// Individual component stories
export const MenuItem = () => (
<div className="space-y-2">
<ContextMenuItem>Default Menu Item</ContextMenuItem>
<ContextMenuItem selected>Selected Menu Item</ContextMenuItem>
<ContextMenuItem hasSubmenu>Menu Item with Submenu</ContextMenuItem>
<ContextMenuItem disabled>Disabled Menu Item</ContextMenuItem>
</div>
);
export const MenuSection = () => (
<ContextMenu>
<ContextMenuSection title="First Section">
<ContextMenuItem>Item 1</ContextMenuItem>
<ContextMenuItem>Item 2</ContextMenuItem>
</ContextMenuSection>
<ContextMenuDivider />
<ContextMenuSection title="Second Section">
<ContextMenuItem>Item 3</ContextMenuItem>
<ContextMenuItem>Item 4</ContextMenuItem>
</ContextMenuSection>
</ContextMenu>
);
export const MenuDivider = () => (
<ContextMenu>
<ContextMenuItem>Item Above</ContextMenuItem>
<ContextMenuDivider />
<ContextMenuItem>Item Below</ContextMenuItem>
</ContextMenu>
);
export const Interactive = () => {
const [selectedItem, setSelectedItem] = useState("");
return (
<ContextMenu>
<ContextMenuItem
selected={selectedItem === "item1"}
onClick={() => setSelectedItem("item1")}
>
Context Menu Item 1
</ContextMenuItem>
<ContextMenuItem
selected={selectedItem === "item2"}
onClick={() => setSelectedItem("item2")}
>
Context Menu Item 2
</ContextMenuItem>
<ContextMenuItem
selected={selectedItem === "item3"}
onClick={() => setSelectedItem("item3")}
>
Context Menu Item 3
</ContextMenuItem>
</ContextMenu>
);
};
// Comparison stories
export const AllVariants = () => (
<div className="space-y-4">
<div>
<h3 className="text-sm font-medium mb-2">Default Items</h3>
<ContextMenu>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
</ContextMenu>
</div>
<div>
<h3 className="text-sm font-medium mb-2">With Submenu Indicators</h3>
<ContextMenu>
<ContextMenuItem hasSubmenu>Context Menu Item</ContextMenuItem>
<ContextMenuItem hasSubmenu>Context Menu Item</ContextMenuItem>
</ContextMenu>
</div>
<div>
<h3 className="text-sm font-medium mb-2">With Selected Item</h3>
<ContextMenu>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
<ContextMenuItem selected>Context Menu Item</ContextMenuItem>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
</ContextMenu>
</div>
<div>
<h3 className="text-sm font-medium mb-2">With Sections</h3>
<ContextMenu>
<ContextMenuSection title="Section Title">
<ContextMenuItem>Context Menu Item</ContextMenuItem>
<ContextMenuItem>Context Menu Item</ContextMenuItem>
</ContextMenuSection>
</ContextMenu>
</div>
</div>
);
+214
View File
@@ -0,0 +1,214 @@
import React, { useState } from "react";
import Select from "../app/components/Select";
export default {
title: "Forms/Select",
component: Select,
argTypes: {
size: {
control: { type: "select" },
options: ["small", "medium", "large"],
},
labelVariant: {
control: { type: "select" },
options: ["default", "horizontal"],
},
state: {
control: { type: "select" },
options: ["default", "hover", "focus", "error", "disabled"],
},
disabled: {
control: { type: "boolean" },
},
error: {
control: { type: "boolean" },
},
placeholder: {
control: { type: "text" },
},
label: {
control: { type: "text" },
},
},
};
const Template = (args) => {
const [value, setValue] = useState("");
return (
<Select {...args} value={value} onChange={(e) => setValue(e.target.value)}>
<option value="item1">Context Menu Item 1</option>
<option value="item2">Context Menu Item 2</option>
<option value="item3">Context Menu Item 3</option>
</Select>
);
};
export const Default = Template.bind({});
Default.args = {
label: "Default Select",
placeholder: "Select",
};
export const Small = Template.bind({});
Small.args = {
label: "Small Select",
size: "small",
placeholder: "Select",
};
export const Medium = Template.bind({});
Medium.args = {
label: "Medium Select",
size: "medium",
placeholder: "Select",
};
export const Large = Template.bind({});
Large.args = {
label: "Large Select",
size: "large",
placeholder: "Select",
};
export const DefaultLabel = Template.bind({});
DefaultLabel.args = {
label: "Default (Top Label)",
labelVariant: "default",
placeholder: "Select",
};
export const HorizontalLabel = Template.bind({});
HorizontalLabel.args = {
label: "Horizontal (Left Label)",
labelVariant: "horizontal",
placeholder: "Select",
};
export const Active = Template.bind({});
Active.args = {
label: "Active State",
state: "default",
placeholder: "Select",
};
export const Hover = Template.bind({});
Hover.args = {
label: "Hover State",
state: "hover",
placeholder: "Select",
};
export const Focus = Template.bind({});
Focus.args = {
label: "Focus State",
state: "focus",
placeholder: "Select",
};
export const Error = Template.bind({});
Error.args = {
label: "Error State",
error: true,
placeholder: "Select",
};
export const Disabled = Template.bind({});
Disabled.args = {
label: "Disabled State",
disabled: true,
placeholder: "Select",
};
export const Interactive = Template.bind({});
Interactive.args = {
label: "Interactive Select",
placeholder: "Choose an option",
};
// Comparison stories
export const AllSizes = () => {
const [smallValue, setSmallValue] = useState("");
const [mediumValue, setMediumValue] = useState("");
const [largeValue, setLargeValue] = useState("");
return (
<div className="space-y-4">
<Select
label="Small"
size="small"
value={smallValue}
onChange={(e) => setSmallValue(e.target.value)}
placeholder="Select"
>
<option value="item1">Context Menu Item 1</option>
<option value="item2">Context Menu Item 2</option>
<option value="item3">Context Menu Item 3</option>
</Select>
<Select
label="Medium"
size="medium"
value={mediumValue}
onChange={(e) => setMediumValue(e.target.value)}
placeholder="Select"
>
<option value="item1">Context Menu Item 1</option>
<option value="item2">Context Menu Item 2</option>
<option value="item3">Context Menu Item 3</option>
</Select>
<Select
label="Large"
size="large"
value={largeValue}
onChange={(e) => setLargeValue(e.target.value)}
placeholder="Select"
>
<option value="item1">Context Menu Item 1</option>
<option value="item2">Context Menu Item 2</option>
<option value="item3">Context Menu Item 3</option>
</Select>
</div>
);
};
export const AllStates = () => {
const [defaultValue, setDefaultValue] = useState("");
const [errorValue, setErrorValue] = useState("");
const [disabledValue, setDisabledValue] = useState("");
return (
<div className="space-y-4">
<Select
label="Default State"
value={defaultValue}
onChange={(e) => setDefaultValue(e.target.value)}
placeholder="Select"
>
<option value="item1">Context Menu Item 1</option>
<option value="item2">Context Menu Item 2</option>
<option value="item3">Context Menu Item 3</option>
</Select>
<Select
label="Error State"
error={true}
value={errorValue}
onChange={(e) => setErrorValue(e.target.value)}
placeholder="Select"
>
<option value="item1">Context Menu Item 1</option>
<option value="item2">Context Menu Item 2</option>
<option value="item3">Context Menu Item 3</option>
</Select>
<Select
label="Disabled State"
disabled={true}
value={disabledValue}
onChange={(e) => setDisabledValue(e.target.value)}
placeholder="Select"
>
<option value="item1">Context Menu Item 1</option>
<option value="item2">Context Menu Item 2</option>
<option value="item3">Context Menu Item 3</option>
</Select>
</div>
);
};