CodeWorlds
Powrót do kolekcji
Przewodnik16 min czytaniaZespół CodeWorlds

Storybook, komponenty w izolacji i testy

Storybook 10 buduje i dokumentuje komponenty w izolacji. Integracja z Vitest, testy interakcji, licencja MIT i realny koszt utrzymania konfiguracji.

Storybook, komponenty w izolacji i testy

Storybook to środowisko, w którym komponent interfejsu uruchamiasz osobno, poza aplikacją, w kilkunastu stanach naraz. Repozytorium storybookjs/storybook ma około 91 tysięcy gwiazdek, licencja to MIT, a bieżąca wersja to 10.5.10. Ten tekst dotyczy tego, co dostajesz w zamian za konfigurację, którą potem trzeba utrzymywać.

Co Storybook właściwie robi

Pod jedną nazwą kryją się trzy różne narzędzia i to pierwsza rzecz, którą trzeba rozdzielić, zanim policzy się koszty.

Pierwsze to środowisko pracy. Zamiast klikać się przez aplikację do formularza w stanie błędu, otwierasz ten stan bezpośrednio z listy po lewej stronie ekranu. Każdy wariant komponentu jest osobnym wpisem, adresowalnym linkiem, który da się wysłać osobie testującej albo projektantce. Przy komponentach ukrytych głęboko w przepływie, na przykład ekranie płatności po trzech krokach formularza, to jest największa oszczędność czasu z całego pakietu.

Drugie to dokumentacja. Storybook potrafi wygenerować stronę opisującą komponent na podstawie typów jego właściwości i zestawu przygotowanych wariantów. Dostajesz tabelę właściwości z typami i wartościami domyślnymi, żywe przykłady i możliwość zmiany argumentów w przeglądarce. Dla zespołu, w którym komponenty konsumuje ktoś spoza zespołu autorskiego, to bywa jedyna dokumentacja, którą ktokolwiek czyta.

Trzecie to warstwa testów. Do wariantu komponentu dopisujesz funkcję, która klika, wpisuje tekst i sprawdza wynik. Ta sama definicja obsługuje wtedy trzy rzeczy naraz: podgląd, dokumentację i test. To jest właściwy argument za tym narzędziem, bo pojedynczy artefakt spłaca się trzy razy.

Czego Storybook nie robi, jest równie istotne. Nie zastępuje testów całej aplikacji, bo komponent uruchomiony w izolacji nie widzi routingu, sesji ani prawdziwego backendu. Nie jest systemem projektowym, tylko miejscem, w którym system projektowy można pokazać. Nie renderuje też sam z siebie stanu globalnego z Reacta czy z magazynu danych: kontekst, który aplikacja dostarcza w korzeniu drzewa, musisz dostarczyć osobno w konfiguracji podglądu.

Instalacja i to, co realnie ląduje w projekcie

Instalacja jest jednym poleceniem, ale to, co po niej zostaje w katalogu zależności, warto obejrzeć przed decyzją.

Code
Bash
# wykrywa framework i buduje katalog .storybook
npx storybook init

# uruchomienie lokalne i budowanie wersji statycznej
npm run storybook
npm run build-storybook

# narzędzia serwisowe dodane przez init
npx storybook upgrade
npx storybook automigrate
npx storybook doctor

Wersja dziesiąta, wydana 28 października 2025 roku, przyniosła jedną zmianę łamiącą zgodność: publikowany kod jest wyłącznie w formacie modułów ES. Wymaga to Node w wersji 20.16 lub nowszej z linii 20, 22.19 lub nowszej z linii 22, albo dowolnej z linii 24. Serwer budujący z przypiętym starszym Node zatrzyma się od razu, zanim dojdzie do jakiejkolwiek konfiguracji.

Rezygnacja z CommonJS zmniejszyła rozmiar instalacji o 29 procent względem wersji dziewiątej. To realna poprawa, ale punkt wyjścia był wysoki i nadal jest wysoki. Sam pakiet storybook po rozpakowaniu zajmuje 20,3 megabajta w 233 plikach i ciągnie siedemnaście zależności bezpośrednich. Wśród nich są @vitest/spy i @vitest/expect przypięte na 3.2.4, @testing-library/dom, @testing-library/user-event, esbuild, oxc-parser i oxc-resolver. Storybook nosi więc w środku spory fragment infrastruktury testowej, zanim jeszcze dodasz jakikolwiek dodatek.

