-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs(components): Document composability best practices [107012] #2136
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,17 +8,15 @@ import { getGIF, loadingGIF } from "./getGIF"; | |
|
||
<Meta title="Guides/Getting started with React" /> | ||
|
||
# Getting Started with React | ||
|
||
## Things to know. | ||
# Getting started with React | ||
|
||
## What is React | ||
|
||
At its core React is simply a JavaScript view library layer. It provides us with | ||
a way to define and render view components. It also aids with tracking and | ||
re-rendering changes to data that the components are representing. | ||
|
||
## What is a Component | ||
## What is a component | ||
|
||
Much as a function in programing allows you to encapsulate, test and reuse logic | ||
a React Component allows you to encapsulate, test and reuse pieces of your UI. | ||
|
@@ -64,7 +62,7 @@ There are a few things going on in the example above. Lets break them down: | |
| `{ text, yell }: MessageProps` | There are two parts to this. Starting on the right `MessageProps` indicates that this funciton takes a parameter of type `MessageProps`. On the left the `{ text, yell }` unpacks the parameter into local variables. | | ||
| `return <p>{text}</p>` | Every React component will return an [element](https://reactjs.org/docs/rendering-elements.html) or [fragment](https://reactjs.org/docs/fragments.html). (Note the [fragment short hand syntax](https://reactjs.org/docs/fragments.html#short-syntax).) | | ||
|
||
## It's Components All the Way Down | ||
## It's components all the way down | ||
|
||
In React everything is a component. A typical page will consist of one top level | ||
component representing the main view. Then within that page you will break down | ||
|
@@ -79,7 +77,7 @@ smaller components. Brad Frost covers this break down very well with | |
When you are writing a front end using React each of the levels he talks about | ||
are represented by components functions. | ||
|
||
## Composing Components | ||
## Composing components | ||
|
||
As mentioned above a lot of the power of React comes from being able to build | ||
components out of other components. Lets take a look at an example on how to do | ||
|
@@ -89,7 +87,7 @@ For this example we are going to build a card that allows you to enter a topic | |
and then search for a related gif. | ||
|
||
<Canvas> | ||
<Story name="Composing Components"> | ||
<Story name="Gif Gift"> | ||
{() => { | ||
const [topic, setTopic] = useState(); | ||
const [url, setURL] = useState(); | ||
|
@@ -117,7 +115,7 @@ and then search for a related gif. | |
> `function getGIF(topic: string): Promise<string>;` that will return a promise | ||
> resolving to a url. | ||
|
||
### Breaking it Down | ||
### Breaking it down | ||
|
||
```tsx | ||
const [topic, setTopic] = useState(); | ||
|
@@ -183,3 +181,43 @@ The final part of our example defines the custom actions needed to power our | |
component. In this case the action when the user clicks on the **Search** | ||
button. Here we call the `setURL` setter to show the `loadingGIF`. Then, we call | ||
`setURL` awaiting the async response of `getGIF`. | ||
|
||
## Types of components in Atlantis and their ability for customization | ||
|
||
#### 1. Primitive components: | ||
|
||
Examples: [Icon](..?path=/docs/components-images-and-icons-icon--docs), | ||
[Avatar](..?path=/docs/components-images-and-icons-avatar--docs) | ||
|
||
These components do not accept children and have minimal customization. | ||
|
||
#### 2. Simple components: | ||
|
||
Examples: [Button](..?path=/docs/components-actions-button--docs), | ||
[Link](..?path=/docs/components-text-and-typography-link--docs) | ||
|
||
These allow basic customization through props or limited children, like | ||
`ReactNode` or specific child types. | ||
|
||
#### 3. Compound components: | ||
|
||
Examples: [Chip](..?path=/docs/components-selections-chip--docs), | ||
[DataList](..?path=/docs/components-lists-and-tables-datalist--docs) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DataList is almost in its own category. it's bordering on an entire feature/view. I suppose it is technically a compound component though. it's just the largest compound component we have. |
||
|
||
These are part of larger compositions and may validate their children types to | ||
maintain internal consistency. | ||
|
||
#### 4. Strict complex components: | ||
|
||
Example: | ||
[Autocomplete](..?path=/docs/components-forms-and-inputs-autocomplete--docs), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we'll have to make a note to update these if we ever make Autocomplete less strict |
||
|
||
These have multiple UI pieces they are built out of but strict APIs and limited | ||
customization. | ||
|
||
#### 5. Customizable complex components: | ||
|
||
Example: [Combobox](..?path=/docs/components-selections-combobox--docs) | ||
|
||
These also have multiple UI pieces they are built out of but offer options for | ||
customization. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { Meta } from "@storybook/addon-docs"; | ||
|
||
<Meta title="Guides/Customizing components" /> | ||
|
||
# Customizing components | ||
|
||
### Philosophy: easy to use, flexible to customize | ||
|
||
Atlantis is designed to make building consistent, accessible, and visually | ||
appealing user interfaces as effortless as possible. Our goal is to create | ||
components that work out of the box, requiring minimal setup or configuration | ||
from consumers. | ||
|
||
While we strive to cover the most common design scenarios with thoughtful | ||
defaults, we understand that unique use cases may require customization. For | ||
these scenarios, we provide mechanisms to extend or modify our components in a | ||
way that maintains flexibility without compromising the integrity of the | ||
components. | ||
|
||
We recommend using the default implementations wherever possible to benefit from | ||
consistency, maintainability, and built in accessibility. However, if you choose | ||
to customize, please note that the responsibility for ensuring proper | ||
functionality and cohesion will rest with you. | ||
|
||
Atlantis aims to strike a balance between simplicity, flexibility, and | ||
consistency. | ||
|
||
### Primary customization approach: named render props | ||
|
||
In Atlantis, our primary approach to enabling customization is through named | ||
render props, using the `customRender____` pattern. This method allows consumers | ||
to inject their own UI logic while retaining the default behaviors and | ||
functionality of the component. | ||
|
||
#### Example: customRenderItem | ||
|
||
Here's an example of how to use a named render prop to customize the rendering | ||
of items in a [List](..?path=/docs/components-lists-and-tables-list--docs) | ||
component: | ||
|
||
```tsx | ||
const renderProductItem = item => ( | ||
<Flex template={["shrink", "grow"]} align="start"> | ||
<Text>{item.price}</Text> | ||
<Heading level={4}>{item.name}</Heading> | ||
</Flex> | ||
); | ||
|
||
export const CustomRenderExample = () => ( | ||
<List items={items} customRenderItem={renderProductItem} /> | ||
); | ||
``` | ||
|
||
In this example, the default List behavior (such as the main list structure and | ||
handling item interactions) is preserved. Only the presentation of individual | ||
items is customized. | ||
|
||
### Other customization approaches | ||
|
||
While custom render functions are our primary approach it is not used in all | ||
places. For simple cases where customization does not depend on internal state, | ||
we have chosen to extend prop types to allow for a `ReactNode` to be passed in. | ||
|
||
#### Example: Tab component (see [Tabs](..?path=/docs/components-navigation-tabs--docs)) | ||
|
||
Instead of introducing `customRenderLabel`, the `Tab` component was updated to | ||
allow the `label` prop to accept a `ReactNode`. | ||
|
||
```tsx | ||
<Tab label={<MyCustomLabel />} /> | ||
``` | ||
|
||
This approach was chosen to provide a simpler experience for those implementing | ||
Atlantis components. Customizing the `label` didn’t require exposing or | ||
interacting with the `Tab`’s internal state (e.g., active state styling). Once | ||
the design becomes more complex a custom render function would become a better | ||
fit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I played around with this for ~20mins to try to prevent the split of a Docs page and a page with this story but still having it render nicely in this docs page and couldn't get it. At least now it has a better name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha I don't get why this is its own section. that can't be by design. something must have changed in a storybook upgrade or something.