پرتوپرتو

تم‌بندی

نحوه سفارشی‌سازی و ایجاد تم‌های سفارشی در دیزاین سیستم پرتو

سیستم تم‌بندی پرتو به شما امکان می‌دهد به راحتی بین تم‌های مختلف جابجا شوید و حتی تم‌های سفارشی خود را ایجاد کنید. سیستم ما بر اساس CSS Variables و Tailwind CSS ساخته شده است که انعطاف‌پذیری کامل را فراهم می‌کند.

تغییر تم

برای تست تم‌های مختلف، از سوئیچ زیر استفاده کنید:

تم‌های پیش‌فرض

دیزاین سیستم پرتو با 2 تم پیش‌فرض عرضه می‌شود:

تم روشن (Light)

تم پیش‌فرض برای محیط‌های روشن با پالت رنگی سفید و خاکستری روشن.

/* globals.css — تم روشن همیشه در :root تعریف می‌شود */
:root {
  --background-default: 0deg 0% 100%;
  --foreground-default: 222.2deg 47.4% 11.2%;
  --foreground-light: 215.4deg 16.3% 46.9%;
  --foreground-lighter: 216deg 12.2% 83.9%;
  --foreground-muted: 220deg 8.9% 46.1%;
  /* ... */
}

بهترین برای:

  • وب‌سایت‌های عمومی
  • اپلیکیشن‌های اداری
  • محیط‌های با نور زیاد

تم تاریک (Dark)

تم مدرن برای محیط‌های کم‌نور با پالت رنگی تیره و خاکستری تاریک.

/* theme-dark.css */
.dark {
  --background-default: 222.2deg 84% 4.9%;
  --foreground-default: 210deg 40% 98%;
  --foreground-light: 217.9deg 10.6% 64.9%;
  --foreground-lighter: 215deg 20.2% 65.1%;
  --foreground-muted: 215.4deg 16.3% 46.9%;
  /* ... */
}

بهترین برای:

  • کار طولانی‌مدت
  • محیط‌های کم‌نور
  • کاربران حساس به نور

نحوه پیاده‌سازی تم‌بندی

استفاده پایه

دیزاین سیستم پرتو با next-themes کار می‌کند. تم روشن پیش‌فرض است (:root) و نیازی به class ندارد. برای تغییر تم، ThemeProvider را راه‌اندازی کنید:

// app/layout.tsx
import { ThemeProvider } from 'next-themes'

export default function RootLayout({ children }) {
  return (
    <html lang="fa" dir="rtl" suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="light" themes={['light', 'dark']}>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}

تغییر دینامیک تم

برای تغییر دینامیک تم، از hook ارائه‌شده توسط next-themes استفاده کنید:

'use client'

import { useTheme } from 'next-themes'
import { Button } from '@parto-system-design/ui'

export function ThemeSwitcher() {
  const { theme, setTheme } = useTheme()

  return (
    <div className="flex gap-2">
      <Button variant={theme === 'light' ? 'default' : 'outline'} onClick={() => setTheme('light')}>
        روشن
      </Button>
      <Button variant={theme === 'dark' ? 'default' : 'outline'} onClick={() => setTheme('dark')}>
        تاریک
      </Button>
    </div>
  )
}

تشخیص تم سیستم

برای تشخیص خودکار تم بر اساس تنظیمات سیستم:

'use client'

import { useEffect, useState } from 'react'

export function useSystemTheme() {
  const [theme, setTheme] = useState<'light' | 'dark'>('light')

  useEffect(() => {
    // تشخیص تم سیستم
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
    setTheme(mediaQuery.matches ? 'dark' : 'light')

    // گوش دادن به تغییرات
    const handler = (e: MediaQueryListEvent) => {
      setTheme(e.matches ? 'dark' : 'light')
    }

    mediaQuery.addEventListener('change', handler)
    return () => mediaQuery.removeEventListener('change', handler)
  }, [])

  return theme
}

ساخت تم سفارشی

ایجاد فایل تم

برای ایجاد تم سفارشی، یک فایل CSS جدید بسازید:

/* theme-custom.css */
.custom-theme {
  /* رنگ‌های پس‌زمینه */
  --background-default: 280deg 40% 10%;
  --background-200: 280deg 40% 12%;
  --background-alternative-default: 260deg 40% 15%;
  --background-alternative-200: 260deg 40% 18%;

  /* سطوح */
  --background-surface-75: 280deg 35% 15%;
  --background-surface-100: 280deg 35% 18%;
  --background-surface-200: 280deg 35% 22%;
  --background-surface-300: 280deg 35% 26%;
  --background-surface-400: 280deg 35% 30%;

  /* رنگ‌های متن */
  --foreground-default: 280deg 20% 95%;
  --foreground-light: 280deg 15% 75%;
  --foreground-lighter: 280deg 10% 60%;
  --foreground-muted: 280deg 8% 50%;
  --foreground-contrast: 0deg 0% 100%;

  /* حاشیه‌ها */
  --border-default: 280deg 30% 25%;
  --border-strong: 280deg 30% 35%;
  --border-stronger: 280deg 30% 45%;
  --border-overlay: 280deg 25% 30%;
  --border-control: 280deg 25% 28%;

  /* رنگ برند */
  --brand-default: 280deg 80% 60%;
  --brand-200: 280deg 80% 70%;
  --brand-300: 280deg 80% 65%;
  --brand-400: 280deg 80% 55%;
  --brand-500: 280deg 80% 50%;
  --brand-600: 280deg 80% 45%;

  /* هشدار */
  --warning-default: 45deg 95% 60%;
  --warning-200: 45deg 95% 75%;
  --warning-300: 45deg 95% 70%;
  --warning-400: 45deg 95% 55%;
  --warning-500: 45deg 95% 50%;
  --warning-600: 45deg 95% 45%;

  /* خطر */
  --destructive-default: 0deg 85% 60%;
  --destructive-200: 0deg 85% 75%;
  --destructive-300: 0deg 85% 70%;
  --destructive-400: 0deg 85% 55%;
  --destructive-500: 0deg 85% 50%;
  --destructive-600: 0deg 85% 45%;
}

وارد کردن تم سفارشی

فایل تم را در globals.css وارد کنید:

/* app/globals.css */
@import '@parto-system-design/ui/styles.css';
@import './theme-custom.css'; /* تم سفارشی شما */

استفاده از تم سفارشی

<html lang="fa" dir="rtl" className="custom-theme">
  <body>{children}</body>
</html>

متغیرهای رنگی اصلی

تمام تم‌ها باید این متغیرهای اصلی را تعریف کنند:

پس‌زمینه‌ها

--background-default
--background-200
--background-alternative-default
--background-alternative-200
--background-selection
--background-control
--background-surface-75
--background-surface-100
--background-surface-200
--background-surface-300
--background-surface-400
--background-overlay-default
--background-overlay-hover
--background-button-default
--background-dialog-default
--background-sidebar
--background-canvas

متن (Foreground)

--foreground-default
--foreground-light
--foreground-lighter
--foreground-muted
--foreground-contrast

حاشیه‌ها

--border-default
--border-strong
--border-stronger
--border-overlay
--border-control
--border-alternative
--border-secondary
--border-button-default
--border-button-hover

رنگ‌های سمانتیک

--brand-default
--brand-200
--brand-300
--brand-400
--brand-500
--brand-600

--warning-default
--warning-200
--warning-300
--warning-400
--warning-500
--warning-600

--destructive-default
--destructive-200
--destructive-300
--destructive-400
--destructive-500
--destructive-600

نکات مهم در طراحی تم

کنتراست مناسب

همیشه اطمینان حاصل کنید که رنگ‌های متن و پس‌زمینه کنتراست کافی دارند (WCAG AA حداقل 4.5:1):

// استفاده از ابزار محاسبه کنتراست
function calculateContrast(color1: string, color2: string): number {
  // محاسبه contrast ratio
  // باید حداقل 4.5:1 باشد
}

سازگاری با Brand Colors

رنگ‌های برند باید در تمام تم‌ها قابل تشخیص باشند:

/* تم روشن */
:root {
  --brand-default: 153deg 60% 53%;
}

/* تم تاریک */
.dark {
  --brand-default: 155deg 78% 40%;
}

تست در شرایط واقعی

قبل از نهایی کردن تم:

  • تست در دستگاه‌های مختلف
  • تست با محتوای واقعی
  • تست accessibility
  • تست در نورهای مختلف

مستندسازی تم

برای هر تم سفارشی، موارد زیر را مستند کنید:

# تم سفارشی من

**هدف:** برای داشبورد مدیریتی
**پالت اصلی:** بنفش و آبی
**بهترین برای:** کار شبانه

## رنگ‌های اصلی

- Primary: #7C3AED (بنفش)
- Secondary: #3B82F6 (آبی)
- Background: #1A1B2E (تیره)

## نکات استفاده

- بهتر است در محیط‌های کم‌نور استفاده شود
- برای متن‌های طولانی مناسب نیست

مثال کامل: راه‌اندازی با next-themes

// app/layout.tsx
import { ThemeProvider } from 'next-themes'
import '@parto-system-design/ui/styles.css'

export default function RootLayout({ children }) {
  return (
    <html lang="fa" dir="rtl" suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="light" themes={['light', 'dark']} enableSystem={false}>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}
// components/theme-switcher.tsx
'use client'

import { useTheme } from 'next-themes'
import { Button } from '@parto-system-design/ui'

export function ThemeSwitcher() {
  const { theme, setTheme } = useTheme()

  return (
    <div className="flex gap-2">
      <Button variant={theme === 'light' ? 'default' : 'outline'} size="small" onClick={() => setTheme('light')}>
        روشن
      </Button>
      <Button variant={theme === 'dark' ? 'default' : 'outline'} size="small" onClick={() => setTheme('dark')}>
        تاریک
      </Button>
    </div>
  )
}

Troubleshooting

مشکل: تم تغییر نمی‌کند

مطمئن شوید که ThemeProvider از next-themes به درستی راه‌اندازی شده و attribute="class" دارد. کلاس .dark باید روی <html> ظاهر شود.

مشکل: Flash of wrong theme در بارگذاری

مطمئن شوید که suppressHydrationWarning روی تگ <html> وجود دارد — این ویژگی برای جلوگیری از خطای hydration هنگام تغییر تم قبل از رندر سمت کلاینت لازم است.

مشکل: تم کلاسیک تاریک کار نمی‌کند

بررسی کنید که darkMode: ['class', '[data-theme*="dark"]'] در tailwind.config.ts تنظیم شده باشد.

منابع مرتبط