Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(action-bar): Refactor ActionBar component #1396

Merged
merged 19 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6239925
feat(action-bar): Refactor ActionBar
RayRedGoose Dec 16, 2021
b4acd4d
test(action-bar): Add jest component test and visual tests for storybook
RayRedGoose Dec 16, 2021
89f6a1f
docs(action-bar): Update documentation for ActionBar
RayRedGoose Dec 16, 2021
658029f
chore(action-bar): Create codemod for ActionBar
RayRedGoose Dec 16, 2021
bc11ed1
fix(action-bar): Fix container padding for responsive styles
RayRedGoose Dec 16, 2021
9065cd4
chore: Add csstype package to react
RayRedGoose Dec 17, 2021
aa859e2
docs: Add ActionBar updates to 7.0-MIGRATION-GUIDE.mdx
RayRedGoose Dec 20, 2021
a305ddd
docs: Update 7.0-MIGRATION-GUIDE.mdx
RayRedGoose Dec 20, 2021
4de8686
feat(action-bar): Convert Styled div to HStack
RayRedGoose Dec 22, 2021
07c1b33
feat(action-bar): Remove export for ActionBarProps
RayRedGoose Dec 22, 2021
6ce5bcb
docs(action-bar): Change to correct component name
RayRedGoose Dec 22, 2021
9f94d91
feat(action-bar): Update ActionBarProps
RayRedGoose Jan 4, 2022
4e0ff55
feat(action-bar): Replace styles from Styled component to props
RayRedGoose Jan 4, 2022
b045b99
chore: Remove unused csstype package
RayRedGoose Jan 4, 2022
07580cd
docs(action-bar): Update modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx
RayRedGoose Jan 6, 2022
801597a
feat(action-bar): Fix issue with default left positioning
RayRedGoose Jan 6, 2022
d583fdc
chore(action-bar): Add a codemod to change a default import
RayRedGoose Jan 7, 2022
c5f898a
Merge branch 'prerelease/major' into 1382iss_refactor-action-bar
RayRedGoose Jan 7, 2022
d97852a
Merge branch 'prerelease/major' into 1382iss_refactor-action-bar
NicholasBoll Jan 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions modules/codemod/lib/v7/compoundActionBar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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/action-bar'
);

if (!containsCanvasImports) {
return file.source;
}

root
.find(
j.JSXElement,
(value: JSXElement) =>
value.openingElement.name.type === 'JSXIdentifier' &&
(value.openingElement.name.name === importMap.ActionBar ||
value.openingElement.name.name === styledMap.ActionBar)
)
.forEach(nodePath => {
const attributes = nodePath.value.openingElement.attributes;

if (attributes) {
// remove these attributes from ActionBar
nodePath.value.openingElement.attributes = attributes.filter(item =>
item.type === 'JSXAttribute' &&
item.name.type === 'JSXIdentifier' &&
['fixed'].includes(item.name.name)
? false
: true
);
}
});

return root.toSource();
}
23 changes: 23 additions & 0 deletions modules/codemod/lib/v7/spec/compoundActionBar.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {expectTransformFactory} from './expectTransformFactory';
import transform from '../compoundActionBar';
import {stripIndent} from 'common-tags';

const expectTransform = expectTransformFactory(transform);

describe('ActionBar', () => {
it('should restructure ActionBar usages with props', () => {
const input = stripIndent`
import {ActionBar} from '@workday/canvas-kit-react/action-bar'

<ActionBar fixed="true" />
`;

const expected = stripIndent`
import {ActionBar} from '@workday/canvas-kit-react/action-bar'

<ActionBar />
`;

expectTransform(input, expected);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two questions:

  • Will this support default imports? import ActionBar from '@workday/canvas-kit-react/action-bar
  • Will this support imports from @workday/canvas-kit-react?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • No. There is no default import from action-bar files.
  • Yes. It supports imports from main directory.

});
});
14 changes: 14 additions & 0 deletions modules/docs/mdx/7.0-MIGRATION-GUIDE.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Below are the breaking changes made in Canvas Kit v7. Please
any questions about the update.

- [Codemod](#codemod)
- [ActionBar Component Updates](#actionbar-component-updates)

## Codemod

Expand All @@ -35,3 +36,16 @@ rollback more easily if necessary.**
[Let us know](https://github.com/Workday/canvas-kit/issues/new?labels=bug&template=bug.md) if you
encounter any issues or use cases that we've missed. The `@workday/canvas-kit-codemod` package will
help us maintain additional codemod transforms to make future migrations easier.

## ActionBar Component Updates

We've refactored our ActionBar components to simplify logic.

PR: https://github.com/Workday/canvas-kit/pull/1396

**Changes:**

- Component has been converted to compound component.
- `fixed` prop has been removed from component.
- Now ActionBar uses `position` prop to set container position instead `fixed` props.
RayRedGoose marked this conversation as resolved.
Show resolved Hide resolved
- Fixed position has been set as default if there is not passed `position` prop.
57 changes: 4 additions & 53 deletions modules/react/action-bar/README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,6 @@
# Canvas Kit Action Bar
# Canvas Kit React Action Bar

Full width toolbar fixed to bottom of screen.
`ActionBar` contains primary and secondary actions related to a page or task.

Although not required, [buttons](../../button/react) are often used in in action bars. The primary
action button should be left aligned followed by secondary buttons. The primary button is on the
right only in task orchestration and on mobile devices.

## Installation

```sh
yarn add @workday/canvas-kit-react
```

## Usage

```tsx
import * as React from 'react';
import {PrimaryButton, SecondaryButton} from '@workday/canvas-kit-react/button';
import {ActionBar} from '@workday/canvas-kit-react/action-bar';

<ActionBar>
<PrimaryButton variant="primary">Button</PrimaryButton>
<SecondaryButton>Button</SecondaryButton>
<SecondaryButton>Button</SecondaryButton>
</ActionBar>;
```

## Static Properties

> None

## Component Props

### Required

> None

### Optional

#### `fixed: boolean`

> Fixes the toolbar to the bottom of the window (uses `position: fixed`)

## Responsive Behavior

At 575px, responsive styles will take effect:

- Applies a flex box to the buttons
- Makes single-button groups full width
- All buttons will become the same width (`flex: 1`).
- Button order will become reversed, making left-aligned primary buttons right-aligned.

> When on a mobile form factor, the button placement should flip to have the primary button on the
> far right.
For more detailed information on this component, please refer to the
[storybook documentation](https://workday.github.io/canvas-kit/?path=/docs/components-buttons-action-bar-react--basic)
4 changes: 0 additions & 4 deletions modules/react/action-bar/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
import ActionBar from './lib/ActionBar';

export default ActionBar;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WIll the codemod also update any default imports to named imports? E.g.

import ActionBar from '@workday/canvas-kit-react/action-bar';

becomes this:

import { ActionBar } from '@workday/canvas-kit-react/action-bar';

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching it! I've updated existing codemod to add a script that changes default import to named or renamed import from action-bar package. Now codemod should cover this problem.

export {ActionBar};
export * from './lib/ActionBar';
109 changes: 44 additions & 65 deletions modules/react/action-bar/lib/ActionBar.tsx
Original file line number Diff line number Diff line change
@@ -1,76 +1,55 @@
import * as React from 'react';
import {styled} from '@workday/canvas-kit-react/common';
import {colors, commonColors, space, CSSProperties} from '@workday/canvas-kit-react/tokens';
import {Globals} from 'csstype';
import {createComponent, styled, StyledType} from '@workday/canvas-kit-react/common';
import {commonColors, colors, space} from '@workday/canvas-kit-react/tokens';
import {HStack, HStackProps} from '@workday/canvas-kit-labs-react';

export interface ActionBarProps extends React.HTMLAttributes<HTMLDivElement> {
type PropertyPosition =
| Globals
| '-webkit-sticky'
| 'absolute'
| 'fixed'
| 'relative'
| 'static'
| 'sticky';

export interface ActionBarProps {
/**
* If true, fix the ActionBar to the bottom of the screen.
* @default false
* Sets the position for the container
* @default "fixed"
*/
fixed?: boolean;
}

function getFixedStyles(fixed = false): CSSProperties {
return fixed
? {
position: 'fixed',
left: 0,
bottom: 0,
right: 0,
}
: {};
position?: PropertyPosition;
}

const ActionBarContainer = styled('div')<ActionBarProps>(
{
borderTop: `solid 1px ${colors.soap400}`,
background: commonColors.background,
const ResponsiveHStack = styled(HStack)<HStackProps & StyledType>(({theme}) => ({
[theme.canvas.breakpoints.down('s')]: {
padding: space.s,
boxShadow: '0 -2px 4px rgba(0, 0, 0, 0.08)',
},
({fixed, theme}) => {
return {
...getFixedStyles(fixed),
[theme.canvas.breakpoints.down('s')]: {
padding: space.xxs,
},
};
}
);

const ChildrenContainer = styled('div')(
{
display: 'inline-block',
padding: `0 ${space.m}`,
'*:not(:first-of-type)': {
marginLeft: space.s,
'> *:not(div)': {
flex: 1,
},
},
({theme}) => ({
[theme.canvas.breakpoints.down('s')]: {
display: 'flex',
padding: space.xxs,
justifyContent: 'center',
flexDirection: 'row-reverse',
'> *': {
flex: 1,
'&:not(:first-of-type)': {
marginRight: space.s,
marginLeft: 0,
},
},
},
})
);
}));

export default class ActionBar extends React.Component<ActionBarProps> {
public render() {
const {fixed, children, ...elemProps} = this.props;
const containerStyles: Omit<HStackProps, 'spacing'> = {
background: commonColors.background,
borderTop: `solid 1px ${colors.soap400}`,
bottom: 0,
depth: 1,
left: 0,
padding: `${space.s} ${space.xl} `,
width: '100%',
};

return (
<ActionBarContainer {...elemProps} fixed={fixed}>
<ChildrenContainer>{children}</ChildrenContainer>
</ActionBarContainer>
);
}
}
export const ActionBar = createComponent('div')({
displayName: 'ActionBar',
Component: ({position = 'fixed', ...elProps}: ActionBarProps, ref, Element) => (
<ResponsiveHStack
ref={ref}
as={Element}
position={position}
spacing="s"
{...containerStyles}
{...elProps}
/>
),
});
RayRedGoose marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 2 additions & 20 deletions modules/react/action-bar/spec/ActionBar.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
import * as React from 'react';
import {mount} from 'enzyme';
import ActionBar from '../index';
import {ActionBar} from '../lib/ActionBar';

describe('ActionBar', () => {
const cb = jest.fn();
afterEach(() => {
cb.mockReset();
});

test('render a action bar with id', () => {
const component = mount(<ActionBar id="myActionBar">Button Label</ActionBar>);
expect(component.find(ActionBar).props().id).toBe('myActionBar');
component.unmount();
});

test('ActionBar should spread extra props', () => {
const component = mount(<ActionBar data-propspread="test" />);
const container = component.at(0).getDOMNode();
expect(container.getAttribute('data-propspread')).toBe('test');
component.unmount();
});
verifyComponent(ActionBar, {});
});
32 changes: 7 additions & 25 deletions modules/react/action-bar/stories/ActionBar.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {Basic} from './examples/Basic';

# Canvas Kit Action Bar

Full width button toolbar fixed to bottom of screen.
Action Bar contains primary and secondary actions related to a page or task.

## Installation

Expand All @@ -22,38 +22,20 @@ yarn add @workday/canvas-kit-react
### Basic Example

Here is a basic example of an `ActionBar` with two buttons. Although not required,
[buttons](../../button) are often used in in action bars. The primary action button should be left
aligned followed by secondary buttons. The primary button is on the right only in "progression-based
UIs" and on mobile devices.
[buttons](../../button) are often used in in action bars. The primary action button should be used
only once and left aligned followed by secondary buttons.

<ExampleCodeBlock code={Basic} />

### Fixed

The Action Bar generally lives at the bottom of the viewport. If you would like this behavior
automatically (using `position: fixed`), you can use the `fixed` prop.

```tsx
<ActionBar fixed={true}>
<PrimaryButton>Button</PrimaryButton>
<SecondaryButton>Button</SecondaryButton>
</ActionBar>
```

## Responsive Behavior

At 575px, responsive styles will take effect:

- Applies a flex box to the buttons
- Makes single-button groups full width
- All buttons will become the same width (`flex: 1`).
- Button order will become reversed, making left-aligned primary buttons right-aligned.
At 768px, responsive styles will take effect:

> When on a mobile form factor, the button placement should flip to have the primary button on the
> far right.
- All primary and secondary buttons will become the same width (`flex: 1`).
- Container Bar padding will be decreased to small (`16px`) for all sides.

## Props

Undocumented props are spread to the underlying container `<div>` element.
Undocumented props are spread to the underlying `HBlock` component.
RayRedGoose marked this conversation as resolved.
Show resolved Hide resolved

<ArgsTable of={ActionBar} />
6 changes: 3 additions & 3 deletions modules/react/action-bar/stories/examples/Basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {ActionBar} from '@workday/canvas-kit-react/action-bar';
import {PrimaryButton, SecondaryButton} from '@workday/canvas-kit-react/button';

export const Basic = () => (
<ActionBar>
<PrimaryButton>Button</PrimaryButton>
<SecondaryButton>Button</SecondaryButton>
<ActionBar position="relative">
<PrimaryButton>First Action</PrimaryButton>
<SecondaryButton>Second Action</SecondaryButton>
</ActionBar>
);
Loading