frontend-ui-dark-ts
microsoft/skills
Entwickeln Sie React-Anwendungen im Dark-Theme unter Verwendung von Tailwind CSS mit benutzerdefinierten Designs, Glassmorphism-Effekten und Framer-Motion-Animationen für Dashboards, Admin-Panels oder datenreiche Benutzeroberflächen.
...Alle erweiternFrontend-UI im dunklen Design (TypeScript)
Ein modernes React-UI-System im dunklen Design, das Tailwind CSS und Framer Motion nutzt. Entwickelt für Dashboards, Admin-Bereiche und datenintensive Anwendungen mit Glassmorphism-Effekten und geschmackvollen Animationen.
Stack
| Paket | Version | Zweck |
|---|---|---|
React |
^18.x | UI-Framework |
React-DOM |
^18.x | DOM-Rendering |
react-router-dom |
^6.x | Routing |
framer-motion |
^11.x | Animationen |
clsx |
^2.x | Klassenzusammenführung |
tailwindcss |
^3.x | Styling |
vite |
^5.x | Build-Tool |
TypeScript |
^5.x | Typsicherheit |
Schnellstart
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
Projektstruktur
public/
├── favicon.ico # Klassisches Favicon (32x32)
├── favicon.svg # Modernes SVG-Favicon
├── apple-touch-icon.png # iOS-Startbildschirm (180x180)
├── og-image.png # Bild für Social-Media-Sharing (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
Konfiguration
index.html
Der HTML-Einstiegspunkt mit mobilem Viewport, Favicons und Social-Media-Meta-Tags:
App-Name
public/site.webmanifest
PWA-Manifest für installierbare 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
/** @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,5 rem',
lg: '0,75 rem',
xl: '1 rem',
},
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)' },
},
},
// Mobilgeräte: Sicherheitsabstände für Geräte mit Aussparung
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)',
},
// Mobilgeräte: Mindestgrößen für Touch-Zielbereiche (44 px gemäß Apple-/Google-Richtlinien)
minHeight: {
'touch': '44px',
},
minWidth: {
'touch': '44px',
},
},
},
plugins: [],
};
postcss.config.js
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
src/styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Schriftarten */
@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;
}
/* Benutzerdefinierte CSS-Eigenschaften */
:root {
/* Markenfarben */
--color-brand: #8251EE;
--color-brand-hover: #9366F5;
--color-brand-light: #A37EF5;
--color-brand-subtle: rgba(130, 81, 238, 0.15);
/* Neutrale Hintergründe */
--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 %);
/* Textfarben */
--color-text-primary: #FFFFFF;
--color-text-secondary: #A1A1AA;
--color-text-muted: #71717A;
/* Rahmenfarben */
--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);
/* Statusfarben */
--color-success: #10B981;
--color-warning: #F59E0B;
--color-error: #EF4444;
--color-info: #3B82F6;
/* Abstände */
--spacing-xs: 0,25rem;
--spacing-sm: 0,5rem;
--spacing-md: 1rem;
--spacing-lg: 1,5rem;
--spacing-xl: 2rem;
--spacing-2xl: 3rem;
/* Eckenradius */
--radius-sm: 0,375rem;
--radius-md: 0,5rem;
--radius-lg: 0,75rem;
--radius-xl: 1rem;
/* Übergänge */
--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300 ms ease;
}
/* Basisstile */
html {
color-scheme: dark;
}
body {
@apply bg-neutral-bg1 text-text-primary font-sans antialiased;
min-height: 100vh;
}
/* Fokusstile */
*:focus-visible {
@apply outline-none ring-2 ring-brand ring-offset-2 ring-offset-neutral-bg1;
}
/* Gestaltung der Bildlaufleiste */
::-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;
}
/* Glas-Hilfsklassen */
@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;
}
}
/* Animations-Hilfsfunktionen */
@layer utilities {
.animate-in {
animation: fadeIn 0.3s ease-out, slideUp 0.3s ease-out;
}
}
src/main.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(
);
src/App.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 (
<Route path="/" element={ } />
<Route path="/settings" element={ } />
);
}
Animationsmuster
Framer-Bewegungsvarianten
// Einblenden beim Laden
export const fadeIn = {
initial: { opacity: 0 },
animate: { opacity: 1 },
exit: { opacity: 0 },
transition: { duration: 0.2 },
};
// Nach oben gleiten beim Laden
export const slideUp = {
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: 20 },
transition: { duration: 0.3, ease: 'easeOut' },
};
// Skalierung beim Hover (für Schaltflächen/Karten)
export const scaleOnHover = {
whileHover: { scale: 1,02 },
whileTap: { scale: 0,98 },
transition: { type: 'spring', stiffness: 400, damping: 17 },
};
// Unterelemente versetzt anzeigen
export 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' },
},
};
Wrapper für Seitenübergänge
import { motion } from 'framer-motion';
import { ReactNode } from 'react';
interface PageTransitionProps {
children: ReactNode;
}
export function PageTransition({ children }: PageTransitionProps) {
return (
{children}
);
}
Glas-Effekt-Muster
Glaskarte
Kartentitel
Hier kommt der Inhalt der Karte hin.
Glas-Panel (Seitenleiste)
Glas-Modal-Overlay
{/* Inhalt des Modals */}
Typografie
| Element | Klassen |
|---|---|
| Seitentitel | text-2xl font-semibold text-text-primary |
| Abschnittstitel | text-lg font-semibold text-text-primary |
| Kartentitel | text-base font-medium text-text-primary |
| Lauftext | text-sm text-text-secondary |
| Bildunterschrift | text-xs text-text-muted |
| Beschriftung | text-sm font-medium text-text-secondary |
Farbverwendung
| Anwendungsfall | Farbe | Klasse |
|---|---|---|
| Primäre Aktion | Marken-Lila | bg-brand text-white |
| Primäre Hover-Funktion | Marken-Hover | hover:bg-brand-hover |
| Seitenhintergrund | Neutraler Hintergrund 1 | bg-neutral-bg1 |
| Kartenhintergrund | Neutral bg2 | bg-neutral-bg2 |
| Erhöhte Oberfläche | Neutraler Hintergrund 3 | bg-neutral-bg3 |
| Eingabehintergrund | Neutral bg2 | bg-neutral-bg2 |
| Eingabefokus | Neutraler Hintergrund 3 | Fokus:bg-neutral-bg3 |
| Standard-Rahmen | Standard-Rahmen | Rahmen-Rahmen |
| Dezente Rahmen | Dezente Umrandung | Rand-Rand-dezent |
| Erfolg | Status: Erfolg | text-status-erfolg |
| Warnung | Status „Warnung“ | text-status-warning |
| Fehler | Status „Fehler“ | text-status-error |
Zugehörige Dateien
- Design-Token – Umfassendes Farbsystem, Abstände, Typografie-Skalen
- Komponenten – Schaltflächen, Karten, Eingabefelder, Dialoge, Registerkarten und mehr
- Muster – Seitenlayouts, Navigation, Listen, Formulare
---
name: frontend-ui-dark-ts
description: Build dark-themed React applications using Tailwind CSS with custom theming, glassmorphism effects, and Framer Motion animations for dashboards, admin panels, or data-rich interfaces.
license: MIT
---
# 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
```bash
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:
```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 mount
export const fadeIn = {
initial: { opacity: 0 },
animate: { opacity: 1 },
exit: { opacity: 0 },
transition: { duration: 0.2 },
};
// Slide up on mount
export 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 children
export 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
| 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](./references/design-tokens.md) — Complete color system, spacing, typography scales
- [Components](./references/components.md) — Button, Card, Input, Dialog, Tabs, and more
- [Patterns](./references/patterns.md) — Page layouts, navigation, lists, forms
Alle Dateien
0 Dateienfrontend-ui-dark-ts installieren
Laden Sie die Skill-Dateien herunter und entpacken Sie sie in Ihr Verzeichnis „.claude/skills/“.
ZIP herunterladenKlonen Sie das Repository und kopieren Sie die Skill-Dateien in Ihr Projekt.
git clone https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-typescript/skills/frontend-ui-dark-ts # Copy SKILL.md to your .claude/skills/ directory
Kopieren





Heim
