Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

██╗   ██╗████████╗ ██╗ ██████╗  ██████╗
██║   ██║╚══██╔══╝███║██╔ ██║██╔╔══██╗
██║   ██║   ██║   ╚██║██║  ██║██║  ██║
╚██╗ ██╔╝   ██║    ██║██║  ██║██║  ██║
 ╚████╔╝    ██║    ██║╚██████╔╝╚██████╔╝
  ╚═══╝     ╚═╝    ╚═╝ ╚═════╝  ╚═════╝

A retro-terminal, motion-first Vue 3 component library.
Phosphor green. Hard cuts. Zero border-radius. No springs.

Screenshot 2026-08-02 at 19 40 07

Vue 3 TypeScript Vite components themes


> what is this_

vt100 is a component library for Vue 3 that treats the constraints of an old CRT terminal as an actual design system, not a texture applied on top of a normal UI kit. One accent color at a time. Flat rectangles, no rounded corners anywhere. Motion that jumps in hard steps() cuts instead of easing. State communicated by glyph and shape, never by a second hue.

Screenshot 2026-08-02 at 19 40 40

It's not a theme — it's ~98 components (forms, overlays, data display, navigation, feedback, charts) that all follow the same small set of rules, so the 90th component you drop into a page looks like it belongs next to the 1st.

$ npm install vt100-ui

> quickstart_

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import 'vt100-ui/style.css'

createApp(App).mount('#app')
<script setup lang="ts">
import { VtButton, VtInput, VtField } from 'vt100-ui'
import { ref } from 'vue'

const name = ref('')
</script>

<template>
  <VtField label="name" hint="what should we call you?">
    <template #default="{ id }">
      <VtInput :id="id" v-model="name" placeholder="joris" />
    </template>
  </VtField>
  <VtButton variant="primary">continue</VtButton>
</template>

> theming_

Screenshot 2026-08-02 at 19 41 32

Four built-in accent themes — green (default), amber, white, blue — swapped at runtime via a data-theme attribute on :root. Every color-bearing token in the library derives from two CSS custom properties, so a fifth theme is just two lines:

[data-theme='sunset'] {
  --vt-accent: #ff5f1f;
  --vt-accent-rgb: 255, 95, 31;
}

Or reach for the composable and skip the CSS entirely:

import { useTheme } from 'vt100-ui'

const { theme, setTheme, toggleTheme, setCustomAccent } = useTheme()

setTheme('amber')
setCustomAccent('#ff5f1f') // any hex color, persisted across reloads

<VtThemeToggle /> wraps this into a single drop-in control.

> see it in context_

Isolated components in a gallery only tell you so much. Running the playground (npm run dev) also gets you four full page mockups under the examples nav group — a SaaS landing page, an admin dashboard, a blog/docs article, and a login screen — built entirely from real vt100 components wired together, not cropped screenshots.

Both the marketing landing page and the full docs/gallery app are also deployed to GitHub Pages: joris63.github.io/vt100 for the landing page, and joris63.github.io/vt100/docs for the docs app itself.

> components_

98 components across 7 categories. Every one ships its own hand-written .d.ts — import only what you use.

forms — 24

Button · Input · Textarea · NumberInput · Slider · RangeSlider · Toggle · ToggleGroup · Checkbox · RadioGroup · Select · Combobox · DatePicker · Calendar · Rating · FileUpload · SegmentedControl · ColorPicker · PinInput · TagsInput · PasswordInput · SplitButton · CopyButton · Field

feedback — 10

Alert · Toast · ProgressBar · Spinner · Skeleton · EmptyState · LoadingBar · Banner · BootSequence · MatrixRain

overlays — 13

Dialog · Drawer · Popover · Menu · CommandPalette · ContextMenu · ConfirmDialog · Tooltip · HoverCard · Tour · Lightbox · NotificationCenter · Popconfirm

navigation — 11

Breadcrumb · Pagination · Tabs · Accordion · Collapsible · Stepper · TreeSelect · BackToTop · Wizard · NavMenu · AnchorNav

data display — 29

Badge · Tag · Card · DataTable · Avatar · AvatarGroup · Kbd · Divider · Timeline · Statistic · ScrollArea · Terminal · List · AspectRatio · Marquee · CodeBlock · Sparkline · DiffViewer · Clock · QrCode · JsonViewer · BarChart · LineChart · Gauge · Ticker · DescriptionList · VirtualList · Countdown · Heatmap

theming — 1

ThemeToggle

utilities — 9

VisuallyHidden · Stack · Container · Splitter · Masonry · CrtOverlay · StatusBar · Affix · InfiniteScroll

> the rules_

Every component in the library is checked against the same small set of constraints:

  • One accent color at a time. State/tone is glyph or shape, never a second hue.
  • Zero border-radius, everywhere. Enforced globally, no per-component overrides.
  • Motion uses steps() easing. Hard cuts, never a smooth or spring curve.
  • Every :hover is gated behind @media (hover: hover) and (pointer: fine) — no sticky hover states on touch.
  • prefers-reduced-motion: reduce is respected everywhere motion appears, both at the token level and per-component.

> development_

Command What it does
npm run dev Playground app, local dev server
npm run build Type-check + build the playground (docs app) → dist-playground/
npm run build:lib Build the publishable package → dist/
npm run type-check vue-tsc --build
npm run test:unit Vitest, watch mode
npm run lint oxlint + eslint, both with --fix
npm run format prettier --write src/
npx vitest run                              # run the full suite once
npx vitest run path/to/File.spec.ts         # a single spec file
npx vitest run -t "test name substring"     # a single test by name

Every component lives at src/components/<Name>/<Name>.vue next to its own <Name>.spec.ts and a <Name>Gallery.vue doc page under src/views/. Shared cross-cutting behavior lives in src/composables/useTheme, useToast, useConfirm, useFloatingPanel, and friends — rather than being reimplemented per component.

> publishing_

Published as vt100-ui (the plain vt100 name is already taken by an unrelated package). .github/workflows/publish.yml handles it — publishing a GitHub Release triggers a build + test + npm publish. To cut a release:

npm version patch   # or minor / major — bumps package.json and tags the commit
git push --follow-tags

Then draft a GitHub Release from that tag (Releases → Draft a new release). The workflow needs an NPM_TOKEN repo secret — an npm Automation token with publish rights on vt100-ui, added under Settings → Secrets and variables → Actions.

The landing page and the docs app both deploy to GitHub Pages together on every push to master, via .github/workflows/deploy-pages.yml — see > see it in context_ above for the live URLs.

> license_

MIT


monospace or nothing.

About

Retro terminal component library for Vue

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages