diff --git a/.changeset/heavy-points-marry.md b/.changeset/heavy-points-marry.md
new file mode 100644
index 00000000000..179ade21518
--- /dev/null
+++ b/.changeset/heavy-points-marry.md
@@ -0,0 +1,41 @@
+---
+'@primer/react': major
+---
+
+The Label component's API and visual design have been updated to be consistent with its counterpart in [Primer ViewComponents' Label component](https://primer.style/view-components/components/label).
+
+Major changes in the new Label component:
+
+- No more `medium` size - only `small` and `large`
+- Labels are outlined by default, so the `outline` prop has been removed
+- Custom text and background colors are discouraged, but still possible via the `sx` prop
+
+If you were using the `Label` component to render issue/PR labels, use the [IssueLabelToken](https://primer.style/react/Token#issuelabeltoken) component instead.
+
+
+
+ Before After
+
+
+
+
+```jsx
+import {Label} from "@primer/react"
+
+default
+danger
+```
+
+
+
+
+```jsx
+import {Label} from "@primer/react"
+
+default
+danger
+```
+
+
+
+
diff --git a/docs/content/Label.mdx b/docs/content/Label.mdx
index 37ccd68e25c..1a28230a651 100644
--- a/docs/content/Label.mdx
+++ b/docs/content/Label.mdx
@@ -1,52 +1,76 @@
---
title: Label
-description: Use Label components to add contextual metadata to a design.
-status: Alpha
-source: https://github.com/primer/react/blob/main/src/Label.tsx
componentId: label
+status: Alpha
+source: https://github.com/primer/react/tree/main/src/Label
+storybook: '/react/storybook?path=story/labels-label--label'
+description: Use Label components to add contextual metadata to a design.
---
-## Example
+## Examples
-```jsx live
-<>
-
- small
-
-
- medium (default)
-
-
- large
-
- xl label
+### Basic
-
-
- good first issue
-
-
- 🚂 deploy: train
-
-
- css
-
-
- documentation
-
-
- primer
-
->
+```javascript live noinline
+render(Default )
+```
+
+### Variants
+
+```javascript live noinline
+render(
+ <>
+ Default
+ Primary
+ Secondary
+ Accent
+ Success
+ Attention
+ Severe
+ Danger
+ Done
+ Sponsors
+ >
+)
+```
+
+### Sizes
+
+```javascript live noinline
+render(
+ <>
+ Small (default)
+ Large
+ >
+)
```
## Props
+### Label
+
-
-
-
-
+
+
## Status
@@ -54,12 +78,13 @@ componentId: label
+
+ small
+
+
+ medium (default)
+
+
+ large
+
+ xl label
+
+
+
+ good first issue
+
+
+ 🚂 deploy: train
+
+
+ css
+
+
+ documentation
+
+
+ primer
+
+>
+```
+
+## Props
+
+
+
+
+
+
+
+
+## Status
+
+
diff --git a/docs/content/drafts/Label2.mdx b/docs/content/drafts/Label2.mdx
deleted file mode 100644
index 5687f1e9cea..00000000000
--- a/docs/content/drafts/Label2.mdx
+++ /dev/null
@@ -1,102 +0,0 @@
----
-title: Label v2
-componentId: label2
-status: Alpha
-source: https://github.com/primer/react/tree/main/src/Label2
-storybook: '/react/storybook?path=story/labels-label--label'
-description: Use Label components to add contextual metadata to a design.
----
-
-## Examples
-
-### Basic
-
-```javascript live noinline
-// import {Label} from '@primer/react/drafts'
-const {Label} = drafts // ignore docs silliness; import like that ↑
-
-render(Default )
-```
-
-### Variants
-
-```javascript live noinline
-// import {Label} from '@primer/react/drafts'
-const {Label} = drafts // ignore docs silliness; import like that ↑
-render(
- <>
- Default
- Primary
- Secondary
- Accent
- Success
- Attention
- Severe
- Danger
- Done
- Sponsors
- >
-)
-```
-
-### Sizes
-
-```javascript live noinline
-// import {Label} from '@primer/react/drafts'
-const {Label} = drafts // ignore docs silliness; import like that ↑
-render(
- <>
- Small (default)
- Large
- >
-)
-```
-
-## Props
-
-### Label
-
-
-
-
-
-
-## Status
-
-
diff --git a/docs/src/@primer/gatsby-theme-doctocat/nav.yml b/docs/src/@primer/gatsby-theme-doctocat/nav.yml
index a7e0219852e..30143970b9c 100644
--- a/docs/src/@primer/gatsby-theme-doctocat/nav.yml
+++ b/docs/src/@primer/gatsby-theme-doctocat/nav.yml
@@ -173,6 +173,8 @@
url: /deprecated/Grid
- title: InputField
url: /deprecated/InputField
+ - title: Label
+ url: /deprecated/Label
- title: Position
url: /deprecated/Position
- title: SelectMenu
diff --git a/src/Label.tsx b/src/Label.tsx
index 8f356d1aa61..7309a6d5e74 100644
--- a/src/Label.tsx
+++ b/src/Label.tsx
@@ -1,72 +1,100 @@
-import styled, {css} from 'styled-components'
-import {borderColor, BorderColorProps, variant} from 'styled-system'
+import styled from 'styled-components'
+import {variant} from 'styled-system'
+import sx, {SxProp, BetterSystemStyleObject} from './sx'
import {get} from './constants'
-import sx, {SxProp} from './sx'
-import {ComponentProps} from './utils/types'
-const outlineStyles = css`
- margin-top: -1px; // offsets the 1px border
- margin-bottom: -1px; // offsets the 1px border
- color: ${get('colors.fg.muted')};
- border: ${get('borderWidths.1')} solid ${get('colors.border.default')};
- box-shadow: none;
- ${borderColor};
- background-color: transparent;
-`
+export type LabelProps = {
+ /** The color of the label */
+ variant?: LabelColorOptions
+ /** How large the label is rendered */
+ size?: LabelSizeKeys
+} & SxProp
-const sizeVariant = variant({
- variants: {
- small: {
- fontSize: 0,
- lineHeight: '16px',
- padding: '0px 8px'
- },
- medium: {
- fontSize: 0,
- lineHeight: '20px',
- padding: '0 8px'
- },
- large: {
- fontSize: 0,
- lineHeight: '24px',
- padding: '0 12px'
- },
- // corresponds to StateLabel fontSize/lineHeight/padding
- xl: {
- fontSize: 1,
- lineHeight: '16px',
- padding: '8px 12px'
- }
- }
-})
+export type LabelColorOptions =
+ | 'default'
+ | 'primary'
+ | 'secondary'
+ | 'accent'
+ | 'success'
+ | 'attention'
+ | 'severe'
+ | 'danger'
+ | 'done'
+ | 'sponsors'
+
+type LabelSizeKeys = 'small' | 'large'
-const Label = styled.span<
- {
- variant?: 'small' | 'medium' | 'large' | 'xl'
- dropshadow?: boolean
- outline?: boolean
- } & BorderColorProps &
- SxProp
->`
- display: inline-block;
- font-weight: ${get('fontWeights.semibold')};
- color: ${get('colors.fg.onEmphasis')};
- border-radius: ${get('radii.3')};
- background-color: ${get('colors.neutral.emphasis')};
+export const variants: Record = {
+ default: {
+ borderColor: 'border.default'
+ },
+ primary: {
+ borderColor: 'fg.default'
+ },
+ secondary: {
+ borderColor: 'border.muted',
+ color: 'fg.muted'
+ },
+ accent: {
+ borderColor: 'accent.emphasis',
+ color: 'accent.fg'
+ },
+ success: {
+ borderColor: 'success.emphasis',
+ color: 'success.fg'
+ },
+ attention: {
+ borderColor: 'attention.emphasis',
+ color: 'attention.fg'
+ },
+ severe: {
+ borderColor: 'severe.emphasis',
+ color: 'severe.fg'
+ },
+ danger: {
+ borderColor: 'danger.emphasis',
+ color: 'danger.fg'
+ },
+ done: {
+ borderColor: 'done.fg',
+ color: 'done.emphasis'
+ },
+ sponsors: {
+ borderColor: 'sponsors.fg',
+ color: 'sponsors.emphasis'
+ }
+}
- &:hover {
- text-decoration: none;
+const sizes: Record = {
+ small: {
+ height: '20px',
+ padding: '0 7px' // hard-coded to align with Primer ViewComponents and Primer CSS
+ },
+ large: {
+ height: '24px',
+ padding: '0 10px' // hard-coded to align with Primer ViewComponents and Primer CSS
}
+}
- ${sizeVariant}
- ${props => (props.dropshadow ? 'box-shadow: inset 0 -1px 0 rgba(27, 31, 35, 0.12)' : '')}
- ${props => (props.outline ? outlineStyles : '')} // must be last to override other values
- ${sx}
+const Label = styled.span`
+ align-items: center;
+ background-color: transparent;
+ border-width: 1px;
+ border-radius: 999px;
+ border-style: solid;
+ display: inline-flex;
+ font-weight: ${get('fontWeights.bold')};
+ font-size: ${get('fontSizes.0')};
+ line-height: 1;
+ white-space: nowrap;
+ ${variant({variants})};
+ ${variant({prop: 'size', variants: sizes})};
+ ${sx};
`
Label.defaultProps = {
- variant: 'medium'
+ size: 'small',
+ variant: 'default'
}
-export type LabelProps = ComponentProps
export default Label
diff --git a/src/Label2.tsx b/src/Label2.tsx
deleted file mode 100644
index a90e6f74d46..00000000000
--- a/src/Label2.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import styled from 'styled-components'
-import {variant} from 'styled-system'
-import sx, {SxProp, BetterSystemStyleObject} from './sx'
-import {get} from './constants'
-
-export type LabelProps = {
- /** The color of the label */
- variant?: LabelColorOptions
- /** How large the label is rendered */
- size?: LabelSizeKeys
-} & SxProp
-
-export type LabelColorOptions =
- | 'default'
- | 'primary'
- | 'secondary'
- | 'accent'
- | 'success'
- | 'attention'
- | 'severe'
- | 'danger'
- | 'done'
- | 'sponsors'
-
-type LabelSizeKeys = 'small' | 'large'
-
-export const variants: Record = {
- default: {
- borderColor: 'border.default'
- },
- primary: {
- borderColor: 'fg.default'
- },
- secondary: {
- borderColor: 'border.muted',
- color: 'fg.muted'
- },
- accent: {
- borderColor: 'accent.emphasis',
- color: 'accent.fg'
- },
- success: {
- borderColor: 'success.emphasis',
- color: 'success.fg'
- },
- attention: {
- borderColor: 'attention.emphasis',
- color: 'attention.fg'
- },
- severe: {
- borderColor: 'severe.emphasis',
- color: 'severe.fg'
- },
- danger: {
- borderColor: 'danger.emphasis',
- color: 'danger.fg'
- },
- done: {
- borderColor: 'done.fg',
- color: 'done.emphasis'
- },
- sponsors: {
- borderColor: 'sponsors.fg',
- color: 'sponsors.emphasis'
- }
-}
-
-const sizes: Record = {
- small: {
- height: '20px',
- padding: '0 7px' // hard-coded to align with Primer ViewComponents and Primer CSS
- },
- large: {
- height: '24px',
- padding: '0 10px' // hard-coded to align with Primer ViewComponents and Primer CSS
- }
-}
-
-export const Label = styled.span`
- align-items: center;
- background-color: transparent;
- border-width: 1px;
- border-radius: 999px;
- border-style: solid;
- display: inline-flex;
- font-weight: ${get('fontWeights.bold')};
- font-size: ${get('fontSizes.0')};
- line-height: 1;
- white-space: nowrap;
- ${variant({variants})};
- ${variant({prop: 'size', variants: sizes})};
- ${sx};
-`
-
-Label.defaultProps = {
- size: 'small',
- variant: 'default'
-}
diff --git a/src/__tests__/Label.test.tsx b/src/__tests__/Label.test.tsx
index fac7245e851..a987dab727a 100644
--- a/src/__tests__/Label.test.tsx
+++ b/src/__tests__/Label.test.tsx
@@ -1,34 +1,40 @@
import React from 'react'
-import {Label} from '..'
-import {render, behavesAsComponent, checkExports} from '../utils/testing'
-import {render as HTMLRender, cleanup} from '@testing-library/react'
+import {render, cleanup} from '@testing-library/react'
import {axe, toHaveNoViolations} from 'jest-axe'
import 'babel-polyfill'
+import Label, {variants, LabelColorOptions} from '../Label'
+import {renderStyles} from '../utils/testing'
expect.extend(toHaveNoViolations)
describe('Label', () => {
- behavesAsComponent({Component: Label})
-
- checkExports('Label', {
- default: Label
- })
-
- it('renders a ', () => {
- expect(render( ).type).toEqual('span')
+ it('renders text node child', () => {
+ const container = render(Default )
+ const label = container.baseElement
+ expect(label.textContent).toEqual('Default')
})
+ it('default size is rendered as "small"', () => {
+ const expectedStyles = {
+ height: '20px',
+ padding: '0 7px'
+ }
+ const defaultStyles = renderStyles( )
- it('should have no axe violations', async () => {
- const {container} = HTMLRender(hello )
- const results = await axe(container)
- expect(results).toHaveNoViolations()
- cleanup()
+ expect(defaultStyles).toEqual(expect.objectContaining(expectedStyles))
})
+ it('default variant is rendered as "default"', () => {
+ const expectedStyles = {
+ ['border-color']: '#d0d7de'
+ }
+ const defaultStyles = renderStyles( )
- it('respects the "outline" prop', () => {
- expect(render( )).toMatchSnapshot()
+ expect(defaultStyles).toEqual(expect.objectContaining(expectedStyles))
})
-
- it('respects the "variant" prop', () => {
- expect(render( )).toMatchSnapshot()
+ it('should have no axe violations', async () => {
+ for (const variant in variants) {
+ const {container} = render(Default )
+ const results = await axe(container)
+ expect(results).toHaveNoViolations()
+ cleanup()
+ }
})
})
diff --git a/src/__tests__/Label2.test.tsx b/src/__tests__/Label2.test.tsx
deleted file mode 100644
index a0989ab845f..00000000000
--- a/src/__tests__/Label2.test.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react'
-import {render, cleanup} from '@testing-library/react'
-import {axe, toHaveNoViolations} from 'jest-axe'
-import 'babel-polyfill'
-import {Label, variants, LabelColorOptions} from '../Label2'
-import {renderStyles} from '../utils/testing'
-expect.extend(toHaveNoViolations)
-
-describe('Label2', () => {
- it('renders text node child', () => {
- const container = render(Default )
- const label = container.baseElement
- expect(label.textContent).toEqual('Default')
- })
- it('default size is rendered as "small"', () => {
- const expectedStyles = {
- height: '20px',
- padding: '0 7px'
- }
- const defaultStyles = renderStyles( )
-
- expect(defaultStyles).toEqual(expect.objectContaining(expectedStyles))
- })
- it('default variant is rendered as "default"', () => {
- const expectedStyles = {
- ['border-color']: '#d0d7de'
- }
- const defaultStyles = renderStyles( )
-
- expect(defaultStyles).toEqual(expect.objectContaining(expectedStyles))
- })
- it('should have no axe violations', async () => {
- for (const variant in variants) {
- const {container} = render(Default )
- const results = await axe(container)
- expect(results).toHaveNoViolations()
- cleanup()
- }
- })
-})
diff --git a/src/__tests__/deprecated/Label.test.tsx b/src/__tests__/deprecated/Label.test.tsx
new file mode 100644
index 00000000000..2b0937758be
--- /dev/null
+++ b/src/__tests__/deprecated/Label.test.tsx
@@ -0,0 +1,34 @@
+import React from 'react'
+import Label from '../../deprecated/Label'
+import {render, behavesAsComponent, checkExports} from '../../utils/testing'
+import {render as HTMLRender, cleanup} from '@testing-library/react'
+import {axe, toHaveNoViolations} from 'jest-axe'
+import 'babel-polyfill'
+expect.extend(toHaveNoViolations)
+
+describe('Label', () => {
+ behavesAsComponent({Component: Label})
+
+ checkExports('deprecated/Label', {
+ default: Label
+ })
+
+ it('renders a ', () => {
+ expect(render( ).type).toEqual('span')
+ })
+
+ it('should have no axe violations', async () => {
+ const {container} = HTMLRender(hello )
+ const results = await axe(container)
+ expect(results).toHaveNoViolations()
+ cleanup()
+ })
+
+ it('respects the "outline" prop', () => {
+ expect(render( )).toMatchSnapshot()
+ })
+
+ it('respects the "variant" prop', () => {
+ expect(render( )).toMatchSnapshot()
+ })
+})
diff --git a/src/__tests__/Label.types.test.tsx b/src/__tests__/deprecated/Label.types.test.tsx
similarity index 86%
rename from src/__tests__/Label.types.test.tsx
rename to src/__tests__/deprecated/Label.types.test.tsx
index 96fe2613bff..dcfa2638521 100644
--- a/src/__tests__/Label.types.test.tsx
+++ b/src/__tests__/deprecated/Label.types.test.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import Label from '../Label'
+import Label from '../deprecated/Label'
export function shouldAcceptCallWithNoProps() {
return
diff --git a/src/__tests__/__snapshots__/Label.test.tsx.snap b/src/__tests__/deprecated/__snapshots__/Label.test.tsx.snap
similarity index 100%
rename from src/__tests__/__snapshots__/Label.test.tsx.snap
rename to src/__tests__/deprecated/__snapshots__/Label.test.tsx.snap
diff --git a/src/deprecated/Label.tsx b/src/deprecated/Label.tsx
new file mode 100644
index 00000000000..d4a49982042
--- /dev/null
+++ b/src/deprecated/Label.tsx
@@ -0,0 +1,75 @@
+import styled, {css} from 'styled-components'
+import {borderColor, BorderColorProps, variant} from 'styled-system'
+import {get} from '../constants'
+import sx, {SxProp} from '../sx'
+import {ComponentProps} from '../utils/types'
+
+const outlineStyles = css`
+ margin-top: -1px; // offsets the 1px border
+ margin-bottom: -1px; // offsets the 1px border
+ color: ${get('colors.fg.muted')};
+ border: ${get('borderWidths.1')} solid ${get('colors.border.default')};
+ box-shadow: none;
+ ${borderColor};
+ background-color: transparent;
+`
+
+const sizeVariant = variant({
+ variants: {
+ small: {
+ fontSize: 0,
+ lineHeight: '16px',
+ padding: '0px 8px'
+ },
+ medium: {
+ fontSize: 0,
+ lineHeight: '20px',
+ padding: '0 8px'
+ },
+ large: {
+ fontSize: 0,
+ lineHeight: '24px',
+ padding: '0 12px'
+ },
+ // corresponds to StateLabel fontSize/lineHeight/padding
+ xl: {
+ fontSize: 1,
+ lineHeight: '16px',
+ padding: '8px 12px'
+ }
+ }
+})
+
+/** @deprecated Use the new Label instead. See https://primer.style/react/Label for more details. */
+const Label = styled.span<
+ {
+ variant?: 'small' | 'medium' | 'large' | 'xl'
+ dropshadow?: boolean
+ outline?: boolean
+ } & BorderColorProps &
+ SxProp
+>`
+ display: inline-block;
+ font-weight: ${get('fontWeights.semibold')};
+ color: ${get('colors.fg.onEmphasis')};
+ border-radius: ${get('radii.3')};
+ background-color: ${get('colors.neutral.emphasis')};
+
+ &:hover {
+ text-decoration: none;
+ }
+
+ ${sizeVariant}
+ ${props => (props.dropshadow ? 'box-shadow: inset 0 -1px 0 rgba(27, 31, 35, 0.12)' : '')}
+ ${props => (props.outline ? outlineStyles : '')} // must be last to override other values
+ ${sx}
+`
+
+Label.defaultProps = {
+ variant: 'medium'
+}
+
+Label.displayName = 'Label'
+
+export type LabelProps = ComponentProps
+export default Label
diff --git a/src/deprecated/index.ts b/src/deprecated/index.ts
index 80261dcdc54..1d47daa6001 100644
--- a/src/deprecated/index.ts
+++ b/src/deprecated/index.ts
@@ -27,6 +27,8 @@ export type {
export {default as FormGroup} from './FormGroup'
export type {FormGroupProps, FormGroupLabelProps} from './FormGroup'
export {default as InputField} from './InputField'
+export {default as Label} from './Label'
+export type {LabelProps} from './Label'
export {default as SelectMenu} from '../SelectMenu'
export type {
SelectMenuProps,
diff --git a/src/drafts/index.ts b/src/drafts/index.ts
index 2e2416f9f6f..42fe62fe81f 100644
--- a/src/drafts/index.ts
+++ b/src/drafts/index.ts
@@ -4,6 +4,3 @@
* But, they are published on npm and you can import them for experimentation/feedback.
* example: import {ActionList} from '@primer/react/drafts
*/
-
-// Components
-export * from '../Label2'
diff --git a/src/index.ts b/src/index.ts
index 672ce99469e..ebe75c33754 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -81,10 +81,10 @@ export {default as Header} from './Header'
export type {HeaderProps, HeaderItemProps, HeaderLinkProps} from './Header'
export {default as Heading} from './Heading'
export type {HeadingProps} from './Heading'
-export {default as LabelGroup} from './LabelGroup'
-export type {LabelGroupProps} from './LabelGroup'
export {default as Label} from './Label'
export type {LabelProps} from './Label'
+export {default as LabelGroup} from './LabelGroup'
+export type {LabelGroupProps} from './LabelGroup'
export {default as Link} from './Link'
export type {LinkProps} from './Link'
export {default as Overlay} from './Overlay'
diff --git a/src/stories/ActionList/fixtures.stories.tsx b/src/stories/ActionList/fixtures.stories.tsx
index 6e68b5c53c2..c002bbd4d42 100644
--- a/src/stories/ActionList/fixtures.stories.tsx
+++ b/src/stories/ActionList/fixtures.stories.tsx
@@ -529,9 +529,7 @@ export function CustomItemChildren(): JSX.Element {
-
- Choose this one
-
+ Choose this one
diff --git a/src/stories/Label2.stories.tsx b/src/stories/Label.stories.tsx
similarity index 94%
rename from src/stories/Label2.stories.tsx
rename to src/stories/Label.stories.tsx
index 74fa851a372..8b2a5d27959 100644
--- a/src/stories/Label2.stories.tsx
+++ b/src/stories/Label.stories.tsx
@@ -2,12 +2,11 @@ import React from 'react'
import {Meta} from '@storybook/react'
import {BaseStyles, ThemeProvider} from '..'
import {ComponentProps} from '../utils/types'
-import {Label} from '../Label2'
+import Label from '../Label'
type Args = ComponentProps
export default {
- // TODO: update story nesting
title: 'Labels/Label',
component: Label,
argTypes: {
diff --git a/src/stories/Overlay.stories.tsx b/src/stories/Overlay.stories.tsx
index bda41e5c109..5d2b59f7132 100644
--- a/src/stories/Overlay.stories.tsx
+++ b/src/stories/Overlay.stories.tsx
@@ -434,7 +434,7 @@ export const MemexIssueOverlay = () => {
>
-
+
Draft
opened 2 days ago,