@arrowster/shared-ui
v0.2.3
Published
Shared Vue 3 component library for Arrowster projects. Built with Vite in library mode; works in plain Vue 3 apps and Nuxt 3 (Nuxt is Vue 3 under the hood).
Readme
@arrowster/shared-ui
Shared Vue 3 component library for Arrowster projects. Built with Vite in library mode; works in plain Vue 3 apps and Nuxt 3 (Nuxt is Vue 3 under the hood).
Requirements
- Node
>=24.15.0(see.nvmrc— runnvm use) - npm (this repo uses npm;
package-lock.jsonis the committed lockfile)
Install (in a consuming app)
npm install @arrowster/shared-uivue (^3.5) is a peer dependency — your app already provides it.
Vue 3
// main.ts
import '@arrowster/shared-ui/style.css'<script setup lang="ts">
import { BaseButton } from '@arrowster/shared-ui'
</script>
<template>
<BaseButton variant="primary">Hi</BaseButton>
</template>Nuxt 3
// nuxt.config.ts
export default defineNuxtConfig({
css: ['@arrowster/shared-ui/style.css'],
})<script setup lang="ts">
import { BaseButton } from '@arrowster/shared-ui'
</script>Dashboard layout
BaseDashboardLayout owns the sidebar and topbar. Pass the menu as an items array and
bind the active item with v-model. Anything you leave out shows a labelled placeholder.
<script setup lang="ts">
import { ref } from 'vue'
import { BaseDashboardLayout, type NavItem } from '@arrowster/shared-ui'
import { HomeIcon, UsersIcon } from './icons' // any Vue components
const active = ref('dashboard')
const items: NavItem[] = [
{ value: 'dashboard', label: 'Dashboard', icon: HomeIcon },
{ value: 'students', label: 'Active Students', icon: UsersIcon, badge: 128 },
{ value: 'archive', label: 'Archived', disabled: true },
]
</script>
<template>
<BaseDashboardLayout v-model="active" brand="Arrowster" :items="items">
<template #topbar>…</template>
<!-- page content -->
</BaseDashboardLayout>
</template>| NavItem field | Type | Notes |
| --------------- | ------------------ | ------------------------------------------------------------------------- |
| value | string \| number | Identifies the item; this is what v-model holds. |
| label | string | Text shown next to the icon. |
| icon | Vue component | Optional. Without one, the collapsed rail shows the label's first letter. |
| badge | string \| number | Optional count pill (expanded sidebar only). |
| disabled | boolean | Optional. Dimmed and not selectable. |
| Layout prop / slot | Purpose |
| ----------------------------- | -------------------------------------------------------------------------- |
| brand prop, #brand slot | Sidebar header text, or a custom logo. |
| #logo slot | Mark shown when the sidebar is collapsed. |
| items prop, #nav slot | Menu items; the slot replaces items for fully custom content. |
| #sidebar-footer slot | Profile or actions at the bottom of the sidebar. |
| #topbar slot | Content inside the topbar. |
| default slot | Page content. |
| hide-sidebar, hide-topbar | Remove those regions (for example on a login page). |
| hide-sidebar-footer | No footer in the sidebar. Without it, an empty footer shows a placeholder. |
Local development
nvm use # match Node version
npm install # install deps
npm run dev # Vite playground (index.html + src/App.vue)Other scripts:
| Command | What it does |
| -------------------- | ---------------------------------------------- |
| npm run dev | Playground dev server with HMR |
| npm run build | Typecheck + lint + test, then build to dist/ |
| npm run typecheck | vue-tsc type check |
| npm run lint | ESLint |
| npm run format | Prettier write |
| npm run test | Vitest run |
| npm run test:watch | Vitest watch |
Project structure
src/
index.ts # published entry (re-exports components + imports CSS)
style.css # Tailwind entry, compiled to dist/style.css
components/
index.ts # component barrel (public exports)
ui/ # UI primitives
BaseButton.vue
BaseButton.spec.ts # colocated tests — every component ships one
App.vue # playground only (not published)
main.ts # playground only (not published)Adding a component
- Create
src/components/ui/YourComponent.vue. - Add a colocated
src/components/ui/YourComponent.spec.ts. - Export it from
src/components/index.ts. - Drop it into
src/App.vueandnpm run devto view it. npm run build— it's in the package automatically.
Publishing
npm version patch # or minor / major
npm publishprepublishOnly runs the full build (typecheck + lint + test + bundle) first, so dist/ is always fresh and verified. Only dist/ + README.md are published (see files in package.json).