From 287868924fb0e3abf40fd26eaf9b14476ec5d62a Mon Sep 17 00:00:00 2001 From: Raisa Primerova Date: Fri, 1 Apr 2022 15:05:06 -0600 Subject: [PATCH 1/3] fix(popup): Remove containerElement prop from Popper --- modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx | 8 +++++++- modules/react/popup/lib/Popper.tsx | 13 ++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx b/modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx index 16e476728b..19ae1095fa 100644 --- a/modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx +++ b/modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx @@ -12,7 +12,8 @@ any questions about the update. - [Component Deprecations](#component-deprecations) - [ActionBar Component Updates](#actionbar-component-updates) - [Status Indicator Width](#status-indicator-width) -- [Popup Cards](popup-cards) +- [Popup Cards](#popup-cards) +- [Popper Props Update](#popper-props-update) - [Component Promotions](#component-promotion) ## Codemod @@ -154,6 +155,11 @@ If your code contains any hacks to make a `Modal` overflow, these hacks should n `max-height` of the `Modal.Body` element using calculations. These should be removed. The `Popup.Card` now has a max height and the `Popup.Body` height is automatically calculated. +## Popper Props Update + +We removed the `containerElement` prop from Popper component because it's no longer needed with +Fullscreen API. + ## Component Promotions After some [assessment](https://github.com/Workday/canvas-kit/issues/1395) we've decided to promote diff --git a/modules/react/popup/lib/Popper.tsx b/modules/react/popup/lib/Popper.tsx index c60ce44c24..74a556aa96 100644 --- a/modules/react/popup/lib/Popper.tsx +++ b/modules/react/popup/lib/Popper.tsx @@ -22,14 +22,6 @@ export interface PopperProps { * `anchorElement`. */ children: ((props: {placement: Placement}) => React.ReactNode) | React.ReactNode; - /** - * The element that contains the portal children when `portal` is true. It is best to not define - * this unless you know what you're doing. Popper works with a PopupStack and in order for - * z-indexes to work correctly, all Popups on your page should live on the same root element - * otherwise you risk running into rendering issues: - * https://philipwalton.com/articles/what-no-one-told-you-about-z-index/ - */ - containerElement?: Element | null; /** * When provided, this optional callback will be used to determine positioning for the Popper element * instead of calling `getBoundingClientRect` on the `anchorElement` prop. Use this when you need @@ -62,7 +54,7 @@ export interface PopperProps { */ popperOptions?: Partial; /** - * If true, attach the Popper to the `containerElement`. If false, render the Popper within the + * If false, render the Popper within the * DOM hierarchy of its parent. A non-portal Popper will constrained by the parent container * overflows. If you set this to `false`, you may experience issues where you content gets cut off * by scrollbars or `overflow: hidden` @@ -113,7 +105,6 @@ const OpenPopper = React.forwardRef( onPlacementChange, children, portal, - containerElement, popperInstanceRef, }: PopperProps, ref @@ -185,7 +176,7 @@ const OpenPopper = React.forwardRef( return contents; } - return ReactDOM.createPortal(contents, containerElement || stackRef.current!); + return ReactDOM.createPortal(contents, stackRef.current!); } ); From c48c19419b68f543e2b233d588f61dad90c36fb1 Mon Sep 17 00:00:00 2001 From: Manuel Carrera Date: Mon, 4 Apr 2022 11:47:23 -0600 Subject: [PATCH 2/3] chore!: Combine Icon Buttons with Primary, Secondary and Tertiary (#1477) Fixes: https://github.com/Workday/canvas-kit/issues/1379 [category:Components] - Combined Icon Buttons with Primary, Secondary, and Tertiary buttons - Remove IconButton component - Add a new XS, L sizes - Removed the `toggled` prop when migrating over Icon Buttons - Converted `SegmentedControl` into a compound component and it no longer renders `IconButton` as children - Changed the values of `IconPosition`: `left` | `right` - > `start` | `end` - Refactored `AccentIcon`, `AppletIcon`, `Graphic`, `Icon`, `Svg`, `SystemIcon`, and `SystemIconCircle` to use create component and remove `iconRef` prop and now just pass the ref forward - Remove `dataLabel` prop from `PrimaryButton` and `SecondaryButton` --- .storybook/routes.js | 1 - cypress/integration/ColorPicker.spec.ts | 6 +- .../codemod/lib/v7/recategorizeIconButtons.ts | 157 +++++++++ modules/codemod/lib/v7/renameIconPosition.ts | 52 +++ modules/codemod/lib/v7/renameIconRef.ts | 82 +++++ .../v7/spec/recategorizeIconButtons.spec.ts | 121 +++++++ .../lib/v7/spec/renameIconPosition.spec.ts | 72 ++++ .../codemod/lib/v7/spec/renameIconRef.spec.ts | 34 ++ .../v7/spec/updateSegmentedControl.spec.ts | 28 ++ .../codemod/lib/v7/updateSegmentedControl.ts | 37 +++ modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx | 310 ++++++++++++++++++ modules/docs/mdx/CONTRIBUTING.mdx | 4 +- modules/labs-react/combobox/README.md | 2 +- modules/labs-react/combobox/lib/Combobox.tsx | 16 +- .../labs-react/drawer/lib/DrawerHeader.tsx | 6 +- .../labs-react/search-form/lib/SearchForm.tsx | 54 +-- .../stories/examples/TextInputWithFormik.tsx | 4 +- .../lib/Breadcrumbs/Dropdown/Button.tsx | 73 +++-- .../lib/Breadcrumbs/List/CurrentItem.tsx | 1 + .../lib/Breadcrumbs/List/ListItem.tsx | 4 + .../color-picker/lib/ColorPicker.tsx | 6 +- .../stories/stories_ColorPicker.tsx | 11 +- .../side-panel/lib/SidePanel.tsx | 55 ++-- .../side-panel/stories/SidePanel.stories.mdx | 4 +- .../stories/examples/GlobalHeader.tsx | 10 +- .../_examples/stories/examples/PageHeader.tsx | 6 +- .../action-bar/stories/examples/Basic.tsx | 2 + modules/react/badge/README.md | 5 +- modules/react/banner/lib/BannerIcon.tsx | 4 +- modules/react/button/README.md | 69 +++- modules/react/button/index.ts | 2 +- .../ButtonContainer.tsx => BaseButton.tsx} | 189 +++++++---- modules/react/button/lib/DeleteButton.tsx | 11 +- modules/react/button/lib/IconButton.tsx | 279 ---------------- modules/react/button/lib/PrimaryButton.tsx | 195 +++++------ modules/react/button/lib/SecondaryButton.tsx | 110 +++---- modules/react/button/lib/TertiaryButton.tsx | 139 +++++--- .../button/lib/ToolbarDropdownButton.tsx | 23 +- .../react/button/lib/ToolbarIconButton.tsx | 39 ++- .../react/button/lib/parts/ButtonLabel.tsx | 19 +- .../button/lib/parts/ButtonLabelData.tsx | 16 - .../button/lib/parts/ButtonLabelIcon.tsx | 84 ++--- modules/react/button/lib/parts/index.tsx | 2 - modules/react/button/lib/types.ts | 4 +- modules/react/button/spec/IconButton.spec.tsx | 117 ------- .../stories/button/examples/Primary.tsx | 11 +- .../button/examples/PrimaryInverse.tsx | 3 +- .../stories/button/examples/Secondary.tsx | 16 +- .../button/examples/SecondaryInverse.tsx | 6 +- .../stories/button/examples/Tertiary.tsx | 6 +- .../button/examples/TertiaryInverse.tsx | 3 +- .../icon-button/IconButton.stories.mdx | 106 ------ .../stories/icon-button/examples/Circle.tsx | 6 - .../icon-button/examples/CircleFilled.tsx | 8 - .../stories/icon-button/examples/Inverse.tsx | 17 - .../icon-button/examples/InverseFilled.tsx | 17 - .../icon-button/examples/MirroredIcon.tsx | 11 - .../stories/icon-button/examples/Plain.tsx | 8 - .../stories/icon-button/examples/Square.tsx | 8 - .../icon-button/examples/SquareFilled.tsx | 8 - .../icon-button/examples/Toggleable.tsx | 20 -- .../visual-testing/stories_IconButton.tsx | 65 ---- .../visual-testing/stories_PrimaryButton.tsx | 50 ++- .../stories_SecondaryButton.tsx | 44 ++- .../visual-testing/stories_TertiaryButton.tsx | 47 ++- .../button/stories/visual-testing/utils.tsx | 72 ---- .../react/common/lib/utils/StaticStates.tsx | 11 +- modules/react/common/spec/styled.spec.tsx | 6 +- .../common/stories/stories_direction.tsx | 12 +- modules/react/icon/README.md | 30 -- modules/react/icon/lib/AccentIcon.tsx | 33 +- modules/react/icon/lib/AppletIcon.tsx | 30 +- modules/react/icon/lib/Graphic.tsx | 23 +- modules/react/icon/lib/Icon.tsx | 18 +- modules/react/icon/lib/Svg.tsx | 26 +- modules/react/icon/lib/SystemIcon.tsx | 33 +- modules/react/icon/lib/SystemIconCircle.tsx | 31 +- modules/react/layout/lib/Box.tsx | 40 +++ .../react/layout/stories/Stack.stories.mdx | 11 +- .../layout/stories/examples/Flex/FlexCard.tsx | 2 +- .../examples/Stack/ShouldWrapChildren.tsx | 20 +- modules/react/modal/stories/Modal.stories.mdx | 24 +- .../pagination/lib/Pagination/Controls.tsx | 16 +- .../pagination/lib/Pagination/PageButton.tsx | 55 +++- .../pagination/lib/Pagination/Pagination.tsx | 10 +- .../stories/PropTables.splitprops.tsx | 2 +- .../pagination/stories/pagination.stories.mdx | 28 +- modules/react/popup/lib/PopupCloseIcon.tsx | 15 +- modules/react/popup/stories/Popup.stories.mdx | 3 +- modules/react/segmented-control/README.md | 17 +- .../lib/SegmentedControl.tsx | 117 +++---- .../lib/SegmentedControlButton.tsx | 109 ++++++ .../spec/SegmentedControl.spec.tsx | 40 ++- .../stories/SegmentedControl.stories.mdx | 4 +- .../stories/examples/Basic.tsx | 24 +- .../stories/stories_VisualTesting.tsx | 9 +- modules/react/side-panel/README.md | 6 +- modules/react/side-panel/lib/SidePanel.tsx | 9 +- modules/react/side-panel/stories/stories.tsx | 23 +- .../text-input/lib/InputIconContainer.tsx | 2 +- modules/react/tooltip/README.md | 11 +- modules/react/tooltip/lib/Tooltip.tsx | 2 +- modules/react/tooltip/lib/useTooltip.tsx | 2 +- .../react/tooltip/stories/Tooltip.stories.mdx | 4 +- .../tooltip/stories/examples/Default.tsx | 4 +- .../tooltip/stories/examples/UseTooltip.tsx | 4 +- 106 files changed, 2195 insertions(+), 1668 deletions(-) create mode 100644 modules/codemod/lib/v7/recategorizeIconButtons.ts create mode 100644 modules/codemod/lib/v7/renameIconPosition.ts create mode 100644 modules/codemod/lib/v7/renameIconRef.ts create mode 100644 modules/codemod/lib/v7/spec/recategorizeIconButtons.spec.ts create mode 100644 modules/codemod/lib/v7/spec/renameIconPosition.spec.ts create mode 100644 modules/codemod/lib/v7/spec/renameIconRef.spec.ts create mode 100644 modules/codemod/lib/v7/spec/updateSegmentedControl.spec.ts create mode 100644 modules/codemod/lib/v7/updateSegmentedControl.ts rename modules/react/button/lib/{parts/ButtonContainer.tsx => BaseButton.tsx} (62%) delete mode 100644 modules/react/button/lib/IconButton.tsx delete mode 100644 modules/react/button/lib/parts/ButtonLabelData.tsx delete mode 100644 modules/react/button/spec/IconButton.spec.tsx delete mode 100644 modules/react/button/stories/icon-button/IconButton.stories.mdx delete mode 100644 modules/react/button/stories/icon-button/examples/Circle.tsx delete mode 100644 modules/react/button/stories/icon-button/examples/CircleFilled.tsx delete mode 100644 modules/react/button/stories/icon-button/examples/Inverse.tsx delete mode 100644 modules/react/button/stories/icon-button/examples/InverseFilled.tsx delete mode 100644 modules/react/button/stories/icon-button/examples/MirroredIcon.tsx delete mode 100644 modules/react/button/stories/icon-button/examples/Plain.tsx delete mode 100644 modules/react/button/stories/icon-button/examples/Square.tsx delete mode 100644 modules/react/button/stories/icon-button/examples/SquareFilled.tsx delete mode 100644 modules/react/button/stories/icon-button/examples/Toggleable.tsx delete mode 100644 modules/react/button/stories/visual-testing/stories_IconButton.tsx create mode 100644 modules/react/segmented-control/lib/SegmentedControlButton.tsx diff --git a/.storybook/routes.js b/.storybook/routes.js index fc1eb711f9..ce844548a3 100644 --- a/.storybook/routes.js +++ b/.storybook/routes.js @@ -14,7 +14,6 @@ const routes = { '/tokens/type/': 'tokens-tokens-react--type', '/components/buttons/button/': 'components-buttons-button-react--primary', '/components/buttons/action-bar/': 'components-buttons-action-bar-react--basic', - '/components/buttons/icon-button/': 'components-buttons-button-react-icon-button--circle', '/components/containers/card/': 'components-containers-card-react--basic', '/components/containers/side-panel/': 'preview-side-panel-react--basic', '/components/containers/table/': 'components-containers-table-react--basic', diff --git a/cypress/integration/ColorPicker.spec.ts b/cypress/integration/ColorPicker.spec.ts index 00188c5c34..2e129b6d35 100644 --- a/cypress/integration/ColorPicker.spec.ts +++ b/cypress/integration/ColorPicker.spec.ts @@ -114,10 +114,10 @@ describe('ColorPicker', () => { cy.viewport(800, 1000); }); - describe('Icon Button ColorPicker Popup', () => { - context('when the IconButton is clicked', () => { + describe('Icon button ColorPicker Popup', () => { + context('when the SecondaryButton is clicked', () => { beforeEach(() => { - h.stories.load(colorPickerStory, 'Icon Button Popup'); + h.stories.load(colorPickerStory, 'Icon button Popup'); getOpenButton().click(); }); diff --git a/modules/codemod/lib/v7/recategorizeIconButtons.ts b/modules/codemod/lib/v7/recategorizeIconButtons.ts new file mode 100644 index 0000000000..1e2e280f30 --- /dev/null +++ b/modules/codemod/lib/v7/recategorizeIconButtons.ts @@ -0,0 +1,157 @@ +import { + API, + FileInfo, + Options, + StringLiteral, + JSXIdentifier, + JSXAttribute, + ASTPath, + JSXElement, +} from 'jscodeshift'; +import {getImportRenameMap} from './utils/getImportRenameMap'; + +const updateJSXTag = (nodePath: ASTPath, newTag: string) => { + const {name: componentName} = nodePath.value.openingElement.name as JSXIdentifier; + if (componentName === 'IconButton') { + (nodePath.value.openingElement.name as JSXIdentifier).name = newTag; + if (nodePath.value.closingElement) { + (nodePath.value.closingElement.name as JSXIdentifier).name = newTag; + } + } +}; + +export default function transformer(file: FileInfo, api: API, options: Options) { + const j = api.jscodeshift; + const root = j(file.source); + const requiredImportSpecifiers: string[] = []; + + /** + * 1. Find button imports + */ + const {containsCanvasImports, importMap, styledMap} = getImportRenameMap( + j, + root, + '@workday/canvas-kit-react/button' + ); + if (!containsCanvasImports) { + return file.source; + } + + let buttonType = 'TertiaryButton'; //default button if no variant is specified + + // Button Mapping + // circle -> tertiary + // circle-filled -> secondary + // inverse -> tertiary inverse + // inverse-filled -> secondary inverse + // plain/square -> not supported + // square-filled -> not supported + + /** + * 2. Find `IconButton` + * - If it has no variant, it means it's "circle" which is the default + * - Swap to `TertiaryButton` + * - Add `TertiaryButton` import if it doesn't exist. + * - If not + * - check the variant of the IconButton + * - Swap it out for the appropriate mapping + */ + root + .find( + j.JSXElement, + (value: JSXElement) => + value.openingElement.name.type === 'JSXIdentifier' && + (value.openingElement.name.name === importMap.IconButton || + value.openingElement.name.name === styledMap.IconButton) + ) + .forEach(nodePath => { + const attrs = nodePath.value.openingElement.attributes; + + const variantProp = attrs?.find( + attr => attr.type === 'JSXAttribute' && attr.name.name === 'variant' + ); + + // Default IconButton variant is `circle` + if (variantProp) { + const variantPropValue = ((variantProp as JSXAttribute).value as StringLiteral)?.value; + buttonType = /filled/gi.test(variantPropValue) ? 'SecondaryButton' : 'TertiaryButton'; + + if (!variantPropValue.includes('inverse')) { + nodePath.value.openingElement.attributes?.splice(attrs?.indexOf(variantProp)!, 1); + } + } + + updateJSXTag(nodePath, buttonType); + requiredImportSpecifiers.push(buttonType); + }); + + // Find all instances of IconButton within a style function + // const StyledIconButton = styled(IconButton) gets renamed to + // const StyledIconButton = styled(CorrectButtonMapping) + root.find(j.VariableDeclarator).forEach(nodePath => { + if ( + nodePath.value.init?.type === 'CallExpression' && + nodePath.value.init.callee.type === 'CallExpression' && + nodePath.value.init.callee.arguments[0].type === 'Identifier' + ) { + nodePath.value.init.callee.arguments[0].name = buttonType; + requiredImportSpecifiers.push(buttonType); + } + }); + + /** + * Remove old imports: `IconButton` + * Add new required imports + */ + const buttonImports = root.find(j.ImportDeclaration, { + source: {value: (value: string) => value.includes('@workday/canvas-kit-react')}, + }); + + if (!buttonImports.length) { + // Add new specifiers to a new import + const allImports = root.find(j.ImportDeclaration); + + const lastImport = allImports.at(allImports.length); + if (lastImport) { + lastImport.insertAfter( + j.importDeclaration( + requiredImportSpecifiers.map(specifier => j.importSpecifier(j.identifier(specifier))), + j.stringLiteral('@workday/canvas-kit-react/button') + ) + ); + } + } else { + buttonImports.forEach(({node}) => { + const specifiersToRemove = ['IconButton']; + + // Remove old specifiers + if ( + typeof node.source.value === 'string' && + node.source.value.includes('@workday/canvas-kit-react') + ) { + node.specifiers?.forEach(specifier => { + if ( + specifier.type === 'ImportSpecifier' && + specifiersToRemove.includes(specifier.imported.name) + ) { + // delete specifier + node.specifiers?.splice(node.specifiers?.indexOf(specifier)!, 1); + } + }); + } + + // Add new specifiers to existing import + requiredImportSpecifiers.forEach(specifier => { + if ( + !node.specifiers?.find( + existing => existing.type === 'ImportSpecifier' && existing.imported.name === specifier + ) + ) { + node.specifiers?.push(j.importSpecifier(j.identifier(specifier))); + } + }); + }); + } + + return root.toSource(); +} diff --git a/modules/codemod/lib/v7/renameIconPosition.ts b/modules/codemod/lib/v7/renameIconPosition.ts new file mode 100644 index 0000000000..7848c22a68 --- /dev/null +++ b/modules/codemod/lib/v7/renameIconPosition.ts @@ -0,0 +1,52 @@ +import {API, FileInfo, Options, JSXElement, JSXAttribute, JSXSpreadAttribute} from 'jscodeshift'; + +import {getImportRenameMap} from './utils/getImportRenameMap'; + +export default function transformer(file: FileInfo, api: API, options: Options) { + const j = api.jscodeshift; + + const root = j(file.source); + + const {containsCanvasImports, importMap, styledMap} = getImportRenameMap( + j, + root, + '@workday/canvas-kit-react/button' + ); + + if (!containsCanvasImports) { + return file.source; + } + + root + .find( + j.JSXElement, + (value: JSXElement) => + value.openingElement.name.type === 'JSXIdentifier' && + (value.openingElement.name.name === + (importMap.PrimaryButton || importMap.SecondaryButton) || + value.openingElement.name.name === (styledMap.PrimaryButton || styledMap.SecondaryButton)) + ) + .forEach(nodePath => { + const findAttribute = (name: string) => (item: JSXAttribute | JSXSpreadAttribute) => + item.type === 'JSXAttribute' && + item.name.type === 'JSXIdentifier' && + item.name.name === name; + + const attributes = nodePath.value.openingElement.attributes; + if (attributes) { + const iconPosition = attributes.find(findAttribute('iconPosition')) as + | JSXAttribute + | undefined; + + if (iconPosition?.value?.type === 'StringLiteral') { + if (iconPosition.value.value === 'left') { + iconPosition.value.value = 'start'; + } else { + iconPosition.value.value = 'end'; + } + } + } + }); + + return root.toSource(); +} diff --git a/modules/codemod/lib/v7/renameIconRef.ts b/modules/codemod/lib/v7/renameIconRef.ts new file mode 100644 index 0000000000..bf7b4ded2a --- /dev/null +++ b/modules/codemod/lib/v7/renameIconRef.ts @@ -0,0 +1,82 @@ +import {API, FileInfo, Options, JSXIdentifier} from 'jscodeshift'; +import {getImportRenameMap} from './utils/getImportRenameMap'; + +const inputsMap: { + [packageName: string]: string[]; +} = { + '@workday/canvas-kit-react/icon': [ + 'AccentIcon', + 'AppletIcon', + 'SystemIcon', + 'SystemIconCircle', + 'Graphic', + 'Svg', + ], +}; + +export default function transformer(file: FileInfo, api: API, options: Options) { + const j = api.jscodeshift; + + const root = j(file.source); + + // defaultImports should be an array of local names that were imported using + // a default import from any of the modules listed in inputsMap. For example, + // given... + // + // ``` + // import Checkbox from '@workday/canvas-kit-react/checkbox'; + // import CanvasTextArea from '@workday/canvas-kit-react/text-area'; + // import {TextInput} from '@workday/canvas-kit-react/text-input'; + // import StatusIndicator from '@workday/canvas-kit-react/status-indicator'; + // ``` + // + // ... defaultImports should be set to `['Checkbox', 'CanvasTextArea']` + const defaultImports: string[] = []; + root.find(j.ImportDefaultSpecifier).forEach(nodePath => { + const packageName = nodePath.parent.node.source.value; + const localName = nodePath.value.local?.name; + if (packageName in inputsMap && localName) { + defaultImports.push(localName); + } + }); + + let runningSource = file.source; + for (const inputPackageName of Object.keys(inputsMap)) { + const currentRoot = j(runningSource); + + const {containsCanvasImports, importMap, styledMap} = getImportRenameMap( + j, + currentRoot, + inputPackageName + ); + + if (containsCanvasImports) { + const inputNames = inputsMap[inputPackageName]; + currentRoot + .find(j.JSXIdentifier, (value: JSXIdentifier) => value.name === 'iconRef') + .replaceWith(nodePath => { + const elementName = nodePath.parent?.parent?.value?.name?.name; + // Rewrite inputRef to ref if any of the following are true: + // (a) elementName was the name used in a default import of the current + // input being processed (e.g., `import TextInput ...`) + // (b) elementName was the name used in a named import of the current + // input being processed (e.g., `import {TextInput} ...` or + // `import {TextInput as CanvasTextInput} ...`) + // (c) elementName was created by calling `styled` on the current input + // being processed (e.g., `const StyledTextInput = styled(TextInput)`) + if ( + defaultImports.includes(elementName) || + inputNames.map(n => importMap[n]).includes(elementName) || + inputNames.map(n => styledMap[n]).includes(elementName) + ) { + return j.jsxIdentifier('ref'); + } + return nodePath.value; + }); + + runningSource = currentRoot.toSource(); + } + } + + return runningSource; +} diff --git a/modules/codemod/lib/v7/spec/recategorizeIconButtons.spec.ts b/modules/codemod/lib/v7/spec/recategorizeIconButtons.spec.ts new file mode 100644 index 0000000000..6847d7eea8 --- /dev/null +++ b/modules/codemod/lib/v7/spec/recategorizeIconButtons.spec.ts @@ -0,0 +1,121 @@ +import {expectTransformFactory} from './expectTransformFactory'; +import transform from '../recategorizeIconButtons'; +import {stripIndent} from 'common-tags'; + +const expectTransform = expectTransformFactory(transform); + +describe('recategorizeIconButtons', () => { + it('should replace "IconButton" with "TertiaryButton" as default use case', () => { + const input = ` + import {IconButton} from '@workday/canvas-kit-react/button' + + + `; + + const expected = ` + import {TertiaryButton} from '@workday/canvas-kit-react/button' + + + `; + + expectTransform(input, expected); + }); + + it('should replace "IconButton" with "TertiaryButton" when imported from main package', () => { + const input = ` + import {IconButton} from '@workday/canvas-kit-react'; + + + `; + + const expected = ` + import {TertiaryButton} from '@workday/canvas-kit-react'; + + + `; + + expectTransform(input, expected); + }); + + it('should replace "IconButton" with "TertiaryButton" if variant "circle" is defined', () => { + const input = ` + import {IconButton} from '@workday/canvas-kit-react/button' + + + `; + + const expected = ` + import {TertiaryButton} from '@workday/canvas-kit-react/button' + + + `; + + expectTransform(input, expected); + }); + + it('should replace "IconButton" with the correct mapping of buttons', () => { + const input = stripIndent` + import {IconButton} from '@workday/canvas-kit-react/button'; + <> + + + + + + `; + const expected = stripIndent` + import { TertiaryButton, SecondaryButton } from '@workday/canvas-kit-react/button'; + <> + + + + + + `; + + expectTransform(input, expected); + }); + + it('should restructure styled IconButton usages', () => { + const input = stripIndent` + import {IconButton} from '@workday/canvas-kit-react/button'; + + const StyledIconButton = styled(IconButton)({}); + + + `; + + const expected = stripIndent` + import {TertiaryButton} from '@workday/canvas-kit-react/button'; + + const StyledIconButton = styled(TertiaryButton)({}); + + + `; + + expectTransform(input, expected); + }); + + it('should import correct button based on styled IconButton', () => { + const input = stripIndent` + import {IconButton} from '@workday/canvas-kit-react/button'; + + const StyledIconButton = styled(IconButton)({}); + + + + + `; + + const expected = stripIndent` + import {SecondaryButton} from '@workday/canvas-kit-react/button'; + + const StyledIconButton = styled(SecondaryButton)({}); + + + + `; + + expectTransform(input, expected); + }); +}); diff --git a/modules/codemod/lib/v7/spec/renameIconPosition.spec.ts b/modules/codemod/lib/v7/spec/renameIconPosition.spec.ts new file mode 100644 index 0000000000..b4b3f287aa --- /dev/null +++ b/modules/codemod/lib/v7/spec/renameIconPosition.spec.ts @@ -0,0 +1,72 @@ +import {expectTransformFactory} from './expectTransformFactory'; +import transform from '../renameIconPosition'; +import {stripIndent} from 'common-tags'; + +const expectTransform = expectTransformFactory(transform); + +describe('Button Icon Position', () => { + it('should rename left to start for SecondaryButton', () => { + const input = stripIndent` + import {SecondaryButton} from '@workday/canvas-kit-react/button' + + {}} iconPosition="left">Primary + `; + + const expected = stripIndent` + import {SecondaryButton} from '@workday/canvas-kit-react/button' + + {}} iconPosition="start">Primary + `; + + expectTransform(input, expected); + }); + + it('should rename left to start for PrimaryButton', () => { + const input = stripIndent` + import {PrimaryButton} from '@workday/canvas-kit-react/button' + + {}} iconPosition="left">Primary + `; + + const expected = stripIndent` + import {PrimaryButton} from '@workday/canvas-kit-react/button' + + {}} iconPosition="start">Primary + `; + + expectTransform(input, expected); + }); + + it('should rename right to end for PrimaryButton', () => { + const input = stripIndent` + import {PrimaryButton} from '@workday/canvas-kit-react/button' + + {}} iconPosition="right">Primary + `; + + const expected = stripIndent` + import {PrimaryButton} from '@workday/canvas-kit-react/button' + + {}} iconPosition="end">Primary + `; + console.log(expected); + + expectTransform(input, expected); + }); + + it('should rename right to end for SecondaryButton', () => { + const input = stripIndent` + import {SecondaryButton} from '@workday/canvas-kit-react/button' + + {}} iconPosition="right">Primary + `; + + const expected = stripIndent` + import {SecondaryButton} from '@workday/canvas-kit-react/button' + + {}} iconPosition="end">Primary + `; + + expectTransform(input, expected); + }); +}); diff --git a/modules/codemod/lib/v7/spec/renameIconRef.spec.ts b/modules/codemod/lib/v7/spec/renameIconRef.spec.ts new file mode 100644 index 0000000000..95b8184175 --- /dev/null +++ b/modules/codemod/lib/v7/spec/renameIconRef.spec.ts @@ -0,0 +1,34 @@ +import {expectTransformFactory} from './expectTransformFactory'; +import transform from '../renameIconRef'; +import {stripIndent} from 'common-tags'; + +const expectTransform = expectTransformFactory(transform); + +describe('renameIconRefs', () => { + it('should rename iconRef to ref', () => { + const input = stripIndent` + import {AccentIcon, AppletIcon, SystemIcon, SystemIconCircle, Graphic, Svg} from '@workday/canvas-kit-react/icon' + <> + + + + + + + + `; + + const expected = stripIndent` + import {AccentIcon, AppletIcon, SystemIcon, SystemIconCircle, Graphic, Svg} from '@workday/canvas-kit-react/icon' + <> + + + + + + + + `; + expectTransform(input, expected); + }); +}); diff --git a/modules/codemod/lib/v7/spec/updateSegmentedControl.spec.ts b/modules/codemod/lib/v7/spec/updateSegmentedControl.spec.ts new file mode 100644 index 0000000000..2c79ce85d0 --- /dev/null +++ b/modules/codemod/lib/v7/spec/updateSegmentedControl.spec.ts @@ -0,0 +1,28 @@ +import {expectTransformFactory} from './expectTransformFactory'; +import transform from '../updateSegmentedControl'; +import {stripIndent} from 'common-tags'; + +const expectTransform = expectTransformFactory(transform); + +describe('SegmentedControl', () => { + it('should rename IconButton to SegmentedControl.Button', () => { + const input = stripIndent` + import {SegmentedControl} from '@workday/canvas-kit-react/segmented-control'; + + + + + + `; + + const expected = stripIndent` + import {SegmentedControl} from '@workday/canvas-kit-react/segmented-control'; + + + + + + `; + expectTransform(input, expected); + }); +}); diff --git a/modules/codemod/lib/v7/updateSegmentedControl.ts b/modules/codemod/lib/v7/updateSegmentedControl.ts new file mode 100644 index 0000000000..de334b5cb2 --- /dev/null +++ b/modules/codemod/lib/v7/updateSegmentedControl.ts @@ -0,0 +1,37 @@ +import {API, FileInfo, Options, JSXElement} from 'jscodeshift'; + +import {getImportRenameMap} from './utils/getImportRenameMap'; + +export default function transformer(file: FileInfo, api: API, options: Options) { + const j = api.jscodeshift; + + const root = j(file.source); + + const {containsCanvasImports, importMap, styledMap} = getImportRenameMap( + j, + root, + '@workday/canvas-kit-react/segmented-control' + ); + + if (!containsCanvasImports) { + return file.source; + } + + root + .find( + j.JSXElement, + (value: JSXElement) => + value.openingElement.name.type === 'JSXIdentifier' && + (value.openingElement.name.name === importMap.SegmentedControl || + value.openingElement.name.name === styledMap.SegmentedControl) + ) + .forEach(nodePath => { + for (const child of nodePath.value.children || []) { + if (child.type === 'JSXElement' && child.openingElement.name.type === 'JSXIdentifier') { + child.openingElement.name.name = 'SegmentedControl.Button'; + } + } + }); + + return root.toSource(); +} diff --git a/modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx b/modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx index 19ae1095fa..db4bbd24a6 100644 --- a/modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx +++ b/modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx @@ -10,6 +10,11 @@ any questions about the update. - [Codemod](#codemod) - [Component Deprecations](#component-deprecations) +- [Component Promotions](#component-promotion) +- [Buttons](#buttons) +- [Segmented Control](#segmented-control) +- [Side Panel](#side-panel) +- [Icons](#icons) - [ActionBar Component Updates](#actionbar-component-updates) - [Status Indicator Width](#status-indicator-width) - [Popup Cards](#popup-cards) @@ -107,6 +112,311 @@ word. ``` +## Buttons + +To consolidate button APIs, we removed `IconButton` in favor of `PrimaryButton`, `SecondaryButton` +and `TertiaryButton`. + +### Breaking Changes + +- Removed the `toggled` prop when migrating from `IconButton` +- Changed the values of `IconPosition: left | right` - > `IconPosition: start | end` +- Remove `dataLabel` prop from `PrimaryButton` and `SecondaryButton` + +🤖 The codemod will handle all these changes automatically: + +- `iconPosition='left'` becomes `iconPosition='start'` +- `iconPosition='right'` becomes `iconPosition='end'` +- `` becomes `` +- `` becomes + `` +- `` becomes + `` +- `` becomes + `` + +#### Manual Changes + +The following changes will not be automatic updated and will require a manual update: + +- Remove `IconButton` variants: `plain`, `square`, and `squareFilled` +- Remove `IconButtonProps` +- Remove `IconButton` prop: `toggled` +- Remove `PrimaryButton` and `SecondaryButton` prop: `dataLabel` + +### Button Mapping + +Below is a mapping of V6 `IconButton` variants to their respective V7 buttons and variants. Further +below is a description of how to manually migrate from unsupported V6 variants. | IconButton variant +| Button Type | | ------------------ | ------------------------------------ | | `circle` | +TertiaryButton | | `circleFilled` | SecondaryButton | | `inverse` | TertiButton with variant inverse +| | `inverseFilled` | SecondaryButton with variant inverse | | `plain` | Not Supporting | | `square` +| Not Supporting | | `squareFilled` | Not Supporting | + +### Remove `IconButton` `plain`, `square`, and `squareFilled` Variants + +As part of simplifying our variants and cleaning up the API, we've removed the variants `square`, +`squareFilled` and `plain`. We've also removed the prop `toggled`. + +Plain, Square, or Square-Filled Icon Buttons should either transition to the new icon only Primary, +Secondary, and Tertiary button variants, the Toolbar Icon Button, or the Segmented Control component + +If you would still like to have a squared icon, you can use +[ToolbarIconButton](https://workday.github.io/canvas-kit/?path=/docs/components-buttons-button-react-toolbar--toolbar-icon-button) +which also has the `toggled`prop. + +If this button doesn't fit your specific use case, we've introduced a low level +[`BaseButton` component](#basebutton-component). This component allows you to modify the colors, +props, and size of the button. For an example of this being used, you can reference our +[PageButton component](https://github.com/Workday/canvas-kit/blob/master/modules/react/pagination/lib/Pagination/PageButton.tsx). + +### Rendering an icon button + +In order to render a icon button, omit any `children` and pass the button an `icon` prop. + +Example + +v6 + +```tsx + +``` + +v7 + +```tsx + +``` + +You can now render what use to be an `IconButton` using our main buttons. + +```tsx + + + + + + +``` + +### Button sizes + +Each button now supports sizes: `extraSmall`, `small`, `medium` and `large` with `medium` being the +default size. + +```tsx + + + // default + +``` + +### Button Icon position + +The prop `iconPosition` which is used to determine which side an icon should be when rendered with +some text, has been changed. The default is `start` + +v6 + +```tsx +iconPosition: 'left' | 'right'; +``` + +v7 + +```tsx +iconPosition: 'start' | 'end'; +``` + +_Note:_ The position of the icon should have no affect if you're rending an icon button. + +### Removal of `dataLabel` Prop + +The `dataLabel` prop has been removed from our Buttons in v7 in order to simplify the API. + +_Note:_ The codemod will not remove this prop since use of this prop varies. If you'd like to still +have a similar effect, below is an example of how to achieve this. + +v6 + +```tsx +Time +``` + +v7 + +```tsx + + Time + + 1:00 + + +``` + +### BaseButton Component + +As part of the restructure of our Buttons, we've created a low level `BaseButton` component. This +component isn't intended to be used outside of Canvas Kit, but we do export it for very specific use +cases which we'll outline below. The `BaseButton` is a styled `button` element which extends our +style properties which allow us to customize a buttons `colors`, `padding`, `width` and other style +properties. + +Basic example: + +```tsx +import * as React from 'react'; +import {colors} from '@workday/canvas-kit-react/tokens'; +import {BaseButton} from '@workday/canvas-kit-react/button'; +import {plusIcon} from '@workday/canvas-system-icons-web'; + +const getBasicButtonColors = () => { + return { + default: { + background: colors.blueberry400, + label: colors.frenchVanilla100, + icon: colors.frenchVanilla100, + }, + hover: { + background: colors.blueberry500, + label: colors.frenchVanilla100, + icon: colors.frenchVanilla100, + }, + active: { + background: colors.blueberry500, + label: colors.frenchVanilla100, + icon: colors.frenchVanilla100, + }, + focus: { + background: colors.blueberry400, + label: colors.frenchVanilla100, + icon: colors.frenchVanilla100, + }, + disabled: { + background: colors.blueberry400, + }, + }; +}; + +export type BasicButtonProps = React.ButtonHTMLAttributes & {}; + +export const BasicButton = ({children, ...elemProps}: BasicButtonProps) => { + return ( + + {children} + + + ); +}; +``` + +**Note:** Under the hood, `BaseButton` uses our `Box` component which allows `BaseButton` to accept +style properties. Because of the flexibility of this component, consumers can use this to create +toggled buttons or a specific button that doesn't fall under the main use case you see in our design +system. + +**Disclaimer** We strongly advise consumers not to use this component if possible and to rely on our +`PrimaryButton`, `SecondaryButton` and `TertiaryButton` when possible. + +## Segmented Control + +Segmente Control use to work when rendering `IconButton` as children. This has now moved to a +compound component and removed the use of `IconButton`. + +### Breaking Change + +`IconButton` is no longer a valid child of segmented control. + +🤖 The codemod will handle all these changes automatically: + +- `IconButton` becomes `SegmentedControl.Button` + +v6 + +```tsx + + console.log('Existing IconButton onClick callback')} + /> + + + + +``` + +v7 + +```tsx + + console.log('Existing IconButton onClick callback')} + /> + + + + +``` + +## Side Panel + +The `SidePanel` in our `preview` package has now been updated so that the toggle button has a +tooltip built in. If you currently have a `Tooltip` component wrapping this element, you should +remove it and provide the appropiate text to the button based on its state. + +Two props where added to the `SidePanel.ToggleButton`: + +```tsx +/** + * The tooltip text to expand the side panel + * @default 'Expand' + */ + tooltipTextExpand?: string; + /** + * The tooltip text to collapse the side panel + * @default 'Collapse' + */ + tooltipTextCollapse?: string; +``` + +## Icons + +We've updated our lower level icon components such as `AccentIcon`, `AppletIcon`, `Graphic`, `Icon`, +`Svg`, `SystemIcon`, and `SystemIconCircle` to use our +[createComponent](https://github.com/Workday/canvas-kit/blob/ff77c5bd83e41c3ab2b9c55e41a8b7c1fde33a1b/modules/react/common/lib/utils/components.ts#L167) +which allows us to `forwardRef`. + +### Breaking Change + +This is a breaking change since we've removed `iconRef`. You can now just pass a `ref` to the +element. + +🤖 The codemod will handle all these changes automatically:\ + +- `iconRef` becomes `ref` + ## Popup Cards `Popup.Card` (this includes `Modal.Card` and `Dialog.Card`) components are now a flexbox container. diff --git a/modules/docs/mdx/CONTRIBUTING.mdx b/modules/docs/mdx/CONTRIBUTING.mdx index 79a4a026e4..39df6ccef9 100644 --- a/modules/docs/mdx/CONTRIBUTING.mdx +++ b/modules/docs/mdx/CONTRIBUTING.mdx @@ -87,8 +87,8 @@ through the commit history. It also automates [semantic versioning](https://semv > **Examples** ``` -feat(IconButton): Add ariaLabel prop for accessibility -fix: Add missing static class variable to IconButton and Avatar +feat(Button): Add proper hover states for secondary buttons +fix: Add missing static class variable to PrimaryButton and Avatar ``` > **DO** diff --git a/modules/labs-react/combobox/README.md b/modules/labs-react/combobox/README.md index 15d36bf39d..2470169e28 100644 --- a/modules/labs-react/combobox/README.md +++ b/modules/labs-react/combobox/README.md @@ -68,7 +68,7 @@ const autocompleteCallback = event => console.log('Adjust menu items here') --- -#### `clearButtonVariant: IconButtonProps['variant']` +#### `clearButtonVariant: TertiaryButtonProps['variant']` > The type of icon button to use for clearing input. diff --git a/modules/labs-react/combobox/lib/Combobox.tsx b/modules/labs-react/combobox/lib/Combobox.tsx index 1bf4544f7e..3ba164393c 100644 --- a/modules/labs-react/combobox/lib/Combobox.tsx +++ b/modules/labs-react/combobox/lib/Combobox.tsx @@ -10,7 +10,7 @@ import { import {space, commonColors, borderRadius} from '@workday/canvas-kit-react/tokens'; import {MenuItemProps} from '@workday/canvas-kit-preview-react/menu'; import {Card} from '@workday/canvas-kit-react/card'; -import {IconButton, IconButtonProps} from '@workday/canvas-kit-react/button'; +import {TertiaryButton, TertiaryButtonProps} from '@workday/canvas-kit-react/button'; import {xSmallIcon} from '@workday/canvas-system-icons-web'; import {TextInputProps} from '@workday/canvas-kit-react/text-input'; import flatten from 'lodash.flatten'; @@ -34,10 +34,9 @@ export interface ComboboxProps extends GrowthBehavior, React.HTMLAttributes( +const ResetButton = styled(TertiaryButton)<{shouldShow: boolean}>( { - width: space.l, - minWidth: space.l, - height: space.l, position: 'absolute', margin: `auto ${space.xxxs}`, top: 0, @@ -173,7 +169,7 @@ const Combobox = ({ onFocus, onBlur, showClearButton, - clearButtonVariant = 'plain', + clearButtonVariant = undefined, clearButtonAriaLabel = `Reset Search Input`, labelId, getStatusText = buildStatusString, @@ -469,9 +465,9 @@ const Combobox = ({ aria-label={clearButtonAriaLabel} icon={xSmallIcon} variant={clearButtonVariant} - toggled={undefined} onClick={resetSearchInput} onBlur={handleBlur} + size="small" type="button" /> )} diff --git a/modules/labs-react/drawer/lib/DrawerHeader.tsx b/modules/labs-react/drawer/lib/DrawerHeader.tsx index a2199cf340..c4773caa38 100644 --- a/modules/labs-react/drawer/lib/DrawerHeader.tsx +++ b/modules/labs-react/drawer/lib/DrawerHeader.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import styled from '@emotion/styled'; import {colors, space, type, CanvasColor, typeColors} from '@workday/canvas-kit-react/tokens'; -import {IconButton} from '@workday/canvas-kit-react/button'; +import {TertiaryButton} from '@workday/canvas-kit-react/button'; import {xIcon} from '@workday/canvas-system-icons-web'; export interface DrawerHeaderProps extends React.HTMLAttributes { @@ -69,7 +69,7 @@ const HeaderTitle = styled('h4')>( }) ); -const CloseButton = styled(IconButton)({ +const CloseButton = styled(TertiaryButton)({ margin: '-8px', // for inverse and plain button, we always want this margin }); @@ -93,7 +93,7 @@ export default class DrawerHeader extends React.Component {onClose && closeIconAriaLabel && ( & {isHidden: boolean}>( - ({isCollapsed, isHidden}) => { - const collapsedSize = 40; - const size = 32; - const collapseStyles: CSSObject = isCollapsed - ? { - minWidth: collapsedSize, - width: collapsedSize, - minHeight: collapsedSize, - height: collapsedSize, - } - : { - minWidth: size, - width: size, - minHeight: size, - height: size, - }; - - return { - position: `absolute`, - margin: isCollapsed ? `auto ${space.xxs}` : `auto ${space.xxxs}`, - top: 0, - bottom: 0, - left: 0, - padding: 0, - zIndex: 3, - display: isHidden ? 'none' : 'flex', - ...collapseStyles, - }; - } -); +const SearchIcon = styled(TertiaryButton)< + Pick & {isHidden: boolean} +>(({isCollapsed, isHidden}) => { + return { + position: `absolute`, + margin: isCollapsed ? `auto ${space.xxs}` : `auto ${space.xxxs}`, + top: 0, + bottom: 0, + left: 0, + padding: 0, + zIndex: 3, + display: isHidden ? 'none' : 'flex', + }; +}); -const CloseButton = styled(IconButton)< +const CloseButton = styled(TertiaryButton)< Pick & Pick >(({isCollapsed, showForm}) => { const collapseStyles: CSSObject = @@ -325,13 +308,13 @@ export class SearchForm extends React.Component { + getIconButtonType = (): TertiaryButtonProps['variant'] => { let background = this.getThemeColors().background || `#fff`; if (this.props.isCollapsed && this.state.showForm) { background = formCollapsedBackground; } const isDarkBackground = chroma(background as string).get('lab.l') < 70; - return isDarkBackground ? 'inverse' : 'plain'; + return isDarkBackground ? 'inverse' : undefined; }; handleSubmit = (event: React.FormEvent): void => { @@ -485,7 +468,6 @@ export class SearchForm extends React.Component { onBlur={formik.handleBlur} value={formik.values.password} /> - { /** * The accessibility label for the button */ @@ -22,35 +22,64 @@ export interface DropdownButtonProps extends IconButtonProps { toggled: boolean; } -export const DropdownButton = createComponent(IconButton)({ +export const DropdownButton = createComponent('button')({ displayName: 'DropdownButton', Component: ( - { - buttonIcon = relatedActionsIcon, - toggled, - variant = 'plain', - ...elemProps - }: DropdownButtonProps, + {buttonIcon = relatedActionsIcon, toggled, ...elemProps}: DropdownButtonProps, ref, Element ) => { - const hasPlainVariant = variant === 'plain'; - + const theme = useTheme(); return ( - + > + + ); }, }); + +const getDropdownColors = (toggled: boolean, theme: EmotionCanvasTheme) => { + const { + canvas: { + palette: {primary: themePrimary}, + }, + } = theme; + + return { + default: { + icon: toggled ? themePrimary.main : colors.blackPepper400, + label: themePrimary.main, + }, + hover: { + background: colors.soap200, + icon: toggled ? themePrimary.dark : colors.blackPepper500, + label: themePrimary.dark, + }, + active: { + background: colors.soap300, + icon: toggled ? themePrimary.dark : colors.blackPepper500, + label: themePrimary.dark, + }, + focus: { + icon: toggled ? themePrimary.main : colors.blackPepper500, + label: themePrimary.main, + }, + disabled: { + icon: toggled ? themePrimary.main : colors.blackPepper400, + label: themePrimary.main, + }, + }; +}; diff --git a/modules/preview-react/breadcrumbs/lib/Breadcrumbs/List/CurrentItem.tsx b/modules/preview-react/breadcrumbs/lib/Breadcrumbs/List/CurrentItem.tsx index d867966a45..53aaeeaab8 100644 --- a/modules/preview-react/breadcrumbs/lib/Breadcrumbs/List/CurrentItem.tsx +++ b/modules/preview-react/breadcrumbs/lib/Breadcrumbs/List/CurrentItem.tsx @@ -23,6 +23,7 @@ const ListItem = styled('li')( flexDirection: 'column', textAlign: 'left', ...type.levels.subtext.large, + fontWeight: 500, }, ({maxWidth}: CurrentItemProps) => ({ diff --git a/modules/preview-react/breadcrumbs/lib/Breadcrumbs/List/ListItem.tsx b/modules/preview-react/breadcrumbs/lib/Breadcrumbs/List/ListItem.tsx index d89516f440..c0bde41389 100644 --- a/modules/preview-react/breadcrumbs/lib/Breadcrumbs/List/ListItem.tsx +++ b/modules/preview-react/breadcrumbs/lib/Breadcrumbs/List/ListItem.tsx @@ -19,6 +19,10 @@ export const BreadcrumbsListItem = ({children, ...props}: ListItemProps) => { icon={icon} color={colors.licorice200} colorHover={colors.licorice200} + size={20} + height={32} + width={32} + styles={{justifyContent: 'center', alignItems: 'center', display: 'inline-flex'}} aria-hidden /> diff --git a/modules/preview-react/color-picker/lib/ColorPicker.tsx b/modules/preview-react/color-picker/lib/ColorPicker.tsx index e71d2f89d6..017af815d2 100644 --- a/modules/preview-react/color-picker/lib/ColorPicker.tsx +++ b/modules/preview-react/color-picker/lib/ColorPicker.tsx @@ -1,7 +1,7 @@ import {colors, space} from '@workday/canvas-kit-react/tokens'; import {checkIcon} from '@workday/canvas-system-icons-web'; import {ColorInput} from '@workday/canvas-kit-react/color-picker'; -import {IconButton} from '@workday/canvas-kit-react/button'; +import {SecondaryButton} from '@workday/canvas-kit-react/button'; import * as React from 'react'; import FormField from '@workday/canvas-kit-react/form-field'; import styled from '@emotion/styled'; @@ -141,7 +141,7 @@ const ColorInputAndLabel = styled(FormField)({ margin: 0, }); -const CheckButton = styled(IconButton)({ +const CheckButton = styled(SecondaryButton)({ alignSelf: 'flex-end', }); @@ -207,7 +207,7 @@ const ColorPicker = ({ showCheck={value === validHexValue || value === customHexValue} /> - + )} diff --git a/modules/preview-react/color-picker/stories/stories_ColorPicker.tsx b/modules/preview-react/color-picker/stories/stories_ColorPicker.tsx index 8be6c02c4d..1b97c31467 100644 --- a/modules/preview-react/color-picker/stories/stories_ColorPicker.tsx +++ b/modules/preview-react/color-picker/stories/stories_ColorPicker.tsx @@ -10,7 +10,7 @@ import { useInitialFocus, useReturnFocus, } from '@workday/canvas-kit-react/popup'; -import {IconButton} from '@workday/canvas-kit-react/button'; +import {TertiaryButton} from '@workday/canvas-kit-react/button'; import {bgColorIcon} from '@workday/canvas-system-icons-web'; import {ColorPicker} from '@workday/canvas-kit-preview-react/color-picker'; import {changeFocus} from '@workday/canvas-kit-react/common'; @@ -22,7 +22,7 @@ storiesOf('Preview/Color Picker/React', module) .addParameters({component: ColorPicker}) .addParameters({ReadmePath: 'preview-react/color-picker'}) .add('Default', () => ) - .add('Icon Button Popup', () => { + .add('Icon button Popup', () => { const model = usePopupModel(); const [color, setColor] = React.useState(''); @@ -42,12 +42,7 @@ storiesOf('Preview/Color Picker/React', module) return ( - + diff --git a/modules/preview-react/side-panel/lib/SidePanel.tsx b/modules/preview-react/side-panel/lib/SidePanel.tsx index af6dfa8c77..122894c4f9 100644 --- a/modules/preview-react/side-panel/lib/SidePanel.tsx +++ b/modules/preview-react/side-panel/lib/SidePanel.tsx @@ -1,13 +1,12 @@ /** @jsxRuntime classic */ /** @jsx jsx */ import * as React from 'react'; -import {styled, useIsRTL, StyledType} from '@workday/canvas-kit-react/common'; -import {css, jsx, keyframes} from '@emotion/react'; -import {IconButton, IconButtonProps} from '@workday/canvas-kit-react/button'; -import {space, colors} from '@workday/canvas-kit-react/tokens'; +import {styled, useIsRTL} from '@workday/canvas-kit-react/common'; +import {css, jsx, keyframes, CSSObject} from '@emotion/react'; +import {TertiaryButton, TertiaryButtonProps} from '@workday/canvas-kit-react/button'; +import {space, colors, depth} from '@workday/canvas-kit-react/tokens'; import {transformationImportIcon} from '@workday/canvas-system-icons-web'; import {Tooltip} from '@workday/canvas-kit-react/tooltip'; -import {Box} from '@workday/canvas-kit-react/layout'; export type SidePanelVariant = 'standard' | 'alternate'; export type SidePanelTransitionStates = 'collapsed' | 'collapsing' | 'expanded' | 'expanding'; @@ -89,7 +88,17 @@ const createKeyframes = (from: number | string, to: number | string) => { `; }; -const StyledPanel = styled(Box)>({ +const containerVariantStyle: Record = { + alternate: { + backgroundColor: colors.frenchVanilla100, + ...depth[3], + }, + standard: { + backgroundColor: colors.soap100, + }, +}; + +const Panel = styled('section')>({ overflow: 'hidden', position: 'relative', boxSizing: 'border-box', @@ -112,7 +121,7 @@ const SidePanel = ({ onExpandedChange, onStateTransition, origin = 'left', - // variant = 'standard', + variant = 'standard', touched, ...elemProps }: SidePanelProps) => { @@ -169,15 +178,20 @@ const SidePanel = ({ }; return ( - {children} - + ); }; -export type ToggleButtonProps = IconButtonProps & { +export type ToggleButtonProps = TertiaryButtonProps & { /** * The tooltip text to expand the side panel * @default 'Expand' @@ -211,7 +225,7 @@ export type ToggleButtonProps = IconButtonProps & { * A toggle button styled specifically for the side panel container. */ const ToggleButton = ({ - variant = 'plain', + variant = undefined, icon = transformationImportIcon, tooltipTextExpand: expandLabel = 'Expand', tooltipTextCollapse: collapseLabel = 'Collapse', @@ -235,9 +249,10 @@ const ToggleButton = ({ const buttonStyle = css({ position: 'absolute', top: space.m, + width: space.l, right: context.state === 'collapsed' ? 0 : rtlOrigin === 'left' ? space.s : undefined, left: context.state === 'collapsed' ? 0 : rtlOrigin === 'right' ? space.s : undefined, - margin: context.state === 'collapsed' ? 'auto' : 0, // to override the -8px margin for IconButton.Plain + margin: context.state === 'collapsed' ? 'auto' : 0, // to override the -8px margin for TertiaryButton.Plain transform: context.state === 'collapsed' || context.state === 'collapsing' ? `scaleX(${rtlOrigin === 'left' ? '1' : '-1'})` @@ -246,7 +261,7 @@ const ToggleButton = ({ return ( - + ); }; diff --git a/modules/preview-react/side-panel/stories/SidePanel.stories.mdx b/modules/preview-react/side-panel/stories/SidePanel.stories.mdx index 6ae8cc08c0..782db0a135 100644 --- a/modules/preview-react/side-panel/stories/SidePanel.stories.mdx +++ b/modules/preview-react/side-panel/stories/SidePanel.stories.mdx @@ -126,8 +126,8 @@ the first child of `SidePanel`. #### Props -This is a standard Canvas Kit `IconButton` and will accept -[all those props](https://workday.github.io/canvas-kit?path=/docs/components-buttons-button-react-icon-button--circle#props). +This is a standard Canvas Kit `TertiaryButton` and will accept +[all those props](http://localhost:9001/?path=/docs/components-buttons-button-react--tertiary#props-2). ## Hooks diff --git a/modules/react/_examples/stories/examples/GlobalHeader.tsx b/modules/react/_examples/stories/examples/GlobalHeader.tsx index c8c5e5911f..e7ea4116ab 100644 --- a/modules/react/_examples/stories/examples/GlobalHeader.tsx +++ b/modules/react/_examples/stories/examples/GlobalHeader.tsx @@ -9,7 +9,7 @@ import { assistantIcon, } from '@workday/canvas-system-icons-web'; -import {IconButton, Hyperlink} from '@workday/canvas-kit-react/button'; +import {TertiaryButton, Hyperlink} from '@workday/canvas-kit-react/button'; import {Avatar} from '@workday/canvas-kit-react/avatar'; import {HStack, HStackProps, StackSpacing} from '@workday/canvas-kit-react/layout'; import {SearchForm} from '@workday/canvas-kit-labs-react'; @@ -21,7 +21,7 @@ interface HeaderItemProps extends Omit { export const Basic = () => ( - + @@ -30,9 +30,9 @@ export const Basic = () => ( 1} /> - - - + + + diff --git a/modules/react/_examples/stories/examples/PageHeader.tsx b/modules/react/_examples/stories/examples/PageHeader.tsx index d4cc51486d..99a52a599e 100644 --- a/modules/react/_examples/stories/examples/PageHeader.tsx +++ b/modules/react/_examples/stories/examples/PageHeader.tsx @@ -4,7 +4,7 @@ import {createComponent, styled} from '@workday/canvas-kit-react/common'; import {colors, gradients, space, type} from '@workday/canvas-kit-react/tokens'; import {HStack, HStackProps, StackSpacing} from '@workday/canvas-kit-react/layout'; -import {IconButton} from '@workday/canvas-kit-react/button'; +import {TertiaryButton} from '@workday/canvas-kit-react/button'; import {justifyIcon, notificationsIcon} from '@workday/canvas-system-icons-web'; interface HeaderItemProps extends Omit { @@ -15,8 +15,8 @@ export const Basic = () => ( Page Header - - + + ); diff --git a/modules/react/action-bar/stories/examples/Basic.tsx b/modules/react/action-bar/stories/examples/Basic.tsx index 31a7d108cc..45a960977f 100644 --- a/modules/react/action-bar/stories/examples/Basic.tsx +++ b/modules/react/action-bar/stories/examples/Basic.tsx @@ -2,10 +2,12 @@ import React from 'react'; import {ActionBar} from '@workday/canvas-kit-react/action-bar'; import {PrimaryButton, SecondaryButton} from '@workday/canvas-kit-react/button'; +import {relatedActionsIcon} from '@workday/canvas-system-icons-web'; export const Basic = () => ( First Action Second Action + ); diff --git a/modules/react/badge/README.md b/modules/react/badge/README.md index 45ee4e7dc9..cb83d3b531 100644 --- a/modules/react/badge/README.md +++ b/modules/react/badge/README.md @@ -32,15 +32,14 @@ const AccessibleHide = styled('div')({ ... - + New notifications diff --git a/modules/react/banner/lib/BannerIcon.tsx b/modules/react/banner/lib/BannerIcon.tsx index dd1cb0cdd4..2a823104b0 100644 --- a/modules/react/banner/lib/BannerIcon.tsx +++ b/modules/react/banner/lib/BannerIcon.tsx @@ -32,8 +32,8 @@ export const BannerIcon = createComponent('span')({ const localModel = useModelContext(BannerModelContext, model); // SystemIcon is still a class based component so we need to set ref manually. - const {ref: iconRef, icon: defaultIcon, ...props} = useBannerIcon(localModel, elemProps, ref); + const {icon: defaultIcon, ...props} = useBannerIcon(localModel, elemProps); - return ; + return ; }, }); diff --git a/modules/react/button/README.md b/modules/react/button/README.md index 374dbc21ca..6d5e33f4a6 100644 --- a/modules/react/button/README.md +++ b/modules/react/button/README.md @@ -2,7 +2,7 @@ Clickable button elements that extend the native `