From 25341beec1b38ccff86dfd3464cce5f40462f0d6 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 22 Sep 2026 07:44:01 +0000 Subject: [PATCH 1/4] docs(component-library): document using your own brand palette MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An app can already supply its own brand palette without any library change, but nothing said so, and the override needs two differently named ramps to be complete: - --color-brand-100..1000 feeds the semantic brand tokens, and through them the PrimeVue preset — primary buttons, checkboxes, focus and selected states, links, and the bg-brand-* / text-brand-* utilities. One set of values covers both colour schemes. - --color-default-bcc-100..1000 feeds the ctx-brand-* context utilities. It is mode-aware, so dark mode takes the same palette in reverse. Overriding only the first leaves ctx-brand-* on the BCC teal while everything else changes, which is easy to hit and hard to diagnose. Documented in the README, and in Foundations > Colors where someone looking for how to change colours will actually go. The llms.txt and llms-full.txt outputs are generated from the Storybook docs pages, so both sections flow into them with no change to the generator. The asterisks in token patterns are written as * in the MDX because MDX parses a pair of them as emphasis, which breaks indexing of the page. A backslash escape parses but leaks the backslash into the generated markdown, since escapes are not processed inside code spans; the numeric entity is decoded on both paths. Verified in Chromium that the documented snippet works verbatim on all three consumer paths — src/style.css, the published theme.css compiled by the app's own Tailwind, and the pre-built style.css with the override in a later stylesheet — in both light and dark mode. Storybook builds, the llms generator's quality check passes, both sections appear in llms-full.txt with the token patterns and links rendered cleanly, and all fourteen docs pages the e2e suite covers load without page errors. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01LyYwdsJiGLEyRrJ6tVdnpK --- component-library/README.md | 64 +++++++++++++++++++ component-library/docs/foundations/Colors.mdx | 52 +++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/component-library/README.md b/component-library/README.md index ae9fa3ac..42e1d6c3 100644 --- a/component-library/README.md +++ b/component-library/README.md @@ -84,6 +84,70 @@ import '@bcc-code/component-library-vue/style.css'; You get the BCC theme and component styles only; no Tailwind utilities in your app. +## Brand color + +The library uses the BCC teal as its brand color. An app outside the BCC profile can supply its own palette by redefining two ramps in its own CSS, after the library import. No configuration or build setup is needed — these are ordinary custom properties. + +```css +@import '@bcc-code/component-library-vue/theme.css'; + +/* Drives the semantic brand tokens: primary buttons, checkboxes and radio + buttons, focus and selected states, links, and the bg-brand-* / text-brand-* + Tailwind utilities. One set of values covers both color schemes — the + semantic layer picks different steps in dark mode. */ +:root { + --color-brand-100: #eff6ff; + --color-brand-200: #dbeafe; + --color-brand-300: #bfdbfe; + --color-brand-400: #93c5fd; + --color-brand-500: #60a5fa; + --color-brand-600: #3b82f6; + --color-brand-700: #2563eb; + --color-brand-800: #1d4ed8; + --color-brand-900: #1e40af; + --color-brand-1000: #172554; +} + +/* Drives the ctx-brand-* context utilities. This ramp is mode-aware: step 100 is + always the step furthest from the text color, so the dark values are the same + palette in reverse. */ +:root { + --color-default-bcc-100: #eff6ff; + --color-default-bcc-200: #dbeafe; + --color-default-bcc-300: #bfdbfe; + --color-default-bcc-400: #93c5fd; + --color-default-bcc-500: #60a5fa; + --color-default-bcc-600: #3b82f6; + --color-default-bcc-700: #2563eb; + --color-default-bcc-800: #1d4ed8; + --color-default-bcc-900: #1e40af; + --color-default-bcc-1000: #172554; +} + +.dark { + --color-default-bcc-100: #172554; + --color-default-bcc-200: #1e40af; + --color-default-bcc-300: #1d4ed8; + --color-default-bcc-400: #2563eb; + --color-default-bcc-500: #3b82f6; + --color-default-bcc-600: #60a5fa; + --color-default-bcc-700: #93c5fd; + --color-default-bcc-800: #bfdbfe; + --color-default-bcc-900: #dbeafe; + --color-default-bcc-1000: #eff6ff; +} +``` + +The blocks have to come after the library's CSS so they win the cascade. In Option 1 that means putting them below the `@import` in your main CSS file; in Option 2, in a stylesheet loaded after `style.css`. Both are verified to work. + +Naming note: `--color-default-bcc-*` keeps the `bcc` in its name because it is generated from the Figma token set, not because it has to hold BCC colors. Overriding it with your own palette is supported. + +Skipping the second ramp leaves `ctx-brand-*` teal while everything else changes, which is usually not what you want. + +### Choosing values + +Step 800 carries small text and primary button backgrounds, so check it against the contrast requirements in the [Colors documentation](https://components.bcc.no/?path=/docs/foundations-colors--docs) — 4.5:1 against step 100 and against white. Supply a full light-to-dark range rather than ten shades of the same tone, since the mirrored dark ramp depends on it. + # Components All components are namespaced with `Bcc`. Use them in templates or register them globally in your `main.ts`. diff --git a/component-library/docs/foundations/Colors.mdx b/component-library/docs/foundations/Colors.mdx index 59abb238..51af849a 100644 --- a/component-library/docs/foundations/Colors.mdx +++ b/component-library/docs/foundations/Colors.mdx @@ -122,6 +122,58 @@ import * as ColorStories from './Colors.stories'; +
+ +
+
+
+

Using your own brand palette

+

Products outside the BCC visual identity can replace the brand color with their own. No configuration or build setup is needed — the brand color is reached through two ramps of ordinary custom properties, and an app redefines them in its own CSS after the library import.

+
+ +
+

The two ramps

+

Both have to be set. Overriding only the first leaves the ctx-brand-* contexts on the BCC teal while everything else changes.

+
    +
  • --color-brand-100 to --color-brand-1000 feeds the semantic brand tokens, and through them primary buttons, checkboxes and radio buttons, focus and selected states, links, and the bg-brand-* / text-brand-* utilities. One set of values covers both color schemes, because the semantic layer picks different steps in dark mode.
  • +
  • --color-default-bcc-100 to --color-default-bcc-1000 feeds the ctx-brand-* context utilities. This ramp is mode-aware — step 100 is always the step furthest from the text color — so the dark values are the same palette in reverse. The bcc in the name comes from the Figma token set it is generated from, not from a requirement to hold BCC colors.
  • +
+
+
+ + +```css +@import '@bcc-code/component-library-vue/theme.css'; + +:root { + --color-brand-100: #eff6ff; + /* ... */ + --color-brand-800: #1d4ed8; + --color-brand-1000: #172554; + + --color-default-bcc-100: #eff6ff; + /* ... */ + --color-default-bcc-800: #1d4ed8; + --color-default-bcc-1000: #172554; +} + +.dark { + /* the same palette, reversed */ + --color-default-bcc-100: #172554; + --color-default-bcc-800: #bfdbfe; + --color-default-bcc-1000: #eff6ff; +} +``` + + +

See the Readme for the full ten-step example and where to put it for each of the two styling options.

+ +
+

Choosing values

+

Step 800 carries small text and primary button backgrounds, so check it against the contrast requirements above — 4.5:1 against step 100 and against white. Supply a full light-to-dark range rather than ten shades of the same tone, since the mirrored dark ramp depends on it.

+
+
+

For the full list of token values and hex codes, see Token Reference.

