Skip to content

Commit

Permalink
add x variant to unordered lists, and leadingVisual, variant and colo…
Browse files Browse the repository at this point in the history
…r props to list items
  • Loading branch information
rezrah committed Feb 16, 2024
1 parent bf80cec commit dd85369
Show file tree
Hide file tree
Showing 16 changed files with 258 additions and 25 deletions.
20 changes: 20 additions & 0 deletions .changeset/small-apricots-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
'@primer/react-brand': patch
---

Added `x` variant to `UnorderedList`, and `leadingVisual`, `variant`, `leadingVisualAriaLabel` and `leadingVisualFill` props to list items.

Example:

```jsx
<UnorderedList variant="x">
<UnorderedList.Item leadingVisual={CheckIcon} leadingVisualFill="green">
Check icon override in green
</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="orange">X icon in orange</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="red">X icon in red</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="blue">X icon in blue</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="purple">X icon in purple</UnorderedList.Item>{' '}
<UnorderedList.Item variant="muted">Muted text color</UnorderedList.Item>
</UnorderedList>
```
53 changes: 48 additions & 5 deletions apps/docs/content/components/UnorderedList/react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,62 @@ import {UnorderedList} from '@primer/react-brand'
</UnorderedList>
```

### `x` variant

```jsx live
<UnorderedList variant="x">
<UnorderedList.Item>
Automatic security and version updates
</UnorderedList.Item>
<UnorderedList.Item>GitHub Security Advisories</UnorderedList.Item>
<UnorderedList.Item>Code and secret scanning</UnorderedList.Item>
<UnorderedList.Item>Dependency review</UnorderedList.Item>
<UnorderedList.Item>
Automated authentication and identity management
</UnorderedList.Item>
</UnorderedList>
```

### Custom colors

```jsx live
<UnorderedList variant="checked">
<UnorderedList.Item leadingVisualFill="var(--brand-color-success-fg)">
Automatic security and version updates
</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="var(--brand-color-success-fg)">
GitHub Security Advisories
</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="var(--brand-color-success-fg)">
Code and secret scanning
</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="var(--brand-color-success-fg)">
Dependency review
</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="var(--brand-color-success-fg)">
Automated authentication and identity management
</UnorderedList.Item>
</UnorderedList>
```

## Component props

### UnorderedList

| Name | Type | Default | Description |
| :---------- | :------------------------------------- | :-------: | :--------------------------------------------------------- |
| `className` | `string` | | Sets a custom class on the root element |
| `variant` | `default`, `checked` | `default` | Specify alternative leading visual for list items |
| `variant` | `default`, `checked` , `x` | `default` | Specify alternative leading visual for list items |
| `children` | `React.ReactNode`, `React.ReactNode[]` | | Content to be displayed within the UnorderedList component |

### UnorderedList.Item

| Name | Type | Default | Description |
| :---------- | :------------------------------------- | :-------: | :------------------------------------------------------- |
| `className` | `string` | | Sets a custom class on the root element |
| `children` | `React.ReactNode`, `React.ReactNode[]` | `default` | Content to be displayed within the OrderedList component |
| Name | Type | Default | Description |
| :----------------------- | :------------------------------------- | :---------: | :-------------------------------------------------------------------------------------------------- |
| `className` | `string` | | Sets a custom class on the root element |
| `children` | `React.ReactNode`, `React.ReactNode[]` | `default` | Content to be displayed within the OrderedList component |
| `leadingVisual` | `Icon` | `undefined` | Sets a custom leading visual ([Octicon](https://primer.style/foundations/icons/)) for the list item |
| `leadingVisualFill` | `string` | `undefined` | Sets a custom color value for the leading visual |
| `leadingVisualAriaLabel` | `string` | `undefined` | Sets `aria-label` on the leading visual icon |

Also forwards the `variant` prop from the [Text component](/components/Text).
4 changes: 2 additions & 2 deletions apps/docs/scripts/components-with-animation.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/* This file is generated by a script. Do not modify. */

export const supportedComponents = [
'Button',
'Box',
'Button',
'ComparisonTable',
'FAQ',
'Heading',
'Image',
'Label',
'Pillar',
'SectionIntro',
'Stack',
'Testimonial',
'Text',
'Timeline',
'SectionIntro',
'Animate',
'River',
'RiverBreakout',
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 12 additions & 1 deletion packages/react/src/list/ListItem/ListItem.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@
gap: var(--base-size-12);
}

.ListItem--default {
color: var(--brand-color-text-default);
}

.ListItem--muted {
color: var(--brand-color-text-muted);
}

.ListItem__leading-visual {
fill: var(--brand-color-text-muted);
margin: var(--base-size-4) 0;
}

.ListItem__leading-visual--muted {
fill: var(--brand-color-text-muted);
}

.OrderedList__item::before {
content: counter(li) '.';
counter-increment: li;
Expand Down
3 changes: 3 additions & 0 deletions packages/react/src/list/ListItem/ListItem.module.css.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
declare const styles: {
readonly "ListItem": string;
readonly "ListItem--default": string;
readonly "ListItem--muted": string;
readonly "ListItem__leading-visual": string;
readonly "ListItem__leading-visual--muted": string;
readonly "OrderedList__item": string;
};
export = styles;
Expand Down
84 changes: 75 additions & 9 deletions packages/react/src/list/ListItem/ListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {type Ref, useContext} from 'react'
import clsx from 'clsx'
import {CheckIcon, DashIcon} from '@primer/octicons-react'
import {Text} from '../../Text'
import {CheckIcon, DashIcon, Icon, IconProps, XIcon} from '@primer/octicons-react'
import {Text, TextProps} from '../../Text'
import type {BaseProps} from '../../component-helpers'
import {ListContext} from '../listContext'

Expand All @@ -16,26 +16,92 @@ export type ListItemProps = BaseProps<HTMLElement> & {
* The ref object to be attached to the list item.
*/
ref?: Ref<HTMLLIElement>
}
/*
* Custom icon to be used as leading visual
*/
leadingVisual?: Icon
/*
* Color of leading icon
*/
leadingVisualFill?: IconProps['fill']
/*
* Aria label for the leading visual
*/
leadingVisualAriaLabel?: string
} & Pick<TextProps, 'variant'>

function Root({className, children, ...props}: ListItemProps) {
function Root({
className,
children,
leadingVisualFill,
leadingVisual: LeadingVisual,
leadingVisualAriaLabel,
variant: textVariant = 'default',
...props
}: ListItemProps) {
const {variant} = useContext(ListContext)

const leadingVisual = () => {
const _leadingVisual = () => {
const iconProps = {fill: leadingVisualFill, 'aria-label': leadingVisualAriaLabel}

if (LeadingVisual) {
return (
<LeadingVisual
className={clsx(
styles['ListItem__leading-visual'],
!leadingVisualFill && styles['ListItem__leading-visual--muted'],
)}
{...iconProps}
/>
)
}

switch (variant) {
case 'checked':
return <CheckIcon className={clsx(styles['ListItem__leading-visual'], styles['ListItem__checked'])} />
return (
<CheckIcon
className={clsx(
styles['ListItem__leading-visual'],
styles['ListItem__checked'],
!leadingVisualFill && styles['ListItem__leading-visual--muted'],
)}
{...iconProps}
/>
)
case 'x':
return (
<XIcon
className={clsx(
styles['ListItem__leading-visual'],
styles['ListItem__x'],
!leadingVisualFill && styles['ListItem__leading-visual--muted'],
)}
{...iconProps}
/>
)
case 'default':
return <DashIcon className={clsx(styles['ListItem__leading-visual'], styles['ListItem__default'])} />
return (
<DashIcon
className={clsx(
styles['ListItem__leading-visual'],
styles['ListItem__default'],
!leadingVisualFill && styles['ListItem__leading-visual--muted'],
)}
{...iconProps}
/>
)

default:
return null
}
}

return (
<li className={clsx(styles.ListItem, !variant && styles.OrderedList__item, className)} {...props}>
{leadingVisual()}
<Text as="span">{children}</Text>
{_leadingVisual()}
<Text as="span" variant={textVariant} className={clsx(styles[`ListItem--${textVariant}`])}>
{children}
</Text>
</li>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import {Meta} from '@storybook/react'

import {UnorderedList} from '.'
import {XIcon} from '@primer/octicons-react'

export default {
title: 'Components/UnorderedList/Features',
Expand All @@ -17,3 +18,56 @@ export const CheckList = () => (
<UnorderedList.Item>Automated authentication and identity management</UnorderedList.Item>
</UnorderedList>
)

export const XList = () => (
<UnorderedList variant="x">
<UnorderedList.Item>Automatic security and version updates</UnorderedList.Item>
<UnorderedList.Item>GitHub Security Advisories</UnorderedList.Item>
<UnorderedList.Item>Code and secret scanning</UnorderedList.Item>
<UnorderedList.Item>Dependency review</UnorderedList.Item>
<UnorderedList.Item>Automated authentication and identity management</UnorderedList.Item>
</UnorderedList>
)

export const customColor = () => (
<UnorderedList variant="checked">
<UnorderedList.Item leadingVisualFill="green">Automatic security and version updates</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="orange">GitHub Security Advisories</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="red">Code and secret scanning</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="blue">Dependency review</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="purple">Automated authentication and identity management</UnorderedList.Item>
</UnorderedList>
)

export const customIcon = () => (
<UnorderedList variant="checked">
<UnorderedList.Item leadingVisualFill="var(--brand-color-success-fg)">
Automatic security and version updates
</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="var(--brand-color-success-fg)">
GitHub Security Advisories
</UnorderedList.Item>
<UnorderedList.Item leadingVisualFill="var(--brand-color-success-fg)">Code and secret scanning</UnorderedList.Item>
<UnorderedList.Item
leadingVisual={XIcon}
leadingVisualFill="var(--brand-color-text-muted)"
leadingVisualAriaLabel="Not included icon"
>
Dependency review
</UnorderedList.Item>
<UnorderedList.Item
leadingVisual={XIcon}
leadingVisualFill="var(--brand-color-text-muted)"
leadingVisualAriaLabel="Not included icon"
>
Automated authentication and identity management
</UnorderedList.Item>
</UnorderedList>
)

export const textVariant = () => (
<UnorderedList>
<UnorderedList.Item>Default</UnorderedList.Item>
<UnorderedList.Item variant="muted">Muted</UnorderedList.Item>
</UnorderedList>
)
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default {
description: 'Specify alternative leading visuals for list items',
control: {
type: 'radio',
options: ['default', 'checked'],
options: ['default', 'checked', 'x'],
},
},
data: {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/list/UnorderedList/UnorderedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type UnorderedListProps = PropsWithChildren<BaseProps<HTMLUListElement>>
/**
* The semantic structure of list that is presented visually setting 'ol' vs 'ul' based on the style the style of the list.
*/
variant?: 'default' | 'checked'
variant?: 'default' | 'checked' | 'x'
}

function Root({variant = 'default', children, ...props}: UnorderedListProps) {
Expand Down
Loading

0 comments on commit dd85369

Please sign in to comment.