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