webcake-ui-kit
webcake-ui-kit
The Vue UI kit that doesn't make you choose.
One library. Two Vue versions. Zero build step. Ship the same components to Vue 2.7 and Vue 3 — from a single source, with one import.
📖 Live Docs & Storybook → ui.webcake.io
Browse every component, prop, slot, and variant — running live in the browser.
👋 Welcome
Migrating from Vue 2 to Vue 3 is painful enough — your UI library shouldn't make it worse.
Most Vue component libraries force you to pick a side. Choose Vue 2 → you're stuck. Choose Vue 3 → you have to rewrite the app first. Either way, you carry the cost.
webcake-ui-kit refuses that tradeoff. Every component is hand-authored under strict dual-compatibility rules so the same import compiles, renders, and behaves identically on Vue 2.7 and Vue 3.4+ — from a codebase you can grep, fork, and theme as if it were your own.
import { WkButton, WkDialog, WkInput } from 'webcake-ui-kit'
// ✅ Vue 2.7 — works
// ✅ Vue 3.x — works
// ✅ Same API. Same styles. Same behavior. One source of truth.
No -vue2 package. No -vue3 package. No build artifact gymnastics. Just .vue files, the way the framework intended.
⚡ Quick start
Get a button on screen in under 60 seconds.
1. Install
npm install webcake-ui-kit
pnpm add webcake-ui-kit
yarn add webcake-ui-kit
Peer dependency:
vue ^2.6.0 || ^3.0.0. That's it.
2. Import the styles once
import 'webcake-ui-kit/styles'
3. Register components
Vue 3
Vue 2.7
// main.js
import { createApp } from 'vue'
import { WkButton, WkDialog, WkInput } from 'webcake-ui-kit'
import 'webcake-ui-kit/styles'
import App from './App.vue'
const app = createApp(App)
app.component('WkButton', WkButton)
app.component('WkDialog', WkDialog)
app.component('WkInput', WkInput)
app.mount('#app')
// main.js
import Vue from 'vue'
import { WkButton, WkDialog, WkInput } from 'webcake-ui-kit'
import 'webcake-ui-kit/styles'
import App from './App.vue'
Vue.component('WkButton', WkButton)
Vue.component('WkDialog', WkDialog)
Vue.component('WkInput', WkInput)
new Vue({ render: h => h(App) }).$mount('#app')
4. Use it
<template>
<div>
<WkButton variant="primary" @click="open = true">Open dialog</WkButton>
<WkDialog v-model="open" title="Hello from webcake 👋">
<WkInput v-model="name" placeholder="Your name" />
</WkDialog>
</div>
</template>
<script>
export default {
data: () => ({ open: false, name: '' })
}
</script>
🎉 That's it. The same .vue file works on both runtimes — no #ifdef, no wrapper, no shim.
✨ Why teams pick webcake
🎯 True dual-compat
One source. Vue 2.7 and Vue 3.x. Tested on both runtimes in CI — every PR, every component.
📦 Ships raw SFC
No pre-compiled artifacts. Your bundler compiles .vue files once, alongside your app. Zero version lock.
🎨 Token-driven theming
Override --color-primary and the whole kit rebrands. No SASS, no providers, no JS theme objects.
♿ Accessible by default
Semantic HTML, :focus-visible rings, ARIA where it matters. Not retrofitted — designed in.
🪶 Tree-shakable
Named exports only. Import Button, leave the rest behind. No Vue.use(KitchenSink).
📖 Storybook included
Every component, every variant, every prop — browsable before you npm install.
🧩 Components
All exports are prefixed with Wk to avoid global name collisions and to be greppable across consumer apps.
| Forms | Overlays | Layout | Display |
|---|---|---|---|
| WkButton | WkDialog | WkAccordion | WkBadge |
| WkButtonGroup | WkAlertDialog | WkAccordionItem | WkTag |
| WkInput | WkTooltip* | WkTabs | WkDivider |
| WkCheckbox | WkBreadcrumb | WkSpinner | |
| WkCheckboxGroup | WkPagination | WkTypography | |
| WkRadio / WkRadioGroup | WkSidebarItem | ||
| WkSelect / WkSelectOption | WkSidebarGroupLabel | ||
| WkSwitch / WkSwitchGroup | |||
| WkToggle / WkToggleGroup | |||
| WkSlider | |||
| WkRichCheckboxGroup | |||
| WkRichSwitchGroup |
* coming soon · more on the way
All components follow the same conventions: validated props, declared emits, BEM-style hooks (ui-button--primary), and v-model where it makes sense.
👉 Want to see them in action? Browse the live Storybook →
🎨 Theming
Every component reads from CSS custom properties. Drop them on :root and the whole kit rebrands:
:root {
--color-primary: #ff6b9d;
--color-primary-hover: #ff4d8a;
--radius-md: 12px;
--font-sans: 'Inter', system-ui, sans-serif;
}
Dark mode? Already wired — every color token has a .dark companion. Toggle a class on <html> and you're done.
.dark {
--color-bg: #0b0b0f;
--color-fg: #f4f4f5;
/* …everything else cascades */
}
No SASS variables. No JS theme provider. No runtime patching. Just CSS, the way the platform meant it.
🛡️ The dual-compat guarantee
Every component compiles cleanly on both runtimes — enforced by a strict authoring contract:
- ✅ Pure Options API — no
<script setup>, nosetup(), no Composition API imports - ✅ Single root template (Vue 2 has no fragments)
- ✅
emitsalways declared (Vue 3 needs it for$attrsseparation) - ✅ No Vue-3-only features (
<Teleport>,<Suspense>, multiv-model) - ✅ No Vue-2-only features (filters,
.native,$listeners)
And every commit runs through four parallel build lanes:
| Runtime | Bundler | What it catches | |
|---|---|---|---|
| 🟢 | Vue 3.4 | Vite + @vitejs/plugin-vue |
Modern compile errors, fragment leaks |
| 🟣 | Vue 2.7 | webpack 4 + vue-template-compiler |
Legacy compile errors, banned APIs |
| 🟡 | Vue 3.2 | Storybook 6.5 | Story-side regressions |
| 🧪 | Both | Vitest × 2 lanes | Runtime + behavior parity |
If a PR doesn't build on either side, it doesn't ship. Period.
🏗️ Why ship raw SFC?
Most Vue libraries publish pre-compiled .js artifacts targeting one Vue runtime. That's how the ecosystem ended up fragmented into -vue2 and -vue3 packages.
webcake-ui-kit publishes the source .vue files directly. Your app's bundler — Vite, webpack, whatever you use — compiles them against your Vue version. One source, two outputs, zero version lock-in.
The tradeoff: you need a bundler that handles
.vue. (You already do.)
This is the entire reason the kit exists. Everything else — the components, the tokens, the Storybook — is downstream of that decision.
🚦 Compatibility
| Version | Status | |
|---|---|---|
| Vue 2 | 2.7.x |
✅ supported |
| Vue 3 | 3.0+ (tested on 3.4) |
✅ supported |
| Bundlers | Vite, webpack 4/5, Rollup, esbuild | ✅ |
| Node (consumer) | any version your bundler supports | ✅ |
| Node (contributor) | 14.x (Vue 2 sandbox uses webpack 4) | ⚠️ pinned |
🧪 Local development
npm run preview # Vue 2 + Vue 3 dev servers side by side (HMR on both)
npm run test:build # Compile-check everything (Vue 2, Vue 3, Storybook) — ~16s
npm test # Unit suite on both runtimes, in parallel
Visit localhost:8001 (Vue 3) and localhost:8080 (Vue 2) side-by-side to spot dual-compat regressions in real time.
Full contributor workflow — including the 10-file checklist for adding a component — lives in CLAUDE.md.
Environment: Node 14 · Python ≤ 3.10 (the Vue 2 playground uses webpack 4 with native deps).
🌐 Resources
| 🌍 Docs & Storybook | ui.webcake.io |
| 📦 npm | npmjs.com/package/webcake-ui-kit |
| 🐙 GitHub | pancake-vn/webcake-ui-kit |
| 🐛 Issues | Report a bug |
| 💬 Discussions | Ask a question |
🤝 Contributing
PRs welcome — especially new components, accessibility fixes, and Vue 2/3 parity bug reports.
Before opening one:
- Read CLAUDE.md — it documents the dual-compat rules and the 10-file checklist for adding a component.
- Run
npm run test:build && npm test— both must pass on Vue 2 and Vue 3 lanes. - Add a Storybook story and a unit spec. New components without both are not accepted.
📜 License
MIT © Webcake Team — use it, fork it, ship it.
Related Packages
Advanced and highly reusable Mobile UI Components built on Vue2 & You can define...
Version History
| Version | Released | License |
|---|---|---|
| 1.3.23 | MIT | |
| 1.3.22 | MIT | |
| 1.3.21 | MIT | |
| 1.3.20 | MIT | |
| 1.3.19 | MIT | |
| 1.3.17 | MIT | |
| 1.3.16 | MIT | |
| 1.3.15 | MIT | |
| 1.3.14 | MIT | |
| 1.3.13 | MIT | |
| 1.3.12 | MIT | |
| 1.3.11 | MIT | |
| 1.3.10 | MIT | |
| 1.3.9 | MIT | |
| 1.3.8 | MIT | |
| 1.3.7 | MIT | |
| 1.3.6 | MIT | |
| 1.3.5 | MIT | |
| 1.3.4 | MIT | |
| 1.3.3 | MIT | |
| 1.3.2 | MIT | |
| 1.3.1 | MIT | |
| 1.3.0 | MIT | |
| 1.2.19 | MIT | |
| 1.2.18 | MIT | |
| 1.2.17 | MIT | |
| 1.2.16 | MIT | |
| 1.2.15 | MIT | |
| 1.2.14 | MIT | |
| 1.2.13 | MIT |
Showing the latest 30 of 112. See every release on npm