Gå til innholdet

Typesikker bruk

Klasser og dataattributter gjør komponentene rammeverksuavhengige, men alt er strenger:

<button class="fs-button" data-variant="secundary">Lagre utkast</button>

Knappen får primærstilen. Ingen feilmelding, bare en variant som stille aldri ble brukt. Derfor finnes fs. Skriver du HTML uten TypeScript, tar utvidelsen for VS Code den samme feilen.

import { fs } from "@fristil/designsystem"
<button {...fs.button({ variant: "secondary" })}>Lagre utkast</button>
<input {...fs.input({ type: "email", state: "invalid" })} />
<span {...fs.badge({ color: "success" })}>Innvilget</span>
<a {...fs.link()} href="/kvittering">Se kvittering</a>

Skriv fs. i editoren, så ser du hele systemet. Hver komponent er en funksjon som tar et valgobjekt og returnerer attributtene du sprer inn i elementet. Formen er den samme for alle.

Returverdiene er vanlige objekter. Derfor virker samme API i React, Astro, Datastar og ren HTML.

I JSX sprer du objektet rett inn i elementet. Uten JSX gjør fs.setAttributes jobben:

const felt = document.querySelector<HTMLInputElement>("#epost")
fs.setAttributes(felt, fs.input({ type: "email", state: "invalid" }))

Kall den på nytt for å endre tilstand. Attributter fra forrige kall som ikke er med i det nye settet blir fjernet, så lenge navnet står i SYSTEM_ATTRIBUTES i dom.ts. Ellers ville feltet blitt stående rødt etter at feilen var rettet. Den rydder bare i systemets egne attributter og fs--klasser; data-testid, name og dine egne klasser står urørt.

fs.button()
// { class: "fs-button" }
fs.button({ variant: "primary" })
// { class: "fs-button" }, primær er standard i CSS-en
fs.button({ variant: "danger" })
// { class: "fs-button", "data-variant": "danger" }

Du sier alltid hvilken variant du vil ha; funksjonen vet når attributtet kan utelates.

fs.button.variants
// readonly ["primary", "secondary", "ghost", "danger"]
fs.button.isVariant("ghost") // true
fs.button.isVariant("gost") // false

Samme mønster overalt: fs.badge.colors og fs.badge.isColor, fs.input.types og fs.input.isType.

Kommer verdien fra et API, en URL eller localStorage, er den en string TypeScript ikke kan garantere noe om. Vakten gir en gyldig verdi eller en trygg reserve:

const svar = await hentKnappeoppsett()
const variant = fs.button.isVariant(svar.variant) ? svar.variant : "primary"
fs.button({ variant })

Etter vakten vet TypeScript at verdien er en ButtonVariant.

ValgHva det betyrHvor
variantVisuell vekt eller betydningbutton, helpText, errorText
colorHva en status betyrbadge
stateValideringstilstandinput, textarea, select
typeHTML-typen på feltetinput

state er én type på tvers av de tre feltkomponentene, så en verdi kan sendes mellom dem uten konvertering:

const tilstand = fs.isState(fraServer) ? fraServer : "default"
fs.input({ state: tilstand })
fs.textarea({ state: tilstand })
fs.select({ state: tilstand })

TypeScript kjenner ikke <fs-field>, <fs-session-timeout> og <fs-connection-status> uten videre. Importer typene én gang i en .d.ts-fil:

src/fristil.d.ts
import "@fristil/designsystem/react-jsx"

Da får attributtene autofullføring og sjekk:

<fs-field required-marker="text" /> // ok
<fs-field required-marker="tekst" /> // feil: "none" | "symbol" | "text"
<fs-session-timeout warnAt={1500} /> // feil: attributtet heter warn-at
<fs-connection-status offline="Nede" /> // feil: ukjent attributt

Ren HTML, Astro og Datastar trenger ikke dette. Der er <fs-field> bare en HTML-tagg.

Attributtene kan spres på feil element. <div {...fs.button({ variant: "danger" })} /> kompilerer, for returverdien er bare et objekt med HTML-attributter.

Returtypen på type er bredere enn verdien du sendte inn. fs.input({ type: "date" }).type er hele unionen, ikke "date".

fs er valgfritt. Uten TypeScript eller byggesteg er dette like gyldig:

<button class="fs-button" data-variant="secondary">Lagre utkast</button>

Resultatet er identisk. Forskjellen er hvor tidlig du får vite at du skrev secundary.

Vil du bare ha én komponent:

import { button } from "@fristil/designsystem/button"

Subpath-ene returnerer class og for, som hovedinngangen. React-varianten finnes bare som samlet fs.