Skip to content

Commit

Permalink
Merge pull request #499 from omnifed/497-feat-update-avatar-to-use-ce…
Browse files Browse the repository at this point in the history
…rbicons

497 feat update avatar to use cerbicons
  • Loading branch information
caseybaggz authored Sep 18, 2024
2 parents 2611504 + a752c31 commit 1c8242e
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 25 deletions.
15 changes: 15 additions & 0 deletions docs/app/components/icons/wu-tang-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function WuTangLogo() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
version="1.0"
viewBox="0 0 500 457.17"
>
<path
d="M244.37 839.542c-.261-1.692-.932-8.701-1.49-15.575-6.877-84.525-10.858-111.377-23.253-156.858l-2.921-10.719-4.955-1.927a909.357 909.357 0 0 1-6.583-2.584c-1.297-.522-2.347.768-5.145 6.324l-3.515 6.981.446 34.684c.385 29.904.733 36.332 2.529 46.642 2.537 14.57 7.445 33.647 13.144 51.095 2.346 7.181 4.265 13.24 4.265 13.465 0 .225-5.517.11-12.259-.255-49.696-2.692-93.61-12.61-128.462-29.015-5.216-2.455-9.669-4.463-9.896-4.463-1.27 0-25.946-15.55-32.058-20.202-44.661-33.987-72.937-81.91-85.025-144.107-4.453-22.91-5.72-35.13-5.746-55.382-.042-34.26 6.483-63.176 22.237-98.548 7.496-16.83 23.156-44.932 28.634-51.385l1.923-2.265 74.993 25.747c41.246 14.16 74.993 26.19 74.993 26.73 0 .542-1.45 2.578-3.224 4.526-4.113 4.521-11.487 16.537-14.909 24.296-8.753 19.848-9.787 44.282-2.513 59.393 5.095 10.585 17.778 19.993 28.698 21.286 4.57.541 4.933.425 5.8-1.854 1.056-2.778.434-6.249-1.527-8.524-1.005-1.166-2.428-1.438-5.626-1.078-5.259.593-7.18-.788-7.18-5.16 0-3.603.876-4.342 22.1-18.642 5.886-3.966 15.927-10.8 22.312-15.188l11.611-7.978 2.357 2.209c8.105 7.596 17.665 25.97 22.03 42.346 1.515 5.683 3.02 10.334 3.342 10.335.853.005 7.507-14.738 10.176-22.545 6.285-18.382 5.092-28.817-5.799-50.682l-7.023-14.102 47.179-19.965 72.916-30.857 25.738-10.893 3.106 3.534c24.536 27.924 40.17 65.29 45.481 108.71 2.365 19.335 2.953 69.541 1.009 86.192-2.848 24.388-8.917 46.861-18.546 68.676-5.21 11.805-6.79 14.907-14.052 27.595-25.058 43.785-75.777 91.552-135.019 127.161l-9.82 5.903-.474-3.077z"
fill="yellow"
transform="translate(66.554 -395.448)"
/>
</svg>
)
}
13 changes: 12 additions & 1 deletion docs/app/react/avatar/components/avatar-preview.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Avatar } from '@cerberus-design/react'
import { css } from '@cerberus-design/styled-system/css'
import { hstack } from '@cerberus/styled-system/patterns'
import { WuTangLogo } from '@/app/components/icons/wu-tang-icon'
import Image from 'next/image'

