Skip to content

Commit

Permalink
adds orderedlist and list item to typography package
Browse files Browse the repository at this point in the history
  • Loading branch information
bruugey committed Dec 11, 2024
1 parent d59d8ee commit 81c84e8
Show file tree
Hide file tree
Showing 19 changed files with 367 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/lovely-planets-sort.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/typography': minor
---

Adds OrderedList and ListItem components
15 changes: 15 additions & 0 deletions packages/typography/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ All props extend the HTMLElementProps of their root tag, however the below compo
| `Label` | `label` |
| `Description` | `p` |
| `Label` | `p` |
| `OrderedList` | `ol` |
| `ListItem` | `li` |

# H1

Expand Down Expand Up @@ -205,3 +207,16 @@ _Note_: `BackLink` is intended for internal linking only
| -------------- | ------------ | ------------------------------------------------ | --------------------------------------------- |
| `darkMode` | `boolean` | Determines if the component renders in dark mode | `false` |
| `baseFontSize` | `13` \| `16` | font-size applied to typography element | Defaults to value set by LeafyGreen Provider. |

# OrderedList

| Prop | Type | Description | Default |
| ---------- | --------- | ------------------------------------------------ | ------- |
| `darkMode` | `boolean` | Determines if the component renders in dark mode | `false` |

# ListItem