Licencja jest MIT i mówią to zgodnie trzy źródła: plik LICENSE w repozytorium, pole license w rejestrze npm oraz metadane wystawiane przez interfejs programistyczny GitHuba. Jest jednak drobiazg, który potrafi zaskoczyć przy audycie: opublikowana paczka nie zawiera pliku z tekstem licencji w ogóle. W archiwum wersji 10.5.10 są tylko README.md, package.json, katalog dist i katalog assets. Skanery zależności czytające zawartość paczek zamiast metadanych rejestru pokażą w tym miejscu brak, choć sama licencja nie budzi wątpliwości.

Konfiguracja mieszka w katalogu .storybook, a jej trzon to plik main.ts.

Code
TypeScript
import type { StorybookConfig } from '@storybook/react-vite'

const config: StorybookConfig = {
  framework: {
    name: '@storybook/react-vite',
    options: {}
  },
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-docs',
    '@storybook/addon-a11y',
    '@storybook/addon-vitest'
  ],
  staticDirs: ['../public'],
  core: {
    disableTelemetry: true
  },
  typescript: {
    reactDocgen: 'react-docgen-typescript'
  }
}

export default config

Pole core.disableTelemetry nie jest tu przypadkiem. Storybook domyślnie wysyła anonimowe dane o użyciu: wywoływane polecenia, wersję, framework, listę dodatków, liczbę wariantów, menedżera pakietów. Wyłącza się to trzema drogami, w pliku konfiguracyjnym pokazanym wyżej, flagą --disable-telemetry albo zmienną STORYBOOK_DISABLE_TELEMETRY=true. Kolejność ma znaczenie, bo zdarzenie startowe wysyłane jest jeszcze przed wczytaniem pliku konfiguracyjnego, więc pełne wyłączenie daje tylko zmienna środowiskowa.

Jak wygląda story

Wariant komponentu opisuje się w formacie Component Story Format, czyli po prostu jako eksportowany obiekt w pliku obok komponentu.

Code
TypeScript
import type { Meta, StoryObj } from '@storybook/react-vite'
import { expect, fn } from 'storybook/test'
import { PaymentForm } from './PaymentForm'

const meta = {
  component: PaymentForm,
  tags: ['autodocs'],
  args: {
    onSubmit: fn(),
    currency: 'PLN'
  },
  argTypes: {
    currency: { control: 'select', options: ['PLN', 'EUR', 'USD'] }
  }
} satisfies Meta<typeof PaymentForm>

export default meta
type Story = StoryObj<typeof meta>

export const Domyslny: Story = {}

export const BrakSrodkow: Story = {
  args: { balance: 0 },
  tags: ['!autodocs']
}

export const WyslanyFormularz: Story = {
  play: async ({ args, canvas, step, userEvent }) => {
    await step('Wypełnienie kwoty', async () => {
      await userEvent.type(canvas.getByLabelText('Kwota'), '250')
    })

    await step('Zatwierdzenie', async () => {
      await userEvent.click(canvas.getByRole('button', { name: 'Zapłać' }))
    })

    await expect(args.onSubmit).toHaveBeenCalledWith({
      amount: 250,
      currency: 'PLN'
    })
  }
}

Kilka rzeczy z tego przykładu wymaga komentarza. Funkcja fn z modułu storybook/test tworzy atrapę, na której da się później potwierdzać wywołania, i jednocześnie loguje je w panelu akcji. Argument canvas przekazywany do funkcji play to obszar renderowania konkretnego wariantu, a nie cały dokument, więc zapytania nie łapią elementów z innych wariantów. Funkcja step grupuje kroki w panelu interakcji i to ona decyduje, jak czytelny będzie raport z nieudanego testu.

Znaczniki działają jako system dziedziczenia od poziomu podglądu, przez metadane komponentu, po pojedynczy wariant. Trzy z nich, dev, manifest i test, są dopisywane do każdego wariantu automatycznie. Znacznik autodocs, który włącza generowaną stronę dokumentacji, trzeba dodać samodzielnie. Zapis z wykrzyknikiem, jak !autodocs w przykładzie, usuwa znacznik odziedziczony wyżej, co przydaje się przy wariantach opisujących stan błędu, których nie chcesz pokazywać w dokumentacji.