export function AvatarPreview() {
Expand Down Expand Up @@ -47,7 +48,7 @@ export function NextAvatar() {
export function CustomAvatar() {
return (
<Avatar
ariaLabel="Wu-Tang Clan"
ariaLabel=""
className={css({
bgColor: 'black',
bgImage: 'none',
Expand All @@ -58,6 +59,16 @@ export function CustomAvatar() {
height={50}
size="4xl"
src=""
icon={
<span
className={css({
display: 'inline-block',
w: '1/3',
})}
>
<WuTangLogo />
</span>
}
width={50}
/>
)
Expand Down
48 changes: 39 additions & 9 deletions docs/app/react/avatar/dev.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { Avatar } from '@cerberus/react'

## Usage

You can mix and match all of the examples to create the button style of your choosing.
<NoteAdmonition description="The avatar uses a smart hierarchy method. It first uses the src if provided. If no source is provided, it falls back to the ariaLabel. If neither are provided, it displays an icon." />

<LivePlaygroundWithCode />

Expand Down Expand Up @@ -60,46 +60,75 @@ function NextAvatar() {
```
</CodePreview>

## Customization
## Style Customization

You can customize the avatar by utilizing the `cx` function.

<CodePreview preview={<CustomAvatar />}>
```tsx title="avatar.tsx"
import { Avatar } from '@cerberus/react'
import { css } from '@cerberus/styled-system/css'
import { WuTangLogo } from '@/app/components/icons/wu-tang-logo'

function CustomAvatar() {
return (
<Avatar
ariaLabel="Random image"
ariaLabel=""
className={css({
bgColor: 'yellow.800',
color: 'black',
_hover: {
bgColor: 'yellow.500',
},
bgColor: 'black',
bgImage: 'none',
border: '6px solid',
borderColor: 'yellow',
color: 'yellow',
})}
src="https://source.unsplash.com/random/100x100"
height={50}
size="4xl"
src=""
icon={
<span
className={css({
display: 'inline-block',
w: '1/3',
})}
>
<WuTangLogo />
</span>
}
width={50}
/>
)
}
```
</CodePreview>

## Default Icon Customization

You can customize the default icon that shows by adding the `avatar` property to the `defineIcons` function at the root level of your app.

```tsx title="app/layout.tsx"
import { defineIcons } from '@cerberus/react'
import { CircleUser } from 'lucide-react'

defineIcons({
avatar: CircleUser,
})
```

## API

```ts showLineNumbers=false
export type AvatarImageProps = HtmlHTMLAttributes<HTMLImageElement> & {
ariaLabel: string
as?: never
icon?: ReactNode
src: string
width?: number
height?: number
}
export type AvatarAsProps = {
as: ReactNode
ariaLabel?: never
icon?: ReactNode
src?: never
width?: never
height?: never
Expand All @@ -122,4 +151,5 @@ The `Avatar` component accepts the following props:
| src | | The source of the image. |
| as | | A differnet element to render as the avatar. |
| height | | The height of the avatar. |
| icon | | A custom icon to render as fallback. |
| width | | The width of the avatar. |
15 changes: 14 additions & 1 deletion docs/app/react/checkbox/dev.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,23 @@ import { Field, Label, Checkbox } from '@cerberus/react'

<LivePlaygroundWithCode />

## Customizing
## Style Customizing

To customize the Checkbox we recommend extending the slot recipe provided by the `@cerberus/panda-preset` package.

## Default Icon Customization

You can customize the default icon that shows by adding the `avatar` property to the `defineIcons` function at the root level of your app.

```tsx title="app/layout.tsx"
import { defineIcons } from '@cerberus/react'
import { Check } from 'lucide-react'

defineIcons({
checkbox: Check,
})
```

## API

<NoteAdmonition description="The Checkbox component must be used within a Field provider." />
Expand Down
47 changes: 33 additions & 14 deletions packages/react/src/components/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
avatar,
type AvatarVariantProps,
} from '@cerberus/styled-system/recipes'
import { UserFilled } from '@cerberus/icons'
import { $cerberusIcons } from '../config/defineIcons'
import type { HtmlHTMLAttributes, ReactNode } from 'react'
import { Show } from './Show'

Expand All @@ -13,19 +13,21 @@ import { Show } from './Show'
* @module
*/

export type AvatarImageProps = HtmlHTMLAttributes<HTMLImageElement> & {
ariaLabel: string
as?: never
src: string
export type SharedAvatarProps = {
icon?: ReactNode
width?: number
height?: number
}
export type AvatarAsProps = {
export type AvatarImageProps = HtmlHTMLAttributes<HTMLImageElement> &
SharedAvatarProps & {
ariaLabel: string
as?: never
src: string
}
export type AvatarAsProps = SharedAvatarProps & {
as: ReactNode
ariaLabel?: never
src?: never
width?: never
height?: never
}

export type AvatarProps = (HtmlHTMLAttributes<HTMLDivElement> &
Expand All @@ -44,8 +46,18 @@ export type AvatarProps = (HtmlHTMLAttributes<HTMLDivElement> &
* ```
*/
export function Avatar(props: AvatarProps) {
const { ariaLabel, as, gradient, size, src, width, height, ...nativeProps } =
props
const {
ariaLabel,
as,
gradient,
size,
src,
width,
height,
icon,
...nativeProps
} = props
const { avatar: AvatarIcon } = $cerberusIcons
const initials = (ariaLabel || '')
.split(' ')
.map((word) => word[0])
Expand All @@ -67,12 +79,19 @@ export function Avatar(props: AvatarProps) {
<Show
when={Boolean(initials)}
fallback={
<UserFilled
size={iconSizeMap[size as keyof typeof iconSizeMap]}
/>
<Show
when={Boolean(icon)}
fallback={
<AvatarIcon
size={iconSizeMap[size as keyof typeof iconSizeMap]}
/>
}
>
{icon}
</Show>
}
>
<>{initials}</>
{initials}
</Show>
}
>
Expand Down
3 changes: 3 additions & 0 deletions packages/react/src/config/cerbIcons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
InformationFilled,
Restart,
TrashCan,
UserFilled,
Warning,
WarningFilled,
type CarbonIconType,
Expand All @@ -19,6 +20,7 @@ import { CheckmarkIcon, IndeterminateIcon } from './icons/checkbox.icons'
export type IconType = CarbonIconType | ElementType

export interface DefinedIcons {
avatar?: IconType
checkbox?: IconType
close?: IconType
confirmModal?: IconType
Expand All @@ -38,6 +40,7 @@ export interface DefinedIcons {
}

export const defaultIcons: DefinedIcons = {
avatar: UserFilled,
checkbox: CheckmarkIcon,
close: CloseFilled,
confirmModal: Information,
Expand Down
14 changes: 14 additions & 0 deletions tests/react/components/avatar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,18 @@ describe('Avatar', () => {
render(<Avatar ariaLabel="Protector Cerberus" src="" />)
expect(screen.getByText('PC')).toBeTruthy()
})

test('should allow a custom element', () => {
render(
<Avatar as={<div data-testid="custom-element">Custom Element</div>} />,
)
expect(screen.getByTestId('custom-element')).toBeTruthy()
})

test('should accept a custom icon', () => {
render(
<Avatar ariaLabel="" icon={<svg data-testid="custom-icon" />} src="" />,
)
expect(screen.getByTestId('custom-icon')).toBeTruthy()
})
})

0 comments on commit 1c8242e

Please sign in to comment.