| Prop | Type | Description | Default |
| ----------- | ----------------- | -------------------------------------------------------------- | ------- |
| title | `string` | The title of the step. | |
| description | `React.ReactNode` | The description of the step. This will render below the title. | |
1 change: 1 addition & 0 deletions packages/typography/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"access": "public"
},
"dependencies": {
"@leafygreen-ui/descendants": "^1.0.1",
"@leafygreen-ui/emotion": "^4.0.8",
"@leafygreen-ui/icon": "^12.6.0",
"@leafygreen-ui/lib": "^13.6.1",
Expand Down
69 changes: 69 additions & 0 deletions packages/typography/src/OrderedList/ListItem/ListItem.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { css } from '@leafygreen-ui/emotion';
import { createUniqueClassName, Theme } from '@leafygreen-ui/lib';
import { palette } from '@leafygreen-ui/palette';
import { spacing, transitionDuration } from '@leafygreen-ui/tokens';

export const contentClassName = createUniqueClassName('content');
export const stepIconClassName = createUniqueClassName('step');

const STEP_SIZE = 20;

export const baseStyles = css`
display: flex;
gap: ${spacing[200]}px;
margin-bottom: ${spacing[100]}px;
&:last-of-type {
.${contentClassName} {
margin: 0;
}
}
`;

export const stepWrapperStyles = css`
position: relative;
&::after {
background: ${palette.gray.base};
position: absolute;
width: 1px;
height: calc(100% - ${STEP_SIZE}px);
left: 50%;
transition: background ${transitionDuration.default}ms ease;
}
`;

export const contentStyles = css`
margin-block-end: ${spacing[400]}px;
transition: margin-block-end ${transitionDuration.slowest}ms ease-in-out;
width: 100%;
`;

export const stepStyles = css`
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid;
transition: ${transitionDuration.default}ms ease;
width: ${STEP_SIZE}px;
height: ${STEP_SIZE}px;
position: relative;
font-size: 12px;
font-weight: 500;
`;

export const titleStyles = css`
font-weight: bold;
line-height: unset;
`;

export const getThemedStateStyles = (theme: Theme) => {
const isLight = theme === Theme.Light;

return css`
color: ${isLight ? palette.gray.dark1 : palette.gray.light1};
background-color: rgba(255, 255, 255, 0);
border-color: ${isLight ? palette.gray.base : palette.gray.light1};
`;
};
51 changes: 51 additions & 0 deletions packages/typography/src/OrderedList/ListItem/ListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';

import { useDescendant } from '@leafygreen-ui/descendants';
import { cx } from '@leafygreen-ui/emotion';
import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';

import { Body, Description } from '../..';
import { OrderedListContext } from '../OrderedListContext/';

import {
baseStyles,
contentClassName,
contentStyles,
getThemedStateStyles,
stepIconClassName,
stepStyles,
stepWrapperStyles,
titleStyles,
} from './ListItem.styles';
import { ListItemProps } from './ListItem.types';

const ListItem = React.forwardRef(
(
{ children, className, title, description, ...rest }: ListItemProps,
forwardRef: React.ForwardedRef<HTMLLIElement>,
) => {
const { index, ref } = useDescendant(OrderedListContext, forwardRef);
const { theme } = useDarkMode();

return (
<li ref={ref} className={cx(baseStyles, className)} {...rest}>
<div className={cx(stepIconClassName, stepWrapperStyles)}>
<div className={cx(stepStyles, getThemedStateStyles(theme))}>
{index + 1}
</div>
</div>

<div className={cx(contentClassName, contentStyles)}>
<Body baseFontSize={16} className={titleStyles}>
{title}
</Body>
<Description>{description}</Description>
</div>
</li>
);
},
);

ListItem.displayName = 'ListItem';

export { ListItem };
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { HTMLElementProps } from '@leafygreen-ui/lib';

import { CommonTypographyProps } from '../../types';

export type ListItemProps = HTMLElementProps<'li'> &
CommonTypographyProps & {
title?: React.ReactNode;
description?: React.ReactNode;
};
2 changes: 2 additions & 0 deletions packages/typography/src/OrderedList/ListItem/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { ListItem } from './ListItem';
export { ListItemProps } from './ListItem.types';
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import { render, screen } from '@testing-library/react';

import { ListItem } from '../ListItem';

import { OrderedList } from './OrderedList';

const renderOL = () => {
return render(
<OrderedList>
<ListItem title="Title" description="Description" />
<ListItem title="Title" description="Description" />
<ListItem title="Title" description="Description" />
</OrderedList>,
);
};

describe('packages/typography/ordered-list', () => {
describe('OrderedList', () => {
test('renders an ordered list', () => {
renderOL();

const ol = screen.getByRole('list', { name: 'OrderedList' });
expect(ol).toBeInTheDocument();
});

test('renders list items', () => {
renderOL();

const items = screen.getAllByRole('listitem');
expect(items).toHaveLength(3);
});

test('renders list items with titles', () => {
renderOL();

const titles = screen.getAllByText('Title');
expect(titles).toHaveLength(3);
});

test('renders list items with descriptions', () => {
renderOL();

const descriptions = screen.getAllByText('Description');
expect(descriptions).toHaveLength(3);
});

test('renders list items with step numbers', () => {
renderOL();

const steps = screen.getAllByRole('listitem');
steps.forEach((step, index) => {
expect(step).toHaveTextContent(`${index + 1}`);
});
});

test('renders list items with step numbers in order', () => {
renderOL();

const steps = screen.getAllByRole('listitem');
steps.forEach((step, index) => {
expect(step).toHaveTextContent(`${index + 1}`);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import { type StoryMetaType } from '@lg-tools/storybook-utils';

import { Link, ListItem, OrderedList } from '../../index';

import { OrderedListProps } from './OrderedList.types';

export const Basic = (args: OrderedListProps) => {
return (
<OrderedList {...args}>
<ListItem
title="Title"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna."
/>
<ListItem
title="Title"
description={
<>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna.{' '}
<Link>Learn more.</Link>
</>
}
/>
<ListItem
title="Title"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna."
/>
</OrderedList>
);
};

const meta: StoryMetaType<typeof OrderedList> = {
title: 'Components/Typography/OrderedList',
component: OrderedList,
parameters: {
default: 'Basic',
generate: {
combineArgs: {
darkMode: [false, true],
},
},
},
args: {
darkMode: false,
},
};
export default meta;

export const Generated = () => <></>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { css } from '@leafygreen-ui/emotion';

export const baseStyles = css`
list-style-type: none;
padding: 0;
margin: 0;
`;
45 changes: 45 additions & 0 deletions packages/typography/src/OrderedList/OrderedList/OrderedList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';

import {
DescendantsProvider,
useInitDescendants,
} from '@leafygreen-ui/descendants';
import { cx } from '@leafygreen-ui/emotion';
import LeafyGreenProvider, {
useDarkMode,
} from '@leafygreen-ui/leafygreen-provider';

import { OrderedListContext } from '../OrderedListContext/OrderedListContext';

import { baseStyles } from './OrderedList.styles';
import { OrderedListProps } from './OrderedList.types';

const OrderedList = React.forwardRef(
(
{ children, className, darkMode: darkModeProp, ...rest }: OrderedListProps,
ref: React.ForwardedRef<HTMLOListElement>,
) => {
const { descendants, dispatch } =
useInitDescendants<HTMLLIElement>(OrderedListContext);

const { darkMode } = useDarkMode(darkModeProp);

return (
<LeafyGreenProvider darkMode={darkMode}>
<DescendantsProvider
context={OrderedListContext}
descendants={descendants}
dispatch={dispatch}
>
<ol {...rest} ref={ref} className={cx(baseStyles, className)}>
{children}
</ol>
</DescendantsProvider>
</LeafyGreenProvider>
);
},
);

OrderedList.displayName = 'OrderedList';

export { OrderedList };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { HTMLElementProps } from '@leafygreen-ui/lib';

export type OrderedListProps = HTMLElementProps<'ol'> & { darkMode?: boolean };
2 changes: 2 additions & 0 deletions packages/typography/src/OrderedList/OrderedList/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { OrderedList } from './OrderedList';
export { OrderedListProps } from './OrderedList.types';
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {
createDescendantsContext,
useDescendantsContext,
} from '@leafygreen-ui/descendants';

export const OrderedListContext =
createDescendantsContext<HTMLLIElement>('OrderedListContext');

export function useOrderedListContext() {
return useDescendantsContext(OrderedListContext);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export {
OrderedListContext,
useOrderedListContext,
} from './OrderedListContext';
6 changes: 6 additions & 0 deletions packages/typography/src/OrderedList/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export { ListItem } from './ListItem';
export { OrderedList, OrderedListProps } from './OrderedList';
export {
OrderedListContext,
useOrderedListContext,
} from './OrderedListContext';
Loading

0 comments on commit 81c84e8

Please sign in to comment.