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(Disclosure): creating an Disclosure component #2859

Merged
merged 54 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
4eac500
mini progress
LinKCoding Apr 9, 2024
e19534a
got something working
LinKCoding Apr 10, 2024
b2b6882
added spacing
LinKCoding Apr 11, 2024
6021804
text aligns to left now
LinKCoding Apr 11, 2024
718ee70
adding styledanchor
LinKCoding Apr 12, 2024
4652803
styling in a decent place
LinKCoding Apr 12, 2024
d64b589
styling ok
LinKCoding Apr 15, 2024
b8d3140
ran prettier
LinKCoding Apr 15, 2024
be8cc2d
Merge branch 'main' into kl-gm-562
LinKCoding Apr 15, 2024
93df6e5
starting on testing
LinKCoding Apr 18, 2024
abfc202
forgot to save file
LinKCoding Apr 18, 2024
74a5e3d
refactored into smaller components
LinKCoding Apr 22, 2024
9151c3a
some progress
LinKCoding Apr 22, 2024
8b7a585
Merge branch 'main' into kl-gm-562
LinKCoding Apr 22, 2024
a943147
made some stuff optional
LinKCoding Apr 22, 2024
b5b16cb
added optionals and first working test
LinKCoding Apr 23, 2024
6d90f39
changed name to disclosure
LinKCoding Apr 23, 2024
647e686
started on more tests
LinKCoding Apr 24, 2024
0b175f0
tests and story and animation
LinKCoding Apr 28, 2024
649dfa6
unsaved change
LinKCoding Apr 28, 2024
e9052e4
changed button to use a switch/case
LinKCoding May 13, 2024
a80b45b
Merge branch 'main' into kl-gm-562
LinKCoding May 14, 2024
0a4aafa
updated button logic
LinKCoding May 21, 2024
d28ff7c
commented out buttonProps
LinKCoding May 21, 2024
1dd7a82
updated heading and icon sizing
LinKCoding May 22, 2024
be03bf3
prettified
LinKCoding May 22, 2024
d24f356
editted button padding and icon size
LinKCoding May 22, 2024
e8a6387
fixed snapshot
LinKCoding May 22, 2024
846ad9d
updated story
LinKCoding May 22, 2024
645d290
Merge branch 'main' into kl-gm-562
LinKCoding May 22, 2024
1876467
prettified
LinKCoding May 22, 2024
248c1bb
edited story
LinKCoding May 22, 2024
083b580
addressed most of Cass's feedback
LinKCoding May 29, 2024
1de1764
prettified
LinKCoding May 29, 2024
c40448c
addressed Stacey's figma feedback
LinKCoding May 29, 2024
d200774
fixed some lingering issues
LinKCoding May 29, 2024
61198e2
changed onClick prop
LinKCoding May 31, 2024
5157b09
made additional variants to provide optional styling
LinKCoding May 31, 2024
2884d47
updated variant names and stories
LinKCoding Jun 5, 2024
17813df
prettified
LinKCoding Jun 5, 2024
9b70efe
fixed up example
LinKCoding Jun 6, 2024
9ceeb2b
Merge branch 'main' into kl-gm-562
LinKCoding Jun 6, 2024
ebeee3e
fixed stories
LinKCoding Jun 6, 2024
80b86a9
fixed up stories and variants
LinKCoding Jun 10, 2024
2868910
prettified
LinKCoding Jun 10, 2024
e78df21
fixed state issue
LinKCoding Jun 11, 2024
5cd8b09
fixed some types stuff
LinKCoding Jun 11, 2024
015241f
Merge branch 'main' into kl-gm-562
LinKCoding Jun 12, 2024
c5b1d11
converted props to types
LinKCoding Jun 12, 2024
effa49b
fixed expanding/contracting issue
LinKCoding Jun 13, 2024
aac71c4
updated snapshot
LinKCoding Jun 14, 2024
874c39a
fixed transition speed
LinKCoding Jun 21, 2024
dd7b717
Merge branch 'main' into kl-gm-562
LinKCoding Jun 21, 2024
c7b6110
Merge branch 'main' into kl-gm-562
LinKCoding Jun 24, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ exports[`Gamut Exported Keys 1`] = `
"DataTable",
"DeprecatedToolTip",
"Dialog",
"Disclosure",
"Drawer",
"ExpandControl",
"FillButton",
Expand Down
23 changes: 23 additions & 0 deletions packages/gamut/src/Animation/ExpandInCollapseOut.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { motion } from 'framer-motion';

Copy link
Contributor

Choose a reason for hiding this comment

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

love this!!! starting to think we need more gamut documentation on our animations (not in this PR but maybe another ticket for the backlog ✨ )

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, you're right -- I'll cut a ticket!

import { WithChildrenProp } from '../utils';

export const ExpandInCollapseOut: React.FC<WithChildrenProp> = ({
children,
}) => {
return (
<motion.div
initial="collapsed"
exit="collapsed"
animate="expanded"
style={{ overflow: 'hidden' }}
variants={{
expanded: { height: 'auto' },
collapsed: { height: 0 },
}}
transition={{ duration: 0.2, ease: 'easeInOut' }}
>
{children}
</motion.div>
);
};
LinKCoding marked this conversation as resolved.
Show resolved Hide resolved
43 changes: 43 additions & 0 deletions packages/gamut/src/Disclosure/DisclosureBody/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react';

import { Text } from '../../Typography';
import { DisclosureBodyWrapper } from '../elements';
import { getSpacing, renderButton } from '../helpers';
import { DisclosureBodyProps } from '../types';

export const DisclosureBody: React.FC<DisclosureBodyProps> = ({
body,
buttonType = 'TextButton',
buttonPlacement = 'right',
ctaCallback,
ctaText,
hasPanelBg = false,
href,
spacing = 'normal',
}) => {
const buttonRequirements = ctaText && ctaCallback;

const getLineHeight = spacing === 'compact' ? 'title' : 'base';
const { verticalSpacing, horizontalSpacing } = getSpacing(spacing);
return (
<DisclosureBodyWrapper
column
hasPanelBg={hasPanelBg}
mb={verticalSpacing}
mt={4}
mx={horizontalSpacing}
>
<Text width="100%" lineHeight={getLineHeight}>
{body}
</Text>
{buttonRequirements &&
renderButton({
buttonPlacement,
buttonType,
ctaCallback,
ctaText,
href,
})}
</DisclosureBodyWrapper>
);
};
97 changes: 97 additions & 0 deletions packages/gamut/src/Disclosure/DisclosureButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import {
ArrowChevronDownIcon,
MiniChevronDownIcon,
} from '@codecademy/gamut-icons';
import * as React from 'react';

import { Rotation, Text } from '../..';
import { Box, FlexBox } from '../../Box';
import { DisclosureButtonWrapper } from '../elements';
import { getRotationSize, getSpacing, getTitleSize } from '../helpers';
import { DisclosureButtonProps } from '../types';

export const DisclosureButton: React.FC<DisclosureButtonProps> = ({
disabled = false,
heading,
headingLevel = 'h3',
isExpanded,
overline,
setIsExpanded,
spacing = 'normal',
subheading,
}) => {
const handleClick = () => {
if (setIsExpanded) {
setIsExpanded((prev: boolean) => !prev);
}
};

const titleSize = getTitleSize(spacing);
const subheadingSize = spacing === 'normal' ? 'p-base' : 'p-small';
const rotationSize = getRotationSize(spacing);
const { verticalSpacing, horizontalSpacing } = getSpacing(spacing);

return (
<FlexBox>
<DisclosureButtonWrapper
aria-label={isExpanded ? 'Collapse Content' : 'Expand Content'}
aria-expanded={isExpanded}
onClick={handleClick}
width="100%"
variant="interface"
py={verticalSpacing}
px={horizontalSpacing}
disabled={disabled}
height="100%"
>
{overline && (
<Text
textAlign="start"
width="100%"
color="text-secondary"
fontFamily="accent"
variant="p-small"
>
{overline}
</Text>
)}
<FlexBox
flexDirection="row"
justifyContent="space-between"
columnGap={40}
alignItems="center"
>
<Text
textAlign="start"
as={headingLevel}
width="100%"
p={0}
variant={titleSize}
fontWeight="title"
>
{heading}
</Text>

<Box p={8}>
<Rotation
rotated={isExpanded}
height={rotationSize}
width={rotationSize}
>
{spacing === 'normal' ? (
<ArrowChevronDownIcon aria-hidden size={rotationSize} />
) : (
<MiniChevronDownIcon aria-hidden size={rotationSize} />
)}
</Rotation>
</Box>
</FlexBox>
{subheading && (
<Text textAlign="start" width="100%" variant={subheadingSize}>
{subheading}
</Text>
)}
</DisclosureButtonWrapper>
</FlexBox>
);
};
57 changes: 57 additions & 0 deletions packages/gamut/src/Disclosure/__tests__/Disclosure.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { setupRtl } from '@codecademy/gamut-tests';
import userEvent from '@testing-library/user-event';

import { Disclosure } from '..';

const ctaCallback = jest.fn();

const defaultProps = {
header: 'hi there!',
body: <div>This should render when expanded </div>,
withBackground: false,
};

const renderView = setupRtl(Disclosure, defaultProps);

describe('Disclosure', () => {
it('renders the DisclosureBody when DisclosureButton is clicked', () => {
const { view } = renderView({
initiallyExpanded: false,
});

const DisclosureButton = view.getByRole('button');
let DisclosureBodyText = view.queryByText(
'This should render when expanded'
);
expect(DisclosureBodyText).toBeNull();
expect(DisclosureButton.getAttribute('aria-expanded')).toBe('false');

userEvent.click(DisclosureButton);

DisclosureBodyText = view.getByText('This should render when expanded');
expect(DisclosureButton.getAttribute('aria-expanded')).toBe('true');
});

it('renders the body when `initiallyExpanded` is set to true', () => {
const { view } = renderView({
initiallyExpanded: true,
});

const DisclosureButton = view.getByRole('button');
view.getByText('This should render when expanded');

expect(DisclosureButton.getAttribute('aria-expanded')).toBe('true');
});

it("renders the DisclosureBody's button when supplied a `cta` and `ctaCallback` argument", () => {
const { view } = renderView({
initiallyExpanded: true,
ctaText: 'click here',
ctaCallback,
});

const CTAButton = view.getByText('click here');
userEvent.click(CTAButton);
expect(ctaCallback).toBeCalled();
});
});
115 changes: 115 additions & 0 deletions packages/gamut/src/Disclosure/elements.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { states, variant } from '@codecademy/gamut-styles';
import { StyleProps } from '@codecademy/variance';
import styled from '@emotion/styled';

import { Anchor } from '../Anchor';
import { FlexBox } from '../Box';
import { FillButton, StrokeButton, TextButton } from '../Button';

const disclosureWrapperVariants = variant({
defaultVariant: 'default',
base: {
width: '100%',
maxHeight: 'fit-content',
},
variants: {
default: {
bg: 'background',
},
subtle: {
bg: 'background-selected',
},
transparent: {
bg: 'background-current',
},
},
});

const disclosureWrapperStates = states({
hasBorder: {
border: 1,
},
});

type DisclosureWrapperStateProps = StyleProps<typeof disclosureWrapperStates>;
type DisclosureWrapperVariantProps = StyleProps<
typeof disclosureWrapperVariants
>;
export type DisclosureWrapperStyles = DisclosureWrapperStateProps &
DisclosureWrapperVariantProps;

export const DisclosureWrapper = styled(FlexBox)<DisclosureWrapperStyles>(
disclosureWrapperStates,
disclosureWrapperVariants
);

export const DisclosureButtonWrapper = styled(Anchor)(
variant({
prop: 'isWrapper',
defaultVariant: 'default',
variants: {
default: {
bg: 'inherit',
'&:hover': {
color: 'text',
bg: 'background-hover',
},
'&:focus': {
color: 'text',
bg: 'background-selected',
},
'&:disabled': {
color: 'text-disabled',
bg: 'background-disabled',
},
},
},
})
);

const sharedVariants = {
left: {
alignSelf: 'flex-start',
justifyContent: 'left',
},
right: {
alignSelf: 'flex-end',
justifyContent: 'right',
},
};

export const StyledTextButton = styled(TextButton)(
variant({
prop: 'placement',
variants: sharedVariants,
})
);

export const StyledStrokeButton = styled(StrokeButton)(
variant({
prop: 'placement',
variants: sharedVariants,
})
);

export const StyledFillButton = styled(FillButton)(
variant({
prop: 'placement',
variants: sharedVariants,
})
);

export type DisclosureBodyWrapperStyles = StyleProps<
typeof disclosureBodyWrapperStates
>;

const disclosureBodyWrapperStates = states({
hasPanelBg: {
bg: 'background-selected',
p: 8,
},
});

export const DisclosureBodyWrapper = styled(
FlexBox
)<DisclosureBodyWrapperStyles>(disclosureBodyWrapperStates);
Loading
Loading