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(ContentSwitcher): add icon-only ContentSwitcher #13378

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
31133ec
feat(ContentSwitcher): add icon-only ContentSwitcher
tw15egan Mar 20, 2023
2067a8d
feat(ContentSwitcher): add icon-only ContentSwitcher functionality
tw15egan Mar 20, 2023
c1191b3
style(ContentSwitcher): add styles for icon-only ContentSwitcher
tw15egan Mar 20, 2023
1a4b4d4
test(ContentSwitcher): add e2e tests for icon-only ContentSwitcher
tw15egan Mar 21, 2023
57b516b
fix(Switch): remove extra aria-label
tw15egan Mar 21, 2023
02aa257
feat(IconSwitch): refactor new features to IconSwitch component
tw15egan Mar 22, 2023
5d44cd3
fix(ContentSwitcher): remove isIconOnly prop
tw15egan Mar 22, 2023
94f7e5f
chore(test): update snapshots
tw15egan Mar 22, 2023
3c33ab8
feat(IconSwitch): add IconButton props, refactor
tw15egan Mar 23, 2023
2f91e68
test(ContentSwitcher): update snapshots
tw15egan Mar 23, 2023
e0d32ec
refactor(IconSwitch): remove defaultProps
tw15egan Mar 23, 2023
526f087
test(IconSwitch): add tests
tw15egan Mar 23, 2023
2ad20ff
refactor(IconSwitch): remove wrapper, add wrapperClasses to IconButton
tw15egan Mar 23, 2023
ce3c38b
chore(test): move test back
tw15egan Mar 31, 2023
840025a
chore(test): move test back
tw15egan Mar 31, 2023
7694702
style(ContentSwitcher): make fixes based on design review
tw15egan Mar 31, 2023
759a8d1
style(ContentSwitcher): fix focus issue
tw15egan Apr 10, 2023
dbf5359
test(e2e): add withLayer story, e2e tests
tw15egan Apr 10, 2023
d0d39ea
Merge branch 'main' into icon-only-content-switcher
tw15egan Apr 10, 2023
69acca9
Merge branch 'main' into icon-only-content-switcher
tw15egan Apr 10, 2023
9677d47
Merge branch 'main' into icon-only-content-switcher
kodiakhq[bot] Apr 10, 2023
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
17 changes: 17 additions & 0 deletions e2e/components/ContentSwitcher/ContentSwitcher-test.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ test.describe('ContentSwitcher', () => {
theme,
});
});

test('icon only with layer @vrt', async ({ page }) => {
await snapshotStory(page, {
component: 'ContentSwitcher',
id: 'components-contentswitcher--icon-only-with-layer',
theme,
});
});
});
});

Expand All @@ -41,5 +49,14 @@ test.describe('ContentSwitcher', () => {
},
});
await expect(page).toHaveNoACViolations('ContentSwitcher');

await visitStory(page, {
component: 'ContentSwitcher',
id: 'components-contentswitcher--icon-only',
globals: {
theme: 'white',
},
});
await expect(page).toHaveNoACViolations('ContentSwitcher');
});
});
77 changes: 77 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4004,6 +4004,9 @@ Map {
],
"type": "oneOf",
},
"wrapperClasses": Object {
"type": "string",
},
},
"render": [Function],
},
Expand All @@ -4014,6 +4017,80 @@ Map {
},
},
},
"IconSwitch" => Object {
"$$typeof": Symbol(react.forward_ref),
"propTypes": Object {
"align": Object {
"args": Array [
Array [
"top",
"top-left",
"top-right",
"bottom",
"bottom-left",
"bottom-right",
"left",
"right",
],
],
"type": "oneOf",
},
"children": Object {
"type": "node",
},
"className": Object {
"type": "string",
},
"disabled": Object {
"type": "bool",
},
"enterDelayMs": Object {
"type": "number",
},
"index": Object {
"type": "number",
},
"leaveDelayMs": Object {
"type": "number",
},
"name": Object {
"args": Array [
Array [
Object {
"type": "string",
},
Object {
"type": "number",
},
],
],
"type": "oneOfType",
},
"onClick": Object {
"type": "func",
},
"onKeyDown": Object {
"type": "func",
},
"selected": Object {
"type": "bool",
},
"size": Object {
"args": Array [
Array [
"sm",
"md",
"lg",
],
],
"type": "oneOf",
},
"text": Object {
"type": "string",
},
},
"render": [Function],
},
"IconTab" => Object {
"$$typeof": Symbol(react.forward_ref),
"propTypes": Object {
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/__tests__/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ describe('Carbon Components React', () => {
"Heading",
"IconButton",
"IconSkeleton",
"IconSwitch",
"IconTab",
"IdPrefix",
"InlineLoading",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ export default class ContentSwitcher extends React.Component {

/**
* Specify the size of the Content Switcher. Currently supports either `sm`, 'md' (default) or 'lg` as an option.
* TODO V11: remove `xl` (replaced with lg)
*/
size: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
size: PropTypes.oneOf(['sm', 'md', 'lg']),
};

static contextType = PrefixContext;
Expand Down Expand Up @@ -141,9 +140,14 @@ export default class ContentSwitcher extends React.Component {
...other
} = this.props;

const isIconOnly = React.Children.map(children, (child) => {
return child.type.displayName === 'IconSwitch';
Copy link
Member

Choose a reason for hiding this comment

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

Just want to make a note here that this locks the API so consumers can only use IconSwitch. It could prove problematic if someone were to to roll their own IconSwitch component and names it something different. Let's cross that bridge if we come to it though - no need to over optimize for it right now imo

}).every((val) => val === true);

const classes = classNames(`${prefix}--content-switcher`, className, {
[`${prefix}--content-switcher--light`]: light,
[`${prefix}--content-switcher--${size}`]: size,
[`${prefix}--content-switcher--icon-only`]: isIconOnly,
});

return (
Expand All @@ -158,6 +162,7 @@ export default class ContentSwitcher extends React.Component {
onKeyDown: this.handleChildChange,
selected: index === this.state.selectedIndex,
ref: this.handleItemRef(index),
size,
})
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
import React from 'react';

import { WithLayer } from '../../../.storybook/templates/WithLayer';

import Switch from '../Switch';

import ContentSwitcher from './ContentSwitcher';
import { Switch, IconSwitch } from '../Switch';
import mdx from './ContentSwitcher.mdx';
import { TableOfContents, Workspace, ViewMode_2 } from '@carbon/icons-react';

export default {
title: 'Components/ContentSwitcher',
component: ContentSwitcher,
subcomponents: {
IconSwitch,
Switch,
},
argTypes: {
Expand Down Expand Up @@ -52,6 +52,36 @@ export const _WithLayer = () => (
</WithLayer>
);

export const IconOnly = (args) => (
<ContentSwitcher {...args}>
<IconSwitch name="one" text="Table of Contents">
<TableOfContents />
</IconSwitch>
<IconSwitch name="two" text="Workspace Test">
<Workspace />
</IconSwitch>
<IconSwitch name="three" text="View Mode">
<ViewMode_2 />
</IconSwitch>
</ContentSwitcher>
);

export const IconOnlyWithLayer = (args) => (
<WithLayer>
<ContentSwitcher {...args}>
<IconSwitch name="one" text="Table of Contents">
<TableOfContents />
</IconSwitch>
<IconSwitch name="two" text="Workspace Test">
<Workspace />
</IconSwitch>
<IconSwitch name="three" text="View Mode">
<ViewMode_2 />
</IconSwitch>
</ContentSwitcher>
</WithLayer>
);

export const Playground = (args) => (
<ContentSwitcher {...args}>
<Switch name="one" text="First section" />
Expand Down
11 changes: 10 additions & 1 deletion packages/react/src/components/IconButton/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import Button from '../Button';
import classNames from 'classnames';
import { Tooltip } from '../Tooltip';
import { usePrefix } from '../../internal/usePrefix';
import cx from 'classnames';
Expand All @@ -23,16 +24,19 @@ const IconButton = React.forwardRef(function IconButton(props, ref) {
kind,
label,
leaveDelayMs,
wrapperClasses,
size = 'md',
...rest
} = props;
const prefix = usePrefix();

const tooltipClasses = classNames(wrapperClasses, `${prefix}--icon-tooltip`);

return (
<Tooltip
align={align}
className={`${prefix}--icon-tooltip`}
closeOnActivation={closeOnActivation}
className={tooltipClasses}
defaultOpen={defaultOpen}
enterDelayMs={enterDelayMs}
label={label}
Expand Down Expand Up @@ -111,6 +115,11 @@ IconButton.propTypes = {
* Specify the size of the Button. Defaults to `md`.
*/
size: PropTypes.oneOf(['sm', 'md', 'lg']),

/**
* Specify an optional className to be added to your Tooltip wrapper
*/
wrapperClasses: PropTypes.string,
};

export { IconButton };
Loading