Skip to content

Commit

Permalink
feat(website): revise composition guide
Browse files Browse the repository at this point in the history
  • Loading branch information
cschroeter committed May 17, 2024
1 parent b186861 commit 64d7a3c
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 72 deletions.
10 changes: 10 additions & 0 deletions packages/react/src/components/popover/examples/as-child.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Popover } from '../..'

export const AsChild = () => (
<Popover.Root>
<Popover.Trigger asChild>
{/* @ts-expect-error */}
<Button>Open</Button>
</Popover.Trigger>
</Popover.Root>
)
9 changes: 9 additions & 0 deletions packages/react/src/components/popover/examples/factory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ark } from '../../factory'

export const ArkFactory = () => (
<ark.div id="parent" className="parent" style={{ background: 'red' }} asChild>
<ark.span id="child" className="child" style={{ color: 'blue' }}>
Ark UI
</ark.span>
</ark.div>
)
8 changes: 8 additions & 0 deletions packages/solid/src/components/popover/examples/as-child.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Popover } from '../..'

export const Basic = () => (
<Popover.Root>
{/* @ts-expect-error */}
<Popover.Trigger asChild={(props) => <Button {...props()} />}>Open</Popover.Trigger>
</Popover.Root>
)
14 changes: 14 additions & 0 deletions packages/solid/src/components/popover/examples/factory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ark } from '../../factory'

export const ArkFactory = () => (
<ark.div
id="parent"
class="parent"
style={{ background: 'red' }}
asChild={(props) => (
<ark.span {...props({ id: 'child', class: 'child', style: { color: 'blue' } })} />
)}
>
Ark UI
</ark.div>
)
11 changes: 11 additions & 0 deletions packages/vue/src/components/popover/examples/as-child.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { Popover } from '../..'
</script>

<template>
<Popover.Root>
<Popover.Trigger asChild>
<Button>Open</Button>
</Popover.Trigger>
</Popover.Root>
</template>
11 changes: 11 additions & 0 deletions packages/vue/src/components/popover/examples/factory.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ark } from '../..'
</script>

<template>
<ark.div id="parent" className="parent" :style="{ background: 'red' }" asChild>
<ark.span id="child" className="child" :style="{ color: 'blue' }" >
Ark UI
</ark.span>
</ark.div>
</template>
1 change: 1 addition & 0 deletions website/src/components/example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const findExamples = async (props: Props) => {
const code = content
.replaceAll(/from '\.\/icons'/g, `from 'lucide-vue-next'`)
.replaceAll(/from '\..*'/g, `from '@ark-ui/${framework}'`)
.replace(/.*@ts-expect-error.*\n/g, '')

const html = await codeToHtml(code, {
lang: extenstion,
Expand Down
1 change: 0 additions & 1 deletion website/src/components/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export * from './heading'
export * as HoverCard from './hover-card'
export * from './icon'
export * from './icon-button'
export { InfoBanner } from './info-banner'
export * from './input'
export * from './link'
export { Kbd } from './kbd'
Expand Down
27 changes: 0 additions & 27 deletions website/src/components/ui/info-banner.tsx

This file was deleted.

61 changes: 19 additions & 42 deletions website/src/content/pages/guides/composition.mdx
Original file line number Diff line number Diff line change
@@ -1,61 +1,38 @@
---
id: composition
title: Composition
description: Customize component rendering with the asChild prop
description: Learn how to compose default components with custom elements
---

## Overview
## The asChild Prop

Ark UI offers a flexible way to render components using the `asChild` prop. This prop allows you to
replace the default component with a custom child element while maintaining the necessary behavior,
such as event handling, and passing down props and refs.
In Ark UI, the `asChild` prop lets you integrate custom components, ensuring consistent styling and
behavior while promoting flexibility and reusability. All Ark components that render a DOM element
accept the `asChild` prop.

Every component that is exported in Ark UI has support for the `asChild` prop.
Here's an example using `asChild` to integrate a custom `Button` component within a `Popover`:

> **Note:** When using the `asChild` prop, be sure that the element you're rendering matches the tag
> name of the original component. Changing the underlying tags might affect the accessibility and
> functionality.
<Example id="as-child" component="popover" />

## Usage
In this example, the `asChild` prop allows the `Button` to be used as the trigger for the `Popover`,
inheriting its behaviors from Popover.Trigger.

Consider a component like `Menu.Trigger`, which also supports the `asChild` prop.
## The Ark Factory

### Default Behavior
You can use the `ark` factory to create your own elements that work just like Ark UI components.

By default, the original `Menu.Trigger` component will be rendered with its default appearance and
behavior:
<Example id="factory" component="popover" />

```jsx
<Menu.Trigger>Open Menu</Menu.Trigger>
```

### Customizing with asChild

To replace the default `Menu.Trigger` with a custom child element (e.g., a Button), set the
`asChild` prop to true and pass the custom child element:
This will produce the following HTML:

```jsx
<Menu.Trigger asChild>
<Button>Open Menu</Button>
</Menu.Trigger>
```html
<span id="child" class="parent child" style="background: red; color: blue;">Ark UI</span>
```

When using the `asChild` prop, the library ensures that the custom child element receives all the
required props from the parent component and combines them with the child's existing props. In
addition, if a ref is provided, it will be composed with the child's ref and passed down correctly.

## Limitations

When using the `asChild` prop, ensure that you only pass a single child element. If you pass
multiple children, the component may not render correctly.

Some components may have specific requirements for the child element, such as the `Checkbox.Root`,
`RadioGroup.Item` and `Switch.Root` component, which requires a `label` element to be passed as a
child element.

## Summary
When using the `asChild` prop, ensure you pass only a single child element. Passing multiple children may cause rendering issues.

The `asChild` prop provides a convenient way to customize the appearance and behavior of components
in Ark UI, such as `Menu.Trigger`. Use the `asChild` prop to replace the original component with a
custom child element, and the library will take care of merging and forwarding props and refs as
needed.
Certain components, such as `Checkbox.Root` or `RadioGroup.Item`, have specific requirements for their child elements.
For instance, they may require a label element as a child.
If you change the underlying element type, ensure it remains accessible and functional.
3 changes: 1 addition & 2 deletions website/src/mdx-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { KeyBindingsTable } from './components/key-bindings-table'
import { Pre } from './components/pre'
import { Quickstart } from './components/quickstart'
import { Story } from './components/story'
import { Code, InfoBanner, Kbd, Link } from './components/ui'
import { Code, Kbd, Link } from './components/ui'
import { Step, Steps } from './components/ui/stepper'

const sharedComponents = {
Expand All @@ -20,7 +20,6 @@ const sharedComponents = {
ComponentTypes,
Example,
Faq,
InfoBanner,
InstallCmd,
kbd: Kbd,
KeyBindingsTable,
Expand Down

0 comments on commit 64d7a3c

Please sign in to comment.