When adding UI components, you should be able to group them in two root domains:
pages
- page scope based componentsshared
- components that are shared all across the app
Folder naming rules:
kebab-case
folder name indicates domain namePascalCase
folders and filenames should be used for components naming
src
├── components
│ ├── pages
│ │ ├── home
│ │ │ ├── HomeHeaderSection
│ │ │ │ └── HomeHeaderSection.tsx
│ │ │ └── HomeTodoListSection
│ │ │ └── HomeTodoListSection.tsx
│ │ └── todo
│ │ ├── TodoHeaderSection
│ │ │ └── TodoHeaderSection.tsx
│ │ └── TodoCreateFormSection
│ │ └── TodoCreateFormSection.tsx
│ └── shared
│ ├── core
│ │ ├── Section
│ │ │ └── Section.tsx
│ │ └── Card
│ │ └── Card.tsx
│ ├── fields
│ │ └── TextField
│ │ └── TextField.tsx
│ └── todo
│ ├── TodoCard
│ │ └── TodoCard.tsx
│ ├── TodoList
│ │ └── TodoList.tsx
│ └── TodoCreateForm
│ └── TodoCreateForm.tsx
└── pages
├── index.tsx
└── todo
└── [id]
└── index.tsx
We can refer to them as atoms, smallest building blocks, highly reusable and composable. You can check the Open UI standard proposal for inspiration how to split components into small segments. Components could be designed as Compound Components or Black-box Components with good "inversion of control" interface like ReactSelect.
Components | Parts | Description |
---|---|---|
Card |
`Card`, `CardImage`, `CardImageOverlay`, `CardTitle`, `CardDescription`, ...
|
From these parts, you'll be able to compose multiple more specific **_molecules_** like `ProductCard` or `UserCard`. |
Section | `Section`, `SectionHeader`, `SectionBody`, .. | This might have multiple background schemes like `dimmed`, `inverted`, `light`. |
Search | `Search`, `SearchInput`, `SearchEmpty`, SearchResults`, ... | `Search` uses context to provide shared state to other parts. `SearchInput` renders input and it could be placed anywhere in the DOM structure (for example, in the page `Header`). `SearchEmpty` and `SearchResults` handles switching between states and showing the result. |
ReactSelect | `ReactSelect`, `./components/ClearIndicator`, `./components/Control`, ... | The list of custom components can be find [here](https://react-select.com/components) |
We can refer to them as molecules. They are more specific components built out of atoms (core components). They are shared components that encapsulate some specific feature of an app.
Component name is always composed out of two parts Context
+ Domain
, for example ArticlesPanel
where Articles
is context and Panel
is domain.
Here are some examples of feature domain names:
Domains | Components | Description |
---|---|---|
`fields` | `InputField`, `TextareaField` | Specific form fields prepared to be used with [React Hook Form](https://react-hook-form.com/) library. Built out of multiple parts, for example `InputGroup`, `InputLeftElement`, `Input` form [Chakra UI](https://chakra-ui.com/docs/form/input#add-elements-inside-input) |
`overlays` | `UnsupportedBrowserOverlay`, `BugsnagErrorOverlay` | Components that covers the whole page and prevents user to interact with the page in some degree. |
`layouts` | `MainLayout`, `AdminLayout` | Components that are shared across the pages and renders the application shell (navigation and footer) |
`messages` | `NoResultsMessage`, `EmptyListMessage`, `LoadingMessage`, `ErrorMessage` | Reusable messages components that could be shared across the pages for handling empty list results, loading states or ErrorBoundaries fallback |
`navigations` | `MainNavigation`, `AdminNavigation` | Different navigations used in layouts to support different app shell styles. They could handle user logged-in/logged-out states and mobile/desktop layouts |
`footers` | `MainFooter`, `AdminFooter` | Different footers used in layouts to support different app shell styles. Serves the same purpose as `navigations` |
`panels` | `ArticlesPanel`, `EventPanel`, `EventSidebarPanel`, `GroupPanel` | Specific panels that holds filtering dropdowns for narrowing down the list results. Usually consists of core `Panel` compound component for sharing the styles and sorting dropdowns. |
`markdowns` | `ArticleMarkdown`, `AnnouncementMarkdown` | Components that handles parsing of the markdown and styling of the generated HTML |
We can refer to them as molecules also, but they are tied to some entity, for example Datx model, algolia resource, google map entity.
Component name is always composed out of two parts Entity
+ Context
, for example TodoList
where Todo
is entity and List
is context.
Domains | Components | Description |
---|---|---|
`todo` | `TodoList`, `TodoCreateForm`, `TodoCard`, ... | They should accept primitive props like `resourceId` and hook to the resource fetching layer via `SWR`. |
`user` | `UserList`, `UserCreateForm`, `UserCard`, ... | |
`ticket` | `TicketList`, `TicketCreateForm`, `TicketCard`, ... |
Utility components usually does not have any visual representation on the screen, but they are still reusable declarative components.
Domains | Components | Description |
---|---|---|
`utilities` | `Meta`, `BugsnagErrorBoundary` | `Meta` inserts `meta` tags into document `head`. `BugsnagErrorBoundary` catches the error, triggers the Bugsnag report and render fallback component |