8cadd00d34
Created by Github action --------- Co-authored-by: Crowdin Bot <support+bot@crowdin.com> Co-authored-by: github-actions <github-actions@twenty.com>
296 lines
8.8 KiB
Plaintext
296 lines
8.8 KiB
Plaintext
---
|
|
title: Guia de Estilo
|
|
image: /images/user-guide/notes/notes_header.png
|
|
---
|
|
|
|
<Frame>
|
|
<img src="/images/user-guide/notes/notes_header.png" alt="Header" />
|
|
</Frame>
|
|
|
|
Este documento inclui as regras a seguir ao escrever código.
|
|
|
|
O objetivo aqui é ter uma base de código consistente, que seja fácil de ler e fácil de manter.
|
|
|
|
Para isso, é melhor ser um pouco mais detalhado do que ser muito conciso.
|
|
|
|
Lembre-se sempre de que as pessoas leem código com mais frequência do que escrevem, especialmente em um projeto de código aberto, onde qualquer um pode contribuir.
|
|
|
|
Existem muitas regras que não estão definidas aqui, mas que são verificadas automaticamente por linters.
|
|
|
|
## React
|
|
|
|
### Use componentes funcionais
|
|
|
|
Sempre use componentes funcionais TSX.
|
|
|
|
Não use `import` padrão com `const`, porque é mais difícil de ler e mais difícil de importar com autocompletar.
|
|
|
|
```tsx
|
|
// ❌ Bad, harder to read, harder to import with code completion
|
|
const MyComponent = () => {
|
|
return <div>Hello World</div>;
|
|
};
|
|
|
|
export default MyComponent;
|
|
|
|
// ✅ Good, easy to read, easy to import with code completion
|
|
export function MyComponent() {
|
|
return <div>Hello World</div>;
|
|
};
|
|
```
|
|
|
|
### Props
|
|
|
|
Crie o tipo das props e chame de `(NomeDoComponente)Props` se não houver necessidade de exportá-lo.
|
|
|
|
Use destruturação de props.
|
|
|
|
```tsx
|
|
// ❌ Bad, no type
|
|
export const MyComponent = (props) => <div>Hello {props.name}</div>;
|
|
|
|
// ✅ Good, type
|
|
type MyComponentProps = {
|
|
name: string;
|
|
};
|
|
|
|
export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
|
|
```
|
|
|
|
#### Abstenha-se de usar `React.FC` ou `React.FunctionComponent` para definir tipos de props
|
|
|
|
```tsx
|
|
/* ❌ - Bad, defines the component type annotations with `FC`
|
|
* - With `React.FC`, the component implicitly accepts a `children` prop
|
|
* even if it's not defined in the prop type. This might not always be
|
|
* desirable, especially if the component doesn't intend to render
|
|
* children.
|
|
*/
|
|
const EmailField: React.FC<{
|
|
value: string;
|
|
}> = ({ value }) => <TextInput value={value} disabled fullWidth />;
|
|
```
|
|
|
|
```tsx
|
|
/* ✅ - Good, a separate type (OwnProps) is explicitly defined for the
|
|
* component's props
|
|
* - This method doesn't automatically include the children prop. If
|
|
* you want to include it, you have to specify it in OwnProps.
|
|
*/
|
|
type EmailFieldProps = {
|
|
value: string;
|
|
};
|
|
|
|
const EmailField = ({ value }: EmailFieldProps) => (
|
|
<TextInput value={value} disabled fullWidth />
|
|
);
|
|
```
|
|
|
|
#### Nenhuma propagação de prop de variável única em elementos JSX
|
|
|
|
Evite usar propagação de prop de variável única em elementos JSX, como `{...props}`. Essa prática geralmente resulta em um código menos legível e mais difícil de manter, pois não está claro quais props o componente está recebendo.
|
|
|
|
```tsx
|
|
/* ❌ - Bad, spreads a single variable prop into the underlying component
|
|
*/
|
|
const MyComponent = (props: OwnProps) => {
|
|
return <OtherComponent {...props} />;
|
|
}
|
|
```
|
|
|
|
```tsx
|
|
/* ✅ - Good, Explicitly lists all props
|
|
* - Enhances readability and maintainability
|
|
*/
|
|
const MyComponent = ({ prop1, prop2, prop3 }: MyComponentProps) => {
|
|
return <OtherComponent {...{ prop1, prop2, prop3 }} />;
|
|
};
|
|
```
|
|
|
|
Racional:
|
|
|
|
- De relance, fica mais claro quais props o código está passando, tornando-o mais fácil de entender e manter.
|
|
- Ajuda a evitar o acoplamento apertado entre componentes por meio de suas props.
|
|
- As ferramentas de linting facilitam a identificação de props com erros ortográficos ou não utilizadas quando você lista explicitamente as props.
|
|
|
|
## JavaScript
|
|
|
|
### Use o operador de coalescência nula `??`
|
|
|
|
```tsx
|
|
// ❌ Bad, can return 'default' even if value is 0 or ''
|
|
const value = process.env.MY_VALUE || 'default';
|
|
|
|
// ✅ Good, will return 'default' only if value is null or undefined
|
|
const value = process.env.MY_VALUE ?? 'default';
|
|
```
|
|
|
|
### Use encadeamento opcional `?.`
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
onClick && onClick();
|
|
|
|
// ✅ Good
|
|
onClick?.();
|
|
```
|
|
|
|
## TypeScript
|
|
|
|
### Use `type` em vez de `interface`
|
|
|
|
Sempre use `type` em vez de `interface`, porque quase sempre se sobrepõem, e `type` é mais flexível.
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
interface MyInterface {
|
|
name: string;
|
|
}
|
|
|
|
// ✅ Good
|
|
type MyType = {
|
|
name: string;
|
|
};
|
|
```
|
|
|
|
### Use literais de string em vez de enums
|
|
|
|
[Literals de string](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) são a maneira ideal de lidar com valores que se assemelham a enum em TypeScript. Eles são mais fáceis de estender com Pick e Omit, e oferecem uma melhor experiência de desenvolvedor, especialmente com autocompletar.
|
|
|
|
Você pode ver por que TypeScript recomenda evitar enums [aqui](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
|
|
|
|
```tsx
|
|
// ❌ Bad, utilizes an enum
|
|
enum Color {
|
|
Red = "red",
|
|
Green = "green",
|
|
Blue = "blue",
|
|
}
|
|
|
|
let color = Color.Red;
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good, utilizes a string literal
|
|
|
|
let color: "red" | "green" | "blue" = "red";
|
|
```
|
|
|
|
#### GraphQL e bibliotecas internas
|
|
|
|
Você deve usar enums que o codegen GraphQL gera.
|
|
|
|
Também é melhor usar um enum ao usar uma biblioteca interna, para que a biblioteca interna não precise expor um tipo de literal de string que não está relacionado à API interna.
|
|
|
|
Exemplo:
|
|
|
|
```TSX
|
|
const {
|
|
setHotkeyScopeAndMemorizePreviousScope,
|
|
goBackToPreviousHotkeyScope,
|
|
} = usePreviousHotkeyScope();
|
|
|
|
setHotkeyScopeAndMemorizePreviousScope(
|
|
RelationPickerHotkeyScope.RelationPicker,
|
|
);
|
|
```
|
|
|
|
## Estilização
|
|
|
|
### Use StyledComponents
|
|
|
|
Estilize os componentes com [styled-components](https://emotion.sh/docs/styled).
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
<div className="my-class">Hello World</div>
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good
|
|
const StyledTitle = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
Prefixe componentes estilizados com "Styled" para diferenciá-los de componentes "reais".
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
const Title = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good
|
|
const StyledTitle = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
### Tematização
|
|
|
|
Utilizar o tema para a maioria das estilizações de componentes é a abordagem preferida.
|
|
|
|
#### Unidades de medida
|
|
|
|
Evite usar valores `px` ou `rem` diretamente dentro dos componentes estilizados. Os valores necessários geralmente já estão definidos no tema, por isso é recomendável usar o tema para esses fins.
|
|
|
|
#### Cores
|
|
|
|
Abstenha-se de introduzir novas cores; em vez disso, use a paleta existente do tema. Caso haja uma situação onde a paleta não se alinhe, por favor, deixe um comentário para que a equipe possa corrigi-la.
|
|
|
|
```tsx
|
|
// ❌ Bad, directly specifies style values without utilizing the theme
|
|
const StyledButton = styled.button`
|
|
color: #333333;
|
|
font-size: 1rem;
|
|
font-weight: 400;
|
|
margin-left: 4px;
|
|
border-radius: 50px;
|
|
`;
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good, utilizes the theme
|
|
const StyledButton = styled.button`
|
|
color: ${({ theme }) => theme.font.color.primary};
|
|
font-size: ${({ theme }) => theme.font.size.md};
|
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
|
margin-left: ${({ theme }) => theme.spacing(1)};
|
|
border-radius: ${({ theme }) => theme.border.rounded};
|
|
`;
|
|
```
|
|
|
|
## Imposição de Importações Sem Tipo
|
|
|
|
Evite importações de tipo. Para garantir esse padrão, uma regra do ESLint verifica e reporta todas as importações de tipo. Isso ajuda a manter a consistência e a legibilidade no código TypeScript.
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
import { type Meta, type StoryObj } from '@storybook/react';
|
|
|
|
// ❌ Bad
|
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
|
|
// ✅ Good
|
|
import { Meta, StoryObj } from '@storybook/react';
|
|
```
|
|
|
|
### Por que Importações Sem Tipo
|
|
|
|
- **Consistência**: Ao evitar importações de tipo e usar uma abordagem única para importações de tipo e valor, a base de código permanece consistente em seu estilo de importação de módulos.
|
|
|
|
- **Legibilidade**: Importações sem tipo melhoram a legibilidade do código, deixando claro quando você está importando valores ou tipos. Isso reduz a ambiguidade e facilita a compreensão do propósito dos símbolos importados.
|
|
|
|
- **Manutenibilidade**: Melhora a manutenibilidade da base de código porque os desenvolvedores podem identificar e localizar importações apenas de tipo ao revisar ou modificar o código.
|
|
|
|
### Regra do ESLint
|
|
|
|
An ESLint rule, `@typescript-eslint/consistent-type-imports`, enforces the no-type import standard. Esta regra gerará erros ou avisos para quaisquer violações de importação de tipo.
|
|
|
|
Observe que esta regra aborda especificamente casos raros em que ocorrem importações de tipo não intencionais. O próprio TypeScript desencoraja essa prática, conforme mencionado nas [notas de lançamento do TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). Na maioria das situações, você não deve precisar usar importações apenas de tipo.
|
|
|
|
Para garantir que seu código esteja em conformidade com essa regra, certifique-se de executar o ESLint como parte do seu fluxo de trabalho de desenvolvimento.
|