From 1085e39042995228efbfe89dc98e67db55b360ca Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 22 Sep 2026 08:29:29 +0000 Subject: [PATCH 2/4] docs(component-library): document the third ramp PrimeVue needs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two documented ramps are not enough. The PrimeVue theme preset in @bcc-code/design-tokens carries the brand ramp as literal values in primitive.color.brand, and semantic.primary references it through PrimeVue's own token syntax, resolved at theme-generation time. That chain never sees --color-brand-*, so --p-primary-color stays on the BCC teal however the documented ramps are set. The split is not obvious from the outside: 16 component sections in the preset read var(--color-*) and do follow the override — button, checkbox, radiobutton, toggleswitch, select, listbox, multiselect, autocomplete, tag, datepicker, tabs, stepper, badge, paginator, carousel, progressbar. Ten read {primary.*} and stay teal — slider, rating, knob, datatable, treetable, tree, editor, timeline, galleria, fileupload — as do --p-highlight-background and --p-highlight-color, which colour selection in overlays. Documents aliasing --p-color-brand-100..1000 to --color-brand-*. That is the variable --p-primary-* actually resolves through, so the steps map one to one and both colour schemes follow from the same ten lines, unlike restating --p-primary-50..950 where the scales differ and dark mode picks a different step. Recorded as a stopgap. The durable fix belongs in the preset: point primitive.color.brand at the CSS variables instead of baking in values, and the third ramp becomes redundant. Verified in Chromium against rendered components, with the README snippet taken verbatim: light gives #1d4ed8 on both a primary button and a slider range, dark gives #bfdbfe, and without the override both stay teal. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01LyYwdsJiGLEyRrJ6tVdnpK --- component-library/README.md | 27 +++++++++++++++++-- component-library/docs/foundations/Colors.mdx | 12 +++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/component-library/README.md b/component-library/README.md index 42e1d6c3..90bb6221 100644 --- a/component-library/README.md +++ b/component-library/README.md @@ -86,7 +86,7 @@ You get the BCC theme and component styles only; no Tailwind utilities in your a ## Brand color -The library uses the BCC teal as its brand color. An app outside the BCC profile can supply its own palette by redefining two ramps in its own CSS, after the library import. No configuration or build setup is needed — these are ordinary custom properties. +The library uses the BCC teal as its brand color. An app outside the BCC profile can supply its own palette by redefining three ramps in its own CSS, after the library import. No configuration or build setup is needed — these are ordinary custom properties. ```css @import '@bcc-code/component-library-vue/theme.css'; @@ -136,13 +136,36 @@ The library uses the BCC teal as its brand color. An app outside the BCC profile --color-default-bcc-900: #dbeafe; --color-default-bcc-1000: #eff6ff; } + +/* Drives the PrimeVue-derived components and the selection highlight in + overlays. PrimeVue keeps its own copy of the ramp, generated from the theme + preset with the BCC values baked in, so point it at the ramp above. The steps + line up one to one, and dark mode follows on its own. */ +:root { + --p-color-brand-100: var(--color-brand-100); + --p-color-brand-200: var(--color-brand-200); + --p-color-brand-300: var(--color-brand-300); + --p-color-brand-400: var(--color-brand-400); + --p-color-brand-500: var(--color-brand-500); + --p-color-brand-600: var(--color-brand-600); + --p-color-brand-700: var(--color-brand-700); + --p-color-brand-800: var(--color-brand-800); + --p-color-brand-900: var(--color-brand-900); + --p-color-brand-1000: var(--color-brand-1000); +} ``` The blocks have to come after the library's CSS so they win the cascade. In Option 1 that means putting them below the `@import` in your main CSS file; in Option 2, in a stylesheet loaded after `style.css`. Both are verified to work. Naming note: `--color-default-bcc-*` keeps the `bcc` in its name because it is generated from the Figma token set, not because it has to hold BCC colors. Overriding it with your own palette is supported. -Skipping the second ramp leaves `ctx-brand-*` teal while everything else changes, which is usually not what you want. +Skip one and you get a half-rebranded UI: without the second, the `ctx-brand-*` contexts stay teal; without the third, so do the slider, rating, knob, data table, tree table, tree, editor, timeline, galleria and file upload, along with the selection highlight in dropdowns and other overlays. Everything else changes, which makes the omission easy to miss. + +### Why the third ramp + +The other two ramps are plain CSS custom properties the whole way down. `--p-color-brand-*` is different: it is generated from the PrimeVue theme preset in `@bcc-code/design-tokens`, which carries the BCC ramp as literal values, so it cannot see `--color-brand-*`. Most components read the semantic tokens and follow the first ramp on their own; the ones listed above read `--p-primary-*`, which resolves through `--p-color-brand-*` instead. + +Aliasing the ten steps as above covers them in both color schemes, because light and dark pick different steps of the same ramp. Treat it as a stopgap: once the preset references the CSS variables rather than baking in values, these ten lines become redundant and can be dropped without changing anything. ### Choosing values diff --git a/component-library/docs/foundations/Colors.mdx b/component-library/docs/foundations/Colors.mdx index 51af849a..e0d0d3ad 100644 --- a/component-library/docs/foundations/Colors.mdx +++ b/component-library/docs/foundations/Colors.mdx @@ -132,11 +132,12 @@ import * as ColorStories from './Colors.stories';
-

