---
title: Stilguide
image: /images/user-guide/notes/notes_header.png
---

<Frame>
  <img src="/images/user-guide/notes/notes_header.png" alt="Header" />
</Frame>

Dette dokument indeholder reglerne, der skal følges, når du skriver kode.

Målet her er at have en konsekvent kodebase, der er let at læse og nem at vedligeholde.

Til dette er det bedre at være lidt mere detaljeret end at være for kortfattet.

Husk altid, at folk læser koden oftere, end de skriver den, især i et open source projekt, hvor alle kan bidrage.

Der er mange regler, der ikke er defineret her, men som automatisk kontrolleres af linters.

## React

### Brug funktionelle komponenter

Brug altid TSX funktionelle komponenter.

Brug ikke standard `import` med `const`, da det er sværere at læse og sværere at importere med kodekomplettering.

```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>;
};
```

### Egenskaber

Create the type of the props and call it `(ComponentName)Props` if there's no need to export it.

Brug destrukturering af 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>;
```

#### Undgå at bruge `React.FC` eller `React.FunctionComponent` til at definere prop typer

```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 />
);
```

#### Ingen Enkeltvariabel Prop Spredning i JSX Elementer

Undgå at bruge enkeltvariabel prop spredning i JSX elementer, som `{...props}`. Denne praksis resulterer ofte i kode, der er mindre læselig og sværere at vedligeholde, da det er uklart, hvilke props komponenten modtager.

```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 }} />;
};
```

Begrundelse:

- Ved et hurtigt blik er det tydeligere, hvilke props koden sender, hvilket gør det lettere at forstå og vedligeholde.
- Det hjælper med at forhindre tæt kobling mellem komponenterne via deres props.
- Linting værktøjer gør det lettere at identificere fejlagtigt stavede eller ubrugte props, når du angiver props eksplicit.

## JavaScript

### Brug nullish-coalescing operatøren `??`

```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';
```

### Brug valgfri kædning `?.`

```tsx
// ❌ Bad 
onClick && onClick();

// ✅ Good
onClick?.();
```

## TypeScript

### Brug `type` i stedet for `interface`

Brug altid `type` i stedet for `interface`, fordi de næsten altid overlapper, og `type` er mere fleksibel.

```tsx
// ❌ Bad
interface MyInterface {
  name: string;
}

// ✅ Good
type MyType = {
  name: string;
};
```

### Brug strenglitteraler i stedet for enums

[Strenglitteraler](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) er den foretrukne måde at håndtere enum-lignende værdier i TypeScript. De er lettere at udvide med Pick og Omit, og tilbyder en bedre udvikleroplevelse, især med kodekomplettering.

Du kan se, hvorfor TypeScript anbefaler at undgå enum [her](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 og interne biblioteker

Du bør bruge enums, som GraphQL codegen genererer.

Det er også bedre at bruge en enum, når du bruger et internt bibliotek, så det interne bibliotek ikke behøver at afsløre en strengliteraltype, der ikke er relateret til den interne API.

Eksempel:

```TSX
const {
  setHotkeyScopeAndMemorizePreviousScope,
  goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();

setHotkeyScopeAndMemorizePreviousScope(
  RelationPickerHotkeyScope.RelationPicker,
);
```

## Styling

### Brug StyledComponents

Style komponenterne med [styled-components](https://emotion.sh/docs/styled).

```tsx
// ❌ Bad
<div className="my-class">Hello World</div>
```

```tsx
// ✅ Good
const StyledTitle = styled.div`
  color: red;
`;
```

Prefix styled components with "Styled" to differentiate them from "real" components.

```tsx
// ❌ Bad
const Title = styled.div`
  color: red;
`;
```

```tsx
// ✅ Good
const StyledTitle = styled.div`
  color: red;
`;
```

### Tema

Brug af temaet til størstedelen af komponentstylingen er den foretrukne tilgang.

#### Måleenheder

Undgå at bruge `px` eller `rem` værdier direkte inden for de stilerede komponenter. De nødvendige værdier er generelt allerede defineret i temaet, så det anbefales at benytte temaet til disse formål.

#### Farver

Undlad at indføre nye farver; brug i stedet den eksisterende palet fra temaet. Skulle der opstå en situation, hvor paletten ikke passer, bedes du efterlade en kommentar, så teamet kan rette det.

```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};
`;
```

## Håndhævelse af Ingen-Type Imports

Undgå type imports. For at håndhæve denne standard kontrollerer en ESLint regel enhver type import og rapporterer dem. Dette hjælper med at opretholde konsistens og læsbarhed i TypeScript koden.

```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';
```

### Hvorfor Ingen-Type Imports

- **Konsistens**: Ved at undgå type imports og bruge en enkelt tilgang til både type og value imports, forbliver kodebasen konsekvent i sin modulimportstil.

- **Læsbarhed**: Ingen-type imports forbedrer kode læsbarheden ved at gøre det klart, når du importerer værdier eller typer. Dette reducerer tvetydighed og gør det lettere at forstå formålet med importerede symboler.

- **Maintainability**: It enhances codebase maintainability because developers can identify and locate type-only imports when reviewing or modifying code.

### ESLint Regel

An ESLint rule, `@typescript-eslint/consistent-type-imports`, enforces the no-type import standard. Denne regel vil generere fejl eller advarsler for enhver overtrædelse af type import.

Bemærk venligst, at denne regel specifikt adresserer sjældne hjørnetilfælde, hvor utilsigtede type imports opstår. TypeScript selv fraråder denne praksis, som nævnt i [TypeScript 3.8 release notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). In most situations, you should not need to use type-only imports.

For at sikre, at din kode overholder denne regel, skal du sørge for at køre ESLint som en del af din udviklingsarbejdsgang.
