Documentation
Everything you need to integrate, customise, and extend Vectra UI Kit. No build tools. No fluff.
Quick Start
Add three CDN links and the two Vectra files to your <head> and you're live — no bundler, no config, no dependencies to install.
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My App</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700
&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
<!-- Bootstrap 5 CSS -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
crossorigin="anonymous" />
<!-- Font Awesome 6 -->
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css"
crossorigin="anonymous" />
<!-- Vectra CSS -->
<link rel="stylesheet" href="assets/css/vectra.css" />
</head>
<body>
<!-- your content -->
<!-- Bootstrap JS (bundle includes Popper) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
crossorigin="anonymous"></script>
<!-- Vectra JS -->
<script src="assets/js/vectra.js"></script>
</body>
</html>
DOMContentLoaded — no manual calls needed.
File Structure
The kit is entirely self-contained. Drop it into any project or serve it directly as a static site.
Vectra-UI-KIT/
├── index.html Landing / showcase page
├── components.html Full component catalog
├── forms.html Form elements reference
├── utilities.html Utility classes reference
├── docs.html This file — documentation
├── pricing.html Pricing section example
├── sections.html Section layout examples
├── LICENSE MIT license
├── README.md Project readme
├── auth/
│ ├── login.html Sign-in page
│ ├── register.html Registration page
│ ├── recover.html Password recovery page
│ └── profile.html Tabbed user settings
└── assets/
├── css/
│ └── vectra.css Design system (~1 700 lines)
└── js/
└── vectra.js JS engine (~450 lines)
Design Tokens
All visual values — colours, radii, shadows, and transitions — live as CSS custom properties on :root. Override any token in your own stylesheet loaded after vectra.css.
/* Change accent to violet — my-overrides.css */
:root {
--v-accent: #7c3aed;
--v-accent-2: #a78bfa;
--v-accent-rgb: 124, 58, 237;
--v-accent-soft: rgba(124, 58, 237, .1);
--v-accent-grad: linear-gradient(135deg, #7c3aed, #a78bfa);
--v-accent-glow: 0 0 0 3px rgba(124, 58, 237, .3);
}
Token reference
| Token | Dark default | Light override | Purpose |
|---|---|---|---|
--v-bg | #111318 | #f5f7fa | Page background |
--v-bg-2 | #171b23 | #eef1f5 | Secondary background |
--v-surface | #1d2333 | #ffffff | Card / panel surface |
--v-surface-2 | #242d3e | #f0f3f7 | Elevated surface |
--v-border | #2e3a4e | #dde3ec | Default border colour |
--v-accent | #00c2cb | #0099a3 | Primary accent |
--v-accent-soft | rgba(0,194,203,.1) | same | Accent tint / badge bg |
--v-text | #e2e8f0 | #0f172a | Primary text |
--v-text-2 | #94a3b8 | #334155 | Secondary text |
--v-text-3 | #627086 | #64748b | Muted / placeholder |
--v-r | 10px | same | Base border-radius |
--v-navbar-h | 64px | same | Fixed navbar height |
Dark & Light Theme
Set data-theme="dark" or data-theme="light" on the <html> element. Vectra JS persists the user's choice to localStorage across sessions.
HTML attribute
<!-- Default dark -->
<html lang="en" data-theme="dark">
<!-- Start in light mode -->
<html lang="en" data-theme="light">
Toggle button
<button class="v-theme-toggle" data-toggle="theme" aria-label="Toggle theme">
<i class="fa-solid fa-sun"></i>
</button>
Programmatic control
// Toggle between dark ↔ light
Vectra.toggleTheme();
// Force a specific theme
document.documentElement.setAttribute('data-theme', 'light');
localStorage.setItem('vectra-theme', 'light');
JavaScript API
vectra.js exposes a global window.Vectra object. Every feature is initialised automatically on page load — call methods manually only when you need programmatic control.
Vectra.toggleTheme() | Switches between dark and light theme. Persists preference to localStorage. |
Vectra.scrollToTop() | Smoothly scrolls the page to the top. |
Vectra.initScrollSpy() | Activates IntersectionObserver scroll spy on [data-scrollspy] nav elements. |
Vectra.initSideNav() | Activates sidebar scroll spy + click-scroll on [data-sidenav] nav elements. |
Vectra.initCounters() | Animates number counters from 0 to data-counter value on viewport entry. |
Vectra.initCopyButtons() | Wires .v-copy-btn to copy the nearest <pre> block to clipboard. |
Vectra.initSliders() | Activates all .v-slider elements with touch, swipe, and dot navigation. |
Vectra.initFileUpload() | Enables drag-and-drop file upload on .v-drop-zone elements. |
Vectra.initFAB() | Wires the Floating Action Button to toggle its action list. |
Vectra.initCookieBanner() | Shows/hides the cookie consent banner; persists accept/decline to localStorage. |
Vectra.initPasswordToggle() | Wires data-pw-toggle buttons to reveal or hide the target password input. |
Data Attributes
Vectra JS discovers and activates features through HTML data attributes — no import statements or manual init calls required.
| Attribute | Element | Behaviour |
|---|---|---|
data-toggle="theme" | <button> | Toggles dark/light theme on click |
data-scrollspy | <nav> | Top-navbar IntersectionObserver scroll spy |
data-sidenav | <nav> | Sidebar scroll spy + smooth anchor scroll |
data-counter="N" | any element | Counts up from 0 to N when scrolled into view |
data-autoplay="ms" | .v-slider | Auto-advances slider every N milliseconds |
data-pw-toggle="id" | <button> | Reveals/hides password input with matching id |
data-cookie-accept | <button> | Accepts cookies and dismisses the banner |
data-cookie-decline | <button> | Declines cookies and dismisses the banner |
Auth Pages — Overview
Four ready-to-use authentication templates live in the auth/ directory. Each is fully themed, responsive, and uses the same design-token system as the rest of the kit.
| Page | File | Description |
|---|---|---|
| Login | auth/login.html |
Email + password card with social buttons, remember-me toggle, and show-password support. |
| Register | auth/register.html |
Full registration form — name, email, password, confirmation, and terms checkbox. |
| Recovery | auth/recover.html |
Two-state flow: email entry then animated "link sent" confirmation. |
| Profile | auth/profile.html |
Tabbed settings dashboard — personal info, security, notifications, and billing. |
Auth — Login
A centred sign-in card with email/password fields, an eye-button for reveal/hide, social login buttons, and a remember-me checkbox.
<form method="post" action="/login">
<input type="email" name="email" required placeholder="Email address" />
<div class="position-relative">
<input type="password" name="password" required placeholder="Password" id="pw" />
<button type="button" data-pw-toggle="pw" aria-label="Show password">
<i class="fa-solid fa-eye"></i>
</button>
</div>
<button type="submit" class="v-btn v-btn-primary w-100">Sign in</button>
</form>
data-pw-toggle="id" is handled automatically by Vectra.initPasswordToggle() — no extra JavaScript required.
Auth — Register
Full registration card with first/last name, email, password, confirm-password, and a required terms checkbox.
<form method="post" action="/register">
<div class="row g-3">
<div class="col-6">
<input type="text" name="first_name" required placeholder="First name" />
</div>
<div class="col-6">
<input type="text" name="last_name" required placeholder="Last name" />
</div>
</div>
<input type="email" name="email" required placeholder="Email address" />
<input type="password" name="password" required placeholder="Password" id="pw" />
<input type="password" name="confirm" required placeholder="Confirm password" />
<label>
<input type="checkbox" name="terms" required />
I agree to the Terms of Service
</label>
<button type="submit" class="v-btn v-btn-primary w-100">Create account</button>
</form>
Auth — Recovery
A two-state page: the email entry form is shown by default. On submit, it animates into a confirmation card confirming the reset link was sent.
<!-- State 1: email form -->
<div id="recoverForm">
<form>
<input type="email" required placeholder="Your email address" />
<button type="submit" class="v-btn v-btn-primary w-100">
Send reset link
</button>
</form>
</div>
<!-- State 2: success confirmation (hidden initially) -->
<div id="recoverSuccess" style="display:none; text-align:center">
<i class="fa-solid fa-circle-check fa-3x" style="color:var(--v-success)"></i>
<h3 class="mt-3">Link sent!</h3>
<p>Check your inbox — a reset link is on its way.</p>
</div>
<script>
document.querySelector('#recoverForm form').addEventListener('submit', e => {
e.preventDefault();
document.getElementById('recoverForm').style.display = 'none';
document.getElementById('recoverSuccess').style.display = 'block';
});
</script>
Auth — Profile
A full-page tabbed settings dashboard with four tabs: Personal Info, Security (password + 2FA toggle), Notifications, and Billing.
<!-- Bootstrap pill tabs -->
<ul class="nav nav-pills" id="profileTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" data-bs-toggle="pill"
data-bs-target="#tab-personal" type="button">Personal Info</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="pill"
data-bs-target="#tab-security" type="button">Security</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="pill"
data-bs-target="#tab-notifications" type="button">Notifications</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="pill"
data-bs-target="#tab-billing" type="button">Billing</button>
</li>
</ul>
<div class="tab-content mt-4">
<div class="tab-pane fade show active" id="tab-personal">
<!-- name, email, bio, avatar upload -->
</div>
<div class="tab-pane fade" id="tab-security">
<!-- change password, 2FA toggle -->
</div>
<div class="tab-pane fade" id="tab-notifications">
<!-- email/push notification toggles -->
</div>
<div class="tab-pane fade" id="tab-billing">
<!-- plan info, payment method, invoices -->
</div>
</div>
Accessibility
Accessibility is a first-class concern, not an afterthought. All components meet or exceed WCAG 2.1 AA.
- Focus rings — every interactive element shows a clearly visible focus ring via
--v-focus. - ARIA labels — icon-only buttons, toggles, and nav elements all carry descriptive
aria-labelattributes. - Reduced motion — all transitions and animations are disabled when
prefers-reduced-motion: reduceis detected. - Colour contrast — all text/background pairs in both themes meet WCAG AA — 4.5:1 for normal text, 3:1 for large.
- Keyboard navigation — modals, dropdowns, accordions, and tabs are keyboard-accessible via Bootstrap's handlers.
- Semantic HTML — heading hierarchy is strict,
<nav>elements carryaria-label, landmark roles are used correctly. - Role attributes — toggle switches carry
role="switch"; modals userole="dialog"witharia-modal.
Customisation
Override CSS tokens in your own stylesheet to retheme the entire kit in seconds — no SASS, no recompilation.
Accent colour
/* Load AFTER vectra.css */
:root {
--v-accent: #7c3aed;
--v-accent-2: #a78bfa;
--v-accent-rgb: 124, 58, 237;
--v-accent-soft: rgba(124, 58, 237, .1);
--v-accent-grad: linear-gradient(135deg, #7c3aed, #a78bfa);
--v-accent-glow: 0 0 0 3px rgba(124, 58, 237, .3);
}
Typography
:root {
--v-font: 'Geist', 'DM Sans', system-ui, sans-serif;
--v-mono: 'Geist Mono', Consolas, monospace;
}
Custom components
Build new components using existing tokens — they will theme-switch automatically.
.my-widget {
background: var(--v-surface);
border: 1px solid var(--v-border);
border-radius: var(--v-r);
padding: 1.25rem;
color: var(--v-text);
box-shadow: var(--v-shadow-sm);
transition: box-shadow var(--v-t);
}
.my-widget:hover { box-shadow: var(--v-shadow); }
Changelog
A summary of releases and what changed in each version.
Complete rewrite. IntersectionObserver-based scroll spy replacing Bootstrap's broken offset implementation. Fully working dark/light themes, 30+ components, 4 auth page templates, cookie banner, FAB, sliders, counters, drag-and-drop file upload, professional docs, MIT licence.
Initial kit using Bootstrap 5, Font Awesome, and AOS. Multiple bugs identified: broken scroll spy, modal backdrop z-index, text not visible in light mode, anchor-under-navbar offset issue, cookie banner styling.