From 2d5f4cfb1e5c650696831a5c2c660c57e6a54f85 Mon Sep 17 00:00:00 2001 From: Simon Finney Date: Tue, 17 Aug 2021 17:05:06 +0100 Subject: [PATCH] feat(toolbar): add `Toolbar`, `ToolbarButton`, and `ToolbarGroup` components (#1103) * feat(toolbar): add `Toolbar`, `ToolbarButton`, and `ToolbarGroup` * build(toolbar): add `ToolbarButton`, and `ToolbarGroup` to canary * docs(storybook): use Story helpers for naming * chore: merge `main` into `67/toolbar` * chore: revert `REVIEWERS_GUIDELINES.md` * fix(toolbar): add border style * chore(toolbar): update styles, story * test(toolbar): add tests to validate props * test(toolbar): add shared specs * test(toolbar): add shared specs * docs(toolbar): add `Dropdown` to example * docs(toolbar): fix Storybook order Co-authored-by: Dave Clark Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../src/components/Toolbar/Toolbar.js | 43 +++++++++ .../src/components/Toolbar/Toolbar.mdx | 26 +++++ .../src/components/Toolbar/Toolbar.stories.js | 95 +++++++++++++++++++ .../src/components/Toolbar/Toolbar.test.js | 59 ++++++++++++ .../src/components/Toolbar/ToolbarButton.js | 21 ++++ .../src/components/Toolbar/ToolbarGroup.js | 40 ++++++++ .../src/components/Toolbar/_index.scss | 8 ++ .../src/components/Toolbar/_toolbar.scss | 48 ++++++++++ .../src/components/Toolbar/index.js | 10 ++ .../src/components/_index.scss | 1 + .../cloud-cognitive/src/components/index.js | 3 +- .../src/global/js/package-settings.js | 3 + .../src/global/js/utils/story-helper.js | 1 + 13 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 packages/cloud-cognitive/src/components/Toolbar/Toolbar.js create mode 100644 packages/cloud-cognitive/src/components/Toolbar/Toolbar.mdx create mode 100644 packages/cloud-cognitive/src/components/Toolbar/Toolbar.stories.js create mode 100644 packages/cloud-cognitive/src/components/Toolbar/Toolbar.test.js create mode 100644 packages/cloud-cognitive/src/components/Toolbar/ToolbarButton.js create mode 100644 packages/cloud-cognitive/src/components/Toolbar/ToolbarGroup.js create mode 100644 packages/cloud-cognitive/src/components/Toolbar/_index.scss create mode 100644 packages/cloud-cognitive/src/components/Toolbar/_toolbar.scss create mode 100644 packages/cloud-cognitive/src/components/Toolbar/index.js diff --git a/packages/cloud-cognitive/src/components/Toolbar/Toolbar.js b/packages/cloud-cognitive/src/components/Toolbar/Toolbar.js new file mode 100644 index 0000000000..1e282a9000 --- /dev/null +++ b/packages/cloud-cognitive/src/components/Toolbar/Toolbar.js @@ -0,0 +1,43 @@ +/** + * Copyright IBM Corp. 2021, 2021 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import cx from 'classnames'; +import { node, string } from 'prop-types'; +import React, { forwardRef } from 'react'; + +import { pkg } from '../../settings'; + +const { checkComponentEnabled, prefix } = pkg; +const blockClass = `${prefix}--toolbar`; + +/** Toolbars are a collection of action items that organize a program’s interaction patterns into a series of closely related commands. */ +let Toolbar = forwardRef(({ children, className, ...rest }, ref) => { + return ( +
+ {children} +
+ ); +}); + +const componentName = 'Toolbar'; +Toolbar.displayName = componentName; + +Toolbar.propTypes = { + /** Provide the content of the `Toolbar` */ + children: node.isRequired, + + /** Provide an optional class to be applied to the containing node */ + className: string, +}; + +Toolbar = checkComponentEnabled(Toolbar, componentName); + +export { blockClass, Toolbar }; diff --git a/packages/cloud-cognitive/src/components/Toolbar/Toolbar.mdx b/packages/cloud-cognitive/src/components/Toolbar/Toolbar.mdx new file mode 100644 index 0000000000..0b90f7a693 --- /dev/null +++ b/packages/cloud-cognitive/src/components/Toolbar/Toolbar.mdx @@ -0,0 +1,26 @@ +import { ArgsTable, Preview, Story } from '@storybook/addon-docs/blocks'; + +import { getStorybookSlug } from '../../../config'; +import { pkg } from '../../settings'; + +import { Toolbar } from '.'; + +# Toolbar + +## Table of Contents + +- [Overview](#overview) +- [Component API](#component-api) + +## Overview + +A toolbar is a collection of action items that organizes a program’s interaction +patterns into a series of closely related commands. + + + + + +## Component API + + diff --git a/packages/cloud-cognitive/src/components/Toolbar/Toolbar.stories.js b/packages/cloud-cognitive/src/components/Toolbar/Toolbar.stories.js new file mode 100644 index 0000000000..142601e82d --- /dev/null +++ b/packages/cloud-cognitive/src/components/Toolbar/Toolbar.stories.js @@ -0,0 +1,95 @@ +/** + * Copyright IBM Corp. 2021, 2021 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { + AlignHorizontalCenter16, + Minimize16, + Printer16, + Redo16, + Save16, + Share16, + Undo16, + Upload16, + ZoomIn16, + ZoomOut16, +} from '@carbon/icons-react'; + +import { + Dropdown, + OverflowMenu, + OverflowMenuItem, +} from 'carbon-components-react'; + +import React, { useState } from 'react'; + +import { getStoryTitle } from '../../global/js/utils/story-helper'; + +import { Toolbar, ToolbarButton, ToolbarGroup } from '../..'; +import mdx from './Toolbar.mdx'; + +export default { + title: getStoryTitle(Toolbar.displayName), + component: Toolbar, + subcomponents: { ToolbarGroup, ToolbarButton }, + + parameters: { + docs: { + page: mdx, + }, + }, +}; + +export function _Toolbar(args) { + const dropdownItems = ['11', '12', '14', '16', '18']; + + const [selectedDropdownItem, setSelectedDropdownItem] = useState( + dropdownItems[(dropdownItems.length / 2) | 0] + ); + + return ( + + + + + + + + + + + + + + + + + + + + setSelectedDropdownItem(selectedItem)} + /> + + + + + + + + + + + + ); +} diff --git a/packages/cloud-cognitive/src/components/Toolbar/Toolbar.test.js b/packages/cloud-cognitive/src/components/Toolbar/Toolbar.test.js new file mode 100644 index 0000000000..7e0936dd69 --- /dev/null +++ b/packages/cloud-cognitive/src/components/Toolbar/Toolbar.test.js @@ -0,0 +1,59 @@ +/** + * Copyright IBM Corp. 2021, 2021 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { render as r, screen } from '@testing-library/react'; +import React, { createRef } from 'react'; + +import { Toolbar, ToolbarButton, ToolbarGroup } from '../..'; +const { getByTestId } = screen; + +function test(T) { + const { displayName } = T; + + describe(displayName, () => { + const dataTestId = 'dataTestId'; + + function render(props) { + return r( + + {displayName} + + ); + } + + it('has no accessibility violations', async () => { + const { container } = render(); + + await expect(container).toBeAccessible(displayName); + await expect(container).toHaveNoAxeViolations(); + }); + + it('adds a class to the containing node', () => { + const className = 'class-name'; + render({ className }); + + expect(getByTestId(dataTestId)).toHaveClass(className); + }); + + it('adds additional props to the containing node', () => { + render(); + + getByTestId(dataTestId); + }); + + it('forwards a reference to the appropriate DOM node', () => { + const ref = createRef(); + render({ ref }); + + expect(getByTestId(dataTestId)).toEqual(ref.current); + }); + }); +} + +test(Toolbar); +test(ToolbarButton); +test(ToolbarGroup); diff --git a/packages/cloud-cognitive/src/components/Toolbar/ToolbarButton.js b/packages/cloud-cognitive/src/components/Toolbar/ToolbarButton.js new file mode 100644 index 0000000000..991213ec8f --- /dev/null +++ b/packages/cloud-cognitive/src/components/Toolbar/ToolbarButton.js @@ -0,0 +1,21 @@ +/** + * Copyright IBM Corp. 2021, 2021 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { Button } from 'carbon-components-react'; +import React, { forwardRef } from 'react'; + +import { pkg } from '../../settings'; + +/** Toolbar buttons are common functions performed as part of a products interface or an open window. */ +export let ToolbarButton = forwardRef((props, ref) => { + return