Skip to content

Commit

Permalink
chore: add stories for input elements
Browse files Browse the repository at this point in the history
  • Loading branch information
mwargan committed Mar 6, 2024
1 parent 07bee19 commit b3278b0
Show file tree
Hide file tree
Showing 6 changed files with 333 additions and 8 deletions.
12 changes: 12 additions & 0 deletions src/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,16 @@ nav form {
.v-enter-from,
.v-leave-to {
opacity: 0;
}

/* If there's an label and the next element is a required input/select, add a star to the label */
label:has(+input:required)::after,
label:has(+textarea:required)::after,
label:has(+select:required)::after,
/* If label has child checkbox, the text will be after the child input */
label:has(>input[type="checkbox"]:required)::after,
label:has(>input[type="radio"]:required)::after {
content: "*";
color: var(--del-color);
margin-left: calc(var(--nav-link-spacing-vertical) / 2);
}
66 changes: 66 additions & 0 deletions src/stories/Inputs/Checkbox.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { Meta, StoryObj } from "@storybook/vue3";

type HTMLInputElementCustom = Omit<HTMLInputElement, "type"> & {
role?: "switch";
ariaInvalid: boolean | undefined;
};

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta: Meta<HTMLInputElementCustom> = {
title: "Components/Inputs/Checkbox",
// We will just show a simple input
render: (args) => ({
setup() {
return { args };
},
// We need to render the checkbox with options from args
template: `
<label for='checkbox'>
<input id='checkbox' type='checkbox' v-bind='args'></input>
{{args.name}}
</label>
`,
}),

// This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
argTypes: {
disabled: {
control: "boolean",
description: "If the input is disabled",
},
// aria-invalid can be true, false, or undefined
ariaInvalid: {
// We need 3 options, true, false, and undefined
options: [true, false, undefined],
control: { type: "select" },
description:
"If the input is invalid. If false, the input is valid. If undefined, the input is neither valid nor invalid",
},
role: {
options: [undefined, "switch"],
control: { type: "select" },
description: "The role of the input",
},
},
args: {
checked: true,
name: "Checkbox",
required: true,
disabled: false,
readOnly: false,
role: undefined,
}, // default value
};

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

export const Default: Story = {};

export const Switch: Story = {
args: {
name: "Switch",
role: "switch",
},
};
52 changes: 52 additions & 0 deletions src/stories/Inputs/Radio.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { Meta, StoryObj } from "@storybook/vue3";

type HTMLInputElementCustom = Omit<HTMLInputElement, "type"> & {
ariaInvalid: boolean | undefined;
};

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta: Meta<HTMLInputElementCustom> = {
title: "Components/Inputs/Radio",
// We will just show a simple input
render: (args) => ({
setup() {
return { args };
},
// We need to render the radio with options from args
template: `
<label for='radio'>
<input id='radio' type='radio' v-bind='args'></input>
{{args.name}}
</label>
`,
}),

// This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
argTypes: {
disabled: {
control: "boolean",
description: "If the input is disabled",
},
// aria-invalid can be true, false, or undefined
ariaInvalid: {
// We need 3 options, true, false, and undefined
options: [true, false, undefined],
control: { type: "select" },
description:
"If the input is invalid. If false, the input is valid. If undefined, the input is neither valid nor invalid",
},
},
args: {
checked: true,
name: "Radio",
required: true,
disabled: false,
readOnly: false,
}, // default value
};

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

export const Default: Story = {};
68 changes: 68 additions & 0 deletions src/stories/Inputs/Select.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { Meta, StoryObj } from "@storybook/vue3";

// Custom HTMLSelectElement type to add options
type HTMLSelectElementCustom = Omit<HTMLSelectElement, "options"> & {
options: string[];
ariaInvalid: boolean | undefined;
};

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta: Meta<HTMLSelectElementCustom> = {
title: "Components/Inputs/Select",
// We will just show a simple input
render: (args) => ({
setup() {
return { args };
},
// We need to render the select with options from args
template:
"<label for='select'>{{args.name}}</label><select id='select' v-bind='args'><option v-for='option in args.options' :value='option'>{{ option }}</option></select>",
}),

// This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
argTypes: {
// @ts-ignore
value: {
control: "text",
description: "The value of the input",
},
disabled: {
control: "boolean",
description: "If the input is disabled",
},
// aria-invalid can be true, false, or undefined
ariaInvalid: {
// We need 3 options, true, false, and undefined
options: [true, false, undefined],
control: { type: "select" },
description:
"If the input is invalid. If false, the input is valid. If undefined, the input is neither valid nor invalid",
},
size: {
control: "number",
description: "The size of the input",
},
},
args: {
value: "Option 1",
required: true,
disabled: false,
multiple: false,
name: "Select",
options: ["Option 1", "Option 2", "Option 3"],
size: undefined,
}, // default value
};

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

export const Default: Story = {};

export const Multiple: Story = {
args: {
multiple: true,
size: 3,
},
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import type { Meta, StoryObj } from "@storybook/web-components";
import type { Meta, StoryObj } from "@storybook/vue3";

// Custom HTMLSelectElement type to add options
type HTMLInputElementCustom = HTMLInputElement & {
ariaInvalid: boolean | undefined;
};

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta: Meta = {
const meta: Meta<HTMLInputElementCustom> = {
title: "Components/Inputs/Input",
// We will just show a simple input
component: "input",
render: (args) => ({
setup() {
return { args };
},
// We need to render the textarea with options from args
template:
"<label for='input'>{{args.name}}</label><input id='input' v-bind='args'></input>",
}),

// This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
Expand All @@ -20,10 +32,21 @@ const meta: Meta = {
},
// Type is an enum
type: {
options: ["text", "password", "email", "number", "tel", "url"],
options: [
"text",
"password",
"email",
"number",
"tel",
"url",
"search",
"date",
"time",
"color",
"file",
"range",
],
control: { type: "select" },
// Default to text
defaultValue: "text",
description: "The type of the input",
},
disabled: {
Expand All @@ -40,17 +63,18 @@ const meta: Meta = {
},
},
args: {
name: "Input",
value: "Hello World",
placeholder: "Hello World",
type: "text",
required: true,
disabled: false,
readonly: false,
readOnly: false,
}, // default value
};

export default meta;
type Story = StoryObj<HTMLInputElement>;
type Story = StoryObj<HTMLInputElementCustom>;

export const Default: Story = {};

Expand Down Expand Up @@ -88,3 +112,45 @@ export const Url: Story = {
type: "url",
},
};

export const Search: Story = {
args: {
value: "Hello World",
type: "search",
},
};

export const Date: Story = {
args: {
value: "2021-01-01",
type: "date",
},
};

export const Time: Story = {
args: {
value: "12:00",
type: "time",
},
};

export const Color: Story = {
args: {
value: "#000000",
type: "color",
},
};

export const File: Story = {
args: {
value: "",
type: "file",
},
};

export const Range: Story = {
args: {
value: "50",
type: "range",
},
};
61 changes: 61 additions & 0 deletions src/stories/Inputs/Textarea.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { Meta, StoryObj } from "@storybook/vue3";

// Custom HTMLSelectElement type to add options
type HTMLTextAreaElementCustom = Omit<HTMLTextAreaElement, "options"> & {
options: string[];
ariaInvalid: boolean | undefined;
};

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta: Meta<HTMLTextAreaElementCustom> = {
title: "Components/Inputs/Textarea",
// We will just show a simple input
render: (args) => ({
setup() {
return { args };
},
// We need to render the textarea with options from args
template:
"<label for='textarea'>{{args.name}}</label><textarea id='textarea' v-bind='args'></textarea>",
}),

// This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
argTypes: {
// @ts-ignore
value: {
control: "text",
description: "The value of the input",
},
placeholder: {
control: "text",
description: "The placeholder of the input",
},
disabled: {
control: "boolean",
description: "If the input is disabled",
},
// aria-invalid can be true, false, or undefined
ariaInvalid: {
// We need 3 options, true, false, and undefined
options: ["true", "false", undefined],
control: { type: "select" },
description:
"If the input is invalid. If false, the input is valid. If undefined, the input is neither valid nor invalid",
},
},
args: {
name: "Textarea",
value: "Hello World",
placeholder: "Hello World",
required: true,
disabled: false,
readOnly: false,
ariaInvalid: undefined,
}, // default value
};

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

export const Default: Story = {};

0 comments on commit b3278b0

Please sign in to comment.