Premium Web Design System
Clean typography pairings, OkLCH color coordinates, frosted glassmorphism overlays, and macOS-style tactile components.
Inject Agent Skill
Inject this premium web design system skill into your workspace agents using the terminal command below.
npx skills add Saunakghosh10/premium-web-design Global CSS configuration
This stylesheet sets up the Inter/EB Garamond font pairs, defines the OkLCH color values, and registers keyframe micro-animations for interactive transitions.
/* Font Pairings */
@theme {
--font-sans: var(--font-inter);
--font-serif: var(--font-eb-garamond);
}
/* Base Color System (OkLCH) */
:root {
--background: oklch(0.985 0 0); /* Soft off-white */
--foreground: oklch(0.145 0 0); /* Soft dark gray */
--primary: oklch(0.205 0 0);
--border: oklch(0.922 0 0);
--accent: oklch(0.60 0.16 250); /* Azure accent approx */
}
.dark {
--background: oklch(0.145 0 0); /* Deep charcoal black */
--foreground: oklch(0.985 0 0); /* Crisp white */
--primary: oklch(0.922 0 0);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
}
/* Micro-Animations & Transitions */
/* 1. Staggered Sidebar Fade-In */
@keyframes sidebarFadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.sidebar-fade-in {
animation: sidebarFadeIn 0.3s ease-out forwards;
animation-delay: 0.1s;
opacity: 0;
}
.sidebar-fade-in-2 {
animation: sidebarFadeIn 0.3s ease-out forwards;
animation-delay: 0.2s;
opacity: 0;
}
/* 2. Shimmer / Skeleton loading animation */
@keyframes shimmer {
from { background-position: 0 0; }
to { background-position: -200% 0; }
}
.animate-shimmer {
animation: shimmer 8s linear infinite;
}
/* 3. Flash Edit State Animation */
@keyframes docxEditFlash {
0%, 20% {
background-color: rgba(59, 130, 246, 0.45);
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.45);
}
100% {
background-color: rgba(59, 130, 246, 0);
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0);
}
}
.docx-edit-flash {
animation: docxEditFlash 2s ease-out;
border-radius: 2px;
}
Tactile UI Component blueprints
Copyable React TSX blueprints crafted in compliance with premium layout depth and interaction rules.
CiteButton.tsx
Tactile quote citation copy-to-clipboard button with visual checkmark success states.
import React, { useState } from "react";
import { Check, Quote } from "lucide-react";
interface CiteButtonProps {
quoteText: string;
citationText: string;
}
export function CiteButton({ quoteText, citationText }: CiteButtonProps) {
const [isCopied, setIsCopied] = useState(false);
const handleClick = async (e: React.MouseEvent) => {
e.stopPropagation();
e.preventDefault();
try {
const compiledText = `"${quoteText.replace(/"/g, "'")}" ${citationText}`.trim();
await navigator.clipboard.writeText(compiledText);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000);
} catch (err) {
console.error("Failed to copy citation:", err);
}
};
return (
<button
onClick={handleClick}
className="transition-colors flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs font-medium bg-secondary text-secondary-foreground hover:bg-secondary/80 border border-border cursor-pointer"
>
{isCopied ? (
<>
<Check className="h-3 w-3 text-green-600 animate-in fade-in zoom-in-75 duration-150" />
<span className="text-green-600">Copied</span>
</>
) : (
<>
<Quote className="h-3 w-3" />
<span>Cite</span>
</>
)}
</button>
);
}
DropdownToggle.tsx
Smooth macOS-style dropdown toggle with rotating chevrons.
import React, { useState } from "react";
import { ChevronDown } from "lucide-react";
interface DropdownToggleProps {
label: string;
}
export function DropdownToggle({ label }: DropdownToggleProps) {
const [isOpen, setIsOpen] = useState(false);
return (
<button
type="button"
onClick={() => setIsOpen(!isOpen)}
className={`flex items-center gap-1.5 rounded-lg px-2 h-8 text-sm transition-colors cursor-pointer text-gray-400 hover:bg-gray-100 hover:text-gray-700 ${
isOpen ? "bg-gray-100 text-gray-700" : ""
}`}
>
<span>{label}</span>
<ChevronDown
className={`h-3 w-3 shrink-0 transition-transform duration-200 ${
isOpen ? "rotate-180" : ""
}`}
/>
</button>
);
}
GlassCapsule.tsx
Premium glass pill utilizing backdrop blur, multi-layered inner shadows, and specular reflection highlights.
import React from "react";
interface GlassCapsuleProps {
href: string;
children: React.ReactNode;
}
export function GlassCapsule({ href, children }: GlassCapsuleProps) {
return (
<div className="relative">
<a
href={href}
className="relative flex items-center rounded-full border pl-3 pr-4 h-13 transition-[background,border-color,box-shadow,backdrop-filter] duration-300 border-gray-300/40 backdrop-blur-lg backdrop-saturate-150 no-underline"
style={{
background: "linear-gradient(135deg, rgba(228, 230, 234, 0.48) 0%, rgba(214, 216, 222, 0.36) 100%)",
boxShadow: "rgba(255, 255, 255, 0.5) 0px 1px 0px 0px inset, rgba(0, 0, 0, 0.03) 0px -1px 0px 0px inset, rgba(17, 24, 39, 0.04) 0px 1px 2px, rgba(17, 24, 39, 0.08) 0px 12px 32px -8px"
}}
>
{/* Highlight Specular Reflection Overlay */}
<div
aria-hidden="true"
className="pointer-events-none absolute inset-x-4 top-0 h-1/2 rounded-t-full"
style={{
background: "linear-gradient(rgba(211, 211, 211, 0.6) 0%, rgba(255, 255, 255, 0) 100%)",
mixBlendMode: "overlay"
}}
/>
{children}
</a>
</div>
);
}
GlassActionBar.tsx
Glassmorphic rounded Action Bar/Toolbar container commonly used for page header actions.
import React from "react";
import { PlusIcon, TrashIcon } from "lucide-react";
export function GlassActionBar() {
return (
<div className="flex shrink-0 items-center gap-1 rounded-full border border-white/70 bg-white px-1 py-1 shadow-[0_8px_24px_rgba(15,23,42,0.06)] backdrop-blur-2xl">
{/* Icon-only action */}
<button aria-label="Add item" className="flex h-7 w-7 items-center justify-center rounded-full text-gray-500 hover:bg-gray-100 hover:text-gray-900 transition-colors cursor-pointer border-0">
<PlusIcon className="h-3.5 w-3.5" aria-hidden="true" />
</button>
{/* Text + icon action */}
<button className="flex h-7 items-center gap-1.5 px-3 rounded-full text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-900 transition-colors cursor-pointer border-0">
New
</button>
{/* Danger action */}
<button aria-label="Delete item" className="flex h-7 w-7 items-center justify-center rounded-full text-gray-500 hover:bg-gray-100 hover:text-red-600 transition-colors cursor-pointer border-0">
<TrashIcon className="h-3.5 w-3.5" aria-hidden="true" />
</button>
</div>
);
}
ConfirmPopup.tsx
Progressive state confirm dialog (fixed at the bottom) with active loader labels.
import React from "react";
interface ConfirmPopupProps {
status: "idle" | "loading" | "complete";
onConfirm: () => void;
onCancel: () => void;
}
export function ConfirmPopup({ status, onConfirm, onCancel }: ConfirmPopupProps) {
function progressiveLabel(label: string) {
return label.toLowerCase().endsWith("e")
? `${label.slice(0,-1)}ing…`
: `${label}ing…`;
}
function completedLabel(label: string) {
return label.toLowerCase().endsWith("e") ? `${label}d` : `${label}ed`;
}
return (
<div className="pointer-events-none fixed inset-x-0 bottom-5 z-[230] flex justify-center px-4">
<div className="pointer-events-auto w-[min(92vw,520px)] rounded-2xl border border-white/70 bg-white px-4 py-3 text-sm shadow-[0_4px_14px_rgba(15,23,42,0.08),inset_0_1px_0_rgba(255,255,255,0.92)] backdrop-blur-2xl">
<div className="text-sm font-medium text-gray-950 mb-1 text-left">Are you sure?</div>
<div className="text-xs text-gray-700 text-left">This action cannot be undone.</div>
<div className="mt-3 flex items-center justify-end gap-2">
<button className="px-3 py-1.5 text-xs font-medium text-gray-700 hover:text-gray-950 cursor-pointer border-0 bg-transparent" onClick={onCancel}>
Cancel
</button>
<button
disabled={status !== "idle"}
className="inline-flex h-7 items-center justify-center rounded-full px-3.5 text-xs font-medium text-white cursor-pointer
border border-red-700/35 bg-red-600/90
shadow-[0_3px_9px_rgba(127,29,29,0.16),inset_0_1px_0_rgba(255,255,255,0.22),inset_0_-4px_9px_rgba(127,29,29,0.18)]
hover:bg-red-600 active:scale-[0.98] disabled:opacity-40 transition-all"
onClick={onConfirm}
>
{status === "loading" ? progressiveLabel("Delete") : status === "complete" ? completedLabel("Delete") : "Delete"}
</button>
</div>
</div>
</div>
);
}
EmailPillInput.tsx
Interactive chip-based input field for validating and adding multiple emails.
import React, { useState } from "react";
import { X } from "lucide-react";
interface EmailPillInputProps {
emails: string[];
onChange: (emails: string[]) => void;
}
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
export function EmailPillInput({ emails, onChange }: EmailPillInputProps) {
const [input, setInput] = useState("");
const [error, setError] = useState<string | null>(null);
function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
if (e.key === "Enter" || e.key === ",") {
e.preventDefault();
commit();
} else if (e.key === "Backspace" && !input && emails.length > 0) {
onChange(emails.slice(0, -1));
}
}
function commit() {
const email = input.trim().toLowerCase();
if (!email || emails.includes(email)) {
setInput("");
return;
}
if (!EMAIL_RE.test(email)) {
setError("Enter a valid email.");
return;
}
onChange([...emails, email]);
setInput("");
setError(null);
}
return (
<div>
<div className={`flex flex-wrap gap-1.5 rounded-lg border bg-gray-50 px-3 py-2 min-h-[40px] ${error ? "border-red-300" : "border-gray-200 focus-within:border-gray-400"}`}>
{emails.map(email => (
<span key={email} className="inline-flex items-center gap-1 rounded-full bg-gray-200 px-2.5 py-0.5 text-xs text-gray-700">
{email}
<button
type="button"
aria-label={`Remove ${email}`}
className="border-0 bg-transparent p-0 cursor-pointer flex items-center justify-center text-gray-400 hover:text-gray-600"
onClick={() => onChange(emails.filter(e => e !== email))}
>
<X className="h-3 w-3" aria-hidden="true" />
</button>
</span>
))}
<input
type="email"
aria-label="Add email address"
value={input}
onChange={e => { setInput(e.target.value); setError(null); }}
onKeyDown={handleKeyDown}
onBlur={commit}
placeholder={emails.length === 0 ? "Add by email…" : ""}
className="flex-1 min-w-[160px] bg-transparent text-sm text-gray-700 placeholder:text-gray-400 outline-none border-0"
/>
</div>
{error && <p className="mt-1.5 text-xs text-red-500 text-left">{error}</p>}
</div>
);
}
Badge.tsx
Context-aware colored badges and semantic color calculators.
import React from "react";
// Sequential color palette for tag arrays
export const TAG_COLORS = [
"bg-blue-100 text-blue-800 dark:bg-blue-950/60 dark:text-blue-200", "bg-violet-100 text-violet-800 dark:bg-violet-950/60 dark:text-violet-200",
"bg-pink-100 text-pink-800 dark:bg-pink-950/60 dark:text-pink-200", "bg-orange-100 text-orange-800 dark:bg-orange-950/60 dark:text-orange-200",
"bg-teal-100 text-teal-800 dark:bg-teal-950/60 dark:text-teal-200", "bg-amber-100 text-amber-800 dark:bg-amber-950/60 dark:text-amber-200",
];
// Semantic yes/no
export function getBoolColor(val: string) {
if (val.toLowerCase() === "yes") return "bg-emerald-100 text-emerald-800 dark:bg-emerald-950/60 dark:text-emerald-200";
if (val.toLowerCase() === "no") return "bg-red-100 text-red-800 dark:bg-red-950/60 dark:text-red-200";
return "bg-gray-100 text-gray-800 dark:bg-zinc-800 dark:text-zinc-200";
}
interface BadgeProps {
children: React.ReactNode;
color: string;
}
// Badge component
export function Badge({ children, color }: BadgeProps) {
return (
<span className={`inline-block rounded-full px-2 py-0.5 text-xs font-medium leading-none ${color}`}>
{children}
</span>
);
}
GlassModal.tsx
Frosted glass-backed modal window with layered shadow elevations and variant controls.
import React from "react";
import { X } from "lucide-react";
interface GlassModalProps {
title: string;
isOpen: boolean;
onClose: () => void;
children: React.ReactNode;
}
export function GlassModal({ title, isOpen, onClose, children }: GlassModalProps) {
if (!isOpen) return null;
return (
<div
className="fixed inset-0 z-[200] flex items-center justify-center px-4 bg-white/30 backdrop-blur-[2px]"
onClick={onClose}
>
<div
className="w-full max-w-xl h-[600px] rounded-2xl flex flex-col border border-white/70 bg-white/94 shadow-[0_12px_36px_rgba(15,23,42,0.1)] backdrop-blur-2xl"
onClick={e => e.stopPropagation()}
>
{/* Header */}
<div className="flex items-start justify-between gap-3 px-4 py-4">
<h2 className="text-base font-medium text-gray-900 m-0">{title}</h2>
<button onClick={onClose} className="text-gray-400 hover:text-gray-600 border-0 bg-transparent p-0 cursor-pointer">
<X className="h-4 w-4" />
</button>
</div>
{/* Scrollable Body */}
<div className="flex min-h-0 flex-1 flex-col overflow-y-auto px-4">{children}</div>
{/* Footer */}
<div className="flex items-center justify-end gap-2 p-3 border-t border-white/60">
<button onClick={onClose} className="px-4 py-1.5 text-sm font-medium text-gray-600 hover:text-gray-950 border-0 bg-transparent cursor-pointer">
Cancel
</button>
<button
className="inline-flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium text-white rounded-full cursor-pointer
border border-blue-500/35 bg-blue-600/90
shadow-[0_3px_9px_rgba(37,99,235,0.16),inset_0_1px_0_rgba(255,255,255,0.28),inset_0_-4px_9px_rgba(29,78,216,0.2)]
hover:bg-blue-600 active:scale-[0.98] transition-all"
>
Save
</button>
</div>
</div>
</div>
);
}
DocCard.tsx
Document status attachment card supporting file uploading states (ready, processing, upload error).
import React from "react";
import { Loader2, AlertCircle, FileText, File, X } from "lucide-react";
interface DocCardProps {
filename: string;
fileType: "pdf" | "doc" | string;
sizeBytes: number;
pages: number;
status: "ready" | "processing" | "error";
onRemove: () => void;
}
export function DocCard({ filename, fileType, sizeBytes, pages, status, onRemove }: DocCardProps) {
const isError = status === "error";
const isProcessing = status === "processing";
function formatBytes(bytes: number) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
return (
<div className={`flex items-center gap-2.5 rounded-lg border px-3 py-2.5 text-sm transition-colors w-full
${isError ? "border-red-300 bg-red-50 text-red-950 dark:bg-red-950/40 dark:border-red-900" : "border-gray-200 bg-white hover:border-gray-300 text-gray-900 dark:bg-zinc-900 dark:border-zinc-800 dark:text-zinc-100"}`}
>
{isProcessing ? <Loader2 className="h-4 w-4 animate-spin text-gray-400 shrink-0" />
: isError ? <AlertCircle className="h-4 w-4 text-red-600 shrink-0" />
: fileType === "pdf" ? <FileText className="h-4 w-4 text-red-600 shrink-0" />
: <File className="h-4 w-4 text-blue-600 shrink-0" />}
<div className="min-w-0 flex-1 text-left">
<p className={`truncate font-semibold m-0 ${isError ? "text-red-950 dark:text-red-100" : "text-gray-900 dark:text-gray-100"}`}>{filename}</p>
<p className={`text-xs m-0 ${isError ? "text-red-900 dark:text-red-200 font-medium" : "text-gray-700 dark:text-gray-300"}`}>
{isProcessing ? "Processing…" : isError ? "Upload failed" : `${formatBytes(sizeBytes)} · ${pages}p`}
</p>
</div>
{!isProcessing && (
<button
type="button"
aria-label={`Remove document ${filename}`}
className="shrink-0 rounded p-0.5 text-gray-400 hover:bg-gray-100 border-0 bg-transparent cursor-pointer flex items-center justify-center"
onClick={onRemove}
>
<X className="h-3.5 w-3.5" aria-hidden="true" />
</button>
)}
</div>
);
}
Workspace Master Prompt
Feed this prompt to any developer agent or coding assistant at the start of a session to instruct it to configure and apply the Premium UI design specifications in a single pass.
# Premium Web Design System Prompt
You are tasked with building a premium, modern web user interface inspired by macOS-like tactile dynamics and clean typography. Configure the project to adhere to the following specifications:
## 1. Typography & Hierarchy
Configure the fonts with the following pairings:
- **Sans-Serif (UI Elements)**: `Inter`, system-default sans-serif. Use for buttons, inputs, labels, sidebars, headers, and dashboard widgets.
- **Serif (Content & Documents)**: `EB Garamond`, Georgia, system-default serif. Use for documents, legal sections, rich text views, and long-form articles.
## 2. Color System (OkLCH)
Avoid flat digital colors. Use natural light scaling and matching palettes:
- **Azure Accent**: `rgb(0, 136, 255)` (for link/highlight/accent actions)
- **Light Theme**:
- `--background`: `oklch(0.985 0 0)` (Soft off-white canvas)
- `--foreground`: `oklch(0.145 0 0)` (Soft dark charcoal text)
- `--primary`: `oklch(0.205 0 0)`
- `--border`: `oklch(0.922 0 0)`
- **Dark Theme**:
- `--background`: `oklch(0.145 0 0)` (Deep charcoal background)
- `--foreground`: `oklch(0.985 0 0)` (Crisp off-white text)
- `--primary`: `oklch(0.922 0 0)`
- `--border`: `oklch(1 0 0 / 10%)`
- `--input`: `oklch(1 0 0 / 15%)`
## 3. macOS Glassmorphism
When building modals, popups, or floaters, utilize the glassmorphism pattern:
- Base style: `border-white/70 bg-white/94 backdrop-blur-2xl`
- Specular highlights: Add an absolute top overlay with a linear gradient (`linear-gradient(rgba(255, 255, 255, 0.6) 0%, rgba(255, 255, 255, 0) 100%)`, blend mode `overlay`)
- Stacked shadows: Combine thin inset shadows with deep, soft ambient drop shadows to emulate macOS window depth:
`box-shadow: rgba(255, 255, 255, 0.5) 0px 1px 0px 0px inset, rgba(0, 0, 0, 0.03) 0px -1px 0px 0px inset, rgba(17, 24, 39, 0.04) 0px 1px 2px, rgba(17, 24, 39, 0.08) 0px 12px 32px -8px`
## 4. UI Tactile Dynamics
- **Confirmations**: When confirming actions, use progressive labeling (`Delete` -> `Deleting...` -> `Deleted`).
- **Citation buttons**: Include instant visual confirmation triggers with checkmarks for clipboard copies.
- **Chevrons**: Smoothly transition state rotations (e.g. `rotate-180` for active dropdown toggles).
## 5. Core Agent Skills & Real-Time Research (last30days & AXI Rules)
- Ensure the `AGENTS.md` ruleset (including the `last30days` search requirement and AXI principles) is copied/installed in the root of the workspace to configure instructions for the installed developer skills (Codebase Architecture, AXI / Browser automation, Language standards, and Motion & Design Engineering).
- Rely on the `last30days` search tool to gather the latest developer and community feedback on packages and frameworks instead of outdated public resources.
- Adhere to the 10 AXI (Agent eXperience Interface) design principles when building agent-facing CLI tools (Token-efficient TOON output, minimal default schemas, truncation, aggregates, clean idempotent errors, ambient context/skills, content-first no-args output, contextual disclosure suggestions, and concise `--help`).
- Install the AXI skill: `npx skills add kunchenguid/axi --skill axi`.
- Install the Emil Kowalski design engineering skill: `npx skills add emilkowalski/skill --all`.