This library is still in development and is available only for internal usage at VTEX.
Skip to main content

Teams

Version: 0.131.0

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