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

fix(expandable): clean up classes #265

Merged
94 changes: 37 additions & 57 deletions packages/expandable/src/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,21 @@ import { ExpandTransition, UnstyledHeading } from '../../_helpers/index.js';
import type { ExpandableProps } from './props.js';

export function Expandable(props: ExpandableProps) {
// eslint-disable-next-line
const { children, expanded = false, title = '', info = false, box = false, bleed = false, buttonClass = '', contentClass = '', className, onChange, chevron = true, animated, headingLevel, ...rest } = props;
const {
children,
expanded = false,
title = '',
box = false,
bleed = false,
buttonClass = '',
contentClass = '',
className,
onChange,
chevron = true,
animated,
headingLevel,
...rest
} = props;

const [stateExpanded, setStateExpanded] = React.useState(expanded);
const [showChevronUp, setShowChevronUp] = React.useState(expanded);
Expand All @@ -29,78 +42,45 @@ export function Expandable(props: ExpandableProps) {
if (onChange) onChange(!state);
};

const wrapperClasses = classNames([ccExpandable.expandable, box && ccExpandable.expandableBox, bleed && ccExpandable.expandableBleed]);

const buttonClasses = classNames(buttonClass, [ccExpandable.button, box && ccExpandable.buttonBox]);

const chevronClasses = classNames([ccExpandable.chevron, !box && ccExpandable.chevronNonBox]);

const chevronIcon = () => {
const upClasses = classNames([ccExpandable.chevronTransform, !stateExpanded && showChevronUp && ccExpandable.chevronCollapse]);
const downClasses = classNames([ccExpandable.chevronTransform, stateExpanded && !showChevronUp && ccExpandable.chevronExpand]);

return showChevronUp ? <IconChevronUp16 className={upClasses} /> : <IconChevronDown16 className={downClasses} />;
};

const contentClasses = classNames(contentClass, [box && ccBox.box, box && title && ccExpandable.contentWithTitle]);

return (
<div
{...rest}
className={classNames(className, {
[ccExpandable.expandable]: true,
[ccExpandable.expandableBox]: box,
[ccExpandable.expandableBleed]: bleed,
})}>
<div {...rest} className={wrapperClasses}>
<UnstyledHeading level={headingLevel}>
<button
type="button"
aria-expanded={stateExpanded}
className={classNames({
[buttonClass || '']: true,
[ccExpandable.button]: true,
[ccExpandable.buttonBox]: box,
})}
onClick={() => toggleExpandable(stateExpanded)}>
<button type="button" aria-expanded={stateExpanded} className={buttonClasses} onClick={() => toggleExpandable(stateExpanded)}>
<div className={ccExpandable.title}>
{typeof title === 'string' ? <span className={ccExpandable.titleType}>{title}</span> : title}
{chevron && (
<div
className={classNames({
[ccExpandable.chevron]: true,
[ccExpandable.chevronBox]: box,
[ccExpandable.chevronNonBox]: !box,
})}>
{showChevronUp ? (
<IconChevronUp16
className={classNames({
[ccExpandable.chevronTransform]: true,
[ccExpandable.chevronCollapse]: !stateExpanded && showChevronUp,
})}
/>
) : (
<IconChevronDown16
className={classNames({
[ccExpandable.chevronTransform]: true,
[ccExpandable.chevronExpand]: stateExpanded && !showChevronUp,
})}
/>
)}
</div>
)}
{chevron && <div className={chevronClasses}>{chevronIcon()}</div>}
</div>
</button>
</UnstyledHeading>
<ExpansionBehaviour animated={animated} stateExpanded={stateExpanded}>
<div
className={classNames({
[contentClass || '']: true,
[ccBox.box]: box,
[ccExpandable.paddingTop]: box && title,
})}>
{children}
</div>
<div className={contentClasses}>{children}</div>
</ExpansionBehaviour>
</div>
);
}

function ExpansionBehaviour({ animated, stateExpanded, children }) {
const expansionClasses = classNames([ccExpandable.expansion, !stateExpanded && ccExpandable.expansionNotExpanded]);

return animated ? (
<ExpandTransition show={stateExpanded}>{children}</ExpandTransition>
) : (
<div
className={classNames({
[ccExpandable.expansion]: true,
[ccExpandable.expansionNotExpanded]: !stateExpanded,
})}
data-testid="expandable-content"
aria-hidden={!stateExpanded ? true : undefined}>
<div className={expansionClasses} data-testid="expandable-content" aria-hidden={!stateExpanded ? true : undefined}>
{children}
</div>
);
Expand Down
6 changes: 0 additions & 6 deletions packages/expandable/src/props.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ export type ExpandableProps = {
*/
bleed?: boolean;

/**
* Styles the box with light blue color
* @default false
*/
info?: boolean;

/**
* The state of the component, either true for expanded or false for closed.
* @default false
Expand Down
17 changes: 5 additions & 12 deletions packages/expandable/stories/Expandable.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,15 @@ export const BoxWithCustomIcon = () => (
<IconBag16 />
</div>
}
box
info>
<h2>I am expandable</h2>
</Expandable>
);

export const InfoBox = () => (
<Expandable title="This is a title" box info>
box>
<h2>I am expandable</h2>
</Expandable>
);

export const Controlled = () => {
const [open, setOpen] = React.useState(false);
return (
<Expandable title={open ? 'Open' : 'Closed'} box info onChange={setOpen}>
<Expandable title={open ? 'Open' : 'Closed'} box onChange={setOpen}>
<h1>I am expandable</h1>
</Expandable>
);
Expand All @@ -52,20 +45,20 @@ export const Controlled = () => {
export const NoChevron = () => {
const [open, setOpen] = React.useState(false);
return (
<Expandable title={open ? 'Open' : 'Closed'} box info chevron={false} onChange={setOpen}>
<Expandable title={open ? 'Open' : 'Closed'} box chevron={false} onChange={setOpen}>
<h2>I am expandable</h2>
</Expandable>
);
};

export const Animated = () => (
<Expandable title="Animated box" box info animated>
<Expandable title="Animated box" box animated>
<h2>I am expandable</h2>
</Expandable>
);

export const AnimatedExpanded = () => (
<Expandable title="Animated box" expanded box info animated>
<Expandable title="Animated box" expanded box animated>
<h2>I am expandable</h2>
</Expandable>
);
Expand Down
Loading