The two ramps

-

Both have to be set. Overriding only the first leaves the ctx-brand-* contexts on the BCC teal while everything else changes.

+

The three ramps

+

All three have to be set. Skip one and you get a half-rebranded UI, which is easy to miss because everything else changes.

  • --color-brand-100 to --color-brand-1000 feeds the semantic brand tokens, and through them primary buttons, checkboxes and radio buttons, focus and selected states, links, and the bg-brand-* / text-brand-* utilities. One set of values covers both color schemes, because the semantic layer picks different steps in dark mode.
  • --color-default-bcc-100 to --color-default-bcc-1000 feeds the ctx-brand-* context utilities. This ramp is mode-aware — step 100 is always the step furthest from the text color — so the dark values are the same palette in reverse. The bcc in the name comes from the Figma token set it is generated from, not from a requirement to hold BCC colors.
  • +
  • --p-color-brand-100 to --p-color-brand-1000 feeds the PrimeVue-derived components — slider, rating, knob, data table, tree table, tree, editor, timeline, galleria, file upload — and the selection highlight in dropdowns and other overlays. PrimeVue keeps its own copy of the ramp, generated from the theme preset with the BCC values baked in, so it cannot see the first ramp; alias it step for step and both color schemes follow. This one is a stopgap: when the preset references the CSS variables instead of baking in values, it can be dropped.
@@ -163,6 +164,13 @@ import * as ColorStories from './Colors.stories'; --color-default-bcc-800: #bfdbfe; --color-default-bcc-1000: #eff6ff; } + +:root { + /* PrimeVue's own copy of the ramp, aliased step for step */ + --p-color-brand-100: var(--color-brand-100); + /* ... */ + --p-color-brand-1000: var(--color-brand-1000); +} ``` From 91ffb225849d0290be94191a7b8071022f8082e4 Mon Sep 17 00:00:00 2001 From: Jan-Sverre Riksfjord Date: Tue, 22 Sep 2026 11:09:05 +0000 Subject: [PATCH 3/4] update tokens --- component-library/package.json | 2 +- component-library/pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/component-library/package.json b/component-library/package.json index c9450d31..2fd86c66 100644 --- a/component-library/package.json +++ b/component-library/package.json @@ -69,7 +69,7 @@ "create-version": "node ./scripts/version.cjs" }, "dependencies": { - "@bcc-code/design-tokens": "^5.2.8", + "@bcc-code/design-tokens": "^5.2.10", "@bcc-code/icons-vue": "^1.5.4", "@primeuix/themes": "^2.0.3", "@tailwindcss/vite": "^4.1.18", diff --git a/component-library/pnpm-lock.yaml b/component-library/pnpm-lock.yaml index 5114de66..30ea629a 100644 --- a/component-library/pnpm-lock.yaml +++ b/component-library/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: .: dependencies: '@bcc-code/design-tokens': - specifier: ^5.2.8 - version: 5.2.8(@primeuix/themes@2.0.3) + specifier: ^5.2.10 + version: 5.2.10(@primeuix/themes@2.0.3) '@bcc-code/icons-vue': specifier: ^1.5.4 version: 1.5.4(vue@3.5.27(typescript@5.7.3)) @@ -199,8 +199,8 @@ packages: resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} - '@bcc-code/design-tokens@5.2.8': - resolution: {integrity: sha512-9V2hZEIeNzWq5g7htRMH2AE631Z2a8FSoBXllGbvYturi0msC7M3JNn3F22n6fbAnll1vX7jVRcBdFJy6+G5yA==} + '@bcc-code/design-tokens@5.2.10': + resolution: {integrity: sha512-xaxl1hclwJh+AbD+54e8Dlg81WRSJYwODZAjr6ZX6IKmUyTHDUDGo+5Ch5xNXWMJi51+jc1Jd7xUBYrdS8nnwA==} engines: {node: '>=18.0.0'} peerDependencies: '@primeuix/themes': ^2.0.0 @@ -3859,7 +3859,7 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@bcc-code/design-tokens@5.2.8(@primeuix/themes@2.0.3)': + '@bcc-code/design-tokens@5.2.10(@primeuix/themes@2.0.3)': dependencies: '@primeuix/themes': 2.0.3 From ad7c9c893fa8d73e9744f631c403f68e4d255d77 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 22 Sep 2026 11:18:32 +0000 Subject: [PATCH 4/4] docs(component-library): drop the third ramp, fixed in design-tokens 5.2.10 design-tokens 5.2.10 points primitive.color.brand at the CSS variables, so --p-primary-* now follows --color-brand-* on its own. The --p-color-brand-* workaround and its explanation are no longer needed, and the docs go back to two ramps. Verified against rendered components on 5.2.10 with the two-ramp README snippet: a primary button and a slider range both give #1d4ed8 in light and #bfdbfe in dark, where the slider previously stayed teal. --p-primary-color tracks the override in both schemes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01LyYwdsJiGLEyRrJ6tVdnpK --- component-library/README.md | 27 ++----------------- component-library/docs/foundations/Colors.mdx | 12 ++------- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/component-library/README.md b/component-library/README.md index 90bb6221..42e1d6c3 100644 --- a/component-library/README.md +++ b/component-library/README.md @@ -86,7 +86,7 @@ You get the BCC theme and component styles only; no Tailwind utilities in your a ## Brand color -The library uses the BCC teal as its brand color. An app outside the BCC profile can supply its own palette by redefining three ramps in its own CSS, after the library import. No configuration or build setup is needed — these are ordinary custom properties. +The library uses the BCC teal as its brand color. An app outside the BCC profile can supply its own palette by redefining two ramps in its own CSS, after the library import. No configuration or build setup is needed — these are ordinary custom properties. ```css @import '@bcc-code/component-library-vue/theme.css'; @@ -136,36 +136,13 @@ The library uses the BCC teal as its brand color. An app outside the BCC profile --color-default-bcc-900: #dbeafe; --color-default-bcc-1000: #eff6ff; } - -/* Drives the PrimeVue-derived components and the selection highlight in - overlays. PrimeVue keeps its own copy of the ramp, generated from the theme - preset with the BCC values baked in, so point it at the ramp above. The steps - line up one to one, and dark mode follows on its own. */ -:root { - --p-color-brand-100: var(--color-brand-100); - --p-color-brand-200: var(--color-brand-200); - --p-color-brand-300: var(--color-brand-300); - --p-color-brand-400: var(--color-brand-400); - --p-color-brand-500: var(--color-brand-500); - --p-color-brand-600: var(--color-brand-600); - --p-color-brand-700: var(--color-brand-700); - --p-color-brand-800: var(--color-brand-800); - --p-color-brand-900: var(--color-brand-900); - --p-color-brand-1000: var(--color-brand-1000); -} ``` The blocks have to come after the library's CSS so they win the cascade. In Option 1 that means putting them below the `@import` in your main CSS file; in Option 2, in a stylesheet loaded after `style.css`. Both are verified to work. Naming note: `--color-default-bcc-*` keeps the `bcc` in its name because it is generated from the Figma token set, not because it has to hold BCC colors. Overriding it with your own palette is supported. -Skip one and you get a half-rebranded UI: without the second, the `ctx-brand-*` contexts stay teal; without the third, so do the slider, rating, knob, data table, tree table, tree, editor, timeline, galleria and file upload, along with the selection highlight in dropdowns and other overlays. Everything else changes, which makes the omission easy to miss. - -### Why the third ramp - -The other two ramps are plain CSS custom properties the whole way down. `--p-color-brand-*` is different: it is generated from the PrimeVue theme preset in `@bcc-code/design-tokens`, which carries the BCC ramp as literal values, so it cannot see `--color-brand-*`. Most components read the semantic tokens and follow the first ramp on their own; the ones listed above read `--p-primary-*`, which resolves through `--p-color-brand-*` instead. - -Aliasing the ten steps as above covers them in both color schemes, because light and dark pick different steps of the same ramp. Treat it as a stopgap: once the preset references the CSS variables rather than baking in values, these ten lines become redundant and can be dropped without changing anything. +Skipping the second ramp leaves `ctx-brand-*` teal while everything else changes, which is usually not what you want. ### Choosing values diff --git a/component-library/docs/foundations/Colors.mdx b/component-library/docs/foundations/Colors.mdx index e0d0d3ad..51af849a 100644 --- a/component-library/docs/foundations/Colors.mdx +++ b/component-library/docs/foundations/Colors.mdx @@ -132,12 +132,11 @@ import * as ColorStories from './Colors.stories';
-

