Frontend Ui Dark Ts

作者 microsoft354361d83247MIT收錄於 2026年10月8日更新於 2026年10月8日

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.

AI 產生的概覽

提供深色主題的 React 與 Tailwind CSS 介面系統,包含毛玻璃效果與 Framer Motion 動畫。

功能
此技能提供使用 TypeScript、Tailwind CSS 與 Framer Motion 建置深色主題 React 應用程式的設定與程式碼模式。內容涵蓋 Tailwind 設定、含設計權杖與毛玻璃工具類別的全域 CSS、動畫變體,以及儀表板與管理後台的版面範例。另附設計權杖、元件與頁面模式的參考文件,以及字型與標誌素材。
適用情境
適合建立儀表板、管理後台或資料密集型介面,且需要精緻深色視覺風格的情境。適用於已採用 React、TypeScript 與 Tailwind CSS,並希望使用毛玻璃樣式與動效預設的專案。
執行需求
需要 React 18 與 TypeScript 專案,並安裝 Tailwind CSS、Framer Motion、clsx、react-router-dom 與 Vite;不隨附指令碼,僅提供說明與參考檔案。

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

PackageVersionPurpose
react^18.xUI framework
react-dom^18.xDOM rendering
react-router-dom^6.xRouting
framer-motion^11.xAnimations
clsx^2.xClass merging
tailwindcss^3.xStyling
vite^5.xBuild tool
typescript^5.xType safety

Quick Start

bash
npm create vite@latest my-app -- --template react-tscd my-appnpm install framer-motion clsx react-router-domnpm install -D tailwindcss postcss autoprefixernpx 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 manifestsrc/├── 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:

html
<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />        <!-- Favicons -->    <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" />        <!-- Theme color for mobile browser chrome -->    <meta name="theme-color" content="#18181B" />        <!-- Open Graph -->    <meta property="og:type" content="website" />    <meta property="og:title" content="App Name" />    <meta property="og:description" content="App description" />    <meta property="og:image" content="https://example.com/og-image.png" />    <meta property="og:url" content="https://example.com" />        <!-- Twitter Card -->    <meta name="twitter:card" content="summary_large_image" />    <meta name="twitter:title" content="App Name" />    <meta name="twitter:description" content="App description" />    <meta name="twitter:image" content="https://example.com/og-image.png" />        <title>App Name</title>  </head>  <body>    <div id="root"></div>    <script type="module" src="/src/main.tsx"></script>  </body></html>

public/site.webmanifest

PWA manifest for installable web apps:

json
{  "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

js
/** @type {import('tailwindcss').Config} */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)',        },        status: {          success: '#10B981',          warning: '#F59E0B',          error: '#EF4444',          info: '#3B82F6',        },        dataviz: {          purple: '#8251EE',          blue: '#3B82F6',          green: '#10B981',          yellow: '#F59E0B',          red: '#EF4444',          pink: '#EC4899',          cyan: '#06B6D4',        },      },      borderRadius: {        DEFAULT: '0.5rem',        lg: '0.75rem',        xl: '1rem',      },      boxShadow: {        glow: '0 0 20px rgba(130, 81, 238, 0.3)',        'glow-lg': '0 0 40px rgba(130, 81, 238, 0.4)',      },      backdropBlur: {        xs: '2px',      },      animation: {        'fade-in': 'fadeIn 0.3s ease-out',        'slide-up': 'slideUp 0.3s ease-out',        'slide-down': 'slideDown 0.3s ease-out',      },      keyframes: {        fadeIn: {          '0%': { opacity: '0' },          '100%': { opacity: '1' },        },        slideUp: {          '0%': { opacity: '0', transform: 'translateY(10px)' },          '100%': { opacity: '1', transform: 'translateY(0)' },        },        slideDown: {          '0%': { opacity: '0', transform: 'translateY(-10px)' },          '100%': { opacity: '1', transform: 'translateY(0)' },        },      },      // Mobile: safe area insets for notched devices      spacing: {        'safe-top': 'env(safe-area-inset-top)',        'safe-bottom': 'env(safe-area-inset-bottom)',        'safe-left': 'env(safe-area-inset-left)',        'safe-right': 'env(safe-area-inset-right)',      },      // Mobile: minimum touch target sizes (44px per Apple/Google guidelines)      minHeight: {        'touch': '44px',      },      minWidth: {        'touch': '44px',      },    },  },  plugins: [],};

postcss.config.js

js
export default {  plugins: {    tailwindcss: {},    autoprefixer: {},  },};

src/styles/globals.css

css
@tailwind base;@tailwind components;@tailwind utilities;
/* Font faces */@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;  font-display: swap;}
/* CSS Custom Properties */:root {  /* Brand colors */  --color-brand: #8251EE;  --color-brand-hover: #9366F5;  --color-brand-light: #A37EF5;  --color-brand-subtle: rgba(130, 81, 238, 0.15);
  /* Neutral backgrounds */  --color-bg-1: hsl(240, 6%, 10%);  --color-bg-2: hsl(240, 5%, 12%);  --color-bg-3: hsl(240, 5%, 14%);  --color-bg-4: hsl(240, 4%, 18%);  --color-bg-5: hsl(240, 4%, 22%);  --color-bg-6: hsl(240, 4%, 26%);
  /* Text colors */  --color-text-primary: #FFFFFF;  --color-text-secondary: #A1A1AA;  --color-text-muted: #71717A;
  /* Border colors */  --color-border-subtle: hsla(0, 0%, 100%, 0.08);  --color-border-default: hsla(0, 0%, 100%, 0.12);  --color-border-strong: hsla(0, 0%, 100%, 0.20);
  /* Status colors */  --color-success: #10B981;  --color-warning: #F59E0B;  --color-error: #EF4444;  --color-info: #3B82F6;
  /* Spacing */  --spacing-xs: 0.25rem;  --spacing-sm: 0.5rem;  --spacing-md: 1rem;  --spacing-lg: 1.5rem;  --spacing-xl: 2rem;  --spacing-2xl: 3rem;
  /* Border radius */  --radius-sm: 0.375rem;  --radius-md: 0.5rem;  --radius-lg: 0.75rem;  --radius-xl: 1rem;
  /* Transitions */  --transition-fast: 150ms ease;  --transition-normal: 200ms ease;  --transition-slow: 300ms ease;}
/* Base styles */html {  color-scheme: dark;}
body {  @apply bg-neutral-bg1 text-text-primary font-sans antialiased;  min-height: 100vh;}
/* Focus styles */*:focus-visible {  @apply outline-none ring-2 ring-brand ring-offset-2 ring-offset-neutral-bg1;}
/* Scrollbar styling */::-webkit-scrollbar {  width: 8px;  height: 8px;}
::-webkit-scrollbar-track {  @apply bg-neutral-bg2;}
::-webkit-scrollbar-thumb {  @apply bg-neutral-bg5 rounded-full;}
::-webkit-scrollbar-thumb:hover {  @apply bg-neutral-bg6;}
/* Glass utility classes */@layer components {  .glass {    @apply backdrop-blur-md bg-white/5 border border-white/10;  }
  .glass-card {    @apply backdrop-blur-md bg-white/5 border border-white/10 rounded-xl;  }
  .glass-panel {    @apply backdrop-blur-lg bg-black/40 border border-white/5;  }
  .glass-overlay {    @apply backdrop-blur-sm bg-black/60;  }
  .glass-input {    @apply backdrop-blur-sm bg-white/5 border border-white/10 focus:border-brand focus:bg-white/10;  }}
/* Animation utilities */@layer utilities {  .animate-in {    animation: fadeIn 0.3s ease-out, slideUp 0.3s ease-out;  }}

src/main.tsx

tsx
import React from 'react';import ReactDOM from 'react-dom/client';import { BrowserRouter } from 'react-router-dom';import App from './App';import './styles/globals.css';
ReactDOM.createRoot(document.getElementById('root')!).render(  <React.StrictMode>    <BrowserRouter>      <App />    </BrowserRouter>  </React.StrictMode>);

src/App.tsx

tsx
import { Routes, Route } from 'react-router-dom';import { AnimatePresence } from 'framer-motion';import { AppShell } from './components/layout/AppShell';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

tsx
// Fade in on mountexport const fadeIn = {  initial: { opacity: 0 },  animate: { opacity: 1 },  exit: { opacity: 0 },  transition: { duration: 0.2 },};
// Slide up on mountexport const slideUp = {  initial: { opacity: 0, y: 20 },  animate: { opacity: 1, y: 0 },  exit: { opacity: 0, y: 20 },  transition: { duration: 0.3, ease: 'easeOut' },};
// Scale on hover (for buttons/cards)export const scaleOnHover = {  whileHover: { scale: 1.02 },  whileTap: { scale: 0.98 },  transition: { type: 'spring', stiffness: 400, damping: 17 },};
// Stagger childrenexport const staggerContainer = {  hidden: { opacity: 0 },  visible: {    opacity: 1,    transition: {      staggerChildren: 0.05,      delayChildren: 0.1,    },  },};
export const staggerItem = {  hidden: { opacity: 0, y: 10 },  visible: {    opacity: 1,    y: 0,    transition: { duration: 0.2, ease: 'easeOut' },  },};

Page Transition Wrapper

tsx
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

tsx
<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)

tsx
<aside className="glass-panel w-64 h-screen p-4">  <nav className="space-y-2">    {/* Navigation items */}  </nav></aside>

Glass Modal Overlay

tsx
<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

ElementClasses
Page titletext-2xl font-semibold text-text-primary
Section titletext-lg font-semibold text-text-primary
Card titletext-base font-medium text-text-primary
Body texttext-sm text-text-secondary
Captiontext-xs text-text-muted
Labeltext-sm font-medium text-text-secondary

Color Usage

Use CaseColorClass
Primary actionBrand purplebg-brand text-white
Primary hoverBrand hoverhover:bg-brand-hover
Page backgroundNeutral bg1bg-neutral-bg1
Card backgroundNeutral bg2bg-neutral-bg2
Elevated surfaceNeutral bg3bg-neutral-bg3
Input backgroundNeutral bg2bg-neutral-bg2
Input focusNeutral bg3focus:bg-neutral-bg3
Border defaultBorder defaultborder-border
Border subtleBorder subtleborder-border-subtle
SuccessStatus successtext-status-success
WarningStatus warningtext-status-warning
ErrorStatus errortext-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

來源與署名

來源:microsoft/skills位於.github/plugins/azure-sdk-typescript/skills/frontend-ui-dark-ts提交354361d

授權條款: MIT

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架