# Closed Components

URL: https://ark-ui.com/docs/guides/closed-components
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/guides/closed-components.mdx

Learn how to create reusable components using the example of an avatar

---

## Motivation

Writing a few lines of code every time you need a simple `Avatar` is tedious. Creating a dedicated component
encapsulates logic, simplifies the API, ensures consistent usage, and maintains clean code. This approach enhances
reusability, making the component easier to maintain and test.

Here's an example of an `Avatar` component that can be used consistently across your application:

**Example: closed**

#### React

```tsx
import { Avatar as ArkAvatar } from '@ark-ui/react/avatar'
import { UserIcon } from 'lucide-react'
import { forwardRef } from 'react'
import styles from 'styles/avatar.module.css'

export interface AvatarProps extends ArkAvatar.RootProps {
  name?: string | undefined
  src?: string | undefined
}

export const Avatar = forwardRef<HTMLDivElement, AvatarProps>((props, ref) => {
  const { name, src, ...rootProps } = props
  return (
    <ArkAvatar.Root ref={ref} className={styles.Root} {...rootProps}>
      <ArkAvatar.Fallback className={styles.Fallback}>{getInitials(name) || <UserIcon />}</ArkAvatar.Fallback>
      <ArkAvatar.Image className={styles.Image} src={src} alt={name} />
    </ArkAvatar.Root>
  )
})

const getInitials = (name = '') =>
  name
    .split(' ')
    .map((part) => part[0])
    .slice(0, 2)
    .join('')
    .toUpperCase()

```

#### Solid

```tsx
import { Avatar as ArkAvatar } from '@ark-ui/solid/avatar'
import { UserIcon } from 'lucide-solid'
import { Show, splitProps } from 'solid-js'
import styles from 'styles/avatar.module.css'

export interface AvatarProps extends ArkAvatar.RootProps {
  name?: string
  src?: string
}

export const Avatar = (props: AvatarProps) => {
  const [localProps, rootProps] = splitProps(props, ['name', 'src'])

  return (
    <ArkAvatar.Root class={styles.Root} {...rootProps}>
      <ArkAvatar.Fallback class={styles.Fallback}>
        <Show when={localProps.name} fallback={<UserIcon />}>
          {getInitials(localProps.name)}
        </Show>
      </ArkAvatar.Fallback>
      <ArkAvatar.Image class={styles.Image} src={localProps.src} alt={localProps.name} />
    </ArkAvatar.Root>
  )
}

const getInitials = (name = '') =>
  name
    .split(' ')
    .map((part) => part[0])
    .splice(0, 2)
    .join('')
    .toUpperCase()

```

#### Vue

```vue
<script setup lang="ts">
import { useForwardPropsEmits } from '@ark-ui/vue'
import { Avatar, type AvatarRootEmits, type AvatarRootProps } from '@ark-ui/vue/avatar'
import { computed } from 'vue'
import styles from 'styles/avatar.module.css'

export interface AvatarProps extends AvatarRootProps {
  src?: string
  name: string
}

const props = defineProps<AvatarProps>()
const emits = defineEmits<AvatarRootEmits>()

const forwarded = useForwardPropsEmits(props, emits)

const getInitials = computed(() =>
  props.name
    .split(' ')
    .map((part) => part[0])
    .slice(0, 2)
    .join('')
    .toUpperCase(),
)
</script>

<template>
  <Avatar.Root :class="styles.Root" v-bind="forwarded">
    <Avatar.Fallback :class="styles.Fallback">{{ getInitials }}</Avatar.Fallback>
    <Avatar.Image :class="styles.Image" :src="props.src" :alt="props.name" />
  </Avatar.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Avatar, type AvatarRootBaseProps } from '@ark-ui/svelte/avatar'
  import { UserIcon } from 'lucide-svelte'
  import styles from 'styles/avatar.module.css'

  interface Props extends AvatarRootBaseProps {
    name?: string | undefined
    src?: string | undefined
  }

  let { name, src, ...rootProps }: Props = $props()

  const getInitials = (name = '') =>
    name
      .split(' ')
      .map((part) => part[0])
      .slice(0, 2)
      .join('')
      .toUpperCase()

  const initials = $derived(getInitials(name))
</script>

<Avatar.Root class={styles.Root} {...rootProps}>
  <Avatar.Fallback class={styles.Fallback}>
    {#if initials}
      {initials}
    {:else}
      <UserIcon />
    {/if}
  </Avatar.Fallback>
  <Avatar.Image class={styles.Image} {src} alt={name} />
</Avatar.Root>

```

## Usage

To use the `Avatar` component, pass the `name` and `src` props as shown below:

```jsx
<Avatar name="Christian" src="https://avatars.githubusercontent.com/u/1846056?v=4" />
```