Testy interakcji i integracja z Vitest

To jest ta część, która przez ostatnie wydania zmieniła się najbardziej i która decyduje o tym, czy Storybook jest w projekcie kosztem, czy inwestycją.

Dodatek @storybook/addon-vitest zamienia warianty w testy uruchamiane przez Vitest. Nie jest to osobny mechanizm równoległy do Twoich testów: to wtyczka do Vitest, która przepuszcza pliki z wariantami przez ten sam potok co resztę zestawu testowego. Domyślna konfiguracja uruchamia je w trybie przeglądarki, w Chromium sterowanym przez Playwright, zamiast w symulowanym środowisku typu jsdom.

Code
Bash
npx storybook add @storybook/addon-vitest
npx playwright install chromium
npx vitest --project storybook

Konfiguracja po stronie Vitest wygląda tak jak poniżej i to jest miejsce, w którym najczęściej coś się rozjeżdża.

Code
TypeScript
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { defineConfig, mergeConfig } from 'vitest/config'
import { playwright } from '@vitest/browser-playwright'
import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'
import viteConfig from './vite.config'

const dirname = path.dirname(fileURLToPath(import.meta.url))

export default mergeConfig(
  viteConfig,
  defineConfig({
    test: {
      projects: [
        {
          extends: true,
          plugins: [
            storybookTest({
              configDir: path.join(dirname, '.storybook'),
              storybookScript: 'npm run storybook -- --no-open',
              tags: { include: ['test'], exclude: ['eksperymentalny'], skip: [] }
            })
          ],
          test: {
            name: 'storybook',
            browser: {
              enabled: true,
              provider: playwright({}),
              headless: true,
              instances: [{ browser: 'chromium' }]
            },
            setupFiles: ['./.storybook/vitest.setup.ts']
          }
        }
      ]
    }
  })
)

Wtyczka storybookTest przyjmuje configDir wskazujący katalog konfiguracji, storybookScript z poleceniem uruchamiającym Storybook w trybie obserwowania, storybookUrl z domyślną wartością http://localhost:6006, obiekt tags z listami include, exclude i skip oraz disableAddonDocs, które domyślnie jest ustawione na prawdę i pomija przetwarzanie plików MDX w czasie testów. Trzy listy znaczników różnią się skutkiem: warianty wykluczone znikają z raportu całkowicie, pominięte pozostają w nim widoczne jako niewykonane.

Plik przygotowujący jest krótki, ale bez niego warianty renderują się bez dekoratorów z pliku podglądu i testy przewracają się na brakującym kontekście.

Code
TypeScript
import { beforeAll } from 'vitest'
import { setProjectAnnotations } from '@storybook/react-vite'
import * as previewAnnotations from './preview'

const annotations = setProjectAnnotations([previewAnnotations])

beforeAll(annotations.beforeAll)

Jest tu jedno twarde ograniczenie, o którym lepiej wiedzieć przed rozpoczęciem pracy. Dodatek działa wyłącznie z frameworkami Storybooka opartymi o Vite: react-vite, vue3-vite, svelte-vite, preact-vite, sveltekit czy nextjs-vite. Projekt na @storybook/nextjs, czyli na wariancie webpackowym, wymaga wcześniejszego przejścia na @storybook/nextjs-vite, a to nie zawsze jest zmiana neutralna. Wymagany jest też Vitest w wersji co najmniej trzeciej, przy czym wersja czwarta zmieniła sposób deklarowania przeglądarki na osobny pakiet @vitest/browser-playwright i przykłady z wcześniejszych materiałów nie przeniosą się jeden do jednego.

Koszt tej wygody to binaria przeglądarki na serwerze budującym. Chromium pobierany przez Playwright waży kilkaset megabajtów i trzeba go albo instalować w każdym przebiegu, albo trzymać w pamięci podręcznej obrazu. Przy potoku uruchamianym kilkadziesiąt razy dziennie to pozycja, którą widać w rachunku za czas pracy maszyn.

Dostępność, dokumentacja i mockowanie modułów

Trzy dodatki decydują o tym, czy Storybook zostaje w projekcie na dłużej, czy zamienia się w galerię, której nikt nie otwiera.

Dodatek @storybook/addon-a11y uruchamia silnik axe na każdym wariancie. Steruje się nim parametrem a11y.test, który przyjmuje trzy wartości. Ustawienie off wyłącza sprawdzanie, todo zgłasza naruszenia jako ostrzeżenia, a error zamienia je w błąd testu. Wartość pośrednia jest tu wbrew pozorom najważniejsza, bo pozwala włączyć sprawdzanie w projekcie, który ma już zaległości, bez zatrzymywania całego potoku pierwszego dnia. Pola a11y.config i a11y.options przekazywane są prosto do wywołań axe.configure i axe.run, więc zawężenie zestawu reguł do wytycznych, które faktycznie Cię obowiązują, jest kwestią jednego obiektu.

Mockowanie modułów w wersji dziesiątej ma własny mechanizm i, co istotne, jedno miejsce, w którym wolno go użyć.

Code
TypeScript
import type { Preview } from '@storybook/react-vite'
import { sb } from 'storybook/test'

sb.mock(import('../src/lib/session.ts'), { spy: true })
sb.mock(import('uuid'))

const preview: Preview = {
  parameters: {
    a11y: {
      test: 'todo',
      options: { runOnly: ['wcag2a', 'wcag2aa'] }
    },
    controls: {
      matchers: { color: /(background|color)$/i }
    }
  },
  tags: ['autodocs']
}

export default preview

Funkcja sb.mock przyjmuje wyrażenie importu, a nie łańcuch znaków ze ścieżką, i musi zostać wywołana w pliku .storybook/preview.*. Opcja spy: true zachowuje oryginalne działanie modułu i tylko owija je atrapą, więc nadaje się do modułów, których zachowanie chcesz obserwować, a nie zastępować. Wywołanie bez opcji podmienia wszystkie eksporty na puste atrapy, co jest właściwym wyborem dla generatorów identyfikatorów albo dat, psujących porównania wizualne.

Dokumentacja generowana automatycznie bierze się z dwóch źródeł. Tabela właściwości powstaje z analizy typów, sterowanej polem typescript.reactDocgen w pliku konfiguracyjnym. Opisy i sekcje prozy piszesz w plikach MDX, dołączanych przez wzorzec w polu stories. Ta druga część jest tą, która najczęściej się starzeje, bo nic nie wymusza jej aktualizacji przy zmianie komponentu.

Realny koszt utrzymania i kiedy przestaje się opłacać

Tu dochodzimy do sedna, bo to pytanie decyduje o powodzeniu wdrożenia częściej niż jakakolwiek funkcja z listy powyżej.

Storybook jest drugim potokiem budowania w projekcie. Ma własny plik konfiguracyjny, własny zestaw dodatków, własną wersję i własne wymagania wobec Node. Zmiana w konfiguracji Tailwind CSS, w aliasach ścieżek albo w sposobie ładowania czcionek musi zostać odzwierciedlona w obu miejscach. Kiedy tego zabraknie, komponenty w Storybooku wyglądają inaczej niż w aplikacji, a wtedy narzędzie przestaje być wiarygodne i po kilku tygodniach nikt do niego nie zagląda.

Rytm wydań też trzeba wliczyć. Wersja dziewiąta ukazała się 28 maja 2025 roku, dziesiąta pięć miesięcy później, a wydania poprawkowe wychodzą praktycznie co tydzień: 10.5.10 opublikowano 20 sierpnia 2026 roku. Projekt jest żywy, co jest zaletą, ale każda wersja główna oznacza przegląd dodatków, z których część nie nadąża. Polecenia storybook upgrade i storybook automigrate przenoszą znaczną część zmian automatycznie, jednak dodatek utrzymywany przez jedną osobę potrafi zatrzymać całą migrację na kilka tygodni.

Trzeci koszt dotyczy testów wizualnych. Storybook sam z siebie porównań zrzutów nie robi, potrzebna jest usługa, która przechowuje historię i pokazuje różnice. Najbliższym wyborem jest Chromatic, prowadzony przez tę samą firmę, i jego cennik warto zobaczyć przed obietnicą złożoną zespołowi.

Plan ChromaticCena miesięcznaRozliczane zrzutyPrzeglądarki
Free0 USD5 000Chrome
Starter179 USD35 000Chrome, Safari, Firefox, Edge
Pro399 USD85 000Chrome, Safari, Firefox, Edge
Enterprisewycena indywidualnabez limituChrome, Safari, Firefox, Edge

