Code Styleguide
Here you can find common code style decisions that you must know before becoming a contributor.
Components
File structure
The standard is to use pattern:
// ✅ Good
Component
|__ __tests__
| |__ __snapshots__
| |__ Component.test.tsx
| |__ ComponentComposite.test.tsx
|
|__ __stories__
| |__ Component.stories.tsx
| |__ ComponentComposite.stories.tsx
|
|__ components
| |__ Component.tsx
| |__ ComponentComposite.tsx
| |__ ComponentContext.tsx
|
|__ hooks
| |__ useComponentHook.ts
|
|_ index.tsx
|_ state.tsx
Prevent the use of React.FC
The use of React.FunctionComponent
(or the React.FC
shorthand) is discouraged to type the component props. If you need to type children explicitly, use React.ReactNode
. Find out some good reasons why.
// ✅ Good
interface Props {
title: string
children?: React.ReactNode
}
function Component(props: Props) {
// ...
}
// 🚨 Bad
interface Props {
title: string
}
const Component = React.FC<Props>(props) {
// ...
}
// 🚨 Bad
interface Props {
title: string
}
const Component = React.FunctionComponent<Props>(props) {
// ...
}
Avoid param destructuring
Prefer destructuring on the component's body.
interface Props {
title: string
// ...
}
// ✅ Good
function Component(props: Props) {
const { title } = props
// ...
}
// 🚨 Bad
function Component({ title }: Props) {
// ...
}
Avoid inline types
Always prefer creating an interface or type for the component props.
// ✅ Good
interface Props {
title: string
}
function Component(props: Props) {
// ...
}
// 🚨 Bad
function Component({ title }: { title: string }) {
// ...
}
Avoid inline extension
Avoid extending other types within the function param directly. Prefer extending or compose a new type for a cleaner code.
// ✅ Good
interface Props extends SomeTypeA {
title: string
}
function Component(props: Props) {
// ...
}
// ✅ Good
type Props = SomeTypeA & SomeTypeB
function Component(props: Props) {
// ...
}
// 🚨 Bad
function Component(props: Props & SomeTypeA) {
// ...
}
Avoid too much nesting
A deep directory nesting can cause a lot of pain points, so you must avoid it as much as you can.Learn why here.
Prefer named exports
Named exports are preferred over default exports.
// ✅ Good
export function Component() {
// ...
}
// 🚨 Bad
export default function Component() {
// ...
}
Testing
File structure
All test files must follow the *.test.(ts|tsx)
pattern, where *
shall never be index
. Use the __tests__
directory to store all the test files
// ✅ Good
Component
|__ __tests__
| |__ __snapshots__
| |__ Component.test.tsx
| |__ ComponentComposite.test.tsx
|
|__ components
| |__ Component.tsx
| |__ ComponentComposite.tsx
| |__ ComponentContext.tsx
|
|_ index.tsx
// 🚨 Bad
Component
|__ index.tsx
|__ Component.tsx
|__ Component.test.tsx
|__ ComponentComposite.tsx
|__ ComponentComposite.test.tsx
Styling
Prefer tokens
Always prefer to use tokens instead of hardcoded values
// ✅ Good
<Box
csx={{
color: 'base',
padding: 2,
}}
/>
// 🚨 Bad
<Box
csx={{
color: '#fff',
padding: '8px',
}}
/>
Prefer shorthands
Prefer props composition and shorthands.
// ✅ Preferred
<Box
csx={{
bg: 'base',
paddingX: 2,
size: '20rem',
}}
/>
// 🚨 Not wrong, but can improve
<Box
csx={{
backgroundColor: 'base',
paddingLeft: 2,
paddingRight: 2,
height: '20rem',
width: '20rem',
}}
/>
Prefer responsive aliases
Responsive aliases are preferred over custom media queries and responsive arrays. The main reasons for this are performance and semantics.
// ✅ Good
<Box
csx={{
padding: 2,
'@tablet': {
padding: 3,
},
'@desktop': {
padding: 4,
}
}}
/>
// 🚨 Bad, not semantic
<Box
csx={{
padding: [2, 3, 4],
}}
/>
// 🚨 Bad, not consistent
<Box
csx={{
padding: 2,
'@media screen and (min-width: 40em)': {
padding: 3,
},
'@media screen and (min-width: 80em)': {
padding: 4,
},
}}
/>
Avoid parent styles
Avoiding parent styles while coding an app does not matter much, but if you are within a library this is a bad practice. The user will not be able to customize the child's style without the !important
flag. So, you must avoid it.
// ✅ Good
<Box
csx={{
padding: 2,
}}
>
<Box as="h1" csx={{ color: 'base' }}>
Title
</Box>
</Box>
// 🚨 Bad
<Box
csx={{
padding: 2,
h1: {
color: 'base'
}
}}
>
<h1>Title</h1>
</Box>
Documentation
Writing stories
In admin-ui we use storybook as our playground to develop components.
File structure
Always use the stories.tsx
suffix. Otherwise, it will not work. Use the __stories__
directory to store all the story files
// ✅ Good
Component
|
|__ __stories__
| |__ Component.stories.tsx
| |__ ComponentComposite.stories.tsx
|
|__ components
| |__ Component.tsx
| |__ ComponentComposite.tsx
| |__ ComponentContext.tsx
|
|_ index.tsx
// 🚨 Bad
Component
|__ index.tsx
|__ Component.tsx
|__ Component.test.tsx
|__ ComponentComposite.tsx
|__ ComponentComposite.test.tsx