diff --git a/.changeset/dirty-pillows-drop.md b/.changeset/dirty-pillows-drop.md
new file mode 100644
index 0000000000..6a35f6ce9d
--- /dev/null
+++ b/.changeset/dirty-pillows-drop.md
@@ -0,0 +1,5 @@
+---
+"@primer/css": patch
+---
+
+Storybook: add Label stories
diff --git a/.vscode/story-template.code-snippets b/.vscode/story-template.code-snippets
new file mode 100644
index 0000000000..19736c0479
--- /dev/null
+++ b/.vscode/story-template.code-snippets
@@ -0,0 +1,80 @@
+{
+ "story-template": {
+ "prefix": "story-template",
+ "body": [
+ "import React from 'react'",
+ "import clsx from 'clsx'",
+ "// import { StoryTemplateName } from './OtherStoryFile.stories' // import stories for component compositions",
+ "",
+ "export default {",
+ " title: 'Components/ComponentName',",
+ " excludeStories: ['ComponentTemplateName'],",
+ " argTypes: {",
+ " booleanExample: {",
+ " control: { type: 'boolean' },",
+ " description: 'true/false toggle to controls',",
+ " table: {",
+ " category: 'Pick one: CSS, HTML, Interactive'",
+ " }",
+ " },",
+ " selectExample: {",
+ " options: [0, 1, 2, 3], // iterator",
+ " mapping: ['string1', 'string2', 'string3', 'string4'], // values",
+ " control: {",
+ " type: 'select',",
+ " labels: ['string1-label', 'string2-label', 'string3-label', 'string4-label'] // public labels",
+ " },",
+ " description: 'select menu mapping to strings (example: use for variant class names)',",
+ " table: {",
+ " category: 'Pick one: CSS, HTML, Interactive'",
+ " }",
+ " },",
+ " stringExample: {",
+ " name: 'stringExample',",
+ " type: 'string',",
+ " description: 'text box control',",
+ " table: {",
+ " category: 'Pick one: CSS, HTML, Interactive'",
+ " }",
+ " },",
+ " children: {",
+ " description: 'creates a slot for children',",
+ " table: {",
+ " category: 'HTML'",
+ " }",
+ " },",
+ " }",
+ "}",
+ "",
+ "// build every component case here in the template (private api)",
+ "export const ComponentTemplateName = ({ booleanExample, selectExample, stringExample, children }) => (",
+ "
",
+ " {/* use {children} for wrapper component templates */}",
+ " <>",
+ " {stringExample}",
+ " {children}",
+ " >",
+ "
",
+ ")",
+ "",
+ "// create a \"playground\" demo page that may set some defaults and allow story to access component controls",
+ "export const Playground = ComponentTemplateName.bind({})",
+ "Playground.args = {",
+ " stringExample: 'Default text',",
+ " booleanExample: false,",
+ " children: (",
+ " <>",
+ " ",
+ " >",
+ " )",
+ "}",
+ ""
+ ],
+ "description": "Basic component story jsx template"
+ }
+}
diff --git a/docs/src/stories/Button.stories.jsx b/docs/src/stories/components/Button/Button.stories.jsx
similarity index 100%
rename from docs/src/stories/Button.stories.jsx
rename to docs/src/stories/components/Button/Button.stories.jsx
diff --git a/docs/src/stories/components/Label/IssueLabel.stories.jsx b/docs/src/stories/components/Label/IssueLabel.stories.jsx
new file mode 100644
index 0000000000..98f99e8247
--- /dev/null
+++ b/docs/src/stories/components/Label/IssueLabel.stories.jsx
@@ -0,0 +1,58 @@
+import React from 'react'
+import clsx from 'clsx'
+
+export default {
+ title: 'Components/Label/IssueLabel',
+ excludeStories: ['IssueLabelTemplate'],
+ argTypes: {
+ variant: {
+ options: [0, 1, 2, 3], // iterator
+ mapping: [
+ 'color-bg-accent-emphasis',
+ 'color-bg-danger-emphasis',
+ 'color-bg-success-emphasis',
+ 'color-bg-attention-emphasis'
+ ], // values
+ control: {
+ type: 'select',
+ labels: ['accent', 'danger', 'success', 'attention'] // public labels
+ },
+ description: 'Colors',
+ table: {
+ category: 'CSS'
+ }
+ },
+ size: {
+ options: [0, 1], // iterator
+ mapping: ['', 'IssueLabel--big'], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'big'] // public labels
+ },
+ description: 'Size',
+ table: {
+ category: 'CSS'
+ }
+ },
+ text: {
+ name: 'stringExample',
+ type: 'string',
+ description: 'Label text',
+ table: {
+ category: 'HTML'
+ }
+ }
+ }
+}
+
+// build every component case here in the template (private api)
+export const IssueLabelTemplate = ({variant, size, text}) => (
+ {text}
+)
+
+// create a "playground" demo page that may set some defaults and allow story to access component controls
+export const Playground = IssueLabelTemplate.bind({})
+Playground.args = {
+ text: 'bug 🐛',
+ variant: 'color-bg-accent-emphasis'
+}
diff --git a/docs/src/stories/components/Label/Label.stories.jsx b/docs/src/stories/components/Label/Label.stories.jsx
new file mode 100644
index 0000000000..292dc87915
--- /dev/null
+++ b/docs/src/stories/components/Label/Label.stories.jsx
@@ -0,0 +1,67 @@
+import React from 'react'
+import clsx from 'clsx'
+
+export default {
+ title: 'Components/Label/Label',
+ excludeStories: ['LabelTemplate'],
+ argTypes: {
+ inline: {
+ control: {type: 'boolean'},
+ description: 'Display label inline',
+ table: {
+ category: 'CSS'
+ }
+ },
+ variant: {
+ options: [0, 1, 2, 3, 4, 5], // iterator
+ mapping: [
+ '',
+ 'Label--primary',
+ 'Label--secondary',
+ 'Label--info',
+ 'Label--success',
+ 'Label--warning',
+ 'Label--danger'
+ ], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'primary', 'secondary', 'info', 'success', 'warning', 'danger']
+ },
+ description: 'Colors',
+ table: {
+ category: 'HTML'
+ }
+ },
+ size: {
+ options: [0, 1], // iterator
+ mapping: ['', 'Label--large'], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'large'] // public labels
+ },
+ description: 'Colors',
+ table: {
+ category: 'CSS'
+ }
+ },
+ text: {
+ name: 'text',
+ type: 'string',
+ description: 'Label text',
+ table: {
+ category: 'HTML'
+ }
+ }
+ }
+}
+
+export const LabelTemplate = ({inline, variant, size, text}) => (
+ {text}
+)
+
+export const Playground = LabelTemplate.bind({})
+Playground.args = {
+ text: 'Label text',
+ inline: false,
+ variant: 'Label--primary'
+}
diff --git a/docs/src/stories/components/Label/LabelCounter.stories.jsx b/docs/src/stories/components/Label/LabelCounter.stories.jsx
new file mode 100644
index 0000000000..538755561e
--- /dev/null
+++ b/docs/src/stories/components/Label/LabelCounter.stories.jsx
@@ -0,0 +1,54 @@
+import React from 'react'
+import clsx from 'clsx'
+
+export default {
+ title: 'Components/Label/Counter',
+ excludeStories: ['LabelCounterTemplate'],
+ argTypes: {
+ variant: {
+ options: [0, 1, 2], // iterator
+ mapping: ['', 'Counter--primary', 'Counter--secondary'], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'primary', 'secondary'] // public labels
+ },
+ table: {
+ category: 'CSS'
+ }
+ },
+ text: {
+ name: 'text',
+ type: 'string',
+ description: 'Label text',
+ table: {
+ category: 'HTML'
+ }
+ },
+ icon: {
+ defaultValue: '',
+ name: 'icon',
+ type: 'string',
+ description: 'Paste [Octicon](https://primer.style/octicons/) in control field',
+ table: {
+ category: 'HTML'
+ }
+ }
+ }
+}
+
+// build every component case here in the template (private api)
+export const LabelCounterTemplate = ({variant, text, icon}) => (
+
+ <>
+ {icon && icon}
+ {text}
+ >
+
+)
+
+// create a "playground" demo page that may set some defaults and allow story to access component controls
+export const Playground = LabelCounterTemplate.bind({})
+Playground.args = {
+ text: '23',
+ variant: 'Counter--primary'
+}
diff --git a/docs/src/stories/components/Label/LabelDiffstat.stories.jsx b/docs/src/stories/components/Label/LabelDiffstat.stories.jsx
new file mode 100644
index 0000000000..75fe64a51c
--- /dev/null
+++ b/docs/src/stories/components/Label/LabelDiffstat.stories.jsx
@@ -0,0 +1,47 @@
+import React from 'react'
+
+export default {
+ title: 'Components/Label/Diffstat',
+ excludeStories: ['LabelDiffstatTemplate'],
+ argTypes: {
+ diffValueIntent: {
+ options: [0, 1, 2], // iterator
+ mapping: ['', 'color-fg-success', 'color-fg-danger'], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'success', 'danger'] // public labels
+ },
+ table: {
+ category: 'CSS'
+ }
+ },
+ diffValue: {
+ name: 'diffValue',
+ type: 'string',
+ description: '7',
+ table: {
+ category: 'HTML'
+ }
+ }
+ }
+}
+
+// build every component case here in the template (private api)
+export const LabelDiffstatTemplate = ({diffValue, diffValueIntent}) => (
+
+ {diffValueIntent === 'color-fg-success' && +{diffValue}}
+ {diffValueIntent === 'color-fg-danger' && -{diffValue}}
+ {diffValueIntent === '' && diffValue}
+
+
+
+
+
+)
+
+// create a "playground" demo page that may set some defaults and allow story to access component controls
+export const Playground = LabelDiffstatTemplate.bind({})
+Playground.args = {
+ diffValue: '7',
+ diffValueIntent: ''
+}
diff --git a/docs/src/stories/components/Label/LabelFeatures.stories.jsx b/docs/src/stories/components/Label/LabelFeatures.stories.jsx
new file mode 100644
index 0000000000..0f7d23088f
--- /dev/null
+++ b/docs/src/stories/components/Label/LabelFeatures.stories.jsx
@@ -0,0 +1,72 @@
+import React from 'react'
+import {LabelTemplate} from './Label.stories' // import stories for component compositions
+
+export default {
+ title: 'Components/Label/Label/Features'
+}
+
+export const VariantDefault = LabelTemplate.bind({})
+VariantDefault.storyName = '[Variant] Default'
+VariantDefault.args = {
+ text: 'Label text',
+ inline: false,
+ variant: 'Label--default'
+}
+
+export const VariantPrimary = LabelTemplate.bind({})
+VariantPrimary.storyName = '[Variant] Primary'
+VariantPrimary.args = {
+ text: 'Label text',
+ inline: false,
+ variant: 'Label--primary'
+}
+
+export const VariantInfo = LabelTemplate.bind({})
+VariantInfo.storyName = '[Variant] Info'
+VariantInfo.args = {
+ text: 'Label text',
+ inline: false,
+ variant: 'Label--info'
+}
+
+export const VariantSuccess = LabelTemplate.bind({})
+VariantSuccess.storyName = '[Variant] Success'
+VariantSuccess.args = {
+ text: 'Label text',
+ inline: false,
+ variant: 'Label--success'
+}
+
+export const VariantWarning = LabelTemplate.bind({})
+VariantWarning.storyName = '[Variant] Warning'
+VariantWarning.args = {
+ text: 'Label text',
+ inline: false,
+ variant: 'Label--warning'
+}
+
+export const VariantDanger = LabelTemplate.bind({})
+VariantDanger.storyName = '[Variant] Danger'
+VariantDanger.args = {
+ text: 'Label text',
+ inline: false,
+ variant: 'Label--danger'
+}
+
+export const AllVariants = ({}) => (
+ <>
+
+
+
+
+
+
+ >
+)
+AllVariants.decorators = [
+ Story => (
+
+
+
+ )
+]
diff --git a/docs/src/stories/components/Label/LabelStates.stories.jsx b/docs/src/stories/components/Label/LabelStates.stories.jsx
new file mode 100644
index 0000000000..93d5643955
--- /dev/null
+++ b/docs/src/stories/components/Label/LabelStates.stories.jsx
@@ -0,0 +1,66 @@
+import React from 'react'
+import clsx from 'clsx'
+
+export default {
+ title: 'Components/Label/States',
+ excludeStories: ['LabelStatesTemplate'],
+ argTypes: {
+ state: {
+ options: [0, 1, 2, 3, 4], // iterator
+ mapping: ['', 'State--draft', 'State--open', 'State--merged', 'State--closed'], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'draft', 'open', 'merged', 'closed'] // public labels
+ },
+ // description: 'Colors & icons',
+ table: {
+ category: 'CSS'
+ }
+ },
+ size: {
+ options: [0, 1], // iterator
+ mapping: ['', 'State--small'], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'small'] // public labels
+ },
+ description: 'Size',
+ table: {
+ category: 'CSS'
+ }
+ },
+ text: {
+ name: 'text',
+ type: 'string',
+ description: 'Label text',
+ table: {
+ category: 'HTML'
+ }
+ },
+ icon: {
+ defaultValue: '',
+ name: 'icon',
+ type: 'string',
+ description: 'Paste [Octicon](https://primer.style/octicons/) in control field',
+ table: {
+ category: 'HTML'
+ }
+ }
+ }
+}
+
+// build every component case here in the template (private api)
+export const LabelStatesTemplate = ({state, size, text, icon}) => (
+
+ <>
+ {icon && } {text}
+ >
+
+)
+
+// create a "playground" demo page that may set some defaults and allow story to access component controls
+export const Playground = LabelStatesTemplate.bind({})
+Playground.args = {
+ text: 'Draft',
+ state: 'State--draft'
+}
diff --git a/docs/src/stories/components/Label/LabelStatesFeatures.stories.jsx b/docs/src/stories/components/Label/LabelStatesFeatures.stories.jsx
new file mode 100644
index 0000000000..6adf106e6d
--- /dev/null
+++ b/docs/src/stories/components/Label/LabelStatesFeatures.stories.jsx
@@ -0,0 +1,66 @@
+import React from 'react'
+import {LabelStatesTemplate} from './LabelStates.stories' // import stories for component compositions
+
+export default {
+ title: 'Components/Label/States/Features'
+}
+
+export const VariantDefault = LabelStatesTemplate.bind({})
+VariantDefault.storyName = '[State] Default'
+VariantDefault.args = {
+ text: 'Label text',
+ inline: false,
+ state: ''
+}
+
+export const VariantDraft = LabelStatesTemplate.bind({})
+VariantDraft.storyName = '[State] Draft'
+VariantDraft.args = {
+ text: 'Label text',
+ inline: false,
+ state: 'State--draft'
+}
+
+export const VariantOpen = LabelStatesTemplate.bind({})
+VariantOpen.storyName = '[State] Open'
+VariantOpen.args = {
+ text: 'Label text',
+ inline: false,
+ state: 'State--open',
+ icon: ``
+}
+
+export const VariantMerged = LabelStatesTemplate.bind({})
+VariantMerged.storyName = '[State] Merged'
+VariantMerged.args = {
+ text: 'Label text',
+ inline: false,
+ state: 'State--merged',
+ icon: ``
+}
+
+export const VariantClosed = LabelStatesTemplate.bind({})
+VariantClosed.storyName = '[State] Closed'
+VariantClosed.args = {
+ text: 'Label text',
+ inline: false,
+ state: 'State--closed',
+ icon: ``
+}
+
+export const AllVariants = ({}) => (
+ <>
+
+
+
+
+
+ >
+)
+AllVariants.decorators = [
+ Story => (
+
+
+
+ )
+]