Zrzuty ponad limit w planie Starter kosztują 0,008 USD za sztukę. Rachunek rośnie iloczynem: liczba wariantów razy liczba przeglądarek razy liczba zgłoszeń zmian. Sto wariantów sprawdzanych w czterech przeglądarkach przy dwudziestu zgłoszeniach dziennie to osiem tysięcy zrzutów dziennie, czyli poza planem darmowym po pierwszym dniu roboczym. Mechanizm TurboSnap ogranicza to, przenosząc zrzuty niezmienionych komponentów zamiast wykonywać je od nowa, ale wymaga poprawnego wykrywania zależności między plikami, a to w monorepozytorium bywa źródłem osobnych kłopotów.

Kiedy więc Storybook przestaje się opłacać. Przy zespole dwuosobowym budującym jedną aplikację, gdzie komponentów jest kilkanaście, wszystkie są używane raz i nikt spoza zespołu ich nie ogląda, druga konfiguracja kosztuje więcej niż daje. Ten sam efekt osiągniesz, uruchamiając testy komponentów bezpośrednio w Vitest w trybie przeglądarki, bez katalogu .storybook i bez interfejsu do utrzymywania.

Podobnie wypada, kiedy komponenty są mocno zrośnięte z aplikacją. Jeśli każdy z nich sięga po dane, sesję i routing, to przygotowanie go do renderowania w izolacji oznacza tyle atrap, że plik z wariantami staje się drugą implementacją komponentu i zaczyna kłamać przy każdej zmianie.

Opłaca się natomiast wtedy, gdy komponenty ma więcej niż jeden odbiorca. Biblioteka współdzielona między aplikacjami, zespół z osobną rolą projektową, produkt z wymogiem dostępności potwierdzanym w zamówieniu publicznym, migracja stylowania na inny system: w każdym z tych przypadków Storybook jest tanią odpowiedzią na pytanie „jak to wygląda teraz". Podobnie przy pracy z gotowymi zestawami komponentów, jak shadcn/ui czy Chakra UI, gdzie katalog wariantów szybko pokazuje, co własny motyw zepsuł.

Storybook a alternatywy

Konkurencja istnieje, ale jest wyraźnie mniejsza i węższa, co samo w sobie jest informacją.

NarzędzieBieżąca wersjaOstatnie wydanieGwiazdkiFrameworkiLicencja
Storybook10.5.10sierpień 2026ok. 91 tys.React, Vue, Svelte, Angular, Web Components, Next.jsMIT
React Cosmos7.4.0sierpień 2026ok. 8,7 tys.React, React NativeMIT
Histoire1.0.0-beta.1styczeń 2026ok. 3,6 tys.Vue, SvelteMIT
Ladle5.1.1listopad 2025ok. 3 tys.ReactMIT

Wnioski z tej tabeli są dość jednoznaczne. Ladle jest lżejszy i szybciej się uruchamia, ale obsługuje wyłącznie Reacta, a ostatnie wydanie ma sprzed dziewięciu miesięcy. Histoire od stycznia 2026 roku stoi na wersji oznaczonej jako przedwydanie, co przy narzędziu wpiętym w potok budowania jest ryzykiem trudnym do uzasadnienia. React Cosmos jest aktywnie rozwijany i ma sensowną niszę w React Native, ale jego ekosystem dodatków nie ma porównania ze Storybookiem.

Piąta opcja to brak narzędzia. Vitest w trybie przeglądarki uruchamia testy komponentów bez żadnej z tych warstw, a stronę z podglądem można zastąpić katalogiem tras w samej aplikacji. Traci się dokumentację i wygodę przeglądania, zyskuje jedną konfigurację zamiast dwóch. Dla małego zespołu to często lepszy bilans.

Typowe błędy

Pierwszy to traktowanie wariantów jako testów jednostkowych logiki. Funkcja play uruchamia prawdziwą przeglądarkę i renderuje komponent, więc sprawdzanie w niej czystej funkcji formatującej datę kosztuje kilkaset razy więcej czasu niż zwykły test. Warianty mają pokrywać zachowanie widoczne dla użytkownika, resztę zostaw normalnemu zestawowi testowemu.

