From dd11ad5f31bc494320767d88dc5a8097b5f56ce5 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Mon, 28 Feb 2022 22:01:10 +1100 Subject: [PATCH 01/12] Move old button to deprecated --- src/ActionMenu.tsx | 2 +- src/{Button => }/ButtonGroup.tsx | 8 +++---- src/Dialog.tsx | 2 +- src/Dialog/Dialog.tsx | 2 +- src/Dropdown.tsx | 2 +- src/__tests__/AnchoredOverlay.test.tsx | 3 ++- src/__tests__/Button.test.tsx | 10 +++++---- src/__tests__/ConfirmationDialog.test.tsx | 2 +- src/__tests__/Details.test.tsx | 5 +++-- src/__tests__/Dialog.test.tsx | 3 ++- src/__tests__/Overlay.test.tsx | 3 ++- src/__tests__/SelectMenu.test.tsx | 3 +-- src/{ => deprecated}/Button/Button.tsx | 6 ++--- src/{ => deprecated}/Button/ButtonBase.tsx | 2 +- src/{ => deprecated}/Button/ButtonClose.tsx | 6 ++--- src/{ => deprecated}/Button/ButtonDanger.tsx | 6 ++--- .../Button/ButtonInvisible.tsx | 6 ++--- src/{ => deprecated}/Button/ButtonOutline.tsx | 6 ++--- src/{ => deprecated}/Button/ButtonPrimary.tsx | 6 ++--- src/{ => deprecated}/Button/ButtonStyles.tsx | 2 +- .../Button/ButtonTableList.tsx | 6 ++--- src/{ => deprecated}/Button/index.ts | 2 -- .../DropdownMenu/DropdownButton.tsx | 2 +- src/deprecated/index.ts | 18 +++++++++++++++ src/index.ts | 22 ++----------------- src/stories/ActionList/fixtures.stories.tsx | 2 +- src/stories/AnchoredOverlay.stories.tsx | 2 +- src/stories/Autocomplete.stories.tsx | 2 +- src/stories/Button.stories.tsx | 10 ++++----- src/stories/ConfirmationDialog.stories.tsx | 4 ++-- src/stories/Dialog.stories.tsx | 3 ++- src/stories/Overlay.stories.tsx | 5 +---- src/stories/deprecated/ActionMenu.stories.tsx | 3 +-- src/stories/useAnchoredPosition.stories.tsx | 3 ++- src/stories/useFocusZone.stories.tsx | 4 ++-- 35 files changed, 86 insertions(+), 87 deletions(-) rename src/{Button => }/ButtonGroup.tsx (87%) rename src/{ => deprecated}/Button/Button.tsx (89%) rename src/{ => deprecated}/Button/ButtonBase.tsx (94%) rename src/{ => deprecated}/Button/ButtonClose.tsx (86%) rename src/{ => deprecated}/Button/ButtonDanger.tsx (91%) rename src/{ => deprecated}/Button/ButtonInvisible.tsx (85%) rename src/{ => deprecated}/Button/ButtonOutline.tsx (91%) rename src/{ => deprecated}/Button/ButtonPrimary.tsx (91%) rename src/{ => deprecated}/Button/ButtonStyles.tsx (94%) rename src/{ => deprecated}/Button/ButtonTableList.tsx (88%) rename src/{ => deprecated}/Button/index.ts (87%) diff --git a/src/ActionMenu.tsx b/src/ActionMenu.tsx index accfa7115eb..59735ff01c7 100644 --- a/src/ActionMenu.tsx +++ b/src/ActionMenu.tsx @@ -6,7 +6,7 @@ import {OverlayProps} from './Overlay' import {useProvidedRefOrCreate, useProvidedStateOrCreate, useMenuInitialFocus, useTypeaheadFocus} from './hooks' import {Divider} from './ActionList/Divider' import {ActionListContainerContext} from './ActionList/ActionListContainerContext' -import {Button, ButtonProps} from './Button2' +import {Button, ButtonProps} from './Button' import {MandateProps} from './utils/types' type MenuContextProps = Pick< diff --git a/src/Button/ButtonGroup.tsx b/src/ButtonGroup.tsx similarity index 87% rename from src/Button/ButtonGroup.tsx rename to src/ButtonGroup.tsx index 31fb38ce688..fa49418dd8e 100644 --- a/src/Button/ButtonGroup.tsx +++ b/src/ButtonGroup.tsx @@ -1,8 +1,8 @@ import styled from 'styled-components' -import Box from '../Box' -import {get} from '../constants' -import sx from '../sx' -import {ComponentProps} from '../utils/types' +import Box from './Box' +import {get} from './constants' +import sx from './sx' +import {ComponentProps} from './utils/types' const ButtonGroup = styled(Box)` vertical-align: middle; diff --git a/src/Dialog.tsx b/src/Dialog.tsx index aee39d5979f..05b078d95b2 100644 --- a/src/Dialog.tsx +++ b/src/Dialog.tsx @@ -1,6 +1,6 @@ import React, {forwardRef, useRef} from 'react' import styled from 'styled-components' -import ButtonClose from './Button/ButtonClose' +import ButtonClose from './deprecated/Button/ButtonClose' import {get} from './constants' import Box from './Box' import useDialog from './hooks/useDialog' diff --git a/src/Dialog/Dialog.tsx b/src/Dialog/Dialog.tsx index 2cc91203db1..2bc1e534077 100644 --- a/src/Dialog/Dialog.tsx +++ b/src/Dialog/Dialog.tsx @@ -1,6 +1,6 @@ import React, {useCallback, useEffect, useRef, useState} from 'react' import styled from 'styled-components' -import Button, {ButtonPrimary, ButtonDanger, ButtonProps} from '../Button' +import Button, {ButtonPrimary, ButtonDanger, ButtonProps} from '../deprecated/Button' import Box from '../Box' import {get} from '../constants' import {useOnEscapePress, useProvidedRefOrCreate} from '../hooks' diff --git a/src/Dropdown.tsx b/src/Dropdown.tsx index fba007a1c38..34778895ac3 100644 --- a/src/Dropdown.tsx +++ b/src/Dropdown.tsx @@ -1,6 +1,6 @@ import React from 'react' import styled from 'styled-components' -import Button, {ButtonProps} from './Button' +import Button, {ButtonProps} from './deprecated/Button' import {get} from './constants' import Details, {DetailsProps} from './Details' import getDirectionStyles from './DropdownStyles' diff --git a/src/__tests__/AnchoredOverlay.test.tsx b/src/__tests__/AnchoredOverlay.test.tsx index 29f2ff6a377..91855bd1e62 100644 --- a/src/__tests__/AnchoredOverlay.test.tsx +++ b/src/__tests__/AnchoredOverlay.test.tsx @@ -4,7 +4,8 @@ import {behavesAsComponent, checkExports} from '../utils/testing' import {render as HTMLRender, cleanup, fireEvent} from '@testing-library/react' import {axe, toHaveNoViolations} from 'jest-axe' import 'babel-polyfill' -import {Button, SSRProvider} from '../index' +import {SSRProvider} from '../index' +import {Button} from '../deprecated' import theme from '../theme' import BaseStyles from '../BaseStyles' import {ThemeProvider} from '../ThemeProvider' diff --git a/src/__tests__/Button.test.tsx b/src/__tests__/Button.test.tsx index f4d1c9293ba..91fc4c36ce5 100644 --- a/src/__tests__/Button.test.tsx +++ b/src/__tests__/Button.test.tsx @@ -6,9 +6,9 @@ import { ButtonDanger, ButtonOutline, ButtonInvisible, - ButtonGroup, ButtonTableList -} from '..' +} from '../deprecated' +import {ButtonGroup} from '../' import {render, behavesAsComponent, checkExports} from '../utils/testing' import {render as HTMLRender, cleanup} from '@testing-library/react' import {axe, toHaveNoViolations} from 'jest-axe' @@ -21,16 +21,18 @@ function noop() {} describe('Button', () => { behavesAsComponent({Component: Button}) - checkExports('Button', { + checkExports('deprecated/Button', { default: Button, ButtonPrimary, ButtonDanger, ButtonOutline, ButtonInvisible, - ButtonGroup, ButtonTableList, ButtonClose }) + checkExports('ButtonGroup', { + default: ButtonGroup + }) it('renders a + + + + + + + +``` + +### Leading and Trailing icons + +In the previous component, we allowed icon components to be direct children. This results in a lot of custom styling for the icon components. +In the new one, we now have `leadinIcon` and `trailingIcon` properties. + +#### Before + +```jsx + +``` + +#### After + +```jsx + +``` + +### Icon buttons + +Icon only buttons are common usages in products. So we now have a component for the specific usecase + +#### Before + +```jsx + +``` + +#### After + +```jsx + +``` + +### Size property + +Earlier we used `variant` to mean size property. Now we have a new property called `size` which is more semantically correct. + +#### Before + +```jsx + +``` + +#### After + +```jsx + +``` From f096f3a7bd0ca394becba929b95ef602c675b4a9 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Tue, 1 Mar 2022 18:59:44 +1100 Subject: [PATCH 04/12] More changes from the checklist --- docs/content/Button.mdx | 4 +- docs/content/{drafts => }/IconButton.mdx | 3 - docs/content/{drafts => }/LinkButton.mdx | 4 - docs/content/deprecated/Buttons.mdx | 2 +- docs/content/migration-guide/Button.mdx | 99 ----------- .../src/@primer/gatsby-theme-doctocat/nav.yml | 16 +- src/__tests__/Button.test.tsx | 158 +++++++----------- src/__tests__/Button2.test.tsx | 98 ----------- src/__tests__/deprecated/Button.test.tsx | 130 ++++++++++++++ src/deprecated/ActionMenu.tsx | 2 +- 10 files changed, 205 insertions(+), 311 deletions(-) rename docs/content/{drafts => }/IconButton.mdx (95%) rename docs/content/{drafts => }/LinkButton.mdx (94%) delete mode 100644 docs/content/migration-guide/Button.mdx delete mode 100644 src/__tests__/Button2.test.tsx create mode 100644 src/__tests__/deprecated/Button.test.tsx diff --git a/docs/content/Button.mdx b/docs/content/Button.mdx index 67154dba84e..e3adc9f2921 100644 --- a/docs/content/Button.mdx +++ b/docs/content/Button.mdx @@ -1,6 +1,6 @@ --- -componentId: button_v2 -title: Button v2 +componentId: button +title: Button status: Alpha source: https://github.com/primer/react/tree/main/src/Button2 storybook: '/react/storybook?path=/story/composite-components-button2' diff --git a/docs/content/drafts/IconButton.mdx b/docs/content/IconButton.mdx similarity index 95% rename from docs/content/drafts/IconButton.mdx rename to docs/content/IconButton.mdx index 3d6c9e5c2c6..68409d6d40e 100644 --- a/docs/content/drafts/IconButton.mdx +++ b/docs/content/IconButton.mdx @@ -6,9 +6,6 @@ storybook: '/react/storybook?path=/story/composite-components-button2' description: An accessible button component with no text and only icon. --- -import {Props} from '../../src/props' -import {ComponentChecklist} from '../../src/component-checklist' - ## Usage ### Installation diff --git a/docs/content/drafts/LinkButton.mdx b/docs/content/LinkButton.mdx similarity index 94% rename from docs/content/drafts/LinkButton.mdx rename to docs/content/LinkButton.mdx index 23cad9811a5..4ba5ad8d208 100644 --- a/docs/content/drafts/LinkButton.mdx +++ b/docs/content/LinkButton.mdx @@ -6,10 +6,6 @@ storybook: '/react/storybook?path=/story/composite-components-button2' description: It is a combination of a button and link. Use this to make your link look like a button. --- -import {Props} from '../../src/props' -import {ComponentChecklist} from '../../src/component-checklist' -import {ArrowRightIcon} from '@primer/octicons-react' - ## Usage ### Installation diff --git a/docs/content/deprecated/Buttons.mdx b/docs/content/deprecated/Buttons.mdx index 5e3bc7983f1..a7d39755c7d 100644 --- a/docs/content/deprecated/Buttons.mdx +++ b/docs/content/deprecated/Buttons.mdx @@ -1,7 +1,7 @@ --- componentId: button title: Button -status: Alpha +status: deprecated source: https://github.com/primer/react/blob/main/src/Button storybook: '/react/storybook?path=/story/composite-components-button--default-button' --- diff --git a/docs/content/migration-guide/Button.mdx b/docs/content/migration-guide/Button.mdx deleted file mode 100644 index a33dd48a61a..00000000000 --- a/docs/content/migration-guide/Button.mdx +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Button migration guide ---- - -## Summary - -The new set of Button components brings a much needed update. -The older version was a set of seven different components. Each variant of the component had a separate component. -The guidelines to put in icons inside the buttons was also vague. With the new components, we now have a great guidance for common button usage. - -## Change list - -### Button variants - -We now support a variant property which takes values `primary`, `invisible`, `outline` and `danger` - -#### Before - -```jsx -import {ButtonPrimary, ButtonInvisible, ButtonOutline, ButtonDanger} from '@primer/react' - - Primary Button - - Invisible Button - - Outline Button - - Danger Button - -``` - -#### After - -```jsx -import {Button} from '@primer/react' - - - - - - - - - -``` - -### Leading and Trailing icons - -In the previous component, we allowed icon components to be direct children. This results in a lot of custom styling for the icon components. -In the new one, we now have `leadinIcon` and `trailingIcon` properties. - -#### Before - -```jsx - -``` - -#### After - -```jsx - -``` - -### Icon buttons - -Icon only buttons are common usages in products. So we now have a component for the specific usecase - -#### Before - -```jsx - -``` - -#### After - -```jsx - -``` - -### Size property - -Earlier we used `variant` to mean size property. Now we have a new property called `size` which is more semantically correct. - -#### Before - -```jsx - -``` - -#### After - -```jsx - -``` diff --git a/docs/src/@primer/gatsby-theme-doctocat/nav.yml b/docs/src/@primer/gatsby-theme-doctocat/nav.yml index c50f7f70dd0..4d42a6e8cfe 100644 --- a/docs/src/@primer/gatsby-theme-doctocat/nav.yml +++ b/docs/src/@primer/gatsby-theme-doctocat/nav.yml @@ -53,8 +53,8 @@ url: /BranchName - title: Breadcrumbs url: /Breadcrumbs - - title: Buttons - url: /Buttons + - title: Button + url: /Button - title: Checkbox url: /Checkbox - title: CheckboxGroup @@ -79,12 +79,16 @@ url: /Header - title: Heading url: /Heading + - title: IconButton + url: /IconButton - title: Label url: /Label - title: LabelGroup url: /LabelGroup - title: Link url: /Link + - title: LinkButton + url: /LinkButton - title: Overlay url: /Overlay - title: Pagehead @@ -141,12 +145,6 @@ url: /UnderlineNav - title: Drafts children: - - title: Button v2 - url: /drafts/Button2 - - title: LinkButton - url: /drafts/LinkButton - - title: IconButton - url: /drafts/IconButton - title: Deprecated children: - title: ActionList @@ -155,6 +153,8 @@ url: /deprecated/ActionMenu - title: BorderBox url: /deprecated/BorderBox + - title: Buttons + url: /deprecated/Buttons - title: Dialog url: /deprecated/Dialog - title: Dropdown diff --git a/src/__tests__/Button.test.tsx b/src/__tests__/Button.test.tsx index 91fc4c36ce5..4da60203806 100644 --- a/src/__tests__/Button.test.tsx +++ b/src/__tests__/Button.test.tsx @@ -1,130 +1,98 @@ import React from 'react' -import { - Button, - ButtonPrimary, - ButtonClose, - ButtonDanger, - ButtonOutline, - ButtonInvisible, - ButtonTableList -} from '../deprecated' -import {ButtonGroup} from '../' -import {render, behavesAsComponent, checkExports} from '../utils/testing' -import {render as HTMLRender, cleanup} from '@testing-library/react' +import {IconButton, Button} from '../Button' +import {behavesAsComponent} from '../utils/testing' +import {render, cleanup, fireEvent} from '@testing-library/react' import {axe, toHaveNoViolations} from 'jest-axe' import 'babel-polyfill' +import {SearchIcon} from '@primer/octicons-react' expect.extend(toHaveNoViolations) -// eslint-disable-next-line @typescript-eslint/no-empty-function -function noop() {} - describe('Button', () => { - behavesAsComponent({Component: Button}) - - checkExports('deprecated/Button', { - default: Button, - ButtonPrimary, - ButtonDanger, - ButtonOutline, - ButtonInvisible, - ButtonTableList, - ButtonClose - }) - checkExports('ButtonGroup', { - default: ButtonGroup - }) + behavesAsComponent({Component: Button, options: {skipAs: true}}) - it('renders a ) + const button = await container.findByRole('button') + expect(button.textContent).toEqual('Default') }) it('should have no axe violations', async () => { - const {container} = HTMLRender() + const {container} = render() const results = await axe(container) expect(results).toHaveNoViolations() cleanup() }) - it('preserves "onClick" prop', () => { - expect(render() + const button = await container.findByRole('button') + fireEvent.click(button) + expect(onClick).toHaveBeenCalledTimes(1) }) - it('respects the "disabled" prop', () => { - const item = render() + const button = await container.findByRole('button') + expect(button).toHaveStyleRule('width', '200px') }) - it('respects the "variant" prop', () => { - expect(render( + ) + const button = await container.findByRole('button') + expect(button.hasAttribute('disabled')).toEqual(true) + fireEvent.click(button) + expect(onClick).toHaveBeenCalledTimes(0) }) - it('renders correct disabled styles', () => { - const item = render() - expect(item).toMatchSnapshot() + it('respects the "variant" prop', async () => { + const container = render() + const button = await container.findByRole('button') + expect(button).toHaveStyleRule('font-size', '12px') }) -}) - -describe('ButtonDanger', () => { - behavesAsComponent({Component: ButtonDanger}) - it('renders a + ) + const button = await container.findByRole('button') + expect(button).toHaveStyleRule('font-size', '20px') }) - it('renders correct disabled styles', () => { - const item = render() - expect(item).toMatchSnapshot() + it('styles primary button appropriately', async () => { + const container = render() + const button = await container.findByRole('button') + expect(button).toMatchSnapshot() }) -}) - -describe('ButtonOutline', () => { - behavesAsComponent({Component: ButtonOutline}) - it('renders a ) + const button = await container.findByRole('button') + expect(button).toMatchSnapshot() }) - it('renders correct disabled styles', () => { - const item = render() - expect(item).toMatchSnapshot() + it('styles danger button appropriately', async () => { + const container = render() + const button = await container.findByRole('button') + expect(button).toMatchSnapshot() }) -}) -describe('ButtonInvisible', () => { - behavesAsComponent({Component: ButtonOutline}) - - it('renders a ) + const button = await container.findByRole('button') + expect(button).toMatchSnapshot() }) - it('renders correct disabled styles', () => { - const item = render() - expect(item).toMatchSnapshot() + it('styles icon only button to make it a square', async () => { + const container = render() + const IconOnlyButton = await container.findByRole('button') + expect(IconOnlyButton).toHaveStyleRule('padding-right', '8px') }) }) - -describe('ButtonGroup', () => { - behavesAsComponent({Component: ButtonGroup}) -}) - -describe('ButtonTableList', () => { - behavesAsComponent({Component: ButtonTableList}) -}) diff --git a/src/__tests__/Button2.test.tsx b/src/__tests__/Button2.test.tsx deleted file mode 100644 index 4da60203806..00000000000 --- a/src/__tests__/Button2.test.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import React from 'react' -import {IconButton, Button} from '../Button' -import {behavesAsComponent} from '../utils/testing' -import {render, cleanup, fireEvent} from '@testing-library/react' -import {axe, toHaveNoViolations} from 'jest-axe' -import 'babel-polyfill' -import {SearchIcon} from '@primer/octicons-react' -expect.extend(toHaveNoViolations) - -describe('Button', () => { - behavesAsComponent({Component: Button, options: {skipAs: true}}) - - it('renders a ) - const button = await container.findByRole('button') - expect(button.textContent).toEqual('Default') - }) - - it('should have no axe violations', async () => { - const {container} = render() - const results = await axe(container) - expect(results).toHaveNoViolations() - cleanup() - }) - - it('preserves "onClick" prop', async () => { - const onClick = jest.fn() - const container = render() - const button = await container.findByRole('button') - fireEvent.click(button) - expect(onClick).toHaveBeenCalledTimes(1) - }) - - it('respects width props', async () => { - const container = render() - const button = await container.findByRole('button') - expect(button).toHaveStyleRule('width', '200px') - }) - - it('respects the "disabled" prop', async () => { - const onClick = jest.fn() - const container = render( - - ) - const button = await container.findByRole('button') - expect(button.hasAttribute('disabled')).toEqual(true) - fireEvent.click(button) - expect(onClick).toHaveBeenCalledTimes(0) - }) - - it('respects the "variant" prop', async () => { - const container = render() - const button = await container.findByRole('button') - expect(button).toHaveStyleRule('font-size', '12px') - }) - - it('respects the "fontSize" prop over the "variant" prop', async () => { - const container = render( - - ) - const button = await container.findByRole('button') - expect(button).toHaveStyleRule('font-size', '20px') - }) - - it('styles primary button appropriately', async () => { - const container = render() - const button = await container.findByRole('button') - expect(button).toMatchSnapshot() - }) - - it('styles invisible button appropriately', async () => { - const container = render() - const button = await container.findByRole('button') - expect(button).toMatchSnapshot() - }) - - it('styles danger button appropriately', async () => { - const container = render() - const button = await container.findByRole('button') - expect(button).toMatchSnapshot() - }) - - it('styles outline button appropriately', async () => { - const container = render() - const button = await container.findByRole('button') - expect(button).toMatchSnapshot() - }) - - it('styles icon only button to make it a square', async () => { - const container = render() - const IconOnlyButton = await container.findByRole('button') - expect(IconOnlyButton).toHaveStyleRule('padding-right', '8px') - }) -}) diff --git a/src/__tests__/deprecated/Button.test.tsx b/src/__tests__/deprecated/Button.test.tsx new file mode 100644 index 00000000000..c1b5d6df449 --- /dev/null +++ b/src/__tests__/deprecated/Button.test.tsx @@ -0,0 +1,130 @@ +import React from 'react' +import { + Button, + ButtonPrimary, + ButtonClose, + ButtonDanger, + ButtonOutline, + ButtonInvisible, + ButtonTableList +} from '../../deprecated' +import {ButtonGroup} from '../..' +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) + +// eslint-disable-next-line @typescript-eslint/no-empty-function +function noop() {} + +describe('Button', () => { + behavesAsComponent({Component: Button}) + + checkExports('deprecated/Button', { + default: Button, + ButtonPrimary, + ButtonDanger, + ButtonOutline, + ButtonInvisible, + ButtonTableList, + ButtonClose + }) + checkExports('ButtonGroup', { + default: ButtonGroup + }) + + it('renders a ) + const results = await axe(container) + expect(results).toHaveNoViolations() + cleanup() + }) + + it('preserves "onClick" prop', () => { + expect(render( `; -exports[`ButtonInvisible renders consistently 1`] = ` +exports[`Button styles invisible button appropriately 1`] = ` .c0 { - position: relative; - display: inline-block; - padding: 6px 16px; + border-radius: 2; + border: 0; font-family: inherit; - font-weight: 600; + font-weight: bold; line-height: 20px; white-space: nowrap; vertical-align: middle; cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - border-radius: 6px; -webkit-appearance: none; -moz-appearance: none; appearance: none; - -webkit-text-decoration: none; - text-decoration: none; - text-align: center; - font-size: 14px; - color: #0969da; - border: 1px solid rgba(27,31,36,0.15); - background-color: #f6f8fa; - box-shadow: 0 1px 0 rgba(27,31,36,0.04); -} - -.c0:hover { - -webkit-text-decoration: none; - text-decoration: none; -} - -.c0:focus { - outline: none; -} - -.c0:disabled { - cursor: default; -} - -.c0:disabled svg { - opacity: 0.6; -} - -.c0:hover { - color: #ffffff; - background-color: #0969da; - border-color: rgba(27,31,36,0.15); - box-shadow: 0 1px 0 rgba(27,31,36,0.1); -} - -.c0:focus { - border-color: rgba(27,31,36,0.15); - box-shadow: 0 0 0 3px rgba(5,80,174,0.4); -} - -.c0:active { - color: #ffffff; - background-color: hsla(212,92%,42%,1); - box-shadow: inset 0 1px 0 rgba(0,33,85,0.2); - border-color: rgba(27,31,36,0.15); -} - -.c0:disabled { - color: rgba(9,105,218,0.5); - background-color: #f6f8fa; - border-color: rgba(27,31,36,0.15); -} - - `; -exports[`ButtonOutline renders correct disabled styles 1`] = ` +exports[`Button styles outline button appropriately 1`] = ` .c0 { - position: relative; - display: inline-block; - padding: 6px 16px; + border-radius: 2; + border: 1px solid; font-family: inherit; - font-weight: 600; + font-weight: bold; line-height: 20px; white-space: nowrap; vertical-align: middle; cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; - border-radius: 6px; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -webkit-text-decoration: none; text-decoration: none; text-align: center; + display: grid; + grid-template-areas: "leadingIcon text trailingIcon"; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 16px; + padding-right: 16px; font-size: 14px; - color: #0969da; - border: 1px solid rgba(27,31,36,0.15); - background-color: #f6f8fa; - box-shadow: 0 1px 0 rgba(27,31,36,0.04); -} - -.c0:hover { - -webkit-text-decoration: none; - text-decoration: none; + color: btn.outline.text; + box-shadow: undefined; } .c0:focus { @@ -609,147 +318,107 @@ exports[`ButtonOutline renders correct disabled styles 1`] = ` .c0:disabled { cursor: default; + color: btn.outline.disabledText; + background-color: btn.outline.disabledBg; + border-color: btn.border; +} + +.c0:disabled [data-component="ButtonCounter"] { + background-color: btn.outline.disabledCounterBg; } .c0:disabled svg { opacity: 0.6; } -.c0:hover { - color: #ffffff; - background-color: #0969da; - border-color: rgba(27,31,36,0.15); - box-shadow: 0 1px 0 rgba(27,31,36,0.1); +.c0 > :not(:last-child) { + margin-right: 8px; } -.c0:focus { - border-color: rgba(27,31,36,0.15); - box-shadow: 0 0 0 3px rgba(5,80,174,0.4); +.c0 [data-component="leadingIcon"] { + grid-area: leadingIcon; } -.c0:active { - color: #ffffff; - background-color: hsla(212,92%,42%,1); - box-shadow: inset 0 1px 0 rgba(0,33,85,0.2); - border-color: rgba(27,31,36,0.15); +.c0 [data-component="text"] { + grid-area: text; } -.c0:disabled { - color: rgba(9,105,218,0.5); - background-color: #f6f8fa; - border-color: rgba(27,31,36,0.15); +.c0 [data-component="trailingIcon"] { + grid-area: trailingIcon; } - `; -exports[`ButtonPrimary renders correct disabled styles 1`] = ` +exports[`Button styles primary button appropriately 1`] = ` .c0 { - position: relative; - display: inline-block; - padding: 6px 16px; + border-radius: 2; + border: 1px solid; + border-color: border.subtle; font-family: inherit; - font-weight: 600; + font-weight: bold; line-height: 20px; white-space: nowrap; vertical-align: middle; cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; - border-radius: 6px; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -webkit-text-decoration: none; text-decoration: none; text-align: center; + display: grid; + grid-template-areas: "leadingIcon text trailingIcon"; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 16px; + padding-right: 16px; font-size: 14px; - color: #ffffff; - border: 1px solid rgba(27,31,36,0.15); - background-color: #2da44e; - box-shadow: 0 1px 0 rgba(27,31,36,0.1); -} - -.c0:hover { - -webkit-text-decoration: none; - text-decoration: none; + color: btn.primary.text; + background-color: btn.primary.bg; + box-shadow: undefined; } .c0:focus { @@ -758,83 +427,57 @@ exports[`ButtonPrimary renders correct disabled styles 1`] = ` .c0:disabled { cursor: default; + color: btn.primary.disabledText; + background-color: btn.primary.disabledBg; } .c0:disabled svg { opacity: 0.6; } -.c0:hover { - background-color: #2c974b; - border-color: rgba(27,31,36,0.15); +.c0 > :not(:last-child) { + margin-right: 8px; } -.c0:focus { - border-color: rgba(27,31,36,0.15); - box-shadow: 0 0 0 3px rgba(45,164,78,0.4); +.c0 [data-component="leadingIcon"] { + grid-area: leadingIcon; } -.c0:active { - background-color: hsla(137,55%,36%,1); - box-shadow: inset 0 1px 0 rgba(0,45,17,0.2); +.c0 [data-component="text"] { + grid-area: text; } -.c0:disabled { - color: rgba(255,255,255,0.8); - background-color: #94d3a2; - border-color: rgba(27,31,36,0.15); +.c0 [data-component="trailingIcon"] { + grid-area: trailingIcon; } - `; diff --git a/src/__tests__/__snapshots__/Button2.test.tsx.snap b/src/__tests__/__snapshots__/Button2.test.tsx.snap deleted file mode 100644 index 4a558a6a82b..00000000000 --- a/src/__tests__/__snapshots__/Button2.test.tsx.snap +++ /dev/null @@ -1,483 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Button renders consistently 1`] = ` -.c0 { - border-radius: 6px; - border: 1px solid; - border-color: rgba(27,31,36,0.15); - font-family: inherit; - font-weight: 600; - line-height: 20px; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-text-decoration: none; - text-decoration: none; - text-align: center; - display: grid; - grid-template-areas: "leadingIcon text trailingIcon"; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 16px; - padding-right: 16px; - font-size: 14px; - color: #24292f; - background-color: #f6f8fa; - box-shadow: 0 1px 0 rgba(27,31,36,0.04),inset 0 1px 0 rgba(255,255,255,0.25); -} - -.c0:focus { - outline: none; -} - -.c0:disabled { - cursor: default; - color: #8c959f; - background-color: btn.disabledBg; -} - -.c0:disabled svg { - opacity: 0.6; -} - -.c0 > :not(:last-child) { - margin-right: 8px; -} - -.c0 [data-component="leadingIcon"] { - grid-area: leadingIcon; -} - -.c0 [data-component="text"] { - grid-area: text; -} - -.c0 [data-component="trailingIcon"] { - grid-area: trailingIcon; -} - -.c0 [data-component="ButtonCounter"] { - font-size: 14px; -} - -.c0:hover:not([disabled]) { - background-color: #f3f4f6; -} - -.c0:focus:not([disabled]) { - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); -} - -.c0:active:not([disabled]) { - background-color: hsla(220,14%,94%,1); - box-shadow: inset 0 0.15em 0.3em rgba(27,31,36,0.15); -} - - -`; - -exports[`Button styles invisible button appropriately 1`] = ` -.c0 { - border-radius: 2; - border: 0; - font-family: inherit; - font-weight: bold; - line-height: 20px; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-text-decoration: none; - text-decoration: none; - text-align: center; - display: grid; - grid-template-areas: "leadingIcon text trailingIcon"; - padding-top: 6px; - padding-bottom: 6px; - padding-left: 16px; - padding-right: 16px; - font-size: 14px; - color: accent.fg; - background-color: transparent; - box-shadow: none; -} - -.c0:focus { - outline: none; -} - -.c0:disabled { - cursor: default; - color: primer.fg.disabled; -} - -.c0:disabled svg { - opacity: 0.6; -} - -.c0 > :not(:last-child) { - margin-right: 8px; -} - -.c0 [data-component="leadingIcon"] { - grid-area: leadingIcon; -} - -.c0 [data-component="text"] { - grid-area: text; -} - -.c0 [data-component="trailingIcon"] { - grid-area: trailingIcon; -} - -.c0 [data-component="ButtonCounter"] { - font-size: 14px; -} - -.c0:hover:not([disabled]) { - background-color: btn.hoverBg; -} - -.c0:focus:not([disabled]) { - box-shadow: undefined; -} - -.c0:active:not([disabled]) { - background-color: btn.selectedBg; -} - - -`; - -exports[`Button styles outline button appropriately 1`] = ` -.c0 { - border-radius: 2; - border: 1px solid; - font-family: inherit; - font-weight: bold; - line-height: 20px; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-text-decoration: none; - text-decoration: none; - text-align: center; - display: grid; - grid-template-areas: "leadingIcon text trailingIcon"; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 16px; - padding-right: 16px; - font-size: 14px; - color: btn.outline.text; - box-shadow: undefined; -} - -.c0:focus { - outline: none; -} - -.c0:disabled { - cursor: default; - color: btn.outline.disabledText; - background-color: btn.outline.disabledBg; - border-color: btn.border; -} - -.c0:disabled [data-component="ButtonCounter"] { - background-color: btn.outline.disabledCounterBg; -} - -.c0:disabled svg { - opacity: 0.6; -} - -.c0 > :not(:last-child) { - margin-right: 8px; -} - -.c0 [data-component="leadingIcon"] { - grid-area: leadingIcon; -} - -.c0 [data-component="text"] { - grid-area: text; -} - -.c0 [data-component="trailingIcon"] { - grid-area: trailingIcon; -} - -.c0 [data-component="ButtonCounter"] { - font-size: 14px; - background-color: btn.outline.counterBg; - color: btn.outline.text; -} - -.c0:hover:not([disabled]) { - color: btn.outline.hoverText; - background-color: btn.outline.hoverBg; - border-color: outline.hoverBorder; - box-shadow: undefined; -} - -.c0:hover:not([disabled]) [data-component="ButtonCounter"] { - background-color: btn.outline.hoverCounterBg; - color: btn.outline.hoverText; -} - -.c0:focus:not([disabled]) { - border-color: btn.outline.focusBorder; - box-shadow: undefined; -} - -.c0:active:not([disabled]) { - color: btn.outline.selectedText; - background-color: btn.outline.selectedBg; - box-shadow: undefined; - border-color: btn.outline.selectedBorder; -} - - -`; - -exports[`Button styles primary button appropriately 1`] = ` -.c0 { - border-radius: 2; - border: 1px solid; - border-color: border.subtle; - font-family: inherit; - font-weight: bold; - line-height: 20px; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-text-decoration: none; - text-decoration: none; - text-align: center; - display: grid; - grid-template-areas: "leadingIcon text trailingIcon"; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 16px; - padding-right: 16px; - font-size: 14px; - color: btn.primary.text; - background-color: btn.primary.bg; - box-shadow: undefined; -} - -.c0:focus { - outline: none; -} - -.c0:disabled { - cursor: default; - color: btn.primary.disabledText; - background-color: btn.primary.disabledBg; -} - -.c0:disabled svg { - opacity: 0.6; -} - -.c0 > :not(:last-child) { - margin-right: 8px; -} - -.c0 [data-component="leadingIcon"] { - grid-area: leadingIcon; -} - -.c0 [data-component="text"] { - grid-area: text; -} - -.c0 [data-component="trailingIcon"] { - grid-area: trailingIcon; -} - -.c0 [data-component="ButtonCounter"] { - font-size: 14px; - background-color: btn.primary.counterBg; - color: btn.primary.text; -} - -.c0:hover:not([disabled]) { - color: btn.primary.hoverText; - background-color: btn.primary.hoverBg; -} - -.c0:focus:not([disabled]) { - box-shadow: undefined; -} - -.c0:active:not([disabled]) { - background-color: btn.primary.selectedBg; - box-shadow: undefined; -} - - -`; diff --git a/src/__tests__/deprecated/__snapshots__/Button.test.tsx.snap b/src/__tests__/deprecated/__snapshots__/Button.test.tsx.snap new file mode 100644 index 00000000000..db323e63e09 --- /dev/null +++ b/src/__tests__/deprecated/__snapshots__/Button.test.tsx.snap @@ -0,0 +1,840 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Button renders consistently 1`] = ` +.c0 { + position: relative; + display: inline-block; + padding: 6px 16px; + font-family: inherit; + font-weight: 600; + line-height: 20px; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-radius: 6px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-text-decoration: none; + text-decoration: none; + text-align: center; + font-size: 14px; + color: #24292f; + background-color: #f6f8fa; + border: 1px solid rgba(27,31,36,0.15); + box-shadow: 0 1px 0 rgba(27,31,36,0.04),inset 0 1px 0 rgba(255,255,255,0.25); +} + +.c0:hover { + -webkit-text-decoration: none; + text-decoration: none; +} + +.c0:focus { + outline: none; +} + +.c0:disabled { + cursor: default; +} + +.c0:disabled svg { + opacity: 0.6; +} + +.c0:hover { + background-color: #f3f4f6; + border-color: rgba(27,31,36,0.15); +} + +.c0:focus { + border-color: rgba(27,31,36,0.15); + box-shadow: 0 0 0 3px rgba(9,105,218,0.3); +} + +.c0:active { + background-color: hsla(220,14%,94%,1); + box-shadow: inset 0 0.15em 0.3em rgba(27,31,36,0.15); +} + +.c0:disabled { + color: #8c959f; + background-color: #f6f8fa; + border-color: rgba(27,31,36,0.15); +} + + Button danger diff --git a/src/stories/deprecated/Button.stories.tsx b/src/stories/deprecated/Button.stories.tsx index 9e61502c884..2b107c9fa79 100644 --- a/src/stories/deprecated/Button.stories.tsx +++ b/src/stories/deprecated/Button.stories.tsx @@ -16,7 +16,7 @@ import {ButtonBaseProps} from '../../deprecated/Button/ButtonBase' type StrictButtonStyleProps = ButtonStyleProps & {variant: ButtonBaseProps['variant']} export default { - title: 'Composite components/Button', + title: 'Deprecated components/Button', decorators: [ Story => { From 0c286b76ee5662e63865b481cffdd96317d4b6e3 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Tue, 1 Mar 2022 23:13:26 +1100 Subject: [PATCH 08/12] Create many-roses-hammer.md --- .changeset/many-roses-hammer.md | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .changeset/many-roses-hammer.md diff --git a/.changeset/many-roses-hammer.md b/.changeset/many-roses-hammer.md new file mode 100644 index 00000000000..fef5879b6cb --- /dev/null +++ b/.changeset/many-roses-hammer.md @@ -0,0 +1,89 @@ +--- +"@primer/react": patch +--- + +## Button deprecation + +The new set of Button components brings a much needed update. +The older version was a set of seven different components. Each variant of the component had a separate component. +The guidelines to put in icons inside the buttons was also vague. With the new components, we now have a great guidance for common button usage. + +## Change list + +### Button variants + +We now support a variant property which takes values `primary`, `invisible`, `outline` and `danger` + +#### Before + +```jsx +import {ButtonPrimary, ButtonInvisible, ButtonOutline, ButtonDanger} from '@primer/react' + Primary Button + Invisible Button + Outline Button + Danger Button +``` + +#### After + +```jsx +import {Button} from '@primer/react' + + + + +``` + +### Leading and Trailing icons + +In the previous component, we allowed icon components to be direct children. This results in a lot of custom styling for the icon components. +In the new one, we now have `leadinIcon` and `trailingIcon` properties. + +#### Before + +```jsx + +``` + +#### After + +```jsx + +``` + +### Icon buttons + +Icon only buttons are common usages in products. So we now have a component for the specific usecase + +#### Before + +```jsx + +``` + +#### After + +```jsx + +``` + +### Size property + +Earlier we used `variant` to mean size property. Now we have a new property called `size` which is more semantically correct. + +#### Before + +```jsx + +``` + +#### After + +```jsx + +``` From 0489b6a61ab814deabba373b965bb336e833513c Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Tue, 1 Mar 2022 23:20:47 +1100 Subject: [PATCH 09/12] Update .changeset/many-roses-hammer.md Co-authored-by: Rez --- .changeset/many-roses-hammer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/many-roses-hammer.md b/.changeset/many-roses-hammer.md index fef5879b6cb..d38cf8b076c 100644 --- a/.changeset/many-roses-hammer.md +++ b/.changeset/many-roses-hammer.md @@ -1,5 +1,5 @@ --- -"@primer/react": patch +"@primer/react": major --- ## Button deprecation From b11a858c72f269905242f489b2dd12ba2cd5c627 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Tue, 1 Mar 2022 23:22:45 +1100 Subject: [PATCH 10/12] Update many-roses-hammer.md --- .changeset/many-roses-hammer.md | 133 +++++++++++++++++++------------- 1 file changed, 81 insertions(+), 52 deletions(-) diff --git a/.changeset/many-roses-hammer.md b/.changeset/many-roses-hammer.md index d38cf8b076c..17c681ec3ea 100644 --- a/.changeset/many-roses-hammer.md +++ b/.changeset/many-roses-hammer.md @@ -1,89 +1,118 @@ --- -"@primer/react": major +'@primer/react': major --- - -## Button deprecation - -The new set of Button components brings a much needed update. -The older version was a set of seven different components. Each variant of the component had a separate component. -The guidelines to put in icons inside the buttons was also vague. With the new components, we now have a great guidance for common button usage. - -## Change list - -### Button variants - +### Button +A new set of `Button` components brings a much needed update. Previously to `v35`, `Button` was a set of seven independent components. In `v35`, we now have common `Button` usage guidelines and more convenient API. +#### Button variants We now support a variant property which takes values `primary`, `invisible`, `outline` and `danger` - -#### Before - + + + + + + + + +
Before (v34) After (v35)
```jsx -import {ButtonPrimary, ButtonInvisible, ButtonOutline, ButtonDanger} from '@primer/react' - Primary Button - Invisible Button - Outline Button - Danger Button + + Primary Button + + + Invisible Button + + + Outline Button + + + Danger Button + ``` - -#### After - + ```jsx -import {Button} from '@primer/react' - - - - +import { + Button +} from '@primer/react' + + + + ``` - +
### Leading and Trailing icons - In the previous component, we allowed icon components to be direct children. This results in a lot of custom styling for the icon components. In the new one, we now have `leadinIcon` and `trailingIcon` properties. - -#### Before - + + + + + + + + +
Before (v34) After (v35)
```jsx ``` - -#### After - + ```jsx ``` - +
### Icon buttons - Icon only buttons are common usages in products. So we now have a component for the specific usecase - -#### Before - + + + + + + + + +
Before (v34) After (v35)
```jsx ``` - -#### After - + ```jsx ``` - +
### Size property - Earlier we used `variant` to mean size property. Now we have a new property called `size` which is more semantically correct. - -#### Before - + + + + + + + + +
Before (v34) After (v35)
```jsx ``` - -#### After - + ```jsx ``` +
From c97fd6e8dfd7dbd930acd5ab37efffdd3d826dda Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Tue, 1 Mar 2022 23:24:34 +1100 Subject: [PATCH 11/12] Update many-roses-hammer.md --- .changeset/many-roses-hammer.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/.changeset/many-roses-hammer.md b/.changeset/many-roses-hammer.md index 17c681ec3ea..e701c15e217 100644 --- a/.changeset/many-roses-hammer.md +++ b/.changeset/many-roses-hammer.md @@ -1,16 +1,20 @@ --- '@primer/react': major --- -### Button +### Button deprecation + A new set of `Button` components brings a much needed update. Previously to `v35`, `Button` was a set of seven independent components. In `v35`, we now have common `Button` usage guidelines and more convenient API. + #### Button variants We now support a variant property which takes values `primary`, `invisible`, `outline` and `danger` +
Before (v34) After (v35)
+ ```jsx + ```jsx import { Button @@ -50,69 +55,91 @@ import { Danger Button ``` +
+ ### Leading and Trailing icons + In the previous component, we allowed icon components to be direct children. This results in a lot of custom styling for the icon components. In the new one, we now have `leadinIcon` and `trailingIcon` properties. +
Before (v34) After (v35)
+ ```jsx ``` + + ```jsx ``` +
+ ### Icon buttons + Icon only buttons are common usages in products. So we now have a component for the specific usecase +
Before (v34) After (v35)
+ ```jsx ``` + + ```jsx ``` +
+ ### Size property + Earlier we used `variant` to mean size property. Now we have a new property called `size` which is more semantically correct. +
Before (v34) After (v35)
+ ```jsx ``` + + ```jsx ``` +
From d8c962ee37c14161e6b05dd555573a376c492795 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Tue, 1 Mar 2022 23:27:36 +1100 Subject: [PATCH 12/12] Update many-roses-hammer.md --- .changeset/many-roses-hammer.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.changeset/many-roses-hammer.md b/.changeset/many-roses-hammer.md index e701c15e217..50bb79bc3f6 100644 --- a/.changeset/many-roses-hammer.md +++ b/.changeset/many-roses-hammer.md @@ -16,17 +16,16 @@ We now support a variant property which takes values `primary`, `invisible`, `ou ```jsx - - Primary Button + +import { ButtonPrimary, ButtonInvisible, + ButtonOutline, ButtonDanger } + from '@primer/react' + + + Primary Button - Invisible Button + Invisible Button Outline Button @@ -35,13 +34,14 @@ We now support a variant property which takes values `primary`, `invisible`, `ou Danger Button
``` + ```jsx -import { - Button -} from '@primer/react' + +import { Button } from '@primer/react' +