diff --git a/cypress.config.ts b/cypress.config.ts index a3408cadd5..d98cf21741 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -8,6 +8,9 @@ export default defineConfig({ retries: { runMode: 2, }, + env: { + NODE_ENV: 'development', // or 'development', 'production', etc. + }, blockHosts: ['cdn.fontawesome.com'], diff --git a/cypress/component/Modal.spec.tsx b/cypress/component/Modal.spec.tsx index 2464aee1fc..975d938365 100644 --- a/cypress/component/Modal.spec.tsx +++ b/cypress/component/Modal.spec.tsx @@ -452,7 +452,6 @@ context(`given the [Components/Popups/Modal, Without close icon] story is render context(`given the [Components/Popups/Modal, Custom focus] story is rendered`, () => { beforeEach(() => { cy.mount(); - cy.wait(150); }); context('when button is focused', () => { @@ -467,7 +466,9 @@ context(`given the [Components/Popups/Modal, Custom focus] story is rendered`, ( context('when the target button is clicked', () => { beforeEach(() => { - cy.findByRole('button', {name: 'Acknowledge License'}).click(); + cy.findByRole('button', {name: 'Acknowledge License'}).should('exist'); + cy.findByRole('button', {name: 'Acknowledge License'}).focus(); + cy.focused().click(); }); it('should open the modal', () => { diff --git a/cypress/component/Select.spec.tsx b/cypress/component/Select.spec.tsx index a3ad25ab40..08e71a9da7 100644 --- a/cypress/component/Select.spec.tsx +++ b/cypress/component/Select.spec.tsx @@ -293,6 +293,14 @@ describe('Select', () => { context('when the menu is opened', () => { beforeEach(() => { + cy.window().then(win => { + // @ts-ignore mocking window process + win.process = { + env: { + NODE_ENV: 'development', + }, + }; + }); cy.findByRole('combobox').focus().realType('{downarrow}'); }); diff --git a/cypress/support/component.ts b/cypress/support/component.ts index 56f0dfaa8f..93794ea43a 100644 --- a/cypress/support/component.ts +++ b/cypress/support/component.ts @@ -46,6 +46,14 @@ declare global { Cypress.Commands.add('mount', mount); before(() => { + cy.window().then(win => { + // @ts-ignore mocking window for each test + win.process = { + env: { + NODE_ENV: 'development', + }, + }; + }); cy.configureAxe({ rules: [ {id: 'landmark-one-main', enabled: false}, // stories don't require navigation rules diff --git a/modules/codemod/lib/v12/index.ts b/modules/codemod/lib/v12/index.ts new file mode 100644 index 0000000000..44d20888f8 --- /dev/null +++ b/modules/codemod/lib/v12/index.ts @@ -0,0 +1,14 @@ +import {Transform} from 'jscodeshift'; + +import renameFormFieldHorizontal from './renameFormFieldHorizontal'; + +const transform: Transform = (file, api, options) => { + // These will run in order. If your transform depends on others, place yours after dependent transforms + const fixes = [ + // add codemods here + renameFormFieldHorizontal, + ]; + return fixes.reduce((source, fix) => fix({...file, source}, api, options) as string, file.source); +}; + +export default transform; diff --git a/modules/codemod/lib/v12/renameFormFieldHorizontal.ts b/modules/codemod/lib/v12/renameFormFieldHorizontal.ts new file mode 100644 index 0000000000..ad7f2ffa6c --- /dev/null +++ b/modules/codemod/lib/v12/renameFormFieldHorizontal.ts @@ -0,0 +1,50 @@ +import {API, FileInfo, Options, JSXOpeningElement, JSXIdentifier} from 'jscodeshift'; +import {hasImportSpecifiers} from '../v6/utils'; +import {getImportRenameMap} from './utils/getImportRenameMap'; + +const formFieldPackage = '@workday/canvas-kit-preview-react/form-field'; +const packages = [formFieldPackage]; +const packageImports = ['FormField']; + +export default function transformer(file: FileInfo, api: API, options: Options) { + const j = api.jscodeshift; + + const root = j(file.source); + + // exit if the named imports aren't found + if (!hasImportSpecifiers(api, root, packages, packageImports)) { + return file.source; + } + + // getImportRenameMap utility will tell us if the file containsCanvasImports + // and give us an importMap to track what identifiers we need to update + const {importMap, styledMap} = getImportRenameMap(j, root, '@workday/canvas-kit-preview-react'); + + root + .find(j.JSXOpeningElement, (value: JSXOpeningElement) => { + const isCorrectImport = Object.entries(importMap).some( + ([original, imported]) => + imported === (value.name as JSXIdentifier).name && packageImports.includes(original) + ); + + const isCorrectStyled = Object.entries(styledMap).some( + ([original, styled]) => + styled === (value.name as JSXIdentifier).name && packageImports.includes(original) + ); + + return isCorrectImport || isCorrectStyled; + }) + .forEach(nodePath => { + nodePath.node.attributes?.forEach(attr => { + if (attr.type === 'JSXAttribute') { + if (attr.name.name === 'orientation') { + if (attr.value && attr.value.type === 'StringLiteral') { + attr.value = j.stringLiteral('horizontalStart'); + } + } + } + }); + }); + + return root.toSource(); +} diff --git a/modules/codemod/lib/v12/spec/expectTransformFactory.ts b/modules/codemod/lib/v12/spec/expectTransformFactory.ts new file mode 100644 index 0000000000..d2ec7424b0 --- /dev/null +++ b/modules/codemod/lib/v12/spec/expectTransformFactory.ts @@ -0,0 +1,6 @@ +import {runInlineTest} from 'jscodeshift/dist/testUtils'; + +export const expectTransformFactory = + (fn: Function) => (input: string, expected: string, options?: Record) => { + return runInlineTest(fn, options, {source: input}, expected, {parser: 'tsx'}); + }; diff --git a/modules/codemod/lib/v12/spec/renameFormFieldHorizontal.spec.ts b/modules/codemod/lib/v12/spec/renameFormFieldHorizontal.spec.ts new file mode 100644 index 0000000000..18afdce33b --- /dev/null +++ b/modules/codemod/lib/v12/spec/renameFormFieldHorizontal.spec.ts @@ -0,0 +1,75 @@ +import {expectTransformFactory} from './expectTransformFactory'; +import transform from '../renameFormFieldHorizontal'; +import {stripIndent} from 'common-tags'; + +const expectTransform = expectTransformFactory(transform); + +describe('rename horizontal', () => { + it('should not change non-canvas imports', () => { + const input = stripIndent` + import {FormField} from 'any-other-package' + <> + + + `; + + const expected = stripIndent` + import {FormField} from 'any-other-package' + <> + + + `; + expectTransform(input, expected); + }); + + it('should rename orientation horizontal to horizontalStart', () => { + const input = stripIndent` + import {FormField} from '@workday/canvas-kit-preview-react/form-field' + <> + + + `; + + const expected = stripIndent` + import {FormField} from '@workday/canvas-kit-preview-react/form-field' + <> + + + `; + expectTransform(input, expected); + }); + + it('should change renamed FormField', () => { + const input = stripIndent` + import {FormField as CanvasForm} from '@workday/canvas-kit-preview-react/form-field' + + <> + + + `; + + const expected = stripIndent` + import {FormField as CanvasForm} from '@workday/canvas-kit-preview-react/form-field' + + <> + + + `; + expectTransform(input, expected); + }); + + it('should change styled FormField', () => { + const input = stripIndent` + import {FormField} from '@workday/canvas-kit-preview-react/form-field' + const StyledForm = styled(FormField)({color: "#000"}); + + `; + + const expected = stripIndent` + import {FormField} from '@workday/canvas-kit-preview-react/form-field' + const StyledForm = styled(FormField)({color: "#000"}); + + `; + expectTransform(input, expected); + }); +}); diff --git a/modules/codemod/lib/v12/utils/getImportRenameMap.ts b/modules/codemod/lib/v12/utils/getImportRenameMap.ts new file mode 100644 index 0000000000..d0c4a70039 --- /dev/null +++ b/modules/codemod/lib/v12/utils/getImportRenameMap.ts @@ -0,0 +1,63 @@ +import {Collection, JSCodeshift, CallExpression} from 'jscodeshift'; + +export function getImportRenameMap( + j: JSCodeshift, + root: Collection, + mainPackage = '@workday/canvas-kit-react', + packageName = '' +) { + let containsCanvasImports = false; + + // build import name remapping - in case someone renamed imports... + // i.e. `import { IconButton as StyledIconButton } ...` + const importMap: Record = {}; + const styledMap: Record = {}; + root.find(j.ImportDeclaration, node => { + // imports our module + const value = node.source.value; + if ( + typeof value === 'string' && + (value === mainPackage || value.startsWith(mainPackage) || value === packageName) + ) { + containsCanvasImports = true; + (node.specifiers || []).forEach(specifier => { + if (specifier.type === 'ImportSpecifier') { + if (!specifier.local || specifier.local.name === specifier.imported.name) { + importMap[specifier.imported.name] = specifier.imported.name; + } else { + importMap[specifier.imported.name] = specifier.local.name; + } + } + }); + } + return false; + }); + + root + .find(j.CallExpression, (node: CallExpression) => { + if ( + node.callee.type === 'Identifier' && + node.callee.name === 'styled' && + node.arguments[0].type === 'Identifier' + ) { + return true; + } + return false; + }) + .forEach(nodePath => { + if ( + (nodePath.parent.value.type === 'CallExpression' || + nodePath.parent.value.type === 'TaggedTemplateExpression') && + nodePath.parent.parent.value.type === 'VariableDeclarator' && + nodePath.parent.parent.value.id.type === 'Identifier' + ) { + const styledName = nodePath.parent.parent.value.id.name; + + if (nodePath.value.arguments[0].type === 'Identifier') { + styledMap[nodePath.value.arguments[0].name] = styledName; + } + } + }); + + return {containsCanvasImports, importMap, styledMap}; +} diff --git a/modules/docs/mdx/12.0-UPGRADE-GUIDE.mdx b/modules/docs/mdx/12.0-UPGRADE-GUIDE.mdx index eb5c98bb48..c4cd5af1fe 100644 --- a/modules/docs/mdx/12.0-UPGRADE-GUIDE.mdx +++ b/modules/docs/mdx/12.0-UPGRADE-GUIDE.mdx @@ -46,6 +46,7 @@ A note to the reader: - [Component Updates](#component-updates) - [Styling API and CSS Tokens](#styling-api-and-css-tokens) - [Avatar](#avatar) + - [Form Field](#form-field) - [Text Area](#text-area) - [Troubleshooting](#troubleshooting) - [Glossary](#glossary) @@ -102,7 +103,8 @@ from Main instead. **PRs:** [#2825](https://github.com/Workday/canvas-kit/pull/2825), [#2795](https://github.com/Workday/canvas-kit/pull/2795), -[#2793](https://github.com/Workday/canvas-kit/pull/2793) +[#2793](https://github.com/Workday/canvas-kit/pull/2793), +[#2881](https://github.com/Workday/canvas-kit/pull/2881) Several components have been refactored to use our new [Canvas Tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs) and @@ -113,6 +115,7 @@ The following components are affected: - `Avatar` - `Dialog` +- `FormField` - `Modal` - `Popup` - `TextArea` @@ -125,13 +128,36 @@ The following components are affected: ### Avatar -- Avatar no longer uses `SystemIconCircle` for sizing. -- `Avatar.Size` is no longer supported. The `size` prop type has change to accept the following: +- `Avatar.Size` has been deprecated. The `size` prop still accepts `Avatar.Size` in addition to the + following values: `"extraExtraLarge" | "extraLarge" | "large" | "medium" | "small" | "extraSmall" | (string{})` -- `Avatar.Variant` is no longer supported. Enum `AvatarVariant` has been removed. The `variant` type - prop now accepts `"dark" | "light"` +- `Avatar.Variant` has been deprecated. The `variant` prop still accepts `Avatar.Variant` in + addition to the following values: `"dark" | "light"` - The `as` prop now accepts any element, not just `div`. +> **Note:** Both `Avatar.Size` and `Avatar.Variant` have been deprecated in favor of the new string +> union types. You will see a console warn message while in development if you're still using this. +> Please update your types and usage before v13. + +### Form Field + +**PR** [#2881](https://github.com/Workday/canvas-kit/pull/2881) + +The orientation prop on the `FormField` component will be updated to accept the following values: +`vertical`, `horizontalStart`, and `horizontalEnd`. `horizontal` will still be accepted as a value +in v12, but it will be deprecated and slated for removal in a future major release. These changes +are intended to provide more flexibility with label alignments on `FormField` elements. + +> **Note**: The horizontal alignment of start and end are relative to its container, meaning start +> and end match the flex property of `flex-start` and `flex-end`. This is especially applicable for +> moving between RTL (right-to-left) and LTR (left-to-right) languages. + +> **Note:** Orientation "horizontal" has been deprecated. You will see a console warn message +> suggesting to update your types and usage to `horizontalStart`, `horizontalEnd` or `vertical`. + +🤖 The codemod will handle the change of `orientation="horizontal"` to +`orientation="horizontalStart"` if you're using the string literal values. + ### Text Area **PR:** [#2825](https://github.com/Workday/canvas-kit/pull/2825) @@ -209,5 +235,5 @@ experimental code and is analagous to code in alpha. Breaking changes can be deployed to Labs at any time without triggering a major version update and may not be subject to the same rigor in communcation and migration strategies reserved for breaking -changes in [Preview](#preview) and [Main](#main). `import { opacity } from -"@workday/canvas-tokens-web/dist/es6/system"` +changes in [Preview](#preview) and [Main](#main). +`import { opacity } from "@workday/canvas-tokens-web/dist/es6/system"` diff --git a/modules/preview-react/form-field/lib/FormField.tsx b/modules/preview-react/form-field/lib/FormField.tsx index 8d3415c40c..fb5ea6857b 100644 --- a/modules/preview-react/form-field/lib/FormField.tsx +++ b/modules/preview-react/form-field/lib/FormField.tsx @@ -10,12 +10,13 @@ import {FormFieldHint} from './FormFieldHint'; import {FormFieldContainer} from './FormFieldContainer'; import {formFieldStencil} from './formFieldStencil'; +//TODO: Remove `horizontal` option in v13 and the console warn message. export interface FormFieldProps extends FlexProps, GrowthBehavior { /** - * The direction the child elements should stack + * The direction the child elements should stack. In v13, `horizontal` will be removed. Please use `horizontalStart` or `horizontalEnd` for horizontal alignment. * @default vertical */ - orientation?: 'vertical' | 'horizontal'; + orientation?: 'vertical' | 'horizontalStart' | 'horizontalEnd' | 'horizontal'; children: React.ReactNode; } @@ -82,7 +83,7 @@ export const FormField = createContainer('div')({ * `FormField.Container` allows you to properly center `FormField.Label` when the `orientation` is set to `horizontal` and there is hint text.. * * ```tsx - * + * * First Name * * console.log(e)} /> @@ -96,13 +97,21 @@ export const FormField = createContainer('div')({ Container: FormFieldContainer, }, })(({children, grow, orientation, ...elemProps}, Element, model) => { + // TODO: Remove this warning in v13 once we remove horizontal support in favor of horizontalStart and horizontalEnd. + if (process && process.env.NODE_ENV === 'development') { + if (orientation === 'horizontal') { + console.warn( + 'FormField: Orientation option of "horizontal" is deprecated and will be removed in v13. Please update your types and value to use the string literal of "horizontalStart". The following values will be accepted in v13: "horizontalStart" | "horizontalEnd" | "vertical".' + ); + } + } return ( -### Label Position Horizontal +### Label Position Set the `orientation` prop of the Form Field to designate the position of the label relative to the -input component. By default, the orientation will be set to `vertical`. +input component. By default, the orientation will be set to `vertical`. If you want your label to be +horizontal, you have two options: `horizontalStart` and `horizontalEnd`. - +If you want the position of the label at the start of the container, set orientation prop to `horizontalStart`. + + + +If you want the position of the label at the end of the container, set orientation prop to `horizontalEnd`. + + ### Grow diff --git a/modules/preview-react/form-field/stories/FormField.stories.ts b/modules/preview-react/form-field/stories/FormField.stories.ts index 3d561dcf40..dc4b7711c5 100644 --- a/modules/preview-react/form-field/stories/FormField.stories.ts +++ b/modules/preview-react/form-field/stories/FormField.stories.ts @@ -6,7 +6,8 @@ import {Basic as BasicExample} from './examples/Basic'; import {Alert as AlertExample} from './examples/Alert'; import {Error as ErrorExample} from './examples/Error'; import {Disabled as DisabledExample} from './examples/Disabled'; -import {LabelPositionHorizontal as LabelPositionHorizontalExample} from './examples/LabelPositionHorizontal'; +import {LabelPositionHorizontalStart as LabelPositionHorizontalStartExample} from './examples/LabelPositionHorizontalStart'; +import {LabelPositionHorizontalEnd as LabelPositionHorizontalEndExample} from './examples/LabelPositionHorizontalEnd'; import {RefForwarding as RefForwardingExample} from './examples/RefForwarding'; import {Required as RequiredExample} from './examples/Required'; import {Custom as CustomExample} from './examples/Custom'; @@ -42,8 +43,11 @@ export const Error: Story = { export const Disabled: Story = { render: DisabledExample, }; -export const LabelPositionHorizontal: Story = { - render: LabelPositionHorizontalExample, +export const LabelPositionHorizontalStart: Story = { + render: LabelPositionHorizontalStartExample, +}; +export const LabelPositionHorizontalEnd: Story = { + render: LabelPositionHorizontalEndExample, }; export const RefForwarding: Story = { render: RefForwardingExample, diff --git a/modules/preview-react/form-field/stories/examples/AllFields.tsx b/modules/preview-react/form-field/stories/examples/AllFields.tsx index 6251291a48..c1de8aec0f 100644 --- a/modules/preview-react/form-field/stories/examples/AllFields.tsx +++ b/modules/preview-react/form-field/stories/examples/AllFields.tsx @@ -47,7 +47,7 @@ export const AllFields = () => { - + Radio Group Legend @@ -69,7 +69,7 @@ export const AllFields = () => { - + Switch Label diff --git a/modules/preview-react/form-field/stories/examples/Custom.tsx b/modules/preview-react/form-field/stories/examples/Custom.tsx index be540db3a8..a1a8c39ae0 100644 --- a/modules/preview-react/form-field/stories/examples/Custom.tsx +++ b/modules/preview-react/form-field/stories/examples/Custom.tsx @@ -45,7 +45,7 @@ export const Custom = () => { const model = useFormFieldModel({isRequired: true}); return ( - + You can be anything diff --git a/modules/preview-react/form-field/stories/examples/Hint.tsx b/modules/preview-react/form-field/stories/examples/Hint.tsx index 13a2dd015a..013b64e9db 100644 --- a/modules/preview-react/form-field/stories/examples/Hint.tsx +++ b/modules/preview-react/form-field/stories/examples/Hint.tsx @@ -13,7 +13,7 @@ export const Hint = () => { return ( - + First Name diff --git a/modules/preview-react/form-field/stories/examples/LabelPositionHorizontal.tsx b/modules/preview-react/form-field/stories/examples/LabelPositionHorizontal.tsx deleted file mode 100644 index d5d70c4417..0000000000 --- a/modules/preview-react/form-field/stories/examples/LabelPositionHorizontal.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import {TextInput} from '@workday/canvas-kit-react/text-input'; -import {FormField} from '@workday/canvas-kit-preview-react/form-field'; - -export const LabelPositionHorizontal = () => { - const [value, setValue] = React.useState(''); - - const handleChange = (event: React.ChangeEvent) => { - setValue(event.target.value); - }; - - return ( - - Email - - - ); -}; diff --git a/modules/preview-react/form-field/stories/examples/LabelPositionHorizontalEnd.tsx b/modules/preview-react/form-field/stories/examples/LabelPositionHorizontalEnd.tsx new file mode 100644 index 0000000000..98e2ab3abb --- /dev/null +++ b/modules/preview-react/form-field/stories/examples/LabelPositionHorizontalEnd.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import {TextInput} from '@workday/canvas-kit-react/text-input'; +import {FormField} from '@workday/canvas-kit-preview-react/form-field'; +import {createStyles} from '@workday/canvas-kit-styling'; +import {system} from '@workday/canvas-tokens-web'; + +const formStyles = createStyles({ + display: 'flex', + gap: system.space.x2, + flexDirection: 'column', +}); + +export const LabelPositionHorizontalEnd = () => { + const [value, setValue] = React.useState(''); + + const handleChange = (event: React.ChangeEvent) => { + setValue(event.target.value); + }; + + return ( +
+ + Email + + + + Password + + +
+ ); +}; diff --git a/modules/preview-react/form-field/stories/examples/LabelPositionHorizontalStart.tsx b/modules/preview-react/form-field/stories/examples/LabelPositionHorizontalStart.tsx new file mode 100644 index 0000000000..10ccdbd4fa --- /dev/null +++ b/modules/preview-react/form-field/stories/examples/LabelPositionHorizontalStart.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import {TextInput} from '@workday/canvas-kit-react/text-input'; +import {FormField} from '@workday/canvas-kit-preview-react/form-field'; +import {createStyles} from '@workday/canvas-kit-styling'; +import {system} from '@workday/canvas-tokens-web'; + +const formStyles = createStyles({ + display: 'flex', + gap: system.space.x2, + flexDirection: 'column', +}); + +export const LabelPositionHorizontalStart = () => { + const [value, setValue] = React.useState(''); + + const handleChange = (event: React.ChangeEvent) => { + setValue(event.target.value); + }; + + return ( +
+ + Email + + + + Password + + +
+ ); +}; diff --git a/modules/preview-react/radio/stories/examples/LabelPosition.tsx b/modules/preview-react/radio/stories/examples/LabelPosition.tsx index 68ab50e34b..4de7943df4 100644 --- a/modules/preview-react/radio/stories/examples/LabelPosition.tsx +++ b/modules/preview-react/radio/stories/examples/LabelPosition.tsx @@ -12,7 +12,7 @@ export const LabelPosition = () => { } }; return ( - + Choose Your Pizza Crust Deep dish diff --git a/modules/preview-react/radio/stories/testing.stories.tsx b/modules/preview-react/radio/stories/testing.stories.tsx index 3b769404c9..1736e8e9e4 100644 --- a/modules/preview-react/radio/stories/testing.stories.tsx +++ b/modules/preview-react/radio/stories/testing.stories.tsx @@ -99,7 +99,7 @@ export const RadioStates = { columnProps={[ { label: 'Left Label', - props: {label: 'Contact', labelPosition: 'horizontal'}, + props: {label: 'Contact', labelPosition: 'horizontalStart'}, }, { label: 'Top Label', @@ -162,7 +162,7 @@ export const RadioStates = {

RadioGroup (wrapping)

- + Really long label. Really long label. Really long label. Really long label. Really long label. Really long label. diff --git a/modules/preview-react/text-area/lib/TextArea.tsx b/modules/preview-react/text-area/lib/TextArea.tsx index dc35a5a696..518688d324 100644 --- a/modules/preview-react/text-area/lib/TextArea.tsx +++ b/modules/preview-react/text-area/lib/TextArea.tsx @@ -35,7 +35,7 @@ export const TextArea = createContainer('div')({ elemProps, formFieldStencil({ grow, - orientation, + orientation: orientation === 'horizontal' ? 'horizontalStart' : orientation, error: model.state.error, required: model.state.isRequired, }) diff --git a/modules/preview-react/text-area/stories/examples/LabelPositionHorizontal.tsx b/modules/preview-react/text-area/stories/examples/LabelPositionHorizontal.tsx index ce122e39f8..a0490f5d7f 100644 --- a/modules/preview-react/text-area/stories/examples/LabelPositionHorizontal.tsx +++ b/modules/preview-react/text-area/stories/examples/LabelPositionHorizontal.tsx @@ -9,7 +9,7 @@ export const LabelPositionHorizontal = () => { }; return ( - diff --git a/modules/preview-react/text-input/lib/TextInput.tsx b/modules/preview-react/text-input/lib/TextInput.tsx index 106f4ef5d3..8f64af8689 100644 --- a/modules/preview-react/text-input/lib/TextInput.tsx +++ b/modules/preview-react/text-input/lib/TextInput.tsx @@ -39,7 +39,7 @@ export const TextInput = createContainer('div')({ elemProps, formFieldStencil({ grow, - orientation, + orientation: orientation === 'horizontal' ? 'horizontalStart' : orientation, error: model.state.error, required: model.state.isRequired, }) diff --git a/modules/preview-react/text-input/stories/examples/LabelPositionHorizontal.tsx b/modules/preview-react/text-input/stories/examples/LabelPositionHorizontal.tsx index 118f2953ee..490cd3ad51 100644 --- a/modules/preview-react/text-input/stories/examples/LabelPositionHorizontal.tsx +++ b/modules/preview-react/text-input/stories/examples/LabelPositionHorizontal.tsx @@ -9,7 +9,7 @@ export const LabelPositionHorizontal = () => { }; return ( - + Email diff --git a/modules/react/avatar/lib/Avatar.tsx b/modules/react/avatar/lib/Avatar.tsx index 7350c827cf..39785ec952 100644 --- a/modules/react/avatar/lib/Avatar.tsx +++ b/modules/react/avatar/lib/Avatar.tsx @@ -1,20 +1,28 @@ import React, {useState} from 'react'; import {Property} from 'csstype'; import {createComponent, focusRing} from '@workday/canvas-kit-react/common'; -import {createStencil, calc, CSProps} from '@workday/canvas-kit-styling'; +import {createStencil, calc, CSProps, px2rem} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; import {borderRadius} from '@workday/canvas-kit-react/tokens'; -import {SystemIcon, systemIconStencil} from '@workday/canvas-kit-react/icon'; +import {SystemIcon, SystemIconCircleSize, systemIconStencil} from '@workday/canvas-kit-react/icon'; import {userIcon} from '@workday/canvas-system-icons-web'; import {system} from '@workday/canvas-tokens-web'; +/** + * @deprecated `AvatarVariant` is deprecated and will be removed in a future major version. Update your types and values to use the string literal of either `light` or `dark`. + */ +export enum AvatarVariant { + Light, + Dark, +} + export interface AvatarProps extends CSProps { /** * The variant of the avatar. Use `light` on dark backgrounds and `dark` on light backgrounds. * @default "light" */ - variant?: 'light' | 'dark'; + variant?: 'light' | 'dark' | AvatarVariant; /** * The size of the Avatar. * - `extraExtraLarge`: 7.5rem x 7.5rem (120px x 120px) @@ -26,7 +34,15 @@ export interface AvatarProps extends CSProps { * @default "medium" */ size?: /** size of small */ - 'extraSmall' | 'small' | 'medium' | 'large' | 'extraLarge' | 'extraExtraLarge' | (string & {}); + | 'extraSmall' + | 'small' + | 'medium' + | 'large' + | 'extraLarge' + | 'extraExtraLarge' + | (string & {}) + | SystemIconCircleSize + | number; /** * The alt text of the Avatar image. This prop is also used for the aria-label. * @default Avatar @@ -239,6 +255,19 @@ export const Avatar = createComponent('button')({ setImageLoaded(false); }, [url]); + // TODO: Remove this warning for a hard breaking change in v13 + if (process && process.env.NODE_ENV === 'development') { + if (typeof variant === 'number') { + console.warn( + 'Avatar: Avatar.Variant is deprecated and will be removed in v13. Please use a string literal of "light" or "dark"' + ); + } + if (typeof size === 'number') { + console.warn( + "Avatar: Avatar.Size is deprecated and will be removed in v13. Use the string literal values for size: 'extraSmall' | 'small | 'medium' | 'large' | 'extraLarge | 'extraExtraLarge' | (string & {})" + ); + } + } return ( ); }, + subComponents: { + /** + * @deprecated `Avatar.Variant` is deprecated and will be removed in a future major version. Use the string literal of `light` or `dark`. + */ + Variant: AvatarVariant, + /** + * @deprecated `Avatar.Size` is deprecated and will be removed in a future major version. Use the string literal values for size: 'extraSmall' | 'small | 'medium' | 'large' | 'extraLarge | 'extraExtraLarge' | (string & {}) + */ + Size: SystemIconCircleSize, + }, }); diff --git a/modules/react/checkbox/stories/examples/Alert.tsx b/modules/react/checkbox/stories/examples/Alert.tsx index 97c38da533..d1722a16c8 100644 --- a/modules/react/checkbox/stories/examples/Alert.tsx +++ b/modules/react/checkbox/stories/examples/Alert.tsx @@ -10,7 +10,7 @@ export const Alert = () => { }; return ( - + { }; return ( - + { }; return ( - + Terms { }; return ( - + Background Color diff --git a/modules/react/color-picker/stories/color-preview/examples/LabelPosition.tsx b/modules/react/color-picker/stories/color-preview/examples/LabelPosition.tsx index 716f51dbb6..4cc0cb029e 100644 --- a/modules/react/color-picker/stories/color-preview/examples/LabelPosition.tsx +++ b/modules/react/color-picker/stories/color-preview/examples/LabelPosition.tsx @@ -4,7 +4,7 @@ import {ColorPreview} from '@workday/canvas-kit-react/color-picker'; export const LabelPosition = () => { return ( - + Background Color diff --git a/modules/react/combobox/stories/examples/Autocomplete.tsx b/modules/react/combobox/stories/examples/Autocomplete.tsx index 165a9ef0b9..2ee55d247b 100644 --- a/modules/react/combobox/stories/examples/Autocomplete.tsx +++ b/modules/react/combobox/stories/examples/Autocomplete.tsx @@ -105,7 +105,7 @@ export const Autocomplete = () => { ); return ( - + Fruit console.log('input', event.currentTarget.value)}> diff --git a/modules/react/form-field/stories/visual-testing/Radio.stories.tsx b/modules/react/form-field/stories/visual-testing/Radio.stories.tsx index c588bac187..d2cca6c537 100644 --- a/modules/react/form-field/stories/visual-testing/Radio.stories.tsx +++ b/modules/react/form-field/stories/visual-testing/Radio.stories.tsx @@ -91,7 +91,7 @@ export const RadioStates = { columnProps={[ { label: 'Left Label', - props: {label: 'Contact', orientation: 'horizontal'}, + props: {label: 'Contact', orientation: 'horizontalStart'}, }, { label: 'Top Label', @@ -102,7 +102,7 @@ export const RadioStates = { {props => ( {props.label} - {props.orientation === 'horizontal' ? ( + {props.orientation === 'horizontalStart' ? ( {testGroup} {props.error && hintText} @@ -138,7 +138,7 @@ export const RadioStates = { {props.label} {testGroup} - {props.orientation === 'horizontal' && ( + {props.orientation === 'horizontalStart' && ( {testGroup} {props.error && hintText} @@ -151,7 +151,7 @@ export const RadioStates = {

RadioGroup (wrapping)

- + Really long label. Really long label. Really long label. Really long label. Really long label. Really long label. diff --git a/modules/react/form-field/stories/visual-testing/stories_Radio.tsx b/modules/react/form-field/stories/visual-testing/stories_Radio.tsx new file mode 100644 index 0000000000..923766dfb4 --- /dev/null +++ b/modules/react/form-field/stories/visual-testing/stories_Radio.tsx @@ -0,0 +1,230 @@ +import * as React from 'react'; + +import { + ComponentStatesTable, + permutateProps, + StaticStates, +} from '@workday/canvas-kit-react/testing'; +import {withSnapshotsEnabled, customColorTheme} from '../../../../../utils/storybook'; + +import {Radio, RadioGroup} from '@workday/canvas-kit-react/radio'; +import {FormField} from '@workday/canvas-kit-preview-react/form-field'; + +export default withSnapshotsEnabled({ + title: 'Testing/Inputs/Radio', + component: FormField, +}); + +const testGroup = ( + + + + + + +); + +export const RadioStates = () => ( +
+

Radio

+ + { + if (props.disabled && !['', 'hover'].includes(props.className)) { + return false; + } + return true; + } + )} + > + {props => ( + {}} // eslint-disable-line no-empty-function + label="Radio" + /> + )} + + + +

Radio Group

+ + + {props => ( + + {props.label} + {props.orientation === 'horizontal' ? ( + + {testGroup} + {props.error && hintText} + + ) : ( + <> + {testGroup} + {props.error && hintText} + + )} + + )} + + +

Radio Group (grow)

+ + + {props => ( + + {props.label} + {testGroup} + {props.orientation === 'horizontal' && ( + + {testGroup} {props.error && hintText} + + )} + {props.error && hintText} + + )} + + + +

RadioGroup (wrapping)

+
+ + + Really long label. Really long label. Really long label. Really long label. Really long + label. Really long label. + + {testGroup} + + + + Really long label. Really long label. Really long label. Really long label. Really long + label. Really long label. Really long label. Really long label. Really long label. Really + long label. Really long label. Really long label. Really long label. Really long label. + Really long label. Really long label. Really long label. Really long label. Really long + label. Really long label. Really long label. Really long label. Really long label. Really + long label. Really long label. Really long label. + + {testGroup} + +
+
+); + +export const InverseRadioStates = () => ( +
+ + { + if (props.disabled && !['', 'hover'].includes(props.className)) { + return false; + } + return true; + } + )} + > + {props => ( +
+ {}} // eslint-disable-line no-empty-function + label="Radio" + /> +
+ )} +
+
+
+); + +export const RadioThemedStates = () => ; +RadioThemedStates.parameters = { + canvasProviderDecorator: { + theme: customColorTheme, + }, +}; + +export const RadioInverseThemedStates = () => ; +RadioInverseThemedStates.parameters = { + canvasProviderDecorator: { + theme: customColorTheme, + }, +}; diff --git a/modules/react/radio/stories/examples/LabelPosition.tsx b/modules/react/radio/stories/examples/LabelPosition.tsx index e8817943cb..df27e35695 100644 --- a/modules/react/radio/stories/examples/LabelPosition.tsx +++ b/modules/react/radio/stories/examples/LabelPosition.tsx @@ -11,7 +11,7 @@ export const LabelPosition = () => { }; return ( - + Choose Your Pizza Crust diff --git a/modules/react/select/stories/examples/LabelPosition.tsx b/modules/react/select/stories/examples/LabelPosition.tsx index 384211603f..32640334e9 100644 --- a/modules/react/select/stories/examples/LabelPosition.tsx +++ b/modules/react/select/stories/examples/LabelPosition.tsx @@ -20,7 +20,7 @@ export const LabelPosition = () => { return (