Category-first state UI for SaaS products built with Vue.
StateKit focuses on the product states teams rebuild constantly but rarely standardize well: empty, onboarding, loading, error, permission, upgrade, and success. It is not a button kit, form kit, or general design system. It is a narrow layer for product-grade state surfaces and workflow checkpoints.
- Docs site: https://state-kit-vue-docs.vercel.app/
- Start with
/recipesto browse preset recipes and/docs/installationfor the install guide. - Legacy
/blocksroutes still redirect to/recipesfor compatibility.
StateKit currently exposes seven public category-first components:
EmptyStateOnboardingStateLoadingStateErrorStatePermissionStateUpgradeStateSuccessState
Those public entries are backed by 21 preset recipes across the same seven categories. Older scenario-specific exports such as EmptySearchState and OfflineErrorState still exist as deprecated compatibility exports, so existing integrations can migrate gradually.
Onboarding now ships as its own category through OnboardingState. The older FirstProjectState preset still exists, but it now reads as a post-setup empty-state bridge rather than the primary onboarding surface.
npm install @statekit-vue/vue<script setup lang="ts">
import { ref } from "vue";
import "@statekit-vue/vue/styles.css";
import { EmptyState } from "@statekit-vue/vue";
const clearing = ref(false);
async function handleClearFilters() {
clearing.value = true;
try {
await Promise.resolve();
} finally {
clearing.value = false;
}
}
</script>
<template>
<EmptyState
title="No matching invoices"
description="Try a different keyword or clear your current filters."
:primary-action="{
label: 'Clear filters',
onClick: handleClearFilters,
loading: clearing,
loadingLabel: 'Clearing filters...',
}"
:secondary-action="{
label: 'Create invoice',
href: '/invoices/new',
}"
/>
</template>All public entries and preset recipes share the same base prop surface:
titledescriptiontonedensitylayoutprimaryActionsecondaryAction
Supported layouts:
inlinepanelpage
Supported tones:
neutralbranddangerwarningsuccess
primaryAction and secondaryAction both accept StateAction | null | undefined.
A StateAction can include:
label: required button texthref: optional link target; when present the action renders as an anchoronClick: optional click handler for buttons or linksloading: optional busy state controlled by the consumerloadingLabel: optional busy text that replaces the defaultWorking...disabled: optional unavailable state that keeps the action visible
Passing rules:
- Use plain attributes for fixed strings and enum values such as
layout="panel"ortone="brand". - Use
:bindings for variables, objects, booleans, andnull. - In Vue templates, prop names stay kebab-case:
primaryActionbecomesprimary-action, andsecondaryActionbecomessecondary-action. - Leaving an action prop
undefinedkeeps the preset default. - Passing
nullremoves the preset action explicitly. - Put CTA behavior inside
primaryAction.onClickorsecondaryAction.onClick, not on the component root.
- Online docs: https://state-kit-vue-docs.vercel.app/
npm run dev:docsopens the local docs app with recipe previews, installation guidance, and example routes.- The docs app now uses
/recipesas the primary route family and preserves/blocksredirects for compatibility. - Each recipe detail page documents:
- how to customize
titleanddescription - how to pass props directly, from
<script setup>, or throughv-bind - how to wire
primaryActionandsecondaryAction - how to use
onClick,href,loading,loadingLabel,disabled, andnull
- how to customize
- The docs example routes cover:
Admin Empty StatesPermissions And UpgradeTask Flow
npm run dev:exampleopens the external admin-style integration example inexamples/vite-vue-admin.
apps/docs
packages/shared
packages/vue
examples/vite-vue-admin
docs
apps/docs: local documentation app with recipe previews, detailed recipe guides, installation guidance, and workflow examplespackages/shared: shared types, ids, metadata, and priority lists that act as the single source of truthpackages/vue: Vue components, compatibility exports, and the default stylesheetexamples/vite-vue-admin: admin-style integration example using the current action APIdocs: internal product, implementation, QA, and release documentation
Run these commands from the workspace root:
npm run dev:docs
npm run dev:example
npm run typecheck
npm run buildRelease-prep checks:
npm run pack:check
npm run smoke:install- Read internal planning and specs in
docs/ - See versioned release notes in
CHANGELOG.md
Use StateKit when you want consistent state interfaces for SaaS dashboards, admin panels, workspaces, and collaboration products without re-deciding layout, tone, and CTA structure for every edge case.
Do not use StateKit as a replacement for a full design system. It is intentionally narrow: category-first state interfaces and preset recipes, not general UI primitives.



