Hvordan lage et nytt prosjekt med Jøkul
Når du skal bruke Jøkul i et nytt prosjekt er det en del å huske på.
Designer som skal lage et nytt prosjekt?
Nye skisser i Figma trenger bare sørge for at Jøkul sitt komponentbibliotek er i bruk under Assets. Etter det blir Jøkul tilgjengelig i skissene dine.
Resten av denne guiden retter seg mot utviklere.
Pakker
Om du skal bygge et nytt prosjekt med Jøkul er det noen grunnleggende pakker du alltid må ha installert:
I tillegg har vi pakker for mange ulike komponenter, og noen pakker med hjelpefunksjoner for validering, formatering, og nyttige React hooks. Det er lettere å få oversikt over komponentene og hva de gjør under Komponenter.
Installer avhengigheter
For å installere det grunnleggende:
yarn add @fremtind/jkl-core @fremtind/jkl-webfonts
yarn add --dev @fremtind/browserslist-config-jkl
Kort om de forskjellige pakkene i Jøkul
Jøkuls kode er delt inn i mange pakker, typisk to pakker per komponent.
Hvorfor to?
Vi skiller på CSS-pakker og React-pakker i Jøkul. Du kan bruke komponentene i Jøkul som rene stilark dersom prosjektet ditt ikke bruker React, for eksempel om du skal bruke Jøkul i et CMS. Alle CSS-stilark finnes i både minifisert og uminifisert utgave. Sørg for å bruke den minifiserte i produksjon.
Det er sterkt anbefalt å bruke React-komponentene om du overhode har mulighet.
Hvis du bruker React-komponenten blir stilpakken automatisk installert som en avhengighet. Du trenger med andre ord ikke både React- og stilpakken i package.json
.
Et eksempel på bruk av en komponent
Ta Accordion som et eksempel. Skal du bruke React-komponenten installerer du den med yarn add @fremtind/jkl-accordion-react
og får automatisk med riktig versjon av @fremtind/jkl-accordion
som en avhengighet. Dersom du bare bruker stilpakken, installerer du den med yarn add @fremtind/jkl-accordion
.
Når du skal ta i bruk en React-komponent trenger du å laste inn både stilen og komponenten. Hvis du har satt opp en CSS-loader i prosjektet ditt kan du importere stilen direkte i TypeScript. Du kan også velge å importere den i en av dine .scss
- eller .css
-filer.
import "@fremtind/jkl-core/core.min.css";
import "@fremtind/jkl-accordion/accordion.min.css";
import { Accordion, AccordionItem } from "@fremtind/jkl-accordion";
Initialisering
For at komponentene i Jøkul skal virke riktig trenger de å vite om brukeren navigerer i løsningen med mus, tastatur eller touch. Det gjøres ved å kjøre initTabListener
funksjonen fra @fremtind/jkl-core
. Det trengs bare gjøres én gang, helst så tidlig som det lar seg gjøre. Normalt vil det være i entrypointet i applikasjonen din.
initTabListener
ser på hvordan siden interageres med – museklikk, tastetrykk, eller touch – og setter automatisk et data
-attributt på <body>
, som Jøkul bruker til blant annet å vise enda tydeligere fokusringer ved tastaturnavigasjon.
import { initTabListener } from "@fremtind/jkl-core";
initTabListener();
Fonter
For at blant annet fonter skal bli riktige må du sette jkl
-klassen på rotnivå i appen din, for eksempel på <body>
eller <div>
-en hvor appen din rendres.
<div class="jkl" id="app">
<!-- app rendres her -->
</div>
Bruk med Sass
Om du bruker Sass-stilark i prosjektet ditt er dette den enkleste måten å få riktige fonter. I rot-.scss
-filen din:
// NB! bruk riktig importsyntaks for din sass-loader (~ er brukt her)
@use "~@fremtind/jkl-webfonts/webfonts.scss" with (
$webfonts-dir: "../relative/path/to/node_modules/@fremtind/jkl-webfonts/fonts"
);
Variabelen $webfonts-dir
angir hvor filene ligger. Hvis den ikke spesifiseres vil stilarket se etter fontfilene i mappen /fonts
.
Bruk med CSS
Om du ikke bruker Sass kan du benytte deg av den vanlige .css
-versjonen. Denne versjonen ser kun etter fontfilene i mappen /fonts
. Om du vil legge fontfilene et annet sted må du kopiere CSS-filen node_modules/@fremtind/jkl-webfonts/webfonts.css
og legge den inn i prosjektet ditt. Deretter må du endre url-en i hver @font-face
-definisjon manuelt så det stemmer med hvor fontfilene dine ligger:
@font-face {
font-family: "Fremtind Grotesk";
font-display: fallback;
font-weight: normal;
font-style: normal;
src: local("Fremtind Grotesk"),
/* Endre de to neste linjene så de stemmer */
url("/relative/path/to/font/files/FremtindGrotesk-Regular-Web.woff2") format("woff2"), url("/relative/path/to/font/files/FremtindGrotesk-Regular-Web.woff")
format("woff");
}
Konfigurasjon
Mange av utviklerverktøyene i frontendverden kan lese en browserslist og automatisk sørge for å optimalisere koden som bygges og til slutt ender opp hos brukerne våre. Jøkul bruker en egen browserslist-config internt, og det er anbefalt at du bruker den samme i prosjektet ditt.
Etter å ha lagt til pakken som en devDependency
bruker du den ved å legge til browserslist
-feltet i package.json
:
{
"browserslist": ["extends @fremtind/browserslist-config-jkl"]
}
Polyfills
All kode blir transpilert til å støtte nettleserne i browserslist, men det kan være brukt funksjonalitet som ikke støttes i alle nettlesere uten å laste inn en polyfill. Disse polyfillene vil i så fall dokumenteres her.
I skrivende stund er det ingen polyfills som trengs, etter at vi droppet støtte for Internet Explorer 11.
Testing library
Det er en feil i @testing-library
sin håndtering av Web Components hvis en test feiler. Det vil kunne vi en evig løkke som skriver ut stack trace til terminalen helt til terminalen tryner. Legg til dette i setupTests.ts
dersom du bruker Jest.
import { configure } from "@testing-library/react";
import prettier from "prettier";
configure({
getElementError: (message, container) => {
return new Error(
[
message,
prettier.format(container.innerHTML, {
parser: "html",
htmlWhitespaceSensitivity: "ignore",
}),
]
.filter(Boolean)
.join("\n\n"),
);
},
});
Skjemaverktøy
React Hook Form
Mange team i Fremtind velger å bruke React Hook Form for å gjøre skjemavalidering.
Skjemakomponentene i Jøkul skal kunne brukes med react-hook-form
på en enkel måte.
I praksis betyr det at de skal fungere som uncontrolled components så register
kan brukes i stedet for Controller.
import React, { FC } from "react";
import { useForm } from "react-hook-form";
import { PrimaryButton } from "@fremtind/jkl-button-react";
import { RadioButtonGroup, RadioButton } from "@fremtind/jkl-radio-button-react";
type FormValues = {
housetype: string;
};
type Props = {
onSubmit: () => void;
};
const HouseDetailsForm: FC<Props> = ({ onSubmit }) => {
const { register, handleSubmit } = useForm<FormValues>();
return (
<form onSubmit={handleSubmit(onSubmit)}>
<RadioButtonGroup legend="Hvilken boligtype?" variant="large">
{["Enebolig", "Tomannsbolig", "Rekkehus", "Leilighet"].map((type) => (
<RadioButton {...register("housetype", { required: true })} key={type} label={type} value={type} />
))}
</RadioButtonGroup>
<PrimaryButton type="submit">Gå videre</PrimaryButton>
</form>
);
};
export default HouseDetailsForm;
Enkelte komponenter kan likevel trenge Controller
i en overgangsperiode. Om du kommer over en komponent som fortsatt krever
Controller
må du gjerne lage et issue på GitHub, og veldig gjerne komme med en pull request!
import React, { FC } from "react";
import { useForm, Controller } from "react-hook-form";
import { PrimaryButton } from "@fremtind/jkl-button-react";
import { Select } from "@fremtind/jkl-select-react";
type FormValues = {
housetype: string;
};
type Props = {
onSubmit: () => void;
};
const AddressForm: FC<Props> = ({ onSubmit }) => {
const { register, handleSubmit } = useForm<FormValues>();
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
control={control}
name="currency"
defaultValue="USD"
render={({ field: { onChange, value, ref } }) => (
<Select
ref={ref}
label="Valuta"
items={["USD", "EUR", "JPY"]}
onChange={onChange}
value={value}
width="6rem"
/>
)}
/>
<PrimaryButton type="submit">Gå videre</PrimaryButton>
</form>
);
};
export default AddressForm;