diff --git a/src/stories/components/Button.mdx b/src/stories/components/Button.mdx
new file mode 100644
index 0000000..b6a0e4a
--- /dev/null
+++ b/src/stories/components/Button.mdx
@@ -0,0 +1,98 @@
+import { Canvas, Controls, Meta, Source } from "@storybook/blocks";
+import * as ButtonStories from "./Button.stories";
+
+
+
+# Button
+
+## Usage notes
+
+Please refer to [GOV.UK Design System documentation on
+buttons](https://design-system.service.gov.uk/components/button/) for more
+information.
+
+## Example
+
+
+
+
+## Variants
+
+### Small size
+
+
+
+### Large size
+
+
+
+## Icons
+
+### with left icon
+
+
+
+### with right icon
+
+
+
+### with icon only
+
+
+
+## States
+
+### Disabled
+
+
+
+## Button as link
+
+
+
+## Implementation notes
+
+- add `ds-button` as base class to a `button` element
+- combine with one size modifier: `ds-button-small` or `ds-button-large`
+- combine with one appearance modifier: `ds-button-secondary`, `ds-button-tertiary`, `ds-button-ghost`
+
+
+
+- for full with add `ds-button-full-width`
+
+
+
+### with icons
+
+- use `svg` for the icon, add `ds-button-icon` class to the icon
+- add `ds-button-with-icon` class to the button
+- wrap text in a `span` with the class `ds-button-label`
+
+
+
+### with icon only
+
+- add `ds-button-with-icon-only` class
+- wrap (invisible) text in a `span` with class `sr-only`
+- have a look at [Accessible Icon Buttons](https://www.sarasoueidan.com/blog/accessible-icon-buttons/)
+
+
+
+### links that look like buttons
+
+- add `role="button"` to the link
+- have a look at this [discussion on links styled as buttons and a11y implications](https://github.com/alphagov/govuk_elements/pull/272)
+
+
+
+### "disabled" buttons
+
+- use a `div` as tag and add `is-disabled` class
+
+
+
+## Further documentation
+
+Please check out the code on the given examples and otherwise
+refer to [mdn web docs on \](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
+for more technical information.
diff --git a/src/stories/components/Button.stories.ts b/src/stories/components/Button.stories.ts
new file mode 100644
index 0000000..c633e04
--- /dev/null
+++ b/src/stories/components/Button.stories.ts
@@ -0,0 +1,251 @@
+import type { Meta, StoryObj } from "@storybook/html";
+import { clsx } from "clsx";
+import dedent from "dedent";
+import {
+ htmlAttrs,
+ loremSentences,
+ loremWords,
+} from "../../../.storybook/utils";
+
+type ButtonArgs = {
+ label: string;
+ size?: "default" | "small" | "large";
+ appearance?: "default" | "secondary" | "tertiary" | "ghost";
+ fullWidth?: boolean;
+ withIcon?: boolean;
+ withIconRight?: boolean;
+ withIconOnly?: boolean;
+ disabled?: boolean;
+ isLink?: boolean;
+};
+
+const meta = {
+ title: "Components/Button",
+ render: ({
+ label,
+ size,
+ appearance,
+ fullWidth,
+ withIcon,
+ withIconRight,
+ withIconOnly,
+ disabled,
+ isLink,
+ }) => {
+ const cssClasses = clsx("ds-button", {
+ "ds-button-large": size === "large",
+ "ds-button-small": size === "small",
+ "ds-button-secondary": appearance === "secondary",
+ "ds-button-tertiary": appearance === "tertiary",
+ "ds-button-ghost": appearance === "ghost",
+ "is-disabled": disabled,
+ "ds-button-with-icon": withIcon || withIconRight,
+ "ds-button-with-icon-only": withIconOnly,
+ "ds-button-full-width": fullWidth,
+ });
+ const attrs = htmlAttrs({ className: cssClasses });
+
+ const icon = dedent`
+
+
+
+ `;
+
+ if (disabled) {
+ return dedent`
+
+ ${label}
+
+ `;
+ }
+
+ if (isLink) {
+ return dedent`
+
+ ${label}
+
+ `;
+ }
+
+ if (withIcon || withIconRight) {
+ return dedent`
+
+ ${withIcon ? icon : ""}
+
+ ${label}
+
+ ${withIconRight ? icon : ""}
+
+ `;
+ }
+
+ if (withIconOnly) {
+ return dedent`
+
+ ${icon}
+
+ ${label}
+
+
+ `;
+ }
+
+ return dedent`
+
+ ${label}
+
+ `;
+ },
+ argTypes: {
+ disabled: {
+ description: "Is the button not available for interaction?",
+ },
+ label: { control: "text" },
+ withIcon: { control: "boolean" },
+ withIconRight: { control: "boolean" },
+ withIconOnly: { control: "boolean" },
+ size: {
+ options: ["default", "small", "large"],
+ control: { type: "radio" },
+ },
+ appearance: {
+ options: ["default", "secondary", "tertiary", "ghost"],
+ control: { type: "radio" },
+ },
+ },
+ args: {
+ disabled: false,
+ label: loremWords(4),
+ size: "default",
+ appearance: "default",
+ withIcon: false,
+ withIconRight: false,
+ withIconOnly: false,
+ },
+} satisfies Meta;
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default = {} satisfies Story;
+export const Small = { args: { size: "small" } } satisfies Story;
+export const Large = { args: { size: "large" } } satisfies Story;
+export const Disabled = { args: { disabled: true } } satisfies Story;
+export const Link = { args: { isLink: true } } satisfies Story;
+export const WithIcon = { args: { withIcon: true } } satisfies Story;
+export const WithIconRight = { args: { withIconRight: true } } satisfies Story;
+export const WithIconOnly = { args: { withIconOnly: true } } satisfies Story;
+export const FullWidth = { args: { fullWidth: true } } satisfies Story;
+export const FullWidthWithIcon = {
+ args: { fullWidth: true, withIcon: true },
+} satisfies Story;
+export const LongText = { args: { label: loremSentences(4) } } satisfies Story;
+export const LongTextWithIcon = {
+ args: { label: loremSentences(4), withIcon: true },
+} satisfies Story;
+
+export const Secondary = { args: { appearance: "secondary" } } satisfies Story;
+export const SecondarySmall = {
+ args: { appearance: "secondary", size: "small" },
+} satisfies Story;
+export const SecondaryLarge = {
+ args: { appearance: "secondary", size: "large" },
+} satisfies Story;
+export const SecondaryDisabled = {
+ args: { appearance: "secondary", disabled: true },
+} satisfies Story;
+export const SecondaryLink = {
+ args: { appearance: "secondary", isLink: true },
+} satisfies Story;
+export const SecondaryWithIcon = {
+ args: { appearance: "secondary", withIcon: true },
+} satisfies Story;
+export const SecondaryWithIconRight = {
+ args: { appearance: "secondary", withIconRight: true },
+} satisfies Story;
+export const SecondaryWithIconOnly = {
+ args: { appearance: "secondary", withIconOnly: true },
+} satisfies Story;
+export const SecondaryFullWidth = {
+ args: { appearance: "secondary", fullWidth: true },
+} satisfies Story;
+export const SecondaryFullWidthWithIcon = {
+ args: { appearance: "secondary", fullWidth: true, withIcon: true },
+} satisfies Story;
+export const SecondaryLongText = {
+ args: { appearance: "secondary", label: loremSentences(4) },
+} satisfies Story;
+export const SecondaryLongTextWithIcon = {
+ args: { appearance: "secondary", label: loremSentences(4), withIcon: true },
+} satisfies Story;
+
+export const Tertiary = { args: { appearance: "tertiary" } } satisfies Story;
+export const TertiarySmall = {
+ args: { appearance: "tertiary", size: "small" },
+} satisfies Story;
+export const TertiaryLarge = {
+ args: { appearance: "tertiary", size: "large" },
+} satisfies Story;
+export const TertiaryDisabled = {
+ args: { appearance: "tertiary", disabled: true },
+} satisfies Story;
+export const TertiaryLink = {
+ args: { appearance: "tertiary", isLink: true },
+} satisfies Story;
+export const TertiaryWithIcon = {
+ args: { appearance: "tertiary", withIcon: true },
+} satisfies Story;
+export const TertiaryWithIconRight = {
+ args: { appearance: "tertiary", withIconRight: true },
+} satisfies Story;
+export const TertiaryWithIconOnly = {
+ args: { appearance: "tertiary", withIconOnly: true },
+} satisfies Story;
+export const TertiaryFullWidth = {
+ args: { appearance: "tertiary", fullWidth: true },
+} satisfies Story;
+export const TertiaryFullWidthWithIcon = {
+ args: { appearance: "tertiary", fullWidth: true, withIcon: true },
+} satisfies Story;
+export const TertiaryLongText = {
+ args: { appearance: "tertiary", label: loremSentences(4) },
+} satisfies Story;
+export const TertiaryLongTextWithIcon = {
+ args: { appearance: "tertiary", label: loremSentences(4), withIcon: true },
+} satisfies Story;
+
+export const Ghost = { args: { appearance: "ghost" } } satisfies Story;
+export const GhostSmall = {
+ args: { appearance: "ghost", size: "small" },
+} satisfies Story;
+export const GhostLarge = {
+ args: { appearance: "ghost", size: "large" },
+} satisfies Story;
+export const GhostDisabled = {
+ args: { appearance: "ghost", disabled: true },
+} satisfies Story;
+export const GhostLink = {
+ args: { appearance: "ghost", isLink: true },
+} satisfies Story;
+export const GhostWithIcon = {
+ args: { appearance: "ghost", withIcon: true },
+} satisfies Story;
+export const GhostWithIconRight = {
+ args: { appearance: "ghost", withIconRight: true },
+} satisfies Story;
+export const GhostWithIconOnly = {
+ args: { appearance: "ghost", withIconOnly: true },
+} satisfies Story;
+export const GhostFullWidth = {
+ args: { appearance: "ghost", fullWidth: true },
+} satisfies Story;
+export const GhostFullWidthWithIcon = {
+ args: { appearance: "ghost", fullWidth: true, withIcon: true },
+} satisfies Story;
+export const GhostLongText = {
+ args: { appearance: "ghost", label: loremSentences(4) },
+} satisfies Story;
+export const GhostLongTextWithIcon = {
+ args: { appearance: "ghost", label: loremSentences(4), withIcon: true },
+} satisfies Story;