Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Button deprecation #1908

Merged
merged 12 commits into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions .changeset/many-roses-hammer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
"@primer/react": patch
pksjce marked this conversation as resolved.
Show resolved Hide resolved
---

## 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todo for later.. we'd want to make these tables, but we can do this in a follow up PR

import {ButtonPrimary, ButtonInvisible, ButtonOutline, ButtonDanger} from '@primer/react'
<ButtonPrimary>Primary Button</ButtonPrimary>
<ButtonInvisible>Invisible Button</ButtonInvisible>
<ButtonOutline>Outline Button</ButtonOutline>
<ButtonDanger>Danger Button</ButtonDanger>
```

#### After

```jsx
import {Button} from '@primer/react'
<Button variant="primary">Primary Button</Button>
<Button variant="invisible">Invisible Button</Button>
<Button variant="outline">Outline Button</Button>
<Button variant="danger">Danger Button</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

```jsx
<Button>
<SearchIcon />
Search
</Button>
```

#### After

```jsx
<Button leadingIcon={SearchIcon}>Search</Button>
```

### Icon buttons

Icon only buttons are common usages in products. So we now have a component for the specific usecase

#### Before

```jsx
<Button>
<XIcon />
</Button>
```

#### After

```jsx
<IconButton aria-label="Close button" icon={XIcon} />
```

### 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
<Button variant="small">Small button</Button>
```

#### After

```jsx
<Button size="small">Small button</Button>
```
6 changes: 2 additions & 4 deletions docs/content/drafts/Button2.mdx → docs/content/Button.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
---
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'
description: Use button for the main actions on a page or form.
---

import {Props} from '../../src/props'
import {ComponentChecklist} from '../../src/component-checklist'
import {Button, IconButton, LinkButton} from '@primer/react/drafts'

## Usage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 9 additions & 2 deletions docs/content/Buttons.mdx → docs/content/deprecated/Buttons.mdx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
---
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'
---

## Deprecation

Use [Button](/Button) instead.

For more info on the changes, have a look at the migration guide.
[Button migration guide](/migration-guide/Button)

`Button` is used for actions, like in forms, while `Link` is used for destinations, or moving from one page to another.

In special cases where you'd like to use a `<a>` styled like a Button, use `<Button as='a'>` and provide an `href`.
Expand All @@ -16,7 +23,7 @@ To create a button group, wrap `Button` elements in the `ButtonGroup` element. `

### Kitchen sink

```jsx live
```jsx live deprecated
<>
<Button>Button</Button>
<ButtonDanger>Button danger</ButtonDanger>
Expand Down
16 changes: 8 additions & 8 deletions docs/src/@primer/gatsby-theme-doctocat/nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
url: /BranchName
- title: Breadcrumbs
url: /Breadcrumbs
- title: Buttons
url: /Buttons
- title: Button
url: /Button
- title: Checkbox
url: /Checkbox
- title: CheckboxGroup
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -155,6 +153,8 @@
url: /deprecated/ActionMenu
- title: BorderBox
url: /deprecated/BorderBox
- title: Buttons
url: /deprecated/Buttons
- title: Dialog
url: /deprecated/Dialog
- title: Dropdown
Expand Down
2 changes: 1 addition & 1 deletion src/ActionMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
48 changes: 13 additions & 35 deletions src/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,17 @@
import styled from 'styled-components'
import {get} from '../constants'
import sx, {SxProp} from '../sx'
import {ComponentProps} from '../utils/types'
import ButtonBase, {ButtonBaseProps} from './ButtonBase'
import React, {forwardRef} from 'react'
import {ButtonProps} from './types'
import {ButtonBase} from './ButtonBase'

const Button = styled(ButtonBase)<ButtonBaseProps & SxProp>`
color: ${get('colors.btn.text')};
background-color: ${get('colors.btn.bg')};
border: 1px solid ${get('colors.btn.border')};
box-shadow: ${get('shadows.btn.shadow')}, ${get('shadows.btn.insetShadow')}};

&:hover {
background-color: ${get('colors.btn.hoverBg')};
border-color: ${get('colors.btn.hoverBorder')};
}

// focus must come before :active so that the active box shadow overrides
&:focus {
border-color: ${get('colors.btn.focusBorder')};
box-shadow: ${get('shadows.btn.focusShadow')};
}

&:active {
background-color: ${get('colors.btn.selectedBg')};
box-shadow: ${get('shadows.btn.shadowActive')};
}

&:disabled {
color: ${get('colors.primer.fg.disabled')};
background-color: ${get('colors.btn.bg')};
border-color: ${get('colors.btn.border')};
const ButtonComponent = forwardRef<HTMLButtonElement, ButtonProps>(
({children, ...props}, forwardedRef): JSX.Element => {
return (
<ButtonBase ref={forwardedRef} {...props} as="button">
{children}
</ButtonBase>
)
}
)

${sx};
`
ButtonComponent.displayName = 'Button'

export type ButtonProps = ComponentProps<typeof Button>
export default Button
export {ButtonComponent}
File renamed without changes.
71 changes: 37 additions & 34 deletions src/Button/ButtonBase.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
import styled from 'styled-components'
import {variant} from 'styled-system'
import {ComponentProps} from '../utils/types'
import buttonBaseStyles from './ButtonStyles'
import React, {ComponentPropsWithRef, forwardRef} from 'react'
import {ForwardRefComponent as PolymorphicForwardRefComponent} from '@radix-ui/react-polymorphic'
import Box from '../Box'
import {merge, SxProp} from '../sx'
import {useTheme} from '../ThemeProvider'
import {ButtonProps, StyledButton} from './types'
import {getVariantStyles, getSizeStyles, getButtonStyles} from './styles'

const variants = variant({
variants: {
small: {
p: '4px 12px',
fontSize: 0
},
medium: {
fontSize: 1
},
large: {
fontSize: 2,
p: '10px 20px'
const ButtonBase = forwardRef<HTMLElement, ButtonProps>(
({children, as: Component = 'button', sx: sxProp = {}, ...props}, forwardedRef): JSX.Element => {
const {leadingIcon: LeadingIcon, trailingIcon: TrailingIcon, variant = 'default', size = 'medium'} = props
const {theme} = useTheme()
const iconWrapStyles = {
display: 'inline-block'
}
const sxStyles = merge.all([
getButtonStyles(theme),
getSizeStyles(size, variant, false),
getVariantStyles(variant, theme),
sxProp as SxProp
])
return (
<StyledButton as={Component} sx={sxStyles} {...props} ref={forwardedRef}>
{LeadingIcon && (
<Box as="span" data-component="leadingIcon" sx={iconWrapStyles}>
<LeadingIcon />
</Box>
)}
{children && <span data-component="text">{children}</span>}
{TrailingIcon && (
<Box as="span" data-component="trailingIcon" sx={{...iconWrapStyles, ml: 2}}>
<TrailingIcon />
</Box>
)}
</StyledButton>
)
}
})
) as PolymorphicForwardRefComponent<'button' | 'a', ButtonProps>

type StyledButtonBaseProps = {
as?: 'button' | 'a' | 'summary' | 'input' | string | React.ReactType
variant?: 'small' | 'medium' | 'large'
}
export type ButtonBaseProps = ComponentPropsWithRef<typeof ButtonBase>

const ButtonBase = styled.button.attrs<StyledButtonBaseProps>(({disabled, onClick}) => ({
onClick: disabled ? undefined : onClick
}))<StyledButtonBaseProps>`
${buttonBaseStyles}
${variants}
`

ButtonBase.defaultProps = {
variant: 'medium'
}

export type ButtonBaseProps = ComponentProps<typeof ButtonBase>
export default ButtonBase
export {ButtonBase}
File renamed without changes.
File renamed without changes.
File renamed without changes.
26 changes: 10 additions & 16 deletions src/Button/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
export {default} from './Button'
export type {ButtonProps} from './Button'
export {default as ButtonDanger} from './ButtonDanger'
export type {ButtonDangerProps} from './ButtonDanger'
export {default as ButtonGroup} from './ButtonGroup'
export type {ButtonGroupProps} from './ButtonGroup'
export {default as ButtonOutline} from './ButtonOutline'
export type {ButtonOutlineProps} from './ButtonOutline'
export {default as ButtonPrimary} from './ButtonPrimary'
export type {ButtonPrimaryProps} from './ButtonPrimary'
export {default as ButtonInvisible} from './ButtonInvisible'
export type {ButtonInvisibleProps} from './ButtonInvisible'
export {default as ButtonTableList} from './ButtonTableList'
export type {ButtonTableListProps} from './ButtonTableList'
export {default as ButtonClose} from './ButtonClose'
export type {ButtonCloseProps} from './ButtonClose'
import {ButtonComponent} from './Button'
import {Counter} from './ButtonCounter'
import {IconButton} from './IconButton'
import {LinkButton} from './LinkButton'
export type {ButtonProps, IconButtonProps} from './types'
export {IconButton, LinkButton}

export const Button = Object.assign(ButtonComponent, {
Counter
})
File renamed without changes.
File renamed without changes.
17 changes: 0 additions & 17 deletions src/Button2/Button.tsx

This file was deleted.

Loading