| name | frontend-ui-dark-ts |
| description | Build dark-themed React applications using Tailwind CSS with custom theming, glassmorphism effects, and Framer Motion animations. Use when creating dashboards, admin panels, or data-rich interfaces with a refined dark aesthetic. |
Frontend UI Dark Theme (TypeScript)
A modern dark-themed React UI system using Tailwind CSS and Framer Motion. Designed for dashboards, admin panels, and data-rich applications with glassmorphism effects and tasteful animations.
Stack
| Package | Version | Purpose |
|---|
react | ^18.x | UI framework |
react-dom | ^18.x | DOM rendering |
react-router-dom | ^6.x | Routing |
framer-motion | ^11.x | Animations |
clsx | ^2.x | Class merging |
tailwindcss | ^3.x | Styling |
vite | ^5.x | Build tool |
typescript | ^5.x | Type safety |
Quick Start
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install framer-motion clsx react-router-dom
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Project Structure
public/
├── favicon.ico # Classic favicon (32x32)
├── favicon.svg # Modern SVG favicon
├── apple-touch-icon.png # iOS home screen (180x180)
├── og-image.png # Social sharing image (1200x630)
└── site.webmanifest # PWA manifest
src/
├── assets/
│ └── fonts/
│ ├── Segoe UI.ttf
│ ├── Segoe UI Bold.ttf
│ ├── Segoe UI Italic.ttf
│ └── Segoe UI Bold Italic.ttf
├── components/
│ ├── ui/
│ │ ├── Button.tsx
│ │ ├── Card.tsx
│ │ ├── Input.tsx
│ │ ├── Badge.tsx
│ │ ├── Dialog.tsx
│ │ ├── Tabs.tsx
│ │ └── index.ts
│ └── layout/
│ ├── AppShell.tsx
│ ├── Sidebar.tsx
│ └── PageHeader.tsx
├── styles/
│ └── globals.css
├── App.tsx
└── main.tsx
Configuration
index.html
The HTML entry point with mobile viewport, favicons, and social meta tags:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
/>
<link
rel="icon"
href="/favicon.ico"
sizes="32x32"
/>
<link
rel="icon"
href="/favicon.svg"
type="image/svg+xml"
/>
<link
rel="apple-touch-icon"
href="/apple-touch-icon.png"
/>
<link
rel="manifest"
href="/site.webmanifest"
/>
<meta
name="theme-color"
content="#18181B"
/>
<meta
property="og:type"
=
/>
App Name
public/site.webmanifest
PWA manifest for installable web apps:
{
"name": "App Name",
"short_name": "App",
"icons": [
{"src": "/favicon.ico", "sizes": "32x32", "type": "image/x-icon"},
{"src": "/apple-touch-icon.png", "sizes": "180x180", "type": "image/png"}
],
"theme_color": "#18181B",
"background_color": "#18181B",
"display": "standalone"
}
tailwind.config.js
export default {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
fontFamily: {
sans: ['Segoe UI', 'system-ui', 'sans-serif'],
},
colors: {
brand: {
DEFAULT: '#8251EE',
hover: '#9366F5',
light: '#A37EF5',
subtle: 'rgba(130, 81, 238, 0.15)',
},
neutral: {
bg1: 'hsl(240, 6%, 10%)',
bg2: 'hsl(240, 5%, 12%)',
bg3: 'hsl(240, 5%, 14%)',
bg4: 'hsl(240, 4%, 18%)',
bg5: 'hsl(240, 4%, 22%)',
bg6: 'hsl(240, 4%, 26%)',
},
text: {
primary: '#FFFFFF',
secondary: '#A1A1AA',
muted: '#71717A',
},
border: {
subtle: 'hsla(0, 0%, 100%, 0.08)',
DEFAULT: 'hsla(0, 0%, 100%, 0.12)',
strong: 'hsla(0, 0%, 100%, 0.20)',
},
: {
: ,
: ,
: ,
: ,
},
: {
: ,
: ,
: ,
: ,
: ,
: ,
: ,
},
},
: {
: ,
: ,
: ,
},
: {
: ,
: ,
},
: {
: ,
},
: {
: ,
: ,
: ,
},
: {
: {
: {: },
: {: },
},
: {
: {: , : },
: {: , : },
},
: {
: {: , : },
: {: , : },
},
},
: {
: ,
: ,
: ,
: ,
},
: {
: ,
},
: {
: ,
},
},
},
: [],
}
postcss.config.js
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
src/styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
@font-face {
font-family: 'Segoe UI';
src: url('../assets/fonts/Segoe UI.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Segoe UI';
src: url('../assets/fonts/Segoe UI Bold.ttf') format('truetype');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Segoe UI';
src: url('../assets/fonts/Segoe UI Italic.ttf') format('truetype');
font-weight: 400;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Segoe UI';
src: url('../assets/fonts/Segoe UI Bold Italic.ttf') format('truetype');
font-weight: 700;
font-style: italic;
: swap;
}
{
: ;
: ;
: ;
: (, , , );
: (, , );
: (, , );
: (, , );
: (, , );
: (, , );
: (, , );
: ;
: ;
: ;
: (, , , );
: (, , , );
: (, , , );
: ;
: ;
: ;
: ;
: ;
: ;
: ;
: ;
: ;
: ;
: ;
: ;
: ;
: ;
: ease;
: ease;
: ease;
}
{
: dark;
}
{
bg-neutral-bg1 text-text-primary font-sans antialiased;
: ;
}
* {
outline-none ring- ring-brand ring-offset- ring-offset-neutral-bg1;
}
::-webkit-scrollbar {
: ;
: ;
}
::-webkit-scrollbar-track {
bg-neutral-bg2;
}
::-webkit-scrollbar-thumb {
bg-neutral-bg5 rounded-full;
}
::-webkit-scrollbar-thumb:hover {
bg-neutral-bg6;
}
components {
{
backdrop-blur-md bg-white/ border border-white/;
}
{
backdrop-blur-md bg-white/ border border-white/ rounded-xl;
}
{
backdrop-blur-lg bg-black/ border border-white/;
}
{
backdrop-blur-sm bg-black/;
}
{
backdrop-blur-sm bg-white/ border border-white/ :border-brand :bg-white/;
}
}
utilities {
{
:
fadeIn ease-out,
slideUp ease-out;
}
}
src/main.tsx
import {BrowserRouter} from 'react-router-dom'
import ReactDOM from 'react-dom/client'
import './styles/globals.css'
import React from 'react'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
)
src/App.tsx
import {AppShell} from './components/layout/AppShell'
import {Routes, Route} from 'react-router-dom'
import {AnimatePresence} from 'framer-motion'
import {Dashboard} from './pages/Dashboard'
import {Settings} from './pages/Settings'
export default function App() {
return (
<AppShell>
<AnimatePresence mode="wait">
<Routes>
<Route
path="/"
element={<Dashboard />}
/>
<Route
path="/settings"
element={<Settings />}
/>
</Routes>
</AnimatePresence>
</AppShell>
)
}
Animation Patterns
Framer Motion Variants
export const fadeIn = {
initial: {opacity: 0},
animate: {opacity: 1},
exit: {opacity: 0},
transition: {duration: 0.2},
}
export const slideUp = {
initial: {opacity: 0, y: 20},
animate: {opacity: 1, y: 0},
exit: {opacity: 0, y: 20},
transition: {duration: 0.3, ease: 'easeOut'},
}
export const scaleOnHover = {
whileHover: {scale: 1.02},
whileTap: {scale: 0.98},
transition: {type: 'spring', stiffness: 400, damping: 17},
}
export const staggerContainer = {
: {: },
: {
: ,
: {
: ,
: ,
},
},
}
staggerItem = {
: {: , : },
: {
: ,
: ,
: {: , : },
},
}
Page Transition Wrapper
import {motion} from 'framer-motion'
import {ReactNode} from 'react'
interface PageTransitionProps {
children: ReactNode
}
export function PageTransition({children}: PageTransitionProps) {
return (
<motion.div
initial={{opacity: 0, y: 20}}
animate={{opacity: 1, y: 0}}
exit={{opacity: 0, y: -20}}
transition={{duration: 0.3, ease: 'easeOut'}}
>
{children}
</motion.div>
)
}
Glass Effect Patterns
Glass Card
<div className="glass-card p-6">
<h2 className="text-lg font-semibold text-text-primary">Card Title</h2>
<p className="text-text-secondary mt-2">Card content goes here.</p>
</div>
Glass Panel (Sidebar)
<aside className="glass-panel w-64 h-screen p-4">
<nav className="space-y-2">{/* Navigation items */}</nav>
</aside>
Glass Modal Overlay
<motion.div
className="fixed inset-0 glass-overlay flex items-center justify-center z-50"
initial={{opacity: 0}}
animate={{opacity: 1}}
exit={{opacity: 0}}
>
<motion.div
className="glass-card p-6 max-w-md w-full mx-4"
initial={{scale: 0.95, opacity: 0}}
animate={{scale: 1, opacity: 1}}
exit={{scale: 0.95, opacity: 0}}
>
{/* Modal content */}
</motion.div>
</motion.div>
Typography
| Element | Classes |
|---|
| Page title | text-2xl font-semibold text-text-primary |
| Section title | text-lg font-semibold text-text-primary |
| Card title | text-base font-medium text-text-primary |
| Body text | text-sm text-text-secondary |
| Caption | text-xs text-text-muted |
| Label | text-sm font-medium text-text-secondary |
Color Usage
| Use Case | Color | Class |
|---|
| Primary action | Brand purple | bg-brand text-white |
| Primary hover | Brand hover | hover:bg-brand-hover |
| Page background | Neutral bg1 | bg-neutral-bg1 |
| Card background | Neutral bg2 | bg-neutral-bg2 |
| Elevated surface | Neutral bg3 | bg-neutral-bg3 |
| Input background | Neutral bg2 | bg-neutral-bg2 |
| Input focus | Neutral bg3 | focus:bg-neutral-bg3 |
| Border default | Border default | border-border |
| Border subtle | Border subtle | border-border-subtle |
| Success | Status success | text-status-success |
| Warning | Status warning | text-status-warning |
| Error | Status error | text-status-error |
Related Files
- Design Tokens — Complete color system, spacing, typography scales
- Components — Button, Card, Input, Dialog, Tabs, and more
- Patterns — Page layouts, navigation, lists, forms