frontend-ui-dark-ts

โดย microsoft

สร้างแอปพลิเคชัน React แบบธีมมืดโดยใช้ Tailwind CSS พร้อมการปรับแต่งธีม เอฟเฟกต์แก้ว และแอนิเมชัน Framer Motion ใช้เมื่อสร้างแดชบอร์ด…

npx skills add https://github.com/microsoft/agent-skills --skill frontend-ui-dark-ts

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

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" />
    
    <!-- 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:

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

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

src/styles/globals.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

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

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

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

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

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

Skills เพิ่มเติมจาก microsoft

oss-growth
microsoft
บุคลิกภาพนักเติบโตโอเอสเอส
official
microsoft-foundry
microsoft
ปรับใช้ ประเมิน และจัดการ Foundry agents แบบครบวงจร: สร้าง Docker, push ไปยัง ACR, สร้าง hosted/prompt agent, เริ่ม container, batch eval, continuous eval, เวิร์กโฟลว์ prompt optimizer, agent.yaml, จัดชุดข้อมูลจาก traces ใช้สำหรับ: ปรับใช้ agent ไปยัง Foundry, hosted agent, สร้าง agent, เรียกใช้ agent, ประเมิน agent, รัน batch eval, continuous eval, การตรวจสอบต่อเนื่อง, สถานะ continuous eval, ปรับแต่ง prompt, ปรับปรุง prompt, prompt optimizer, ปรับแต่งคำแนะนำ agent, ปรับปรุง agent...
officialdevelopmentdevops
azure-ai
microsoft
ใช้สำหรับ Azure AI: ค้นหา, คำพูด, OpenAI, การประมวลผลเอกสารอัจฉริยะ ช่วยในการค้นหา, การค้นหาแบบเวกเตอร์/ไฮบริด, การแปลงคำพูดเป็นข้อความ, การแปลงข้อความเป็นคำพูด, การถอดเสียง, OCR เมื่อ: การค้นหา AI, การค้นหาคำถาม, การค้นหาแบบเวกเตอร์, การค้นหาแบบไฮบริด, การค้นหาเชิงความหมาย, การแปลงคำพูดเป็นข้อความ, การแปลงข้อความเป็นคำพูด, การถอดเสียง, OCR, แปลงข้อความเป็นคำพูด
officialdevelopmentapi
azure-deploy
microsoft
ดำเนินการปรับใช้ Azure สำหรับแอปพลิเคชันที่เตรียมไว้แล้วซึ่งมีไฟล์ .azure/deployment-plan.md และไฟล์โครงสร้างพื้นฐานอยู่แล้ว ห้ามใช้ทักษะนี้เมื่อผู้ใช้ขอสร้างแอปพลิเคชันใหม่ ให้ใช้ azure-prepare แทน ทักษะนี้รันคำสั่ง azd up, azd deploy, terraform apply และ az deployment พร้อมการกู้คืนข้อผิดพลาดในตัว ต้องมี .azure/deployment-plan.md จาก azure-prepare และสถานะที่ตรวจสอบแล้วจาก azure-validate เมื่อ: "run azd up", "run azd deploy", "execute deployment",...
officialdevopsaws
azure-storage
microsoft
บริการ Azure Storage รวมถึง Blob Storage, File Shares, Queue Storage, Table Storage และ Data Lake ตอบคำถามเกี่ยวกับระดับการเข้าถึงพื้นที่จัดเก็บ (hot, cool, cold, archive) ว่าเมื่อใดควรใช้แต่ละระดับ และการเปรียบเทียบระดับ ให้บริการจัดเก็บวัตถุ, แชร์ไฟล์ SMB, การส่งข้อความแบบอะซิงโครนัส, NoSQL key-value และการวิเคราะห์ข้อมูลขนาดใหญ่ รวมถึงการจัดการวงจรชีวิต ใช้สำหรับ: blob storage, file shares, queue storage, table storage, data lake, อัปโหลดไฟล์, ดาวน์โหลด blobs, storage accounts, access tiers,...
officialdevelopmentdatabase
azure-diagnostics
microsoft
ดีบักปัญหาการผลิตบน Azure โดยใช้ AppLens, Azure Monitor, สถานะทรัพยากร และการจัดลำดับความสำคัญอย่างปลอดภัย เมื่อ: ดีบักปัญหาการผลิต, แก้ไขปัญหาแอปบริการ, แอปบริการ CPU สูง, แอปบริการล้มเหลวในการปรับใช้, แก้ไขปัญหาคอนเทนเนอร์แอป, แก้ไขปัญหาฟังก์ชัน, แก้ไขปัญหา AKS, kubectl ไม่สามารถเชื่อมต่อ, kube-system/CoreDNS ล้มเหลว, pod รอ, crashloop, node ไม่พร้อม, การอัปเกรดล้มเหลว, วิเคราะห์บันทึก, KQL, ข้อมูลเชิงลึก, การดึงอิมเมจล้มเหลว, ปัญหาการเริ่มต้นเย็น, การตรวจสอบสถานะล้มเหลว,...
officialdevopsdevelopment
azure-prepare
microsoft
เตรียมแอปพลิเคชัน Azure สำหรับการปรับใช้ (infra Bicep/Terraform, azure.yaml, Dockerfiles) ใช้สำหรับสร้าง/ปรับปรุงให้ทันสมัย หรือสร้าง+ปรับใช้ ไม่ใช่สำหรับการย้ายข้ามคลาวด์ (ใช้ azure-cloud-migrate) ห้ามใช้สำหรับ: แอป copilot-sdk (ใช้ azure-hosted-copilot-sdk) เมื่อ: "สร้างแอป", "สร้างเว็บแอป", "สร้าง API", "สร้าง HTTP API แบบไร้เซิร์ฟเวอร์", "สร้างฟรอนต์เอนด์", "สร้างแบ็กเอนด์", "สร้างบริการ", "ปรับปรุงแอปพลิเคชันให้ทันสมัย", "อัปเดตแอปพลิเคชัน", "เพิ่มการรับรองความถูกต้อง", "เพิ่มการแคช", "โฮสต์บน Azure", "สร้างและ...
officialdevelopmentdevops
azure-validate
microsoft
การตรวจสอบความพร้อมก่อนการปรับใช้สำหรับ Azure ตรวจสอบเชิงลึกเกี่ยวกับการกำหนดค่า โครงสร้างพื้นฐาน (Bicep หรือ Terraform) การกำหนดบทบาท RBAC สิทธิ์ของ managed identity และข้อกำหนดเบื้องต้นก่อนการปรับใช้ เมื่อ: ตรวจสอบแอปของฉัน ตรวจสอบความพร้อมในการปรับใช้ เรียกใช้การตรวจสอบก่อนดำเนินการ ยืนยันการกำหนดค่า ตรวจสอบว่าพร้อมปรับใช้หรือไม่ ตรวจสอบ azure.yaml ตรวจสอบ Bicep ทดสอบก่อนปรับใช้ แก้ไขข้อผิดพลาดในการปรับใช้ ตรวจสอบ Azure Functions ตรวจสอบ function app ตรวจสอบ serverless...
officialdevopstesting