@sajeevan-edrevel/icons
v0.5.7
Published
A production-ready, cross-framework design system and component library built with **Lit Web Components**, **TypeScript**, **Shadow DOM**, **CSS Custom Properties**, and **React Wrappers**.
Readme
Edrevel UI (@sajeevan-edrevel/ui) — Complete Architecture & Framework Usage Guide
A production-ready, cross-framework design system and component library built with Lit Web Components, TypeScript, Shadow DOM, CSS Custom Properties, and React Wrappers.
Designed for React, Next.js, Angular, Vue, Svelte, Micro Frontends, and Plain HTML/JS (Zero-Node) projects.
💡 Architecture Overview
Edrevel UI uses a single implementation source of truth based on W3C Standard Web Components:
EDREVEL DESIGN TOKENS
│
▼
@sajeevan-edrevel/tokens (CSS Variables)
│
▼
@sajeevan-edrevel/components (Lit Web Components + Shadow DOM)
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
Plain HTML (No Node) Angular / Vue / Svelte @sajeevan-edrevel/react (React Wrapper)
(Standalone JS) (Custom Elements) │
┌────────┴────────┐
▼ ▼
React Next.js- Design Tokens (
@sajeevan-edrevel/tokens): Primitive, semantic, and component CSS Custom Properties supporting Light Theme, Dark Theme (data-ed-theme="dark"), and custom theme overrides. - Icons (
@sajeevan-edrevel/icons): Accessible SVG icons. - Utilities (
@sajeevan-edrevel/utilities): Custom event dispatchers, focus management, and DOM helpers. - Web Components (
@sajeevan-edrevel/components): Lit Web Components (<ed-button>,<ed-kpi-card>,<ed-input>, etc.). Provides ES Modules and a standalone bundled JS file (dist/edrevel-components.bundle.js) for non-Node projects. - React Wrappers (
@sajeevan-edrevel/react): React component wrappers for React 18/19 and Next.js (<Button />,<KpiCard />,<Input />, etc.). - All-in-One (
@sajeevan-edrevel/ui): Single unified package importing tokens, components, and React wrappers.
🧩 Available Components
| Component | Web Component Tag | React Component | Description / Attributes |
|---|---|---|---|
| KPI Card | <ed-kpi-card> | <KpiCard /> | tag, stat, delta, delta-trend, sub, accent, accent-bg, compound, compare-grid, compare-cols |
| Button | <ed-button> | <Button /> | variant (primary/secondary/danger/ghost), size (sm/md/lg), loading, disabled, ed-click |
| Input | <ed-input> | <Input /> | label, placeholder, value, error, disabled, ed-input, ed-change |
| Select | <ed-select> | <Select /> | label, options, value, placeholder, disabled, ed-change |
| Checkbox | <ed-checkbox> | <Checkbox /> | label, checked, indeterminate, disabled, ed-change |
| Modal | <ed-modal> | <Modal /> | title, open, size, ed-close |
| Drawer | <ed-drawer> | <Drawer /> | title, open, position (left/right), ed-close |
| Table | <ed-table> | <Table /> | columns, data, sortable, selectable, ed-sort, ed-select-change |
| Pagination | <ed-pagination> | <Pagination /> | total, page-size, page, ed-page-change |
| Empty State | <ed-empty-state> | <EmptyState /> | heading, description, compact, slotted action buttons |
📦 Package Installation
Install the main package or modular sub-packages:
# All-in-One package
npm install @sajeevan-edrevel/ui
# Or individual modular packages
npm install @sajeevan-edrevel/components @sajeevan-edrevel/tokens
# For React / Next.js
npm install @sajeevan-edrevel/react @sajeevan-edrevel/tokens🌐 Usage across Frameworks
1. Plain HTML / JS (Zero-Node / Static CDN)
Link the design tokens stylesheet and standalone component bundle directly in your HTML <head>:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Plain HTML Demo</title>
<!-- Import Design Tokens CSS -->
<link rel="stylesheet" href="https://unpkg.com/@sajeevan-edrevel/tokens/dist/index.css" />
<!-- Option A: Load All Components (Full Bundle) -->
<script type="module" src="https://unpkg.com/@sajeevan-edrevel/components/dist/edrevel-components.bundle.js"></script>
<!-- Option B: Load Only Specific Individual Components -->
<!-- <script type="module" src="https://unpkg.com/@sajeevan-edrevel/components/dist/components/button.js"></script> -->
<!-- <script type="module" src="https://unpkg.com/@sajeevan-edrevel/components/dist/components/input.js"></script> -->
<!-- <script type="module" src="https://unpkg.com/@sajeevan-edrevel/components/dist/components/kpi-card.js"></script> -->
</head>
<body>
<!-- Standard KPI Card -->
<ed-kpi-card
tag="INSIGHT"
stat="123"
delta="+4%"
delta-trend="up"
sub="Active Learners"
></ed-kpi-card>
<!-- Button & Modal -->
<ed-button id="open-btn" variant="primary">Open Modal</ed-button>
<ed-modal id="demo-modal" title="Welcome to Edrevel UI">
<p>Component loaded in plain HTML without Node!</p>
</ed-modal>
<script>
document.querySelector('#open-btn').addEventListener('ed-click', () => {
document.querySelector('#demo-modal').setAttribute('open', '');
});
</script>
</body>
</html>2. React JS (Vite / Create React App / SPA)
Install packages:
npm install @sajeevan-edrevel/react @sajeevan-edrevel/tokensImport styles in main.tsx or App.tsx:
import '@sajeevan-edrevel/tokens/css';Use React component wrappers with type-safe props and ref support:
import React, { useState } from 'react';
import '@sajeevan-edrevel/tokens/css';
import { KpiCard, Button, Input, Select } from '@sajeevan-edrevel/react';
export default function Dashboard() {
const [name, setName] = useState('');
return (
<div style={{ padding: 24, display: 'flex', flexDirection: 'column', gap: 16 }}>
{/* KPI Card */}
<KpiCard
tag="INSIGHT"
stat="1,240"
delta="+12%"
deltaTrend="up"
sub="Active Students"
/>
{/* Input & Button */}
<Input
label="Student Name"
value={name}
onInput={(e: any) => setName(e.detail.value)}
/>
<Button variant="primary" onClick={() => alert(`Saved: ${name}`)}>
Save Student
</Button>
</div>
);
}3. Next.js (App Router & Pages Router)
In Next.js App Router (app/page.tsx), declare "use client" when using interactive client components:
"use client";
import '@sajeevan-edrevel/tokens/css';
import { KpiCard, Button, Input, Modal } from '@sajeevan-edrevel/react';
import { useState } from 'react';
export default function NextPage() {
const [open, setOpen] = useState(false);
return (
<main style={{ padding: 32 }}>
<h1>Next.js Dashboard</h1>
<KpiCard
compound
compareGrid
compareCols={2}
tag="PERFORMANCE"
stat="89.4"
delta="+3.2"
deltaTrend="up"
sub="Average Score"
/>
<Button variant="primary" onClick={() => setOpen(true)}>
Open Notification
</Button>
<Modal title="Next.js Integration" open={open} onClose={() => setOpen(false)}>
<p>Edrevel UI components run seamlessly in Next.js!</p>
</Modal>
</main>
);
}4. Angular Applications
Install components:
npm install @sajeevan-edrevel/components @sajeevan-edrevel/tokensImport Design Tokens CSS in
src/styles.css:@import "@sajeevan-edrevel/tokens/css";Register Custom Elements Schema in Angular component:
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import '@sajeevan-edrevel/components'; @Component({ selector: 'app-dashboard', standalone: true, templateUrl: './dashboard.component.html', schemas: [CUSTOM_ELEMENTS_SCHEMA] // 👈 Required for custom <ed-*> HTML tags }) export class DashboardComponent { onCardClick() { console.log('KPI card clicked'); } }Angular Template (
dashboard.component.html):<ed-kpi-card tag="INSIGHT" stat="94.2%" delta="+1.8%" delta-trend="up" sub="Mastery Rate" (ed-click)="onCardClick()" ></ed-kpi-card> <ed-button variant="primary">Click Me</ed-button>
5. Vue.js 3 Applications
Install components:
npm install @sajeevan-edrevel/components @sajeevan-edrevel/tokensConfigure
vite.config.tsto recognize<ed-*>custom tags:import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [ vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('ed-') } } }) ] });Usage in Vue SFC (
App.vue):<script setup> import '@sajeevan-edrevel/tokens/css'; import '@sajeevan-edrevel/components'; </script> <template> <div style="padding: 24px;"> <ed-kpi-card tag="ENROLLMENT" stat="13,043" sub="Enrolled Learners" ></ed-kpi-card> <ed-button variant="secondary">Vue Button</ed-button> </div> </template>
6. Svelte & SvelteKit
Install components:
npm install @sajeevan-edrevel/components @sajeevan-edrevel/tokensUse directly in Svelte components (+page.svelte):
<script>
import '@sajeevan-edrevel/tokens/css';
import '@sajeevan-edrevel/components';
</script>
<main style="padding: 24px;">
<ed-kpi-card
accent="#10b981"
accent-bg="#d1fae5"
tag="COMPETENCY"
stat="94.2%"
delta="+1.8%"
delta-trend="up"
sub="Mastery Rate"
></ed-kpi-card>
<ed-button variant="primary">Svelte Action</ed-button>
</main>🎨 Dark Theme Support
Edrevel UI supports dark theme scoping out of the box using data-ed-theme="dark":
<!-- Apply to <body> or any container -->
<div data-ed-theme="dark" style="background: #0f172a; padding: 24px; color: white;">
<ed-kpi-card
tag="INSIGHT"
stat="123"
sub="Active Learners"
></ed-kpi-card>
<ed-button variant="primary">Dark Primary</ed-button>
</div>🎨 Theme Color Customization & Multi-Tenant Setup
Edrevel UI allows runtime theme customization per application or per tenant using @sajeevan-edrevel/tokens/js/tenant-theme.
Base Theme Customization Source
The base design token colors are managed in tokens/color.json:
{
"brandPrimary": "#0e7ba0",
"brandPrimaryHover": "#1497b8",
"brandSecondary": "#d9952b",
"action": "#0e7ba0",
"actionHover": "#1497b8",
"surfaceApp": "#eef2f7",
"surfaceCard": "#ffffff",
"textStrong": "#0e2440",
"border": "#e2e8f0"
}Framework Usage Guide for loadTenantTheme
1. Plain HTML / JS (CDN or Local)
Import the theme loader script and pass either a base CDN directory or a direct S3 JSON URL:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Plain HTML Theme Demo</title>
<!-- 1. Design Tokens CSS -->
<link rel="stylesheet" href="https://unpkg.com/@sajeevan-edrevel/tokens@latest/dist/index.css" />
<!-- 2. Web Components JS Bundle -->
<script type="module" src="https://unpkg.com/@sajeevan-edrevel/components@latest/dist/edrevel-components.bundle.js"></script>
</head>
<body>
<ed-kpi-card tag="TENANT" stat="98.5%" sub="System Active"></ed-kpi-card>
<ed-button variant="primary">Tenant Action</ed-button>
<script type="module">
import { loadTenantTheme } from "https://unpkg.com/@sajeevan-edrevel/tokens@latest/dist/tenant-theme.js";
// Option A: Direct AWS S3 JSON URL
await loadTenantTheme({
baseUrl: "https://edrevel-design-tokens.s3.us-east-1.amazonaws.com/design-tokens/dev4.edrevel.com.json",
root: document.documentElement
});
// Option B: Multi-tenant directory (fetches /themes/<hostname>.json automatically)
/*
await loadTenantTheme({
baseUrl: "https://cdn.edrevel.com/design-tokens",
root: document.documentElement
});
*/
</script>
</body>
</html>2. React / Next.js Applications
Call loadTenantTheme() during application boot (e.g. inside useEffect in App.tsx or providers.tsx):
import React, { useEffect } from 'react';
import '@sajeevan-edrevel/tokens/css';
import { loadTenantTheme } from '@sajeevan-edrevel/tokens/js/tenant-theme';
import { Button, KpiCard } from '@sajeevan-edrevel/react';
export default function App() {
useEffect(() => {
// Loads theme dynamically based on current hostname or direct S3 JSON URL
loadTenantTheme({
baseUrl: 'https://edrevel-design-tokens.s3.us-east-1.amazonaws.com/design-tokens/dev4.edrevel.com.json',
root: document.documentElement,
});
}, []);
return (
<div style={{ padding: 24 }}>
<KpiCard tag="INSIGHT" stat="1,240" sub="Active Students" />
<Button variant="primary">Save Record</Button>
</div>
);
}3. Angular Applications
Call loadTenantTheme() inside APP_INITIALIZER or AppComponent.ngOnInit():
import { Component, OnInit, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { loadTenantTheme } from '@sajeevan-edrevel/tokens/js/tenant-theme';
import '@sajeevan-edrevel/components';
@Component({
selector: 'app-root',
standalone: true,
template: `
<div style="padding: 24px;">
<ed-kpi-card tag="ANGULAR" stat="100%" sub="Tenant Theme Ready"></ed-kpi-card>
<ed-button variant="primary">Angular Tenant Action</ed-button>
</div>
`,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppComponent implements OnInit {
async ngOnInit() {
await loadTenantTheme({
baseUrl: 'https://cdn.edrevel.com/design-tokens',
root: document.documentElement
});
}
}4. Instant Local Theme Override (applyTenantTheme)
If you want to test color overrides programmatically in any framework without an external HTTP fetch:
import { applyTenantTheme } from '@sajeevan-edrevel/tokens/js/tenant-theme';
// Programmatically apply custom theme colors
applyTenantTheme({
action: "#6B3FB5",
actionHover: "#8059C7",
surfaceCard: "#F5F2FB",
textStrong: "#24152F",
border: "#D8CDE5"
}, document.documentElement);5. Shadow DOM Embed Host Targeting
For embedded widgets or Shadow DOM hosts:
await loadTenantTheme({
baseUrl: 'https://cdn.edrevel.com/design-tokens',
root: document.querySelector('#embed-host')
});6. Failure Behavior & Security Rules
- Fail-Open Strategy: If a tenant JSON file is missing, invalid, returns 404, or hits a CORS error,
loadTenantTheme()safely defaults to the base CSS theme without crashing. - Allowlist Protected: Only approved semantic color keys (
brandPrimary,action,surfaceCard,textStrong,border, etc.) are mapped to CSS properties. Raw palette tokens (--ink,--ink-2,--ink-3) and arbitrary CSS injection are strictly blocked.
📄 License
MIT © Edrevel UI
