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.
Add this skill
npx mdskills install sickn33/frontend-ui-dark-tsComprehensive dark theme UI system with detailed configuration and reusable patterns
1---2name: frontend-ui-dark-ts3description: 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.4---56# Frontend UI Dark Theme (TypeScript)78A 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.910## Stack1112| Package | Version | Purpose |13|---------|---------|---------|14| `react` | ^18.x | UI framework |15| `react-dom` | ^18.x | DOM rendering |16| `react-router-dom` | ^6.x | Routing |17| `framer-motion` | ^11.x | Animations |18| `clsx` | ^2.x | Class merging |19| `tailwindcss` | ^3.x | Styling |20| `vite` | ^5.x | Build tool |21| `typescript` | ^5.x | Type safety |2223## Quick Start2425```bash26npm create vite@latest my-app -- --template react-ts27cd my-app28npm install framer-motion clsx react-router-dom29npm install -D tailwindcss postcss autoprefixer30npx tailwindcss init -p31```3233## Project Structure3435```36public/37├── favicon.ico # Classic favicon (32x32)38├── favicon.svg # Modern SVG favicon39├── apple-touch-icon.png # iOS home screen (180x180)40├── og-image.png # Social sharing image (1200x630)41└── site.webmanifest # PWA manifest42src/43├── assets/44│ └── fonts/45│ ├── Segoe UI.ttf46│ ├── Segoe UI Bold.ttf47│ ├── Segoe UI Italic.ttf48│ └── Segoe UI Bold Italic.ttf49├── components/50│ ├── ui/51│ │ ├── Button.tsx52│ │ ├── Card.tsx53│ │ ├── Input.tsx54│ │ ├── Badge.tsx55│ │ ├── Dialog.tsx56│ │ ├── Tabs.tsx57│ │ └── index.ts58│ └── layout/59│ ├── AppShell.tsx60│ ├── Sidebar.tsx61│ └── PageHeader.tsx62├── styles/63│ └── globals.css64├── App.tsx65└── main.tsx66```6768## Configuration6970### index.html7172The HTML entry point with mobile viewport, favicons, and social meta tags:7374```html75<!DOCTYPE html>76<html lang="en">77 <head>78 <meta charset="UTF-8" />79 <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />8081 <!-- Favicons -->82 <link rel="icon" href="/favicon.ico" sizes="32x32" />83 <link rel="icon" href="/favicon.svg" type="image/svg+xml" />84 <link rel="apple-touch-icon" href="/apple-touch-icon.png" />85 <link rel="manifest" href="/site.webmanifest" />8687 <!-- Theme color for mobile browser chrome -->88 <meta name="theme-color" content="#18181B" />8990 <!-- Open Graph -->91 <meta property="og:type" content="website" />92 <meta property="og:title" content="App Name" />93 <meta property="og:description" content="App description" />94 <meta property="og:image" content="https://example.com/og-image.png" />95 <meta property="og:url" content="https://example.com" />9697 <!-- Twitter Card -->98 <meta name="twitter:card" content="summary_large_image" />99 <meta name="twitter:title" content="App Name" />100 <meta name="twitter:description" content="App description" />101 <meta name="twitter:image" content="https://example.com/og-image.png" />102103 <title>App Name</title>104 </head>105 <body>106 <div id="root"></div>107 <script type="module" src="/src/main.tsx"></script>108 </body>109</html>110```111112### public/site.webmanifest113114PWA manifest for installable web apps:115116```json117{118 "name": "App Name",119 "short_name": "App",120 "icons": [121 { "src": "/favicon.ico", "sizes": "32x32", "type": "image/x-icon" },122 { "src": "/apple-touch-icon.png", "sizes": "180x180", "type": "image/png" }123 ],124 "theme_color": "#18181B",125 "background_color": "#18181B",126 "display": "standalone"127}128```129130### tailwind.config.js131132```js133/** @type {import('tailwindcss').Config} */134export default {135 content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],136 theme: {137 extend: {138 fontFamily: {139 sans: ['Segoe UI', 'system-ui', 'sans-serif'],140 },141 colors: {142 brand: {143 DEFAULT: '#8251EE',144 hover: '#9366F5',145 light: '#A37EF5',146 subtle: 'rgba(130, 81, 238, 0.15)',147 },148 neutral: {149 bg1: 'hsl(240, 6%, 10%)',150 bg2: 'hsl(240, 5%, 12%)',151 bg3: 'hsl(240, 5%, 14%)',152 bg4: 'hsl(240, 4%, 18%)',153 bg5: 'hsl(240, 4%, 22%)',154 bg6: 'hsl(240, 4%, 26%)',155 },156 text: {157 primary: '#FFFFFF',158 secondary: '#A1A1AA',159 muted: '#71717A',160 },161 border: {162 subtle: 'hsla(0, 0%, 100%, 0.08)',163 DEFAULT: 'hsla(0, 0%, 100%, 0.12)',164 strong: 'hsla(0, 0%, 100%, 0.20)',165 },166 status: {167 success: '#10B981',168 warning: '#F59E0B',169 error: '#EF4444',170 info: '#3B82F6',171 },172 dataviz: {173 purple: '#8251EE',174 blue: '#3B82F6',175 green: '#10B981',176 yellow: '#F59E0B',177 red: '#EF4444',178 pink: '#EC4899',179 cyan: '#06B6D4',180 },181 },182 borderRadius: {183 DEFAULT: '0.5rem',184 lg: '0.75rem',185 xl: '1rem',186 },187 boxShadow: {188 glow: '0 0 20px rgba(130, 81, 238, 0.3)',189 'glow-lg': '0 0 40px rgba(130, 81, 238, 0.4)',190 },191 backdropBlur: {192 xs: '2px',193 },194 animation: {195 'fade-in': 'fadeIn 0.3s ease-out',196 'slide-up': 'slideUp 0.3s ease-out',197 'slide-down': 'slideDown 0.3s ease-out',198 },199 keyframes: {200 fadeIn: {201 '0%': { opacity: '0' },202 '100%': { opacity: '1' },203 },204 slideUp: {205 '0%': { opacity: '0', transform: 'translateY(10px)' },206 '100%': { opacity: '1', transform: 'translateY(0)' },207 },208 slideDown: {209 '0%': { opacity: '0', transform: 'translateY(-10px)' },210 '100%': { opacity: '1', transform: 'translateY(0)' },211 },212 },213 // Mobile: safe area insets for notched devices214 spacing: {215 'safe-top': 'env(safe-area-inset-top)',216 'safe-bottom': 'env(safe-area-inset-bottom)',217 'safe-left': 'env(safe-area-inset-left)',218 'safe-right': 'env(safe-area-inset-right)',219 },220 // Mobile: minimum touch target sizes (44px per Apple/Google guidelines)221 minHeight: {222 'touch': '44px',223 },224 minWidth: {225 'touch': '44px',226 },227 },228 },229 plugins: [],230};231```232233### postcss.config.js234235```js236export default {237 plugins: {238 tailwindcss: {},239 autoprefixer: {},240 },241};242```243244### src/styles/globals.css245246```css247@tailwind base;248@tailwind components;249@tailwind utilities;250251/* Font faces */252@font-face {253 font-family: 'Segoe UI';254 src: url('../assets/fonts/Segoe UI.ttf') format('truetype');255 font-weight: 400;256 font-style: normal;257 font-display: swap;258}259260@font-face {261 font-family: 'Segoe UI';262 src: url('../assets/fonts/Segoe UI Bold.ttf') format('truetype');263 font-weight: 700;264 font-style: normal;265 font-display: swap;266}267268@font-face {269 font-family: 'Segoe UI';270 src: url('../assets/fonts/Segoe UI Italic.ttf') format('truetype');271 font-weight: 400;272 font-style: italic;273 font-display: swap;274}275276@font-face {277 font-family: 'Segoe UI';278 src: url('../assets/fonts/Segoe UI Bold Italic.ttf') format('truetype');279 font-weight: 700;280 font-style: italic;281 font-display: swap;282}283284/* CSS Custom Properties */285:root {286 /* Brand colors */287 --color-brand: #8251EE;288 --color-brand-hover: #9366F5;289 --color-brand-light: #A37EF5;290 --color-brand-subtle: rgba(130, 81, 238, 0.15);291292 /* Neutral backgrounds */293 --color-bg-1: hsl(240, 6%, 10%);294 --color-bg-2: hsl(240, 5%, 12%);295 --color-bg-3: hsl(240, 5%, 14%);296 --color-bg-4: hsl(240, 4%, 18%);297 --color-bg-5: hsl(240, 4%, 22%);298 --color-bg-6: hsl(240, 4%, 26%);299300 /* Text colors */301 --color-text-primary: #FFFFFF;302 --color-text-secondary: #A1A1AA;303 --color-text-muted: #71717A;304305 /* Border colors */306 --color-border-subtle: hsla(0, 0%, 100%, 0.08);307 --color-border-default: hsla(0, 0%, 100%, 0.12);308 --color-border-strong: hsla(0, 0%, 100%, 0.20);309310 /* Status colors */311 --color-success: #10B981;312 --color-warning: #F59E0B;313 --color-error: #EF4444;314 --color-info: #3B82F6;315316 /* Spacing */317 --spacing-xs: 0.25rem;318 --spacing-sm: 0.5rem;319 --spacing-md: 1rem;320 --spacing-lg: 1.5rem;321 --spacing-xl: 2rem;322 --spacing-2xl: 3rem;323324 /* Border radius */325 --radius-sm: 0.375rem;326 --radius-md: 0.5rem;327 --radius-lg: 0.75rem;328 --radius-xl: 1rem;329330 /* Transitions */331 --transition-fast: 150ms ease;332 --transition-normal: 200ms ease;333 --transition-slow: 300ms ease;334}335336/* Base styles */337html {338 color-scheme: dark;339}340341body {342 @apply bg-neutral-bg1 text-text-primary font-sans antialiased;343 min-height: 100vh;344}345346/* Focus styles */347*:focus-visible {348 @apply outline-none ring-2 ring-brand ring-offset-2 ring-offset-neutral-bg1;349}350351/* Scrollbar styling */352::-webkit-scrollbar {353 width: 8px;354 height: 8px;355}356357::-webkit-scrollbar-track {358 @apply bg-neutral-bg2;359}360361::-webkit-scrollbar-thumb {362 @apply bg-neutral-bg5 rounded-full;363}364365::-webkit-scrollbar-thumb:hover {366 @apply bg-neutral-bg6;367}368369/* Glass utility classes */370@layer components {371 .glass {372 @apply backdrop-blur-md bg-white/5 border border-white/10;373 }374375 .glass-card {376 @apply backdrop-blur-md bg-white/5 border border-white/10 rounded-xl;377 }378379 .glass-panel {380 @apply backdrop-blur-lg bg-black/40 border border-white/5;381 }382383 .glass-overlay {384 @apply backdrop-blur-sm bg-black/60;385 }386387 .glass-input {388 @apply backdrop-blur-sm bg-white/5 border border-white/10 focus:border-brand focus:bg-white/10;389 }390}391392/* Animation utilities */393@layer utilities {394 .animate-in {395 animation: fadeIn 0.3s ease-out, slideUp 0.3s ease-out;396 }397}398```399400### src/main.tsx401402```tsx403import React from 'react';404import ReactDOM from 'react-dom/client';405import { BrowserRouter } from 'react-router-dom';406import App from './App';407import './styles/globals.css';408409ReactDOM.createRoot(document.getElementById('root')!).render(410 <React.StrictMode>411 <BrowserRouter>412 <App />413 </BrowserRouter>414 </React.StrictMode>415);416```417418### src/App.tsx419420```tsx421import { Routes, Route } from 'react-router-dom';422import { AnimatePresence } from 'framer-motion';423import { AppShell } from './components/layout/AppShell';424import { Dashboard } from './pages/Dashboard';425import { Settings } from './pages/Settings';426427export default function App() {428 return (429 <AppShell>430 <AnimatePresence mode="wait">431 <Routes>432 <Route path="/" element={<Dashboard />} />433 <Route path="/settings" element={<Settings />} />434 </Routes>435 </AnimatePresence>436 </AppShell>437 );438}439```440441## Animation Patterns442443### Framer Motion Variants444445```tsx446// Fade in on mount447export const fadeIn = {448 initial: { opacity: 0 },449 animate: { opacity: 1 },450 exit: { opacity: 0 },451 transition: { duration: 0.2 },452};453454// Slide up on mount455export const slideUp = {456 initial: { opacity: 0, y: 20 },457 animate: { opacity: 1, y: 0 },458 exit: { opacity: 0, y: 20 },459 transition: { duration: 0.3, ease: 'easeOut' },460};461462// Scale on hover (for buttons/cards)463export const scaleOnHover = {464 whileHover: { scale: 1.02 },465 whileTap: { scale: 0.98 },466 transition: { type: 'spring', stiffness: 400, damping: 17 },467};468469// Stagger children470export const staggerContainer = {471 hidden: { opacity: 0 },472 visible: {473 opacity: 1,474 transition: {475 staggerChildren: 0.05,476 delayChildren: 0.1,477 },478 },479};480481export const staggerItem = {482 hidden: { opacity: 0, y: 10 },483 visible: {484 opacity: 1,485 y: 0,486 transition: { duration: 0.2, ease: 'easeOut' },487 },488};489```490491### Page Transition Wrapper492493```tsx494import { motion } from 'framer-motion';495import { ReactNode } from 'react';496497interface PageTransitionProps {498 children: ReactNode;499}500501export function PageTransition({ children }: PageTransitionProps) {502 return (503 <motion.div504 initial={{ opacity: 0, y: 20 }}505 animate={{ opacity: 1, y: 0 }}506 exit={{ opacity: 0, y: -20 }}507 transition={{ duration: 0.3, ease: 'easeOut' }}508 >509 {children}510 </motion.div>511 );512}513```514515## Glass Effect Patterns516517### Glass Card518519```tsx520<div className="glass-card p-6">521 <h2 className="text-lg font-semibold text-text-primary">Card Title</h2>522 <p className="text-text-secondary mt-2">Card content goes here.</p>523</div>524```525526### Glass Panel (Sidebar)527528```tsx529<aside className="glass-panel w-64 h-screen p-4">530 <nav className="space-y-2">531 {/* Navigation items */}532 </nav>533</aside>534```535536### Glass Modal Overlay537538```tsx539<motion.div540 className="fixed inset-0 glass-overlay flex items-center justify-center z-50"541 initial={{ opacity: 0 }}542 animate={{ opacity: 1 }}543 exit={{ opacity: 0 }}544>545 <motion.div546 className="glass-card p-6 max-w-md w-full mx-4"547 initial={{ scale: 0.95, opacity: 0 }}548 animate={{ scale: 1, opacity: 1 }}549 exit={{ scale: 0.95, opacity: 0 }}550 >551 {/* Modal content */}552 </motion.div>553</motion.div>554```555556## Typography557558| Element | Classes |559|---------|---------|560| Page title | `text-2xl font-semibold text-text-primary` |561| Section title | `text-lg font-semibold text-text-primary` |562| Card title | `text-base font-medium text-text-primary` |563| Body text | `text-sm text-text-secondary` |564| Caption | `text-xs text-text-muted` |565| Label | `text-sm font-medium text-text-secondary` |566567## Color Usage568569| Use Case | Color | Class |570|----------|-------|-------|571| Primary action | Brand purple | `bg-brand text-white` |572| Primary hover | Brand hover | `hover:bg-brand-hover` |573| Page background | Neutral bg1 | `bg-neutral-bg1` |574| Card background | Neutral bg2 | `bg-neutral-bg2` |575| Elevated surface | Neutral bg3 | `bg-neutral-bg3` |576| Input background | Neutral bg2 | `bg-neutral-bg2` |577| Input focus | Neutral bg3 | `focus:bg-neutral-bg3` |578| Border default | Border default | `border-border` |579| Border subtle | Border subtle | `border-border-subtle` |580| Success | Status success | `text-status-success` |581| Warning | Status warning | `text-status-warning` |582| Error | Status error | `text-status-error` |583584## Related Files585586- [Design Tokens](./references/design-tokens.md) — Complete color system, spacing, typography scales587- [Components](./references/components.md) — Button, Card, Input, Dialog, Tabs, and more588- [Patterns](./references/patterns.md) — Page layouts, navigation, lists, forms589
Full transparency — inspect the skill content before installing.