From 75c74a32dd3f1045a1fa3d686cdca32a560bdc12 Mon Sep 17 00:00:00 2001 From: Anneke Sinnema Date: Tue, 22 Sep 2026 12:44:41 +0200 Subject: [PATCH] feat: show angular code examples without unnecessary brackets --- packages/angular/.storybook/preview.ts | 10 ++++++++ .../src/angular-docs-source.ts | 24 +++++++++++++++++++ packages/storybook-config/src/index.ts | 3 +++ 3 files changed, 37 insertions(+) create mode 100644 packages/storybook-config/src/angular-docs-source.ts diff --git a/packages/angular/.storybook/preview.ts b/packages/angular/.storybook/preview.ts index 2952ac2a..6773ed68 100644 --- a/packages/angular/.storybook/preview.ts +++ b/packages/angular/.storybook/preview.ts @@ -3,6 +3,7 @@ import { frameworkGlobalTypes, frameworkSwitcher, sharedParameters, + simplifyAngularDocsSource, themeGlobalTypes, themeInitialGlobals, themeSwitcher, @@ -18,6 +19,15 @@ export default { parameters: { ...sharedParameters, ...a11yParameters, + docs: { + source: { + // Drop brackets around plain string args (e.g. `[variant]="variant"` + // -> `variant="outline"`) in the "Show code" snippet only — see + // simplifyAngularDocsSource for why the live story keeps binding them. + transform: (code: string, { args }: { args: Record }) => + simplifyAngularDocsSource(code, args), + }, + }, // Must be a literal (Storybook reads it via static analysis, not // execution). Keep in sync with packages/react/.storybook/preview.ts. options: { diff --git a/packages/storybook-config/src/angular-docs-source.ts b/packages/storybook-config/src/angular-docs-source.ts new file mode 100644 index 00000000..1d7171b5 --- /dev/null +++ b/packages/storybook-config/src/angular-docs-source.ts @@ -0,0 +1,24 @@ +// Angular-only. `argsToTemplate()` (from `@storybook/angular`) always emits a +// property binding — `[variant]="variant"` — for every arg, because it has no +// way to know whether a value needs Angular expression evaluation or is just +// a static string. That's correct for the live canvas (bindings must be +// reactive so Controls can update it), but it makes the "Show code" snippet +// print brackets even for a plain enum like `variant` that carries no logic. +// +// This only rewrites the *displayed* source, via `docs.source.transform` — +// the story's real template still uses `argsToTemplate()` and stays reactive. +// It unwraps a passthrough binding `[key]="key"` into a plain attribute +// `key="value"`, and only for string-valued args (so `[disabled]="disabled"` +// and other non-string bindings, where the plain-attribute form would change +// meaning, are left untouched). +export function simplifyAngularDocsSource( + source: string, + args: Record = {}, +): string { + return Object.entries(args).reduce((code, [key, value]) => { + if (typeof value !== 'string') return code; + const pattern = new RegExp(`\\[${key}\\]="${key}"`, 'g'); + const escaped = value.replace(/"/g, '"'); + return code.replace(pattern, () => `${key}="${escaped}"`); + }, source); +} diff --git a/packages/storybook-config/src/index.ts b/packages/storybook-config/src/index.ts index 58d54a3b..723eedbe 100644 --- a/packages/storybook-config/src/index.ts +++ b/packages/storybook-config/src/index.ts @@ -16,6 +16,9 @@ export type { // Browser-safe a11y config; the audit lives behind the `./test-runner` subpath. export { WCAG_22_AA_TAGS, a11yParameters } from './a11y.js'; +// Angular-only docs "Show code" cleanup; see the file for why. +export { simplifyAngularDocsSource } from './angular-docs-source.js'; + // Shared preview parameters so every framework's Storybook renders stories the // same way. //