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

Disclosure: Add size support #1633

Merged
merged 5 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
21 changes: 21 additions & 0 deletions .changeset/wet-bananas-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
'braid-design-system': minor
---

---
updated:
- Disclosure
---

**Disclosure:** Add `size` support

Introduce the `size` prop to the `Disclosure` component, providing the same options as the `Text` component.

**EXAMPLE USAGE:**
```jsx
<Disclosure
size="small"
>
...
</Disclosure>
```
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import type { ComponentDocs } from 'site/types';
import { Disclosure, Text, TextLink, Strong } from '..';
import { Disclosure, Text, TextLink, Strong, Stack, Notice } from '..';
import source from '@braid-design-system/source.macro';

const docs: ComponentDocs = {
Expand Down Expand Up @@ -43,53 +43,123 @@ const docs: ComponentDocs = {
],
additional: [
{
label: 'Custom space',
label: 'Visual weight',
description: (
<Text>
The space between the disclosure label and content can be customised
via the <Strong>space</Strong> prop.
By default, the call to action will have the same affordance as{' '}
<TextLink href="/components/TextLinkButton">TextLinkButton</TextLink>.
Optionally, the visual weight can be decreased by setting{' '}
<Strong>weight</Strong> to <Strong>weak</Strong>.
</Text>
),
Example: ({ id, setDefaultState, getState, setState }) =>
source(
<>
{setDefaultState('expanded', true)}
{setDefaultState('expanded', false)}

<Disclosure
id={id}
weight="weak"
expandLabel="Show content"
collapseLabel="Hide content"
expanded={getState('expanded')}
onToggle={setState('expanded')}
space="small"
>
<Text>Content</Text>
</Disclosure>
</>,
),
},
{
label: 'Visual weight',
label: 'Sizing',
description: (
<>
<Text>
The size can be customised via the <Strong>size</Strong> prop, which
accepts the same sizes as the{' '}
<TextLink href="/components/Text">Text</TextLink> component.
</Text>
<Notice>
<Text>
The provided <Strong>size</Strong> will also be used as the
default size for <TextLink href="/components/Text">Text</TextLink>{' '}
components within the content of the disclosure.
</Text>
</Notice>
</>
),
Example: ({ id, handler }) =>
source(
<Stack space="large">
<Disclosure
id={`${id}_1`}
expandLabel="Large size"
size="large"
expanded={true}
onToggle={handler}
>
<Text>
Defaults to <Strong>large</Strong> text size
</Text>
</Disclosure>
<Disclosure
id={`${id}_2`}
expandLabel="Standard size"
size="standard"
expanded={true}
onToggle={handler}
>
<Text>
Defaults to <Strong>standard</Strong> text size
</Text>
</Disclosure>
<Disclosure
id={`${id}_3`}
expandLabel="Small size"
size="small"
expanded={true}
onToggle={handler}
>
<Text>
Defaults to <Strong>small</Strong> text size
</Text>
</Disclosure>
<Disclosure
id={`${id}_4`}
expandLabel="Xsmall size"
size="xsmall"
expanded={true}
onToggle={handler}
>
<Text>
Defaults to <Strong>xsmall</Strong> text size
</Text>
</Disclosure>
</Stack>,
),
},
{
label: 'Custom space',
description: (
<Text>
By default, the call to action will have the same affordance as{' '}
<TextLink href="/components/TextLinkButton">TextLinkButton</TextLink>.
Optionally, the visual weight can be decreased by setting{' '}
<Strong>weight</Strong> to <Strong>weak</Strong>.
The default space between the disclosure label and content will be
determined by the <TextLink href="#sizing">size</TextLink>.
Alternatively, this can be customised via the <Strong>space</Strong>{' '}
prop.
</Text>
),
Example: ({ id, setDefaultState, getState, setState }) =>
source(
<>
{setDefaultState('expanded', false)}
{setDefaultState('expanded', true)}

<Disclosure
id={id}
weight="weak"
expandLabel="Show content"
collapseLabel="Hide content"
expanded={getState('expanded')}
onToggle={setState('expanded')}
space="large"
>
<Text>Content</Text>
</Disclosure>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import React, { type ReactNode } from 'react';
import type { ComponentScreenshot } from 'site/types';
import { Disclosure, Text } from '../';
import { Disclosure, Stack, Text } from '../';
import { Box } from '../Box/Box';
import { textSizeUntrimmed } from '../../css/typography.css';

const Container = ({ children }: { children: ReactNode }) => (
<Box style={{ maxWidth: 250 }}>{children}</Box>
);

const textSizes = Object.keys(textSizeUntrimmed) as Array<
keyof typeof textSizeUntrimmed
>;

export const screenshots: ComponentScreenshot = {
screenshotWidths: [320],
examples: [
Expand Down Expand Up @@ -182,5 +187,46 @@ export const screenshots: ComponentScreenshot = {
</Text>
),
},
{
label: 'Sizes and default spacing',
Example: ({ id, handler }) => (
<Stack space="large">
{textSizes.map((size) => (
<Disclosure
key={size}
id={`${id}_${size}`}
expandLabel={`${size.charAt(0).toUpperCase()}${size.slice(
1,
)} size`}
size={size}
expanded={true}
onToggle={handler}
>
<Text>Defaults to {size} text size</Text>
</Disclosure>
))}
</Stack>
),
},
{
label: 'Inline: Sizes and default spacing',
Example: ({ id, handler }) => (
<Stack space="large">
{textSizes.map((size) => (
<Text size={size} key={size}>
Inline disclosure in{' '}
<Disclosure
id={`${id}_${size}`}
expandLabel={`${size} size`}
expanded={true}
onToggle={handler}
>
Defaults to {size} text size
</Disclosure>
</Text>
))}
</Stack>
),
},
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { type ReactNode, useContext } from 'react';
import assert from 'assert';
import { Box } from '../Box/Box';
import type { ResponsiveSpace } from '../../css/atoms/atoms';
import { Text } from '../Text/Text';
import { Text, type TextProps } from '../Text/Text';
import {
type TextLinkButtonProps,
TextLinkButton,
Expand All @@ -15,23 +15,36 @@ import buildDataAttributes, {
} from '../private/buildDataAttributes';
import { TextContext } from '../Text/TextContext';
import HeadingContext from '../Heading/HeadingContext';
import { DefaultTextPropsProvider } from '../private/defaultTextProps';

export interface DisclosureBaseProps {
expandLabel: string;
collapseLabel?: string;
space?: ResponsiveSpace;
size?: TextProps['size'];
weight?: TextLinkButtonProps['weight'];
data?: DataAttributeMap;
children: ReactNode;
}
export type DisclosureProps = DisclosureBaseProps & UseDisclosureProps;
export type { DisclosureStateProps } from './useDisclosure';

const defaultSpaceForSize: Record<
NonNullable<DisclosureProps['size']>,
ResponsiveSpace
> = {
large: 'medium',
standard: 'medium',
xsmall: 'small',
small: 'small',
};

export const Disclosure = ({
id,
expandLabel,
collapseLabel = expandLabel,
space = 'medium',
space,
size: sizeProp,
children,
data,
weight,
Expand All @@ -51,6 +64,13 @@ export const Disclosure = ({
const headingContext = useContext(HeadingContext);
const isInline = Boolean(textContext || headingContext);

assert(
typeof sizeProp === 'undefined' || !isInline,
`Specifying a custom \`size\` for a \`Disclosure\` inside the context of a \`<${
textContext ? 'Text' : 'Heading'
}>\` component is invalid. See the documentation for correct usage: https://seek-oss.github.io/braid-design-system/components/Disclosure`,
);

const { expanded, buttonProps, contentProps } = useDisclosure({
id,
...(restProps.expanded !== undefined
Expand All @@ -63,6 +83,15 @@ export const Disclosure = ({
}),
});

const size = sizeProp ?? textContext?.size ?? 'standard';
const defaultSpace = isInline
? /*
* If inline, only use `xxsmall` as the space between the trigger
* and the content will include the line height of the text
*/
michaeltaranto marked this conversation as resolved.
Show resolved Hide resolved
'xxsmall'
: defaultSpaceForSize[size];

const trigger = (
<TextLinkButton hitArea="large" weight={weight} {...buttonProps}>
{expanded ? collapseLabel : expandLabel}
Expand All @@ -84,15 +113,21 @@ export const Disclosure = ({
display={isInline ? 'inline' : undefined}
userSelect="none"
>
{isInline ? <> {trigger}</> : <Text>{trigger}</Text>}
{isInline ? <> {trigger}</> : <Text size={size}>{trigger}</Text>}
</Box>
<Box
component={component}
paddingTop={space}
paddingTop={space ?? defaultSpace}
display={expanded ? 'block' : 'none'}
{...contentProps}
>
{children}
{isInline ? (
children
) : (
<DefaultTextPropsProvider size={size}>
{children}
</DefaultTextPropsProvider>
)}
</Box>
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2952,6 +2952,11 @@ exports[`Disclosure 1`] = `
expanded?: boolean
id: string
onToggle?: (expanded: boolean) => void
size?:
| "large"
| "small"
| "standard"
| "xsmall"
space?:
| "gutter"
| "large"
Expand Down