The three ramps

-

All three have to be set. Skip one and you get a half-rebranded UI, which is easy to miss because everything else changes.

+

The two ramps

+

Both have to be set. Overriding only the first leaves the ctx-brand-* contexts on the BCC teal while everything else changes.

  • --color-brand-100 to --color-brand-1000 feeds the semantic brand tokens, and through them primary buttons, checkboxes and radio buttons, focus and selected states, links, and the bg-brand-* / text-brand-* utilities. One set of values covers both color schemes, because the semantic layer picks different steps in dark mode.
  • --color-default-bcc-100 to --color-default-bcc-1000 feeds the ctx-brand-* context utilities. This ramp is mode-aware — step 100 is always the step furthest from the text color — so the dark values are the same palette in reverse. The bcc in the name comes from the Figma token set it is generated from, not from a requirement to hold BCC colors.
  • -
  • --p-color-brand-100 to --p-color-brand-1000 feeds the PrimeVue-derived components — slider, rating, knob, data table, tree table, tree, editor, timeline, galleria, file upload — and the selection highlight in dropdowns and other overlays. PrimeVue keeps its own copy of the ramp, generated from the theme preset with the BCC values baked in, so it cannot see the first ramp; alias it step for step and both color schemes follow. This one is a stopgap: when the preset references the CSS variables instead of baking in values, it can be dropped.
@@ -164,13 +163,6 @@ import * as ColorStories from './Colors.stories'; --color-default-bcc-800: #bfdbfe; --color-default-bcc-1000: #eff6ff; } - -:root { - /* PrimeVue's own copy of the ramp, aliased step for step */ - --p-color-brand-100: var(--color-brand-100); - /* ... */ - --p-color-brand-1000: var(--color-brand-1000); -} ```