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.7 KiB
Plaintext
296 lines
8.7 KiB
Plaintext
---
|
|
title: Stylgids
|
|
image: /images/user-guide/notes/notes_header.png
|
|
---
|
|
|
|
<Frame>
|
|
<img src="/images/user-guide/notes/notes_header.png" alt="Header" />
|
|
</Frame>
|
|
|
|
Hierdie dokument bevat die reëls wat gevolg moet word wanneer kode geskryf word.
|
|
|
|
Die doel hier is om 'n konsekwente kodebasis te hê, wat maklik is om te lees en maklik te onderhou.
|
|
|
|
Hiervoor is dit beter om 'n bietjie meer breedvoerig te wees as om te kortaf te wees.
|
|
|
|
Hou altyd in gedagte dat mense kode meer gereeld lees as wat hulle dit skryf, veral in 'n oopbronprojek, waar enige iemand kan bydra.
|
|
|
|
Daar is baie reëls wat nie hier gedefinieer is nie, maar wat outomaties nagegaan word deur linters.
|
|
|
|
## React
|
|
|
|
### Gebruik funksionele komponente
|
|
|
|
Gebruik altyd TSX-funksionele komponente.
|
|
|
|
Moet nie `import` met `const` gebruik nie, want dit is moeiliker om te lees en moeiliker om met kodevoltooiing in te voer.
|
|
|
|
```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>;
|
|
};
|
|
```
|
|
|
|
### Eienskappe
|
|
|
|
Create the type of the props and call it `(ComponentName)Props` if there's no need to export it.
|
|
|
|
Use props destructuring.
|
|
|
|
```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>;
|
|
```
|
|
|
|
#### Refrain from using `React.FC` or `React.FunctionComponent` to define prop types
|
|
|
|
```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 />
|
|
);
|
|
```
|
|
|
|
#### Geen Enkele Veranderlike Rekwisiet- Verspreiding in JSX-elemente nie
|
|
|
|
Vermy om 'n enkele veranderlike prop-sprei in JSX-elemente te gebruik, soos `{...props}`. Hierdie praktyk lei dikwels tot kode wat minder leesbaar en moeiliker is om te onderhou omdat dit onduidelik is watter rekwisiete die komponent ontvang.
|
|
|
|
```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 }} />;
|
|
};
|
|
```
|
|
|
|
Rasionalisering:
|
|
|
|
- Met 'n oogopslag is dit duideliker watter rekwisiete die kode deurgee, wat dit makliker maak om te verstaan en te onderhou.
|
|
- Dit help om noue koppeling tussen komponente via hul rekwisiete te voorkom.
|
|
- Lint-instrumente maak dit makliker om verkeerd gespelde of ongebruikte rekwisiete te identifiseer wanneer jy rekwisiete eksplisiet lys.
|
|
|
|
## JavaScript
|
|
|
|
### Gebruik nullish-coalescing-operateur `??`
|
|
|
|
```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';
|
|
```
|
|
|
|
### Gebruik opsionele ketting `?.`
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
onClick && onClick();
|
|
|
|
// ✅ Good
|
|
onClick?.();
|
|
```
|
|
|
|
## TypeScript
|
|
|
|
### Gebruik `type` in plaas van `interface`
|
|
|
|
Gebruik altyd `type` in plaas van `interface`, omdat hulle amper altyd oorvleuel, en `type` meer buigsaam is.
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
interface MyInterface {
|
|
name: string;
|
|
}
|
|
|
|
// ✅ Good
|
|
type MyType = {
|
|
name: string;
|
|
};
|
|
```
|
|
|
|
### Gebruik string-literale in plaas van enums
|
|
|
|
[String-literale](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) is die go-to manier om enum-agtige waardes in TypeScript te hanteer. Hulle is makliker om uit te brei met Keuse en Weglating, en bied 'n beter ontwikkelaarservaring, veral met kodevoltooiing.
|
|
|
|
Jy kan sien waarom TypeScript aanbeveel om enums te vermy [hier](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 en interne biblioteke
|
|
|
|
Jy moet enums gebruik wat GraphQL-kodegen genereer.
|
|
|
|
Dit is ook beter om 'n enum te gebruik wanneer jy 'n interne biblioteek gebruik, sodat die interne biblioteek nie 'n string-literaal tipe hoef bloot te stel wat nie met die interne API verband hou nie.
|
|
|
|
Voorbeeld:
|
|
|
|
```TSX
|
|
const {
|
|
setHotkeyScopeAndMemorizePreviousScope,
|
|
goBackToPreviousHotkeyScope,
|
|
} = usePreviousHotkeyScope();
|
|
|
|
setHotkeyScopeAndMemorizePreviousScope(
|
|
RelationPickerHotkeyScope.RelationPicker,
|
|
);
|
|
```
|
|
|
|
## Stilisties
|
|
|
|
### Gebruik Gestileerde Komponente
|
|
|
|
Styl die komponente met [styled-components](https://emotion.sh/docs/styled).
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
<div className="my-class">Hello World</div>
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good
|
|
const StyledTitle = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
Voeg "Gestileerde" voor aan gestileerde komponente om hulle van "regte" komponente te onderskei.
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
const Title = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good
|
|
const StyledTitle = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
### Temas
|
|
|
|
Die gebruik van die tema vir die meeste komponentstyl is die voorkeurbenadering.
|
|
|
|
#### Meetinhede
|
|
|
|
Vermy om `px` of `rem` waardes direk binne die gestileerde komponente te gebruik. Die nodige waardes is oor die algemeen reeds in die tema gedefinieër, so dit word aanbeveel om die tema vir hierdie doeleindes te gebruik.
|
|
|
|
#### Kleure
|
|
|
|
Refrain from introducing new colors; instead, use the existing palette from the theme. Moet daar 'n situasie wees waar die palet nie ooreenstem nie, los asseblief 'n opmerking sodat die span dit kan regstel.
|
|
|
|
```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};
|
|
`;
|
|
```
|
|
|
|
## No Force-Type Imports
|
|
|
|
Vermy tipe invoere. Om hierdie standaard te handhaaf, kyk 'n ESLint-reël na en rapporteer enige tipe invoere. Dit help om konsekwentheid en leesbaarheid in die TypeScript-kode te behou.
|
|
|
|
```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';
|
|
```
|
|
|
|
### Waarom Geen Tipe-Invoere Nie
|
|
|
|
- **Konsekwentheid**: Deur tipe invoere te vermy en 'n enkele benadering vir beide tipe en waarde invoere te gebruik, bly die kodebasis konsekwent in sy module invoer styl.
|
|
|
|
- **Leesbaarheid**: Geen-tipe invoere verbeter kode-leesbaarheid deur dit duidelik te maak wanneer jy waarde of tipes invoer. This reduces ambiguity and makes it easier to understand the purpose of imported symbols.
|
|
|
|
- **Onderhoubaarheid**: Dit verbeter kodebasis-onderhoubaarheid omdat ontwikkelaars tipe-alleen invoere kan identifiseer en lokaliseer wanneer hulle kode hersien of wysig.
|
|
|
|
### ESLint-reël
|
|
|
|
'n ESLint-reël, `@typescript-eslint/consistent-type-imports`, handhaaf die geen-tipe invoer standaard. Hierdie reël sal foute of waarskuwings genereer vir enige tipe invoeroortredings.
|
|
|
|
Neem asseblief kennis dat hierdie reël spesifiek skaars randgevalle aanspreek waar onbedoelde tipe-invoere voorkom. TypeScript ontmoedig self hierdie praktyk, soos genoem in die [TypeScript 3.8 vrystellingsnotas](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). In most situations, you should not need to use type-only imports.
|
|
|
|
Om seker te maak jou kode voldoen aan hierdie reël, maak seker om ESLint as deel van jou ontwikkelingswerkvloei uit te voer.
|