@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 — run nvm use)
  • npm (this repo uses npm; package-lock.json is the committed lockfile)

Install (in a consuming app)

npm install @arrowster/shared-ui

vue (^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

  1. Create src/components/ui/YourComponent.vue.
  2. Add a colocated src/components/ui/YourComponent.spec.ts.
  3. Export it from src/components/index.ts.
  4. Drop it into src/App.vue and npm run dev to view it.
  5. npm run build — it's in the package automatically.

Publishing

npm version patch   # or minor / major
npm publish

prepublishOnly 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).