From edb4de3d9d26b004e3b6b307c12ecfb168e37a09 Mon Sep 17 00:00:00 2001 From: Laliq <105340174+martalalik@users.noreply.github.com> Date: Wed, 24 Aug 2022 15:02:23 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20=20=20Add=20ButtonGroup=20to=20S?= =?UTF-8?q?torybook=20(#2420)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 📝 Update Usage * 📝 Add ButtonGroup * ✏️ Fix typo * 📝 Add Introduction * ✨ Add vertical prop & story * 🚧 Add SplitButton * ✨ Add role to Group * 💄 Fix menu btn position * 💄 Update group style * ♿️ Add aria-label & a11y description * ♿️ Update a11y description * 📝 Update component name from Group to ButtonGroup * 💄 Change display * 💄 Update display to flex-inline * 🎨 Move ButtonGroup under Button * ♿️ Add aria-label * ✏️ Fix typo --- .../src/components/Button/Button.docs.mdx | 78 +++++++--- .../src/components/Button/Button.stories.tsx | 135 +++++++++++++++--- .../ButtonGroup/ButtonGroup.tokens.ts} | 0 .../Button/ButtonGroup/ButtonGroup.tsx | 68 +++++++++ .../components/Button/ButtonGroup/index.ts | 1 + .../src/components/Button/index.ts | 15 +- .../src/components/Group/Group.tsx | 44 ------ .../src/components/Group/index.ts | 1 - 8 files changed, 257 insertions(+), 85 deletions(-) rename packages/eds-core-react/src/components/{Group/Group.tokens.ts => Button/ButtonGroup/ButtonGroup.tokens.ts} (100%) create mode 100644 packages/eds-core-react/src/components/Button/ButtonGroup/ButtonGroup.tsx create mode 100644 packages/eds-core-react/src/components/Button/ButtonGroup/index.ts delete mode 100644 packages/eds-core-react/src/components/Group/Group.tsx delete mode 100644 packages/eds-core-react/src/components/Group/index.ts diff --git a/packages/eds-core-react/src/components/Button/Button.docs.mdx b/packages/eds-core-react/src/components/Button/Button.docs.mdx index 919e5375d6..352491e439 100644 --- a/packages/eds-core-react/src/components/Button/Button.docs.mdx +++ b/packages/eds-core-react/src/components/Button/Button.docs.mdx @@ -1,7 +1,6 @@ import { Story, PropsTable, Links } from './../../../.storybook/components' -import { Button } from '.' - +import { Button } from '.' # Button Allows users to take action with a single click or tap. @@ -26,45 +25,62 @@ import { Button } from '@equinor/eds-core-react' ``` +### Using the 'as' prop to render as another component + +The `as` prop allows you to render the `Button` as another html element or even react component. + +```tsx + +``` +This is especially useful if you want to use the `Button` as as a navigation component for a third party routing library such as react-router. + +```tsx +import { Link } from "react-router-dom" +import { Button } from '@equinor/eds-core-react' + + +``` + ## Examples ### Basic - The `Button` come with four variants; `contained`, `outlined`, `ghost` and `ghost_icon`. + ### Icon button - The `ghost_icon` & `contained_icon`variant is meant for standalone icon buttons using the `` component. Make sure to defined `aria-label` with descriptive text of `Button` interaction. + ### Color + ### Hierarchy - Use variants to differentiate the hierarchy.
  • Contained - being high-emphasis.
  • Outlined - being medium-emphasis.
  • Ghost - being low-emphasis.
+ ### File upload - Example of how to do file upload button. Please note this demo only works in Storybook Canvas (isolated example only). + ### Progress button - Use the `Progress` component if you need progress indication on a button. + ### All - Example All button combinations. + ### Full width @@ -72,22 +88,48 @@ Example All button combinations. ### Compact - Compact `Button` using `EdsProvider`. + -### Using the 'as' prop to render as another component +## Button.Group +Is used to group related buttons. -The `as` prop allows you to render the `Button` as another html element or even react component. +### Usage +The buttons can be grouped by wrapping them with the `Button.Group` component. ```tsx - -``` -This is especially useful if you want to use the `Button` as as a navigation component for a third party routing library such as react-router. - -```tsx -import { Link } from "react-router-dom" import { Button } from '@equinor/eds-core-react' - + + + + + ``` + +### Accessibility + +#### ARIA +
    +
  • Button.Group has role="group".
  • +
  • You should provide an accessible label with aria-label="label", aria-labelledby="id" or <label>.
  • +
+ +## Examples + +### Horizontal +The `Button.Group` is displayed horizontally by default. + + + +### Vertical +The `Button.Group` can be displayed vertically using the `vertical` prop. + + + +### Split +`Button.Group` can also be used to create a split button.
+The dropdown can change the button action (as in this example) or be used to immediately trigger a related action. + + \ No newline at end of file diff --git a/packages/eds-core-react/src/components/Button/Button.stories.tsx b/packages/eds-core-react/src/components/Button/Button.stories.tsx index 9149c69038..a2a7cca8c4 100644 --- a/packages/eds-core-react/src/components/Button/Button.stories.tsx +++ b/packages/eds-core-react/src/components/Button/Button.stories.tsx @@ -1,16 +1,18 @@ import { useState, useEffect } from 'react' +import { action } from '@storybook/addon-actions' import { Button, - Icon, ButtonProps, + ButtonGroupProps, + Icon, EdsProvider, Density, + Menu, Progress, } from '../..' import { Story, ComponentMeta } from '@storybook/react' import { menu, add, save } from '@equinor/eds-icons' import { Stack } from './../../../.storybook/components' -// import { Group } from '../Group' import page from './Button.docs.mdx' export default { @@ -254,30 +256,30 @@ export const FullWidth: Story = () => ( - - - - - - - - @@ -305,9 +307,15 @@ export const Compact: Story = () => { - + + + + + + ) } @@ -319,13 +327,98 @@ Compact.decorators = [ ), ] -// export const ButtonGroup: Story = () => ( -// -// -// -// -// -// -// -// -// ) +export const GroupHorizontal: Story = () => ( + + + + + + +) +GroupHorizontal.decorators = [ + (Story) => ( + + + + ), +] + +export const GroupVertical: Story = () => ( + + + + + + +) +GroupVertical.decorators = [ + (Story) => ( + + + + ), +] + +export const GroupSplit: Story = () => { + const options = ['Create task', 'Update task', 'Delete task'] + const [isOpen, setIsOpen] = useState(false) + const [anchorEl, setAnchorEl] = useState(null) + const [selectedIndex, setSelectedIndex] = useState(0) + + const handleMenuItemClick = (event: React.MouseEvent, index: number) => { + action('click')(event) + event.stopPropagation() + setSelectedIndex(index) + } + + const openMenu = () => { + setIsOpen(true) + } + + const closeMenu = () => { + setIsOpen(false) + } + + return ( + + + + + {options.map((option, index) => ( + + handleMenuItemClick(event, index) + } + > + {option} + + ))} + + + ) +} +GroupSplit.decorators = [ + (Story) => ( + + + + ), +] diff --git a/packages/eds-core-react/src/components/Group/Group.tokens.ts b/packages/eds-core-react/src/components/Button/ButtonGroup/ButtonGroup.tokens.ts similarity index 100% rename from packages/eds-core-react/src/components/Group/Group.tokens.ts rename to packages/eds-core-react/src/components/Button/ButtonGroup/ButtonGroup.tokens.ts diff --git a/packages/eds-core-react/src/components/Button/ButtonGroup/ButtonGroup.tsx b/packages/eds-core-react/src/components/Button/ButtonGroup/ButtonGroup.tsx new file mode 100644 index 0000000000..79b52b5777 --- /dev/null +++ b/packages/eds-core-react/src/components/Button/ButtonGroup/ButtonGroup.tsx @@ -0,0 +1,68 @@ +import { forwardRef, HTMLAttributes } from 'react' +import styled, { css } from 'styled-components' +import { group as tokens } from './ButtonGroup.tokens' + +const { border } = tokens + +export type ButtonGroupProps = { + /** Display ButtonGroup vertically. */ + vertical?: boolean +} & HTMLAttributes + +const radius = border.type === 'border' && border.radius + +const ButtonGroupBase = styled.div` + display: inline-flex; + > * { + border-radius: 0; + @media (hover: hover) and (pointer: fine) { + &:hover { + border-radius: 0; + } + } + } + ${({ vertical }) => + vertical + ? css` + flex-direction: column; + > :first-child { + border-top-left-radius: ${radius}; + border-top-right-radius: ${radius}; + } + > :last-child { + border-bottom-left-radius: ${radius}; + border-bottom-right-radius: ${radius}; + } + > :not(:last-child) { + border-bottom: none; + } + ` + : css` + > :first-child { + border-top-left-radius: ${radius}; + border-bottom-left-radius: ${radius}; + } + > :last-child { + border-top-right-radius: ${radius}; + border-bottom-right-radius: ${radius}; + } + > :not(:last-child) { + border-right: none; + } + `} +` + +export const ButtonGroup = forwardRef( + function ButtonGroup({ children, vertical, ...rest }, ref) { + const props = { + ref, + vertical, + ...rest, + } + return ( + + {children} + + ) + }, +) diff --git a/packages/eds-core-react/src/components/Button/ButtonGroup/index.ts b/packages/eds-core-react/src/components/Button/ButtonGroup/index.ts new file mode 100644 index 0000000000..d22d23bfc3 --- /dev/null +++ b/packages/eds-core-react/src/components/Button/ButtonGroup/index.ts @@ -0,0 +1 @@ +export * from './ButtonGroup' diff --git a/packages/eds-core-react/src/components/Button/index.ts b/packages/eds-core-react/src/components/Button/index.ts index 8486fd6d62..60930ef5bf 100644 --- a/packages/eds-core-react/src/components/Button/index.ts +++ b/packages/eds-core-react/src/components/Button/index.ts @@ -1 +1,14 @@ -export * from './Button' +import { Button as ButtonWrapper, ButtonProps } from './Button' +import { ButtonGroup, ButtonGroupProps } from './ButtonGroup/ButtonGroup' + +type ButtonCompoundProps = typeof ButtonWrapper & { + Group: typeof ButtonGroup +} + +const Button = ButtonWrapper as ButtonCompoundProps +Button.Group = ButtonGroup + +Button.Group.displayName = 'Button.Group' + +export { Button } +export type { ButtonProps, ButtonGroupProps } diff --git a/packages/eds-core-react/src/components/Group/Group.tsx b/packages/eds-core-react/src/components/Group/Group.tsx deleted file mode 100644 index cd3eb90761..0000000000 --- a/packages/eds-core-react/src/components/Group/Group.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { forwardRef } from 'react' -import styled, { css } from 'styled-components' -import { group as tokens } from './Group.tokens' - -const { border } = tokens - -const GroupBase = styled.div(() => { - const radius = border.type === 'border' && border.radius - - return css` - > * { - border-radius: 0; - @media (hover: hover) and (pointer: fine) { - &:hover { - border-radius: 0; - } - } - } - > :first-child { - border-top-left-radius: ${radius}; - border-bottom-left-radius: ${radius}; - } - > :last-child { - border-top-right-radius: ${radius}; - border-bottom-right-radius: ${radius}; - } - > :not(:last-child) { - border-right: none; - } - ` -}) - -export type GroupProps = React.HTMLAttributes - -export const Group = forwardRef(function Group( - { children, ...rest }, - ref, -) { - return ( - - {children} - - ) -}) diff --git a/packages/eds-core-react/src/components/Group/index.ts b/packages/eds-core-react/src/components/Group/index.ts deleted file mode 100644 index e3ad05435d..0000000000 --- a/packages/eds-core-react/src/components/Group/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Group'