diff --git a/.changeset/stale-badgers-search.md b/.changeset/stale-badgers-search.md new file mode 100644 index 00000000000..f36cef414f8 --- /dev/null +++ b/.changeset/stale-badgers-search.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Introduces a draft for component to replace the existing Label component diff --git a/docs/content/drafts/Label2.mdx b/docs/content/drafts/Label2.mdx new file mode 100644 index 00000000000..5687f1e9cea --- /dev/null +++ b/docs/content/drafts/Label2.mdx @@ -0,0 +1,102 @@ +--- +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() +``` + +### Variants + +```javascript live noinline +// import {Label} from '@primer/react/drafts' +const {Label} = drafts // ignore docs silliness; import like that ↑ +render( + <> + + + + + + + + + + + +) +``` + +### Sizes + +```javascript live noinline +// import {Label} from '@primer/react/drafts' +const {Label} = drafts // ignore docs silliness; import like that ↑ +render( + <> + + + +) +``` + +## Props + +### Label + + + + + + +## Status + + diff --git a/src/Label2.tsx b/src/Label2.tsx new file mode 100644 index 00000000000..34ea8357750 --- /dev/null +++ b/src/Label2.tsx @@ -0,0 +1,98 @@ +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 ViewCompnents and Primer CSS + }, + large: { + height: '24px', + padding: '0 10px' // hard-coded to align with Primer ViewCompnents 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__/Label2.test.tsx b/src/__tests__/Label2.test.tsx new file mode 100644 index 00000000000..a0989ab845f --- /dev/null +++ b/src/__tests__/Label2.test.tsx @@ -0,0 +1,40 @@ +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() + 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(