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