@bcc-code/component-library-vue
| Install | |
|---|---|
npm install @bcc-code/component-library-vue |
|
| Latest Version: | 1.5.3 |
| Vue: | 3 |
| License: | Apache-2.0 |
| Last Updated: | Oct 22, 2026 |
| Links: | GitHub · npm |
@bcc-code/component-library-vue
Vue 3 component library built on PrimeVue and BCC design tokens. You only need this package—no separate Tailwind or PrimeVue install.
Storybook Link
Install
pnpm add @bcc-code/component-library-vue
# or
npm install @bcc-code/component-library-vue
# or
yarn add @bcc-code/component-library-vue
Min requirements: Vue 3.
Note to PNPM installs: The library uses @bcc-code/icons-vue and @bcc-code/design-tokens. To use them in your own app (e.g. import { CheckIcon } from '@bcc-code/icons-vue') without needing to explicitly add install them in your own package.json, add this to your project’s .npmrc so pnpm hoists them:
public-hoist-pattern[]=@bcc-code/icons-vue
public-hoist-pattern[]=@bcc-code/design-tokens
Then run pnpm install again. With npm or Yarn this is not needed.
Quick start
- Register the library in your app (e.g.
main.ts):
import { createApp } from 'vue';
import App from './App.vue';
import { BccComponentLibrary } from '@bcc-code/component-library-vue';
const app = createApp(App);
app.use(BccComponentLibrary);
app.mount('#app');
- Add styles using one of the two options below.
Styles Option 1 — Recommended: full Tailwind in your app
Use this if you want Tailwind utility classes in your own templates while still letting the library's components render correctly.
- Add the Tailwind Vite plugin (the package brings Tailwind in as a dependency; you only wire it up):
// vite.config.ts
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [vue(), tailwindcss()],
// ...
});
- Import the theme in your main CSS file (e.g.
src/main.cssorsrc/assets/main.css):
@import '@bcc-code/component-library-vue/theme.css';
/* Optional, if not already included */
@import '@bcc-code/component-library-vue/archivo-font.css';
That single import is enough. theme.css includes:
- BCC design tokens,
@theme/@utilitydefinitions, and the rest of the design-system CSS inlined fromsrc/style.css(including component-specific rules such asBccInputicon sizing andBccButtoncontext tokens). library-utilities.css, the pre-compiled Tailwind utility class rules used inside library templates (which your build cannot infer from the published JS).
Do not rely on library-utilities.css alone with a minimal “base” import: you still need the full theme.css (or style.css for Option 2) so non-utility component styles and tokens are present.
Styles Option 2 — Pre-built CSS only
Use this if you don’t want Tailwind in your project and only need the library’s styles and components.
In your entry file (e.g. main.ts), before mounting the app:
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.
@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 — 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.
Example:
<template>
<div class="flex gap-4 p-4">
<BccButton label="Save" />
<BccInput v-model="name" placeholder="Name" />
</div>
</template>
<script setup lang="ts">
import { BccButton, BccInput } from '@bcc-code/component-library-vue';
import { ref } from 'vue';
const name = ref('');
</script>
Example:
// main.ts
...
import { BccButton, BccInput } from '@bcc-code/component-library-vue';
// After app.use(BccComponentLibrary)
app.component('BccButton', BccButton);
app.component('BccInput', BccInput);
The library exports both custom BCC components (e.g. BccBadge, BccFrame, BccReact) and wrapped PrimeVue components (e.g. BccButton, BccDialog, BccDataTable). PrimeVue services (Toast, Confirm, Dialog) are configured by BccComponentLibrary; use the composables useToast, useConfirm, and useDialog from the library when you need them.
Bundle size
The ES build is tree-shakeable: you pay for the components you import, not for the whole library. Importing a single small component adds a few kB on top of Vue; heavier components (BccDataTable, BccEditor, BccDatePicker) cost proportionally more because they carry their PrimeVue implementation and styles.
Two things are needed on the consumer side:
- Import from the package root and let your bundler shake it —
import { BccBadge } from '@bcc-code/component-library-vue'. There is no need to deep-import individual files. - Build for production. Dev servers do not tree-shake, so
pnpm devwill always look like the whole library is loaded.
Styles are not tree-shaken: style.css (Option 2) always contains the rules for every component. If CSS size matters, use Option 1 (theme.css + Tailwind in your app), where Tailwind only emits the utilities you actually use.
Development
pnpm install
pnpm run start # Storybook on port 6006
pnpm run build # Typecheck, types, and Vite build
pnpm run docs:ai # Build Storybook, then generate AI-ready docs outputs
pnpm run build:llms # Regenerate AI docs from an existing storybook-static/index.json
pnpm run build:vite # Vite build only (includes theme.css)
Build output shape (do not flatten it)
vite build emits one file per module (output.preserveModules) rather than a single bundle, and package.json declares "sideEffects": ["**/*.css"]. Both are required for consumers to tree-shake the package, and either one alone does nothing — see #369.
The reason a single bundle cannot be shaken: PrimeVue's per-component style modules call BaseStyle.extend() and the theme preset calls definePreset() at module top level. Concatenated into one file, those become impure top-level statements that a consumer's bundler must keep, which dragged ~785 kB of unused code into every consumer bundle.
Consequences to keep in mind when touching the build:
- Dependencies are bundled and re-rooted under
dist/vendor/<package>/.... PrimeVue in particular must not be made external: the@primevue/iconspatch that swaps in BCC icons only reaches consumers through our own build output. preserveModulesonly supports the ES format, so the UMD bundle is built separately byvite.config.umd.ts.pnpm run test:bundle-sizebundles a probe app againstdistand fails if importing one component costs more than 40 kB. It runs in CI after the build.
AI-ready docs outputs
pnpm run docs:ai generates the public AI documentation artifacts into storybook-static/:
/llms.txt: Markdown index of public docs pages./llms-full.txt: concatenated Markdown for all public docs pages./docs/<page>.md: per-page Markdown mirroring the Storybook docs route, e.g./docs/foundations-colors--docs->/docs/foundations-colors--docs.md.
build-storybook runs the same generation after Storybook builds, so deployed docs get these files at runtime. The generated files live in storybook-static/, which is ignored and not committed; CI does not need a drift check unless these build artifacts are committed later.
The generator uses Storybook's storybook-static/index.json as the route source of truth, converts MDX to readable Markdown, and summarizes autodocs story pages from story metadata. It only reads public docs entries from docs and src through the Storybook manifest, and excludes private/internal/secrets paths, env files, dependency folders, build outputs, and caches.
Override the published URL base with LLMS_BASE_URL=https://your-docs-host pnpm run build:llms if needed. Only static Markdown and JSON documentation artifacts are produced.
Folder structure (where to work)
src/components/custom: New BCC-first components and component-specific styles/logic.src/components/wrapped: PrimeVue wrapped components (Bcc*) where we adapt APIs, defaults, slots, and behavior.src/styles: Design-system CSS layers (theme, contexts, semantic tokens, utility classes).src/index.ts: Public exports; add new components/composables here so consumers can import them.docsand*.mdx: Storybook docs pages and design guidance content.*.stories.ts/*.mdx(insrcordocs): Demos, docs, and regression coverage for components.
Patching PrimeVue icons
Some PrimeVue icons are replaced with @bcc-code/icons-vue so the library uses BCC iconography. The patch is maintained with pnpm’s built-in patching.
1. Start or re-enter the patch
pnpm patch @primevue/icons
pnpm will print a path to a writable copy of the package (e.g. node_modules/.pnpm_patches/@primevue/icons@4.5.4).
2. Edit the icon mappings
-
Main barrel: Edit
index.mjsin that folder. Each line that re-exports from@bcc-code/icons-vuedefines one override, e.g.:export { ExpandMoreIcon as ChevronDownIcon } from '@bcc-code/icons-vue'; -
Per-icon files: After changing the main
index.mjs, run the sync script so each icon’s ownindex.mjs(e.g.chevrondown/index.mjs) is updated to use the same BCC component:pnpm run sync:primevue-icon-patchesThat way both
@primevue/iconsand@primevue/icons/chevrondown(and other overridden icons) use the BCC icon.
3. Save the patch
From the project root (where package.json lives), run:
pnpm patch-commit <path-pnpm-printed-in-step-1>
Example, if pnpm printed ~/Projects/bcc-design/component-library/node_modules/.pnpm_patches/@primevue/icons@4.5.4:
pnpm patch-commit node_modules/.pnpm_patches/@primevue/icons@4.5.4
The patch is written to patches/@primevue__icons.patch and applied automatically on pnpm install.
License
Apache-2.0
Related Packages
Version History
| Version | Released | License |
|---|---|---|
| 1.5.3 | Apache-2.0 | |
| 1.5.2 | Apache-2.0 | |
| 1.5.0 | Apache-2.0 | |
| 1.4.40 | Apache-2.0 | |
| 1.4.39 | Apache-2.0 | |
| 1.4.38 | Apache-2.0 | |
| 1.4.37 | Apache-2.0 | |
| 1.4.36 | Apache-2.0 | |
| 1.4.35 | Apache-2.0 | |
| 1.4.34 | Apache-2.0 | |
| 1.4.33 | Apache-2.0 | |
| 1.4.32 | Apache-2.0 | |
| 1.4.31 | Apache-2.0 | |
| 1.4.30 | Apache-2.0 | |
| 1.4.29 | Apache-2.0 | |
| 1.4.28 | Apache-2.0 | |
| 1.4.27 | Apache-2.0 | |
| 1.4.26 | Apache-2.0 | |
| 1.4.25 | Apache-2.0 | |
| 1.4.24 | Apache-2.0 | |
| 1.4.23 | Apache-2.0 | |
| 1.4.22 | Apache-2.0 | |
| 1.4.21 | Apache-2.0 | |
| 1.4.19 | Apache-2.0 | |
| 1.4.18 | Apache-2.0 | |
| 1.4.13 | Apache-2.0 | |
| 1.4.12 | Apache-2.0 | |
| 1.4.11 | Apache-2.0 | |
| 1.4.10 | Apache-2.0 | |
| 1.4.9 | Apache-2.0 |
Showing the latest 30 of 136. See every release on npm
Pre-releases (249)
| Version | Released | License |
|---|---|---|
| 0.0.0-dev.892612c | Apache-2.0 | |
| 0.0.0-dev.1a5d955 | Apache-2.0 | |
| 0.0.0-dev.f41f3d5 | Apache-2.0 | |
| 0.0.0-dev.ac6c08f | Apache-2.0 | |
| 0.0.0-dev.181fcd0 | Apache-2.0 | |
| 0.0.0-dev.d6deb51 | Apache-2.0 | |
| 0.0.0-dev.d10219f | Apache-2.0 | |
| 0.0.0-dev.d2014a2 | Apache-2.0 | |
| 0.0.0-dev.6c4e9f3 | Apache-2.0 | |
| 0.0.0-dev.9d48a36 | Apache-2.0 | |
| 0.0.0-dev.abb83d2 | Apache-2.0 | |
| 0.0.0-dev.9fbaadb | Apache-2.0 | |
| 0.0.0-dev.df70a52 | Apache-2.0 | |
| 0.0.0-dev.95d9d2b | Apache-2.0 | |
| 0.0.0-dev.fc9ad3c | Apache-2.0 | |
| 0.0.0-dev.234d6ea | Apache-2.0 | |
| 0.0.0-dev.5dfa3f9 | Apache-2.0 | |
| 0.0.0-dev.cbc8f81 | Apache-2.0 | |
| 0.0.0-dev.08c18bd | Apache-2.0 | |
| 0.0.0-dev.9bfba01 | Apache-2.0 | |
| 0.0.0-dev.dd8ae9d | Apache-2.0 | |
| 0.0.0-dev.163eda9 | Apache-2.0 | |
| 0.0.0-dev.9702651 | Apache-2.0 | |
| 0.0.0-dev.944a07d | Apache-2.0 | |
| 0.0.0-dev.ab69cdb | Apache-2.0 | |
| 0.0.0-dev.e994f0d | Apache-2.0 | |
| 0.0.0-dev.dbcae8b | Apache-2.0 | |
| 0.0.0-dev.615d5b7 | Apache-2.0 | |
| 0.0.0-dev.bd6507a | Apache-2.0 | |
| 0.0.0-dev.26b926c | Apache-2.0 |
Showing the latest 30 of 249. See every release on npm