Skip to content

Commit 8b01ea9

Browse files
feat!: richer menus, multi-level mobile nav, keyboard-shortcut variants, and a loading backdrop (#124)
### Highlights - **Richer menus.** `nldd-menu` items can now be links (`href`) and show keyboard-shortcut hints, and the menu sizes to its content up to a viewport-aware maximum. - **Multi-level mobile navigation.** The `nldd-top-navigation-bar` mobile menu sheet now supports nested, multi-level menus with drill-down navigation and a back button per level. - **Keyboard-shortcut variants.** `nldd-keyboard-shortcut` gained `box` and `simple` variants, `sm` / `md` / `inherit` sizes and `neutral` / `inherit` colors, so a shortcut fits both a standalone keycap and inline running text. - **Loading backdrop.** `nldd-activity-indicator` can dim and blur the content behind it while loading (opt-in `backdrop`), and a static-skeleton-loading principle was added to the `Docs/Ontwerprichtlijnen` reference. ### Added - **`nldd-menu`** — menu items accept an `href` (rendered as a real `<a>`, so middle-click and open-in-new-tab work) and a keyboard-shortcut hint (`shortcut`, `shortcut-mac`, `shortcut-windows`, `shortcut-linux`); the menu now sizes to its content between a minimum and `min(100vw - inset, 640px)`, with an explicit `width` to pin it. - **`nldd-keyboard-shortcut`** — a `box` (keycap) and `simple` (plain-text) variant, `sm` / `md` / `inherit` sizes (the `inherit` size scales with the surrounding text), and `neutral` / `inherit` colors (the latter follows `currentColor`, e.g. on a colored panel). - **`nldd-activity-indicator`** — an opt-in `backdrop` that dims and blurs the content underneath while loading: the context parent background color (fallback: base surface) at one minus the disabled opacity, plus a backdrop blur. - **`nldd-top-navigation-bar`** — the mobile menu sheet supports multi-level (drill-down) menus, with a back button per level. ### Changed - **`nldd-byline`** — on a small container (≤ sm), a byline with two or more avatars stacks the avatar row above the names so the text keeps the full width; single-avatar bylines stay inline. ### Breaking - **`nldd-menu`** — the `translations` key `components.menu.back` was renamed to `components.menu.back-action` (matching the existing `components.menu.submenu-back-action`); the rendered label is unchanged. Update any `translations` override that sets the old key. ### Fixed - **`nldd-hero`** — full-width media (`main-width="full"`) now stacks beside the text panel instead of behind it, so the media's rounded corner is no longer hidden by the panel. - **`nldd-multi-line-text-field`** — with `resize="auto"`, the configured `rows` is honored as a minimum height, so the field no longer shrinks below it (it still grows with content). - **`nldd-top-navigation-bar`** — menu sheet list items render as real `<button>` elements.
1 parent 68e6023 commit 8b01ea9

38 files changed

Lines changed: 1669 additions & 192 deletions
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
name: ontwerprichtlijnen
3+
description: "Een verzameling ontwerprichtlijnen en interface-principes. Gebruik deze skill wanneer er iets ontworpen, gebouwd of beoordeeld wordt aan een interface — websites, apps, dashboards, forms, componenten, mockups — zodat de keuzes aansluiten bij deze voorkeuren. Trigger ook bij vragen over \"hoe zou je dit vormgeven\", interactie-design, microcopy, of het reviewen van bestaande UI."
4+
user-invocable: true
5+
---
6+
7+
<!--
8+
GEGENEREERD BESTAND — niet handmatig bewerken.
9+
Bron: src/docs/design-guidelines.mdx (Storybook "Docs/Ontwerprichtlijnen").
10+
Hergenereren: npm run generate:skill-docs
11+
-->
12+
13+
# Ontwerprichtlijnen
14+
15+
Een verzameling ontwerprichtlijnen en interface-principes. Gebruik deze skill wanneer er iets ontworpen, gebouwd of beoordeeld wordt aan een interface — websites, apps, dashboards, forms, componenten, mockups — zodat de keuzes aansluiten bij deze voorkeuren. Trigger ook bij vragen over "hoe zou je dit vormgeven", interactie-design, microcopy, of het reviewen van bestaande UI.
16+
17+
## Invoer en formulieren
18+
19+
- **Vermijd disabled knoppen.** Laat de gebruiker de actie uitvoeren en geef daarna feedback — in de huidige view of op de volgende — over wat er mis is en hoe het op te lossen. Disabled knoppen verbergen de reden en frustreren.
20+
- **Vermijd destructieve knop naast een bevestigende knop.** Plaats acties als "Annuleer", "Verwijder" of "Reset" niet pal naast "Bewaar" of "Bevestig". Geef ze visuele en fysieke afstand om misklikken te voorkomen. Bijvoorbeeld: "Annuleer" rechtsboven in de title bar en "Bewaar" als primaire knop onderaan. Hetzelfde geldt voor een "Terug"-knop pal naast "Volgende stap" in een multi-page progress-flow: een misklik gooit de gebruiker een stap terug en kost ingevulde voortgang, dus geef ook daar de terug-actie afstand van de primaire vooruit-knop.
21+
- **Markeer optionele velden, niet verplichte.** Label alleen wat optioneel is, niet wat verplicht is met een asterisk. Zet daarvoor het `optional`-attribuut op `nldd-form-field` — dat toont automatisch een "Optioneel"-badge bij het label (aanpasbaar via `optional-label`); je schrijft de tekst dus niet zelf. Een formulier hoort zo klein mogelijk te zijn, dus optionele velden zouden in de minderheid moeten zijn — en dan is het efficiënter om die uitzonderingen te markeren dan de regel.
22+
- **Volgorde van vragen volgt het gedachteproces van de gebruiker, niet de database.** Vraag eerst waar de gebruiker mee zit (bericht, betaalwijze, productvoorkeur) en bewaar verplichte contactgegevens voor het eind. Zo verlaag je de cognitieve last vroeg en bouw je commitment op. Bij een contactformulier dus eerst het berichtveld tonen, daarna pas naam en e-mail — niet andersom, zoals de meeste formulieren doen.
23+
- **Volledige naam in één veld, niet voornaam/tussenvoegsel/achternaam apart.** Vraag aanspreeknaam apart als optioneel veld met een label als "Hoe wil je dat we je aanspreken?". Uit onderzoek bij een klant bleek 68% met voornaam aangesproken te willen worden — dat beslis je niet voor de gebruiker.
24+
- **Groepeer velden met dezelfde interactievorm, waar dat logisch kan.** Alle text-inputs bij elkaar, alle checkboxes bij elkaar. Voorkomt onnodig wisselen tussen toetsenbord en muis (desktop) of tussen verschillende input-types (mobiel). Niet forceren als de inhoudelijke volgorde belangrijker is.
25+
- **Zet "Onthoud mij" / "Stay signed in" standaard aan.** Tegenwoordig is dit de juiste default — gebruikers verwachten het, en wie het niet wil zet het zelf uit.
26+
27+
## Navigatie en structuur
28+
29+
- **Vermijd FAQ's, gebruik inline help.** Plaats uitleg op de plek waar de vraag ontstaat in plaats van die te verbannen naar een aparte FAQ-pagina. Een losse FAQ dwingt de gebruiker te zoeken en duidt vaak op een interface die zichzelf niet uitlegt; inline help lost de twijfel op precies waar die opkomt.
30+
- **Vermijd expand/collapse.** Als content uitklapt verschuift de pagina en raakt de gebruiker zijn oriëntatie kwijt, waardoor hij ondersteunende taken moet uitvoeren zoals terugscrollen — werk dat niets met zijn eigenlijke doel te maken heeft. Toon liever weinig informatie direct, of presenteer veel informatie los van de hoofdpagina — in een sheet of op een losse pagina.
31+
- **Verwerk UI en navigatie zoveel mogelijk in de content.** Verminder de hoeveelheid en focus op UI buiten de content. Hetzelfde geldt voor het menu — laat de homepage zelf het menu zijn in plaats van een rijtje woorden in de header.
32+
- **Geen carrousels, tenzij de items samen één doel dragen.** Carrousels op homepages worden vrijwel niet geklikt. Acceptabel is een carrousel met items die gezamenlijk hetzelfde doel hebben (vakantiefoto's, portfoliowerk, één productlijn).
33+
- **Geen megamenu's.** Inflexibel (één dimensie terwijl content meerdere heeft), creëren onzekerheid (de website accepteert de keuze van de gebruiker niet maar opent weer een menu), werken slecht op touch en mobiel. Vervangen door overzicht op een landingspagina gaf in IBM-onderzoek 219% meer engagement.
34+
- **Geen wizards.** Een wizard is een symptoom van een slechte onderliggende UI. Maak die UI goed in plaats van er een procesomweg omheen te bouwen. Als een stap-voor-stap proces de juiste interface is (bijv. een echte werkstroom), noem het dan ook geen wizard — het *is* de interface.
35+
- **Kruimelpaden als ondersteunende interactie, niet als dominante navigatie.** Een breadcrumb in de footer is prima als orientatiehulp. Bovenaan de pagina als hoofdnavigatie werkt 'm averechts: kruimelpaden laten zien waar je *bent*, niet waar je naartoe *wilt*, terwijl gebruikersgedachten niet lineair-hiërarchisch zijn.
36+
- **Geen vage container-begrippen.** Vermijd "informatie", "documenten", "downloads", "service", "folders", "algemeen". Beschrijf het onderwerp of doel ("Ondersteuning" i.p.v. "Service"; "Printbare promotie" i.p.v. "Downloads"). De gebruiker mag niet hoeven gokken wat erachter zit.
37+
38+
## Feedback en state
39+
40+
- **Eén optie is geen optie.** Bied geen modal dialog met maar één knop aan. Als er niets te kiezen valt, hoeft de gebruiker niet onderbroken te worden met een dialoog die hij toch alleen maar kan wegklikken — gebruik dan een minder opdringerige melding (toast, inline bericht) of laat de onderbreking helemaal weg.
41+
- **Undo boven confirm.** Een actie ongedaan kunnen maken is bijna altijd beter dan vooraf bevestigen. Mensen klikken op autopilot "OK", dus confirm-dialogen vangen weinig fouten. Autosave + versies > "wil je opslaan?". Modals alleen als er écht geen weg terug is.
42+
- **Liever een contextueel-window dan een modal.** Een contextueel-window zit visueel aan de actie vast (zoals een popover bij een knop) en dekt de onderliggende pagina niet af. Het forceert geen keuze: wegkijken = annuleren. Bij een echte modal verdwijnt vaak juist de informatie die de gebruiker nodig heeft om te beslissen.
43+
- **In een bevestigingsmodal voor een destructieve actie is "Behoud" de primary, niet "Verwijder".** Toon de niet-destructieve uitweg ("Behoud document") als primary actie en de destructieve actie als secondary. De primary knop is waar de gebruiker op autopilot naartoe gaat — dat hoort de veilige uitweg te zijn, niet de onomkeerbare actie.
44+
- **Statische skeleton loading, geen shimmer-animatie.** Een shimmer — en animatie in het algemeen — trekt te veel aandacht en verlegt die naar het wachten zelf in plaats van naar de opbouw van de interface, en vertraagt zo de beleving onnodig; hou de skeleton daarom statisch. Toon een statische skeleton die direct de uiteindelijke structuur van het scherm weerspiegelt: de vormen, content en interface-elementen die ook in het eindresultaat aanwezig zijn, of een blurred versie van de uiteindelijke image. Dat geeft de gebruiker meteen context over wat er laadt en richt de aandacht op wat er gaat verschijnen. Doordat enkel de definitieve vormen alvast getoond worden, ontstaat een vloeiende overgang van leeg naar volledig geladen — elementen verschijnen niet eerst in een voorlopige staat om daarna nog te veranderen of te verdwijnen, waardoor de interface consistenter en voorspelbaarder aanvoelt.
45+
- **Duurt het laden langer dan één seconde, toon dan een activity indicator over het geheel.** Geef expliciet aan dat het laden langer duurt dan verwacht. De reeds ingeladen content wordt daarbij gedeeltelijk gedimd of vervaagd achter de indicator, zodat duidelijk is dat het proces nog gaande is.
46+
47+
## Microcopy en toon
48+
49+
- **Directe actie = gebiedende wijs, indirecte actie = volledig werkwoord.** Een knop die de actie meteen uitvoert krijgt de gebiedende wijs ("Log in" submit het formulier). Een knop die ergens naartoe leidt waar de actie nog moet gebeuren krijgt het hele werkwoord ("Inloggen" → opent het inlogscherm). Zo voelt de gebruiker het verschil tussen "nu gebeurt het" en "ik ga ergens heen".
50+
- **Knoplabels beschrijven de actie, gebruik geen "OK".** "Bewaar", "Verwijder account", "Verder naar overzicht" — dan begrijpt de gebruiker wat een knop doet zonder de begeleidende tekst te lezen. "OK" en "Annuleren" dwingen tot lezen en zijn dubbelzinnig.
51+
- **Begin knoppen en titels met een betekenisvol woord.** Niet "de"/"het"/"een" of een vulwoord — gebruikers scannen de eerste woorden. Plaats het beschrijvende zelfstandig naamwoord of werkwoord vooraan.
52+
- **Geen ALL-CAPS in knoppen of labels.** Verzwakt het woordbeeld en maakt scannen lastiger. "Menu", niet "MENU".
53+
54+
## Visueel en layout
55+
56+
- **Tekst heeft voorkeur boven iconen.** Een tekstlabel is ondubbelzinnig; een icoon vraagt om interpretatie en wordt vaak verkeerd begrepen. Gebruik tekst als primaire drager van betekenis, en iconen hooguit ter ondersteuning ernaast. Uitzondering: iconen die al universeel zijn aangeleerd (zoals navigatiepijltjes vorige/volgende).
57+
- **Hiërarchie primair via lichtsterkte, ondersteund door saturatie — niet via kleurtoon.** Twee tabs in andere kleurtonen lezen als "gelijkwaardig anders"; een verschil in lichtsterkte (en in mindere mate saturatie) leest als hiërarchie. Bijkomend voordeel: kleurenblinde gebruikers zien het onderscheid ook. Test je UI in grijstinten om te checken of de hiërarchie nog werkt.
58+
- **Plaats primaire actieknoppen in lijn met de oogbeweging.** Onder het laatste inputveld, niet rechts uitgelijnd ergens waar de gebruiker eerst moet zoeken. De ogen verwachten de volgende actie in het verlengde van wat ze net gedaan hebben.
59+
- **`cursor: pointer` alleen voor links, niet voor buttons.** Wees een goed system citizen: respecteer het native gedrag waarbij de pointer navigatie aankondigt. Dat de hele industrie pointer óók op buttons zet is een slechte norm — links (zeker die in een nieuwe tab openen) zijn daardoor niet meer herkenbaar, terwijl gebruikers het onderscheid tussen "binnen de browser" en "buiten de browser" wél nodig hebben. Een link navigeert, een knop doet iets; de cursor hoort dat verschil te bewaren. Een knop is een knop.
60+
61+
## Strategie en proces
62+
63+
- **Ontwerp voor doelen, niet voor doelgroepen of persona's.** Persona's zijn nuttig om ideeën aan te toetsen, maar slecht om vanuit te ontwerpen — ze leiden tot modi (verschillende UI per doelgroep) en onhoudbare interfaces voor gebruikers die tussen doelgroepen wisselen. Een doel is stabiel; een doelgroep niet.
64+
- **Ontwerp voor effectiviteit en efficiëntie, geen korte-termijntrucs.** Banner-blindness omzeilen door dingen te verschuiven werkt één keer, dan ontwikkelen gebruikers nieuwe blindheid en zit je gevangen in een kat-en-muis-spel. Ontwerp op effectiviteit en efficiëntie voor de lange termijn; gebruikers zijn niet achterlijk en passen zich aan een serieuze UI aan.
65+
- **Minder of simpeler ogende controls is niet altijd beter.** Eenvoud is een middel, geen doel. Een control die de taak nodig heeft weghalen of versimpelen om het beeld op te ruimen, verschuift de complexiteit alleen — naar verborgen modi, extra stappen of giswerk — en maakt de taak niet eenvoudiger. Stem het aantal en de zichtbaarheid van controls af op wat de taak vraagt, niet op hoe opgeruimd het oogt. (Jef Raskin, *The Humane Interface*, 2004, p. 54: "Fewer buttons and simpler-looking controls are not always better. The lesson applies to screen design as well as to instruments and appliances.")
66+
- **A/B-test pas binnen een theoretisch kader.** Zonder kader "bewijs" je significant onzin, want statistiek vertelt je niet *waarom*. Stel een hypothese op basis van bestaande kennis, test om die te toetsen — niet om 'm te vinden. (Klassiek voorbeeld: de hamburger-icoon A/B-tests die elkaar tegenspraken omdat affordance niet als variabele werd meegenomen.)
67+
68+
## Overig
69+
70+
_(nog leeg)_

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,34 @@ the type of conventional-commit determines the release. Conventional types
99
`chore`, `docs`, `ci`, `style`, `test`, `build` are intentionally omitted
1010
here; consult the commit history if you need that level of detail.
1111

12+
### Highlights
13+
14+
- **Richer menus.** `nldd-menu` items can now be links (`href`) and show keyboard-shortcut hints, and the menu sizes to its content up to a viewport-aware maximum.
15+
- **Multi-level mobile navigation.** The `nldd-top-navigation-bar` mobile menu sheet now supports nested, multi-level menus with drill-down navigation and a back button per level.
16+
- **Keyboard-shortcut variants.** `nldd-keyboard-shortcut` gained `box` and `simple` variants, `sm` / `md` / `inherit` sizes and `neutral` / `inherit` colors, so a shortcut fits both a standalone keycap and inline running text.
17+
- **Loading backdrop.** `nldd-activity-indicator` can dim and blur the content behind it while loading (opt-in `backdrop`), and a static-skeleton-loading principle was added to the `Docs/Ontwerprichtlijnen` reference.
18+
19+
### Added
20+
21+
- **`nldd-menu`** — menu items accept an `href` (rendered as a real `<a>`, so middle-click and open-in-new-tab work) and a keyboard-shortcut hint (`shortcut`, `shortcut-mac`, `shortcut-windows`, `shortcut-linux`); the menu now sizes to its content between a minimum and `min(100vw - inset, 640px)`, with an explicit `width` to pin it.
22+
- **`nldd-keyboard-shortcut`** — a `box` (keycap) and `simple` (plain-text) variant, `sm` / `md` / `inherit` sizes (the `inherit` size scales with the surrounding text), and `neutral` / `inherit` colors (the latter follows `currentColor`, e.g. on a colored panel).
23+
- **`nldd-activity-indicator`** — an opt-in `backdrop` that dims and blurs the content underneath while loading: the context parent background color (fallback: base surface) at one minus the disabled opacity, plus a backdrop blur.
24+
- **`nldd-top-navigation-bar`** — the mobile menu sheet supports multi-level (drill-down) menus, with a back button per level.
25+
26+
### Changed
27+
28+
- **`nldd-byline`** — on a small container (≤ sm), a byline with two or more avatars stacks the avatar row above the names so the text keeps the full width; single-avatar bylines stay inline.
29+
30+
### Breaking
31+
32+
- **`nldd-menu`** — the `translations` key `components.menu.back` was renamed to `components.menu.back-action` (matching the existing `components.menu.submenu-back-action`); the rendered label is unchanged. Update any `translations` override that sets the old key.
33+
34+
### Fixed
35+
36+
- **`nldd-hero`** — full-width media (`main-width="full"`) now stacks beside the text panel instead of behind it, so the media's rounded corner is no longer hidden by the panel.
37+
- **`nldd-multi-line-text-field`** — with `resize="auto"`, the configured `rows` is honored as a minimum height, so the field no longer shrinks below it (it still grows with content).
38+
- **`nldd-top-navigation-bar`** — menu sheet list items render as real `<button>` elements.
39+
1240
## <small>0.8.58 (2026-06-12)</small>
1341

1442
* feat!: status bar, byline, hero, on-color support, and rich-text width zones (#123) ([5932b63](https://github.com/MinBZK/storybook/commit/5932b63)), closes [#123](https://github.com/MinBZK/storybook/issues/123)

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,8 @@
403403
"generate:palettes": "node scripts/generate-palettes.js",
404404
"generate:component-reference": "node scripts/generate-component-reference.js",
405405
"generate:skill-changelog": "node scripts/generate-skill-changelog.js",
406-
"generate:skill-docs": "npm run generate:component-reference && npm run generate:skill-changelog",
406+
"generate:skill-principles": "node scripts/generate-skill-principles.js",
407+
"generate:skill-docs": "npm run generate:component-reference && npm run generate:skill-changelog && npm run generate:skill-principles",
407408
"validate:styles": "node scripts/validate-css-variables.js",
408409
"build:components": "npm run clean:components && npm run build:icons && npm run build:components:modules && npm run build:components:bundle && npm run build:exports",
409410
"build:icons": "node scripts/generate-icon-registry.js && node scripts/generate-logo.js",
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Generates the user-invocable "ontwerprichtlijnen" skill from the canonical
3+
* design-guidelines doc (src/docs/design-guidelines.mdx — the Storybook
4+
* "Docs/Ontwerprichtlijnen" page).
5+
*
6+
* The MDX is the single source of truth. This script strips the MDX-only lines
7+
* (the JS import and the <Meta> element) and wraps the remaining Markdown in a
8+
* SKILL.md with frontmatter, so the invocable skill never drifts from the
9+
* documented principles. The skill description is derived from the doc's intro
10+
* paragraph.
11+
*
12+
* WARNING: overwrites .claude/skills/ontwerprichtlijnen/SKILL.md in-place. Run
13+
* `npm run generate:skill-docs` after editing the guidelines and commit the
14+
* result.
15+
*
16+
* Usage: node scripts/generate-skill-principles.js
17+
*/
18+
19+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
20+
import { resolve, dirname } from 'node:path';
21+
import { fileURLToPath } from 'node:url';
22+
23+
const __dirname = dirname(fileURLToPath(import.meta.url));
24+
const sourcePath = resolve(__dirname, '../src/docs/design-guidelines.mdx');
25+
const outputDir = resolve(__dirname, '../.claude/skills/ontwerprichtlijnen');
26+
const outputPath = resolve(outputDir, 'SKILL.md');
27+
28+
let mdx;
29+
try {
30+
mdx = readFileSync(sourcePath, 'utf-8');
31+
} catch (err) {
32+
if (err.code === 'ENOENT') {
33+
console.error(`design-guidelines.mdx not found at ${sourcePath}.`);
34+
console.error('Verwacht de canonieke ontwerprichtlijnen in src/docs/design-guidelines.mdx.');
35+
process.exit(1);
36+
}
37+
throw err;
38+
}
39+
40+
// Keep only the Markdown body: drop the JS import line(s) and the <Meta>
41+
// element that make this an MDX/Storybook page. Everything else is plain
42+
// Markdown and is carried over verbatim.
43+
const body = `${mdx
44+
.split('\n')
45+
.filter((line) => !/^\s*import\s/.test(line) && !/^\s*<Meta\b/.test(line))
46+
.join('\n')
47+
.replace(/^\n+/, '')
48+
.trimEnd()}\n`;
49+
50+
// Derive the skill description from the first paragraph after the H1: collapse
51+
// to a single line and escape it for a double-quoted YAML scalar.
52+
const introMatch = body.match(/^#\s+.+?\n+([\s\S]+?)\n\s*\n/);
53+
const intro = (introMatch ? introMatch[1] : 'Ontwerprichtlijnen en interface-principes van het NLDD Design System.')
54+
.replace(/\s+/g, ' ')
55+
.trim();
56+
const description = intro.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
57+
58+
const skill = `---
59+
name: ontwerprichtlijnen
60+
description: "${description}"
61+
user-invocable: true
62+
---
63+
64+
<!--
65+
GEGENEREERD BESTAND — niet handmatig bewerken.
66+
Bron: src/docs/design-guidelines.mdx (Storybook "Docs/Ontwerprichtlijnen").
67+
Hergenereren: npm run generate:skill-docs
68+
-->
69+
70+
${body}`;
71+
72+
mkdirSync(outputDir, { recursive: true });
73+
writeFileSync(outputPath, skill);
74+
75+
console.log(`Wrote ${outputPath} (${skill.split('\n').length} lines)`);

0 commit comments

Comments
 (0)