diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index d912b269c735..f823f3823373 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -102,6 +102,8 @@ Map { "kind": "primary", "size": "default", "tabIndex": 0, + "tooltipAlignment": "center", + "tooltipPosition": "top", "type": "button", }, "displayName": "Button", diff --git a/packages/react/src/components/Button/Button-story.js b/packages/react/src/components/Button/Button-story.js index 1f29feb8279a..b32c2cadae02 100644 --- a/packages/react/src/components/Button/Button-story.js +++ b/packages/react/src/components/Button/Button-story.js @@ -6,7 +6,6 @@ */ import React from 'react'; -import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { withKnobs, boolean, select, text } from '@storybook/addon-knobs'; import { iconAddSolid, iconSearch } from 'carbon-icons'; @@ -14,6 +13,7 @@ import { Add16, AddFilled16, Search16 } from '@carbon/icons-react'; import Button from '../Button'; import ButtonSkeleton from '../Button/Button.Skeleton'; import ButtonSet from '../ButtonSet'; +import mdx from './Button.mdx'; const icons = { None: 'None', @@ -62,7 +62,13 @@ const props = { }; }, iconOnly: () => { - const iconToUse = iconMap[select('Icon (icon)', icons, 'Add16')]; + let iconToUse; + + if (iconMap[select('Icon (icon)', icons, 'Add16')] == undefined) { + iconToUse = Add16; + } else { + iconToUse = iconMap[select('Icon (icon)', icons, 'Add16')]; + } return { className: 'some-class', kind: select( @@ -114,90 +120,65 @@ const props = { }, }; -Button.displayName = 'Button'; - -const CustomLink = ({ children, href, ...other }) => ( - - {children} - -); - -storiesOf('Button', module) - .addParameters({ +export default { + title: 'Button', + decorators: [withKnobs], + parameters: { component: Button, subcomponents: { + ButtonSet, ButtonSkeleton, }, - }) - .addDecorator(withKnobs) - .add( - 'Default', - () => { - const regularProps = props.regular(); - return ( -
- -   - -   - -   - -
- ); + docs: { + page: mdx, }, - { - info: { - text: ` - Buttons are used to initialize an action, either in the background or - foreground of an experience. - - There are several kinds of buttons. + }, +}; - Primary buttons should be used for the principle call to action - on the page. +export const _Default = () => { + return ; +}; - Secondary buttons should be used for secondary actions on each page. +_Default.story = { + name: 'Button', +}; - Danger buttons should be used for a negative action (such as Delete) on the page. +export const Secondary = () => { + return ; +}; - Modify the behavior of the button by changing its event properties. +export const Tertiary = () => { + return ; +}; - Field buttons may be use directly next to an input element, to visually align their heights. +export const Danger = () => { + return ; +}; - Small buttons may be used when there is not enough space for a - regular sized button. This issue is most found in tables. Small button should have three words - or less. +export const Ghost = () => { + return ; +}; - When words are not enough, icons can be used in buttons to better communicate what the button does. Icons are - always paired with text. - `, - }, - } - ) - .add('Icon-only buttons', () => +   + + +
- ); - }, - { - info: { - text: ` - When an action required by the user has more than one option, always use a negative action button (secondary) paired with a positive action button (primary) in that order. Negative action buttons will be on the left. Positive action buttons should be on the right. When these two types buttons are paired in the correct order, they will automatically space themselves apart. - `, - }, - } - ) - .add( - 'skeleton', - () => ( -
- -   - -   -
- ), - { - info: { - text: ` - Placeholder skeleton state to use when content is loading. - `, - }, - } + ); +}; + +export const IconButton = () => + + + ); +}; + +export const Skeleton = () => ( +
+ +   + +
+); diff --git a/packages/react/src/components/Button/Button.js b/packages/react/src/components/Button/Button.js index 8d13c0dfd335..c5b5baf7c5e9 100644 --- a/packages/react/src/components/Button/Button.js +++ b/packages/react/src/components/Button/Button.js @@ -206,6 +206,8 @@ Button.defaultProps = { disabled: false, kind: 'primary', size: 'default', + tooltipAlignment: 'center', + tooltipPosition: 'top', }; export default Button; diff --git a/packages/react/src/components/Button/Button.mdx b/packages/react/src/components/Button/Button.mdx new file mode 100644 index 000000000000..f8f0e668b247 --- /dev/null +++ b/packages/react/src/components/Button/Button.mdx @@ -0,0 +1,308 @@ +import { Story, Props, Source, Preview } from '@storybook/addon-docs/blocks'; +import { withKnobs, boolean, select, text } from '@storybook/addon-knobs'; +import * as stories from './Button-story.js'; +import Button from '../Button'; +import ButtonSet from '../ButtonSet'; +import { Add16, Delete16 } from '@carbon/icons-react'; + +# Button + + + + +## Table of Contents + +- [Overview](#overview) +- [Skeleton state](#skeleton-state) +- [Component API](#component-api) +- [References](#references) +- [Feedback](#feedback) + + + +## Overview + +Buttons are clickable elements that are used to trigger actions. They +communicate calls to action to the user and allow users to interact with pages +in a variety of ways. `Button` labels express what action will occur when the +user interacts with it. + + + + + + + + + +## Icon-only Buttons + +Icon buttons allow users to take actions, and make choices, with a single tap. +Icon buttons can take the form of any of the five types (Primary, Secondary, +Tertiary, Danger and Ghost) but most commonly will be styled as primary or ghost +buttons. + + + + + +## Set of Buttons + +You can wrap two `Button` elements in a `ButtonSet` when an action required by +the user has more than one option. Always use a negative action button +(secondary) paired with a positive action button (primary) in that order. +Negative action buttons will be on the left. Positive action buttons should be +on the right. When these two types buttons are paired in the correct order, they +will automatically space themselves apart. + + + + + +## Skeleton state + +You can use the `ButtonSkeleton` component to render a skeleton variant of a +button. This is useful to display on initial page load to indicate to users that +content is being loaded. + + + + + +## Component API + + + +Additional props passed into `Button` will be forwarded along to the underlying +button element. + +### Button `as` + +This prop allows you to specify a different element to be rendered as a +`Button`. You may also need to add a [role](#button-role) for accessibility if +an element other than a `button` is rendered. + +```jsx + +``` + +### Button `className` + +The className prop passed into `Button` will be forwarded along to the +underlying `Button` element. This is useful for specifying a custom class name +for layout. + +```jsx + +``` + +### Button `hasIconOnly` + +Use this prop to render the icon-only variant of `Button`. First you'll pass in +the `renderIcon` prop to tell the `Button` which icon to render. Next, you'll +need to specify the `iconDescription` ([read more](#button-icondescription)), +which is used to populate the tooltip that is shown when the icon button is +interacted with, as well as internal `aria-label` for screen-readers. Lastly, +you can configure both the `tooltipAlignment` +([read more](#button-tooltipalignment)) and `tooltipPosition` +([read more](#button-tooltipposition)) props to tell the `Button` where your +tooltip should be rendered. These props default to `center` and `bottom`, +respectively. + + + +```jsx + +``` + +### Button `iconDescription` + +If using the `hasIconOnly` prop, `iconDescription` becomes a required prop for +accessibility reasons. The text provided here populates the internal +`aria-label` tag on the icon, as well as provides text to be shown when the icon +button is interacted with. + +```jsx + + +```jsx + + + + + +``` + +### Button `renderIcon` + +This prop is used to tell `Button` which icon should be rendered inside the +button. Before you pass in the icon, you'll need to import the icon(s) you would +like to render, like so: + +```js +import { Add16, Delete16 } from '@carbon/icons-react'; +``` + +Once the icons are imported, you can pass them directly in to the `Button` +component. Keep in mind, you will also need to add an `iconDescription` to help +with screen-reader support if you use the `renderIcon` prop. If you are trying +to render icon-only buttons, please refer to the section on the +[hasIconOnly](#button-hasicononly) prop + + + +```jsx + + +``` + +### Button `role` + +If you use the [as](#button-as) prop to render a non-button as a button, you may +need to add a `role` for accessibility reasons. Adding `role="button"` will make +an element appear as a button control to a screen reader. Check out the +[References](#references) section for more information. + + + +```jsx + +``` + +### Button `size` + +This prop specifies which size the `Button` should be rendered at. Valid values +are `field`, `small`, and `default`. If no `size` is specified, it renders as +`default`. + + + +```jsx + + + +``` + +### Button `tooltipAlignment` + +The `tooltipAlignment` prop is used to change where the tooltip text and caret +is rendered in relation to the `Button`. Accepted options are `start`, `center`, +and `end`. The default alignment is `center`. + + + + + +```jsx + + + + +``` + +## References + +- [MDN: ARIA button role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role) +- [W3: Role attribute](https://www.w3.org/WAI/PF/HTML/wiki/RoleAttribute) +- [W3: ARIA button role example](https://www.w3.org/TR/2016/WD-wai-aria-practices-1.1-20160317/examples/button/button.html) + +## Feedback + +Help us improve these docs by +[editing this file on GitHub](https://github.com/carbon-design-system/carbon/edit/master/packages/react/src/components/Accordion/Accordion.stories.mdx) + +``` + +``` diff --git a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap index e4b9f7388dff..d72b44f0bdef 100644 --- a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap +++ b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap @@ -1891,6 +1891,8 @@ exports[`DataTable should render 1`] = ` onClick={[MockFunction]} size="small" tabIndex={0} + tooltipAlignment="center" + tooltipPosition="top" type="button" > Add new @@ -2053,6 +2055,8 @@ exports[`DataTable should render 1`] = ` } size="default" tabIndex={0} + tooltipAlignment="center" + tooltipPosition="top" type="button" >