Drupal SDC
Denne guiden viser hvordan du tar i bruk Artsdatabanken Web Components i et Drupal-tema ved hjelp av Single Directory Components (SDC), introdusert i Drupal 10.1.
To lag — ikke ett
SDC og Web Component er to forskjellige ting som jobber sammen:
| Lag | Hva det er | Brukes av |
|---|---|---|
<adb-button> (Web Component) | Selve komponenten — atferd, styling, shadow DOM | Alle konsumenter: Drupal, Angular, React, m.m. |
SDC button/ | En Drupal-adapter — pakker WC inn i Drupals komponentsystem | Drupal-utviklere / temabyggere |
SDC erstatter ikke Web Componenten — den er et tynt Drupal-skall rundt den.
npm-pakke (@artsdatabanken/components) ← kilde til sannhet, deles overalt ↓Drupal-bibliotek (libraries.yml) ← laster inn JS som type="module" ↓SDC-komponent (button/) ← Drupal-vennlig API (props → WC-attributter) ↓Twig-maler ← brukes via {% include 'artsdatabanken:button' %}Den største fordelen med å gå via SDC fremfor å skrive <adb-button> direkte i en Twig-mal:
- Prop-validering —
button.component.ymlhåndhever tillatte verdier (enum), slik at feil oppdages tidlig - PHP render arrays — backend-moduler kan rendre knapper uten å berøre Twig
- Sentralisert attributt-mapping — hvis en WC-attributt omdøpes, er det bare SDC-malen som må oppdateres
- Automatisk biblioteksinnlasting —
libraryOverridessørger for at JS lastes inn hver gang komponenten inkluderes
Filstruktur
web/themes/custom/artsdatabanken/├── artsdatabanken.libraries.yml└── components/ └── button/ ├── button.component.yml ← SDC-definisjon (props, slots) ├── button.twig ← rendrer <adb-button> └── button.css ← valgfritt: token-overstyringerSteg 1 — Last inn Web Componenten
Alternativ A: Vite-entry (anbefalt for artsdatabanken.no)
Siden artsdatabanken.no bruker Vite, er det enkleste å importere komponentene i temaets TypeScript-entry. Vite tree-shaker og bundler kun det du faktisk importerer.
import '@artsdatabanken/components/dist/adb-button.js';Registrer Vite-outputfilen som et Drupal-bibliotek i stedet for å peke direkte til node_modules.
Alternativ B: libraries.yml
adb-components: js: /themes/custom/artsdatabanken/node_modules/@artsdatabanken/components/dist/index.js: attributes: type: module dependencies: - core/drupalSteg 2 — Definer SDC-komponenten
button.component.yml
name: Buttondescription: Artsdatabanken-knapp — pakker inn adb-button Web Component.props: type: object properties: variant: type: string title: Variant default: primary enum: [primary, secondary, ghost] size: type: string title: Størrelse default: md enum: [sm, md, lg] disabled: type: boolean title: Deaktivert default: falseslots: label: title: EtikettlibraryOverrides: dependencies: - artsdatabanken/adb-componentsSteg 3 — Skriv Twig-malen
button.twig
<adb-button variant="{{ variant|default('primary') }}" size="{{ size|default('md') }}" {{ disabled ? 'disabled' : '' }}> {% block label %}{{ label }}{% endblock %}</adb-button>Steg 4 — Bruk komponenten
Fra en Twig-mal:
{% include 'artsdatabanken:button' with { variant: 'primary', size: 'md', label: 'Lagre'|t} %}Fra PHP (render array):
$build['save_button'] = [ '#type' => 'component', '#component' => 'artsdatabanken:button', '#props' => [ 'variant' => 'primary', 'size' => 'md', ], '#slots' => [ 'label' => ['#markup' => $this->t('Lagre')], ],];FOUC — Flash of Unstyled Content
Web Components oppgraderes klient-side etter at JS er lastet. Inntil da kan nettleseren vise ustilt markup. Bruk en lagdelt tilnærming:
Lag 1 — Basisskjuling (alle komponenter)
Legg til i temaets globale CSS:
adb-button:not(:defined),adb-card:not(:defined),adb-input:not(:defined) { visibility: hidden;}Skjuler udefinerte elementer til de er oppgradert. Enkel løsning, ingen ekstra infrastruktur.
Lag 2 — Kritiske komponenter over folden: Declarative Shadow DOM
For høyt synlige komponenter over folden kan du bygge inn shadow root direkte i server-rendret HTML, slik at nettleseren kan male den før JS lastes:
{# button.twig — DSD-variant for kritisk bruk over folden #}<adb-button variant="{{ variant }}" size="{{ size }}" {{ disabled ? 'disabled' : '' }}> <template shadowrootmode="open"> <style> :host { display: inline-block; } :host([disabled]) { opacity: 0.5; pointer-events: none; } button { background: var(--adb-color-primary, #2d6a4f); color: var(--adb-color-primary-text, #fff); border: 2px solid var(--adb-color-primary, #2d6a4f); border-radius: var(--adb-radius, 0.375rem); padding: 0.5rem 0.75rem; font-family: inherit; cursor: pointer; } </style> <button part="base"><slot></slot></button> </template> {{ label }}</adb-button>NB: Denne tilnærmingen dupliserer komponent-CSS i Twig. Bruk den kun for et lite antall kritiske komponenter (hero-CTAer, handlingsknapper over folden). Når JS lastes, overtar Lit uten visuell endring.
Lag 3 — Innholdskomponenter: meningsfulle light DOM-slots
For innholdsrike komponenter (kort, artikler) — plasser meningsfullt innhold i light DOM-slots. Det er alltid synlig for brukere og søkemotorer, uavhengig av JS:
<adb-card> <h3 slot="title">{{ title }}</h3> <p slot="description">{{ description }}</p> <img slot="image" src="{{ image_url }}" alt="{{ image_alt }}"></adb-card>Sjekkliste for ny komponent i Drupal
- Komponenten er bygget og eksportert fra
@artsdatabanken/components - Komponenten er importert i Vite-entry (eller lagt til i
libraries.yml) - SDC
component.ymler skrevet med riktige props og slots - Twig-mal rendrer custom element med mappede attributter
-
:not(:defined)-regel er lagt til i global tema-CSS - DSD-mal skrevet for eventuell bruk over folden