Skip to content

Commit

Permalink
docs: Add info to create compound component regarding createComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
manuel.carrera committed Nov 20, 2024
1 parent 9a6f57a commit 00c2a06
Showing 1 changed file with 55 additions and 0 deletions.
55 changes: 55 additions & 0 deletions modules/docs/mdx/CREATING_COMPOUND_COMPONENTS.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,67 @@ document to learn about what a compound component is.
This document will go through building a simplified Disclosure component to help solidify the
concepts. We will cover:

- [createComponent vs createContainer](#create-component-vs-create-container)
- [Models](#models)
- [Container Components](#disclosure-component)
- [Sub-components](#disclosuretarget-component)
- [Model Composition](#model-composition)
- [Behavior hooks](#behavior-hooks)

## `createComponent` vs `createContainer`

When creating compound components, which factory function you choose depends on whether or not your
component just renders an element or there is behavior that you want to expose like internal state
and events.

### `createComponent`

Use `createComponent` when you want to create a rendered element with _no behavior_. This is useful
for elements that you want to use for styling purposes like container elements, or sub components
that are simple rendered elements. This utility function will wrap you component in a
`React.ForwardRef` and allow you to add sub components as well.

```tsx
export const Card = createComponent('div')({
displayName: 'Card',
subComponents: {
Heading: CardHeading, // this is also using createComponent
},
Component: ({children, ...elemProps}: CardProps, ref, Element) => {
return (
<Box as={Element} {...elemProps} ref={ref}>
{children}
</Box>
);
},
});
```

### `createContainer`

Use `createContainer` when you're building a compound component that might expose internal state and
events that users might want access too. This is also useful of your sub components rely on the
`model` for any state or events. `createContainer` requires a `model` to be defined, meaning your
compound component has state and events.

```tsx
const Disclosure = createContainer()({
displayName: 'Disclosure',
modelHook: useDisclosureModel, // model defined that exposes state and events.
})<DisclosureProps>(({children, ...elemProps}, Element, model) => {
return (
<button
onClick={() =>
model.state.visibility === 'visible' ? model.events.hide() : model.events.show()
}
{...elemProps}
>
{model.state.visibility === 'visible' ? 'close' : 'open'}
</button>
);
});
```

## Models

A model is composed of state and events. The shape of the model used by components looks like this:
Expand Down

0 comments on commit 00c2a06

Please sign in to comment.