Drugi to rozjazd między konfiguracją aplikacji a konfiguracją Storybooka. Aliasy ścieżek, zmienne środowiskowe i warstwa stylów muszą być wspólne. W projekcie na Vite najprościej jest wciągnąć istniejącą konfigurację przez viteFinal w pliku main.ts, zamiast utrzymywać dwie listy wtyczek, które rozjeżdżają się po pierwszym miesiącu.

Trzeci to pominięcie pliku przygotowującego przy dodatku Vitest. Bez wywołania setProjectAnnotations warianty renderują się bez dekoratorów z pliku podglądu, więc testy padają na brakującym motywie albo dostawcy kontekstu, a komunikat wskazuje na komponent, który jest zupełnie niewinny.

Czwarty to wystawianie zbudowanego Storybooka publicznie bez zastanowienia. Katalog storybook-static zawiera pełny kod komponentów, komentarze, adresy interfejsów programistycznych z plików podglądu i wszystko, co trafiło do atrap. Przy wewnętrznym systemie administracyjnym to publikacja mapy jego funkcji.

Piąty to hodowanie wariantów bez sprzątania. Plik z wariantami jest kodem, który się starzeje: komponent zmienia właściwości, a warianty zostają w wersji sprzed pół roku i renderują się z domyślnymi wartościami, których nikt nie zamierzał. Uruchamianie wariantów jako testów w potoku rozwiązuje to samo, bo martwy wariant przestaje się kompilować i wymusza decyzję.

Szósty to instalowanie dodatku na każdą potrzebę. Każdy dodatek to kod ładowany przy starcie interfejsu i kolejna pozycja do sprawdzenia przy zmianie wersji głównej. Trzy dodatki, które faktycznie zmieniają sposób pracy zespołu, są warte więcej niż dwanaście, z których połowa zatrzyma następną migrację.

FAQ

Czy Storybook zastępuje testy jednostkowe i end-to-end?

Nie zastępuje żadnych z nich. Testy interakcji sprawdzają jeden komponent w izolacji, bez routingu, sesji i prawdziwego backendu. Logikę bez interfejsu nadal testujesz zwykłymi testami, a przepływy przez całą aplikację narzędziem do testów end-to-end.

Czy dodatek Vitest działa z Next.js?

Działa, ale wyłącznie przez framework @storybook/nextjs-vite i przy Next.js w wersji co najmniej 14.1. Wariant webpackowy @storybook/nextjs nie spełnia wymagania, bo dodatek jest wtyczką do Vite. Przejście między tymi frameworkami trzeba zaplanować osobno.

Ile kosztuje uruchomienie testów wizualnych?

Sam Storybook nic, bo porównywania zrzutów nie robi. Usługa zewnętrzna już tak: plan darmowy Chromatic obejmuje 5 tysięcy rozliczanych zrzutów miesięcznie i tylko przeglądarkę Chrome, plan Starter kosztuje 179 USD miesięcznie za 35 tysięcy zrzutów, a Pro 399 USD za 85 tysięcy. Zrzuty ponad limit w planie Starter to 0,008 USD za sztukę.

Czy Storybook wysyła dane o moim projekcie?

Domyślnie tak, w formie anonimowej telemetrii obejmującej wersję, framework, listę dodatków i liczbę wariantów. Wyłączysz to polem core.disableTelemetry, flagą --disable-telemetry albo zmienną STORYBOOK_DISABLE_TELEMETRY. Tylko ta ostatnia droga wyłącza też zdarzenie startowe, wysyłane przed wczytaniem konfiguracji.

Jakiej wersji Node wymaga wersja dziesiąta?

Node 20.16 lub nowszego z linii 20, 22.19 lub nowszego z linii 22, albo dowolnego z linii 24. Wynika to z przejścia na wyłącznie moduły ES, które wymaga obsługi wczytywania takich modułów przez require.

Czy da się używać Storybooka bez pisania osobnych plików z wariantami?

Nie w sensowny sposób. Wariant jest tu jednostką podstawową i wszystko, dokumentacja, testy, przegląd wizualny, bierze się z niego. Jeśli pisanie tych plików wydaje się kosztem nie do przyjęcia, to jest to sygnał, że w tym projekcie narzędzie się nie zwróci.

Dokumentację znajdziesz na stronie Storybooka, kod źródłowy w repozytorium na GitHubie, a cennik testów wizualnych na stronie Chromatic.

Czytaj dalej

Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie