Skip to content

Commit

Permalink
feat(ContentSwitcher): add icon only ContentSwitcherVariant
Browse files Browse the repository at this point in the history
  • Loading branch information
dakahn committed Oct 14, 2021
1 parent a82d3f4 commit b311e7b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@
height: rem(48px);
}

.#{$prefix}--content-switcher--icon-only {
width: rem(160px);

.#{$prefix}--content-switcher-btn {
display: flex;
justify-content: center;
}
}

.#{$prefix}--content-switcher-btn {
@include reset;
@include type-style('body-short-01');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { withKnobs, boolean, select } from '@storybook/addon-knobs';
import ContentSwitcher from '../ContentSwitcher';
import Switch from '../Switch';
import mdx from './ContentSwitcher.mdx';
import { Sunrise16, Sun16, Sunset16 } from '@carbon/icons-react';

const selectionModes = {
'Change selection automatically upon focus (automatic)': 'automatic',
Expand Down Expand Up @@ -65,6 +66,20 @@ export const Default = () => (
</ContentSwitcher>
);

export const IconOnly = () => (
<ContentSwitcher hasIconOnly onChange={() => {}}>
<Switch name="one" aria-label="breakfast menu">
<Sunrise16 />
</Switch>
<Switch name="two" aria-label="lunch menu">
<Sun16 />
</Switch>
<Switch name="three" aria-label="dinner menu">
<Sunset16 />
</Switch>
</ContentSwitcher>
);

Default.story = { name: 'Content Switcher' };

export const ContentSwitcherPlayground = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export default class ContentSwitcher extends React.Component {
*/
className: PropTypes.string,

/**
* Specify if the button is an icon-only button
*/
hasIconOnly: PropTypes.bool,

/**
* `true` to use the light variant.
*/
Expand Down Expand Up @@ -138,18 +143,21 @@ export default class ContentSwitcher extends React.Component {
selectedIndex, // eslint-disable-line no-unused-vars
selectionMode, // eslint-disable-line no-unused-vars
size,
hasIconOnly,
...other
} = this.props;

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

return (
<div {...other} className={classes} role="tablist">
{React.Children.map(children, (child, index) =>
React.cloneElement(child, {
hasIconOnly,
index,
onClick: composeEventHandlers([
this.handleChildChange,
Expand Down
36 changes: 31 additions & 5 deletions packages/react/src/components/Switch/Switch.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const { prefix } = settings;

const Switch = React.forwardRef(function Switch(props, tabRef) {
const {
children,
className,
disabled,
index,
Expand All @@ -22,6 +23,7 @@ const Switch = React.forwardRef(function Switch(props, tabRef) {
onKeyDown,
selected,
text,
hasIconOnly,
...other
} = props;

Expand Down Expand Up @@ -56,16 +58,29 @@ const Switch = React.forwardRef(function Switch(props, tabRef) {
aria-selected={selected}
{...other}
{...commonProps}>
<span className={`${prefix}--content-switcher__label`} title={text}>
{text}
</span>
{hasIconOnly ? (
React.Children.map(children, (child) =>
React.cloneElement(child, {
className: `${prefix}--content-switcher__icon`,
})
)
) : (
<span className={`${prefix}--content-switcher__label`} title={text}>
{text}
</span>
)}
</button>
);
});

Switch.displayName = 'Switch';

Switch.propTypes = {
/**
* Pass in an icon to be rendered in an iconOnly content switcher button
*/
children: PropTypes.node,

/**
* Specify an optional className to be added to your Switch
*/
Expand All @@ -76,6 +91,18 @@ Switch.propTypes = {
*/
disabled: PropTypes.bool,

/**
* If specifying the `hasIconOnly` prop, provide an aria-label for each tab that can
* be read by screen readers
*/
hasIconOnly: (props) => {
if (props.hasIconOnly && !props['aria-label']) {
return new Error(
'hasIconOnly property specified without also providing aria-labels.'
);
}
},

/**
* The index of your Switch in your ContentSwitcher that is used for event handlers.
* Reserved for usage in ContentSwitcher
Expand Down Expand Up @@ -107,12 +134,11 @@ Switch.propTypes = {
/**
* Provide the contents of your Switch
*/
text: PropTypes.string.isRequired,
text: PropTypes.string,
};

Switch.defaultProps = {
selected: false,
text: 'Provide text',
onClick: () => {},
onKeyDown: () => {},
};
Expand Down

0 comments on commit b311e7b

Please sign in to comment.