feat: integrate poyraz-ui and reactive-switcher for theme management
- Added poyraz-ui preset CSS import to globals.css for styling. - Created theme-switcher.md documentation for reactive-switcher usage. - Added usage-guide.md for comprehensive Poyraz UI instructions. - Updated package.json to include reactive-switcher as a dependency. - Modified pnpm-lock.yaml to reflect the addition of reactive-switcher. - Established themes.ts to export Poyraz UI themes for use in the application.
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
@import "poyraz-ui/preset.css";
|
||||||
|
|||||||
@@ -0,0 +1,934 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="./public/logo/Logo.png" alt="Reactive Switcher Logo" width="180" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1 align="center">Reactive Switcher</h1>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<strong>Type-safe, modular, and instant theme switching for React & Tailwind CSS v4</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://www.npmjs.com/package/reactive-switcher">
|
||||||
|
<img src="https://badge.fury.io/js/reactive-switcher.svg" alt="npm version" />
|
||||||
|
</a>
|
||||||
|
<a href="https://opensource.org/licenses/MIT">
|
||||||
|
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/poyrazavsever/reactive-switcher">
|
||||||
|
<img src="https://img.shields.io/badge/TypeScript-100%25-blue.svg" alt="TypeScript" />
|
||||||
|
</a>
|
||||||
|
<a href="https://bundlephobia.com/package/reactive-switcher">
|
||||||
|
<img src="https://img.shields.io/bundlephobia/minzip/reactive-switcher" alt="Bundle Size" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="#-features">Features</a> •
|
||||||
|
<a href="#-installation">Installation</a> •
|
||||||
|
<a href="#-quick-start">Quick Start</a> •
|
||||||
|
<a href="#-api-reference">API</a> •
|
||||||
|
<a href="#-demo">Demo</a> •
|
||||||
|
<a href="#türkçe">Türkçe</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Features
|
||||||
|
|
||||||
|
- 🚀 **Zero Runtime Overhead** - Uses CSS variables for instant theme switching
|
||||||
|
- 📦 **TypeScript First** - Full type safety with autocomplete support
|
||||||
|
- 🎨 **Tailwind CSS v4 Ready** - Seamless integration with the new engine
|
||||||
|
- 💾 **Persistent Themes** - LocalStorage support out of the box
|
||||||
|
- 🌙 **System Theme Detection** - Respects `prefers-color-scheme`
|
||||||
|
- ⚡ **No Flash** - SSR compatible with hydration flash prevention
|
||||||
|
- 🎯 **Scoped Theming** - Apply different themes to different parts of your app
|
||||||
|
- 🧩 **Ready-to-use Components** - `ThemeSwitcher` and `ThemeToggle` included
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install reactive-switcher
|
||||||
|
# or
|
||||||
|
pnpm add reactive-switcher
|
||||||
|
# or
|
||||||
|
yarn add reactive-switcher
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### 1. Define Your Themes
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// themes.ts
|
||||||
|
import { ThemesConfig } from "reactive-switcher";
|
||||||
|
|
||||||
|
export const themes: ThemesConfig = {
|
||||||
|
light: {
|
||||||
|
name: "light",
|
||||||
|
type: "light",
|
||||||
|
colors: {
|
||||||
|
background: "#ffffff",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "#3b82f6",
|
||||||
|
foreground: "#ffffff",
|
||||||
|
50: "#eff6ff",
|
||||||
|
500: "#3b82f6",
|
||||||
|
600: "#2563eb",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "#64748b",
|
||||||
|
foreground: "#ffffff",
|
||||||
|
},
|
||||||
|
surface: {
|
||||||
|
50: "#f8fafc",
|
||||||
|
100: "#f1f5f9",
|
||||||
|
200: "#e2e8f0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
name: "dark",
|
||||||
|
type: "dark",
|
||||||
|
colors: {
|
||||||
|
background: "#020617",
|
||||||
|
foreground: "#f8fafc",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "#60a5fa",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "#94a3b8",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
},
|
||||||
|
surface: {
|
||||||
|
50: "#0f172a",
|
||||||
|
100: "#1e293b",
|
||||||
|
200: "#334155",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Wrap Your App with ThemeProvider
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/layout.tsx (Next.js)
|
||||||
|
import { ThemeProvider } from "reactive-switcher";
|
||||||
|
import { themes } from "./themes";
|
||||||
|
|
||||||
|
export default function RootLayout({ children }) {
|
||||||
|
return (
|
||||||
|
<html lang="en" suppressHydrationWarning>
|
||||||
|
<body>
|
||||||
|
<ThemeProvider themes={themes} defaultTheme="light">
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Use the Theme
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
"use client";
|
||||||
|
import { useTheme, ThemeToggle } from "reactive-switcher";
|
||||||
|
|
||||||
|
export function Header() {
|
||||||
|
const { theme, setTheme, toggleTheme } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className="bg-background text-foreground">
|
||||||
|
<p>Current Theme: {theme}</p>
|
||||||
|
|
||||||
|
{/* Ready-to-use toggle */}
|
||||||
|
<ThemeToggle />
|
||||||
|
|
||||||
|
{/* Or manual control */}
|
||||||
|
<button onClick={() => setTheme("dark")}>Dark</button>
|
||||||
|
<button onClick={toggleTheme}>Toggle</button>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Configure Tailwind CSS v4
|
||||||
|
|
||||||
|
```css
|
||||||
|
/* globals.css */
|
||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--color-background: var(--color-background);
|
||||||
|
--color-foreground: var(--color-foreground);
|
||||||
|
--color-primary: var(--color-primary-DEFAULT);
|
||||||
|
--color-primary-foreground: var(--color-primary-foreground);
|
||||||
|
--color-secondary: var(--color-secondary-DEFAULT);
|
||||||
|
--color-surface-50: var(--color-surface-50);
|
||||||
|
--color-surface-100: var(--color-surface-100);
|
||||||
|
--color-surface-200: var(--color-surface-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
body {
|
||||||
|
background-color: var(--color-background);
|
||||||
|
color: var(--color-foreground);
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 API Reference
|
||||||
|
|
||||||
|
### ThemeProvider Props
|
||||||
|
|
||||||
|
| Prop | Type | Default | Description |
|
||||||
|
| --------------- | ------------------------- | ---------------------------- | ------------------------------- |
|
||||||
|
| `themes` | `ThemesConfig` | **required** | Theme configurations object |
|
||||||
|
| `defaultTheme` | `string` | `"light"` | Initial theme name |
|
||||||
|
| `enableStorage` | `boolean` | `true` | Persist theme to localStorage |
|
||||||
|
| `storageKey` | `string` | `"reactive-switcher-theme"` | localStorage key |
|
||||||
|
| `enableSystem` | `boolean` | `true` | Detect system color scheme |
|
||||||
|
| `selector` | `string` | `":root"` | CSS selector for scoped theming |
|
||||||
|
| `styleId` | `string` | `"reactive-switcher-styles"` | Style tag ID |
|
||||||
|
| `attribute` | `"class" \| "data-theme"` | `"class"` | HTML attribute for theme |
|
||||||
|
|
||||||
|
### useTheme() Hook
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const {
|
||||||
|
theme, // Current theme name (string)
|
||||||
|
resolvedTheme, // Actual theme (resolves "system")
|
||||||
|
setTheme, // (name: string) => void
|
||||||
|
toggleTheme, // () => void - Cycle through themes
|
||||||
|
themes, // Available theme names (string[])
|
||||||
|
systemTheme, // System preference ("light" | "dark")
|
||||||
|
} = useTheme();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Built-in Components
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { ThemeSwitcher, ThemeToggle } from "reactive-switcher";
|
||||||
|
|
||||||
|
// Dropdown/Button switcher with multiple variants
|
||||||
|
<ThemeSwitcher variant="buttons" /> // Side-by-side buttons
|
||||||
|
<ThemeSwitcher variant="dropdown" /> // Dropdown menu
|
||||||
|
<ThemeSwitcher variant="toggle" /> // Toggle button
|
||||||
|
|
||||||
|
// Simple two-theme toggle
|
||||||
|
<ThemeToggle />
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Advanced Usage
|
||||||
|
|
||||||
|
### Scoped Theming
|
||||||
|
|
||||||
|
Apply different themes to different parts of your app:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { ThemeProvider } from "reactive-switcher";
|
||||||
|
import { themes } from "./themes";
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<ThemeProvider themes={themes} defaultTheme="light">
|
||||||
|
<main>Main content with light theme</main>
|
||||||
|
|
||||||
|
{/* Scoped dark theme section */}
|
||||||
|
<ThemeProvider
|
||||||
|
themes={themes}
|
||||||
|
defaultTheme="dark"
|
||||||
|
selector="#preview-panel"
|
||||||
|
enableStorage={false}
|
||||||
|
>
|
||||||
|
<div id="preview-panel">This section has its own theme!</div>
|
||||||
|
</ThemeProvider>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Color Palettes
|
||||||
|
|
||||||
|
Define nested color tokens:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const themes: ThemesConfig = {
|
||||||
|
ocean: {
|
||||||
|
name: "ocean",
|
||||||
|
type: "dark",
|
||||||
|
colors: {
|
||||||
|
background: "#042f2e",
|
||||||
|
foreground: "#ccfbf1",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "#2dd4bf",
|
||||||
|
foreground: "#042f2e",
|
||||||
|
50: "#042f2e",
|
||||||
|
100: "#115e59",
|
||||||
|
200: "#0f766e",
|
||||||
|
// ... more shades
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: "#facc15",
|
||||||
|
foreground: "#422006",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌐 Demo
|
||||||
|
|
||||||
|
Check out the live demo: [reactive-switcher.vercel.app](https://reactive-switcher.vercel.app)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
||||||
|
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
||||||
|
4. Push to the branch (`git push origin feature/amazing-feature`)
|
||||||
|
5. Open a Pull Request
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
MIT © [Poyraz Avsever](https://github.com/poyrazavsever)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
# Türkçe
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<strong>React ve Tailwind CSS v4 için tip güvenli, modüler ve anlık tema değiştirici</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Özellikler
|
||||||
|
|
||||||
|
- 🚀 **Sıfır Çalışma Zamanı Yükü** - Anlık tema değişimi için CSS değişkenleri kullanır
|
||||||
|
- 📦 **TypeScript Öncelikli** - Otomatik tamamlama desteği ile tam tip güvenliği
|
||||||
|
- 🎨 **Tailwind CSS v4 Uyumlu** - Yeni motor ile kusursuz entegrasyon
|
||||||
|
- 💾 **Kalıcı Temalar** - Kutudan çıktığı gibi localStorage desteği
|
||||||
|
- 🌙 **Sistem Teması Algılama** - `prefers-color-scheme` tercihine uyar
|
||||||
|
- ⚡ **Yanıp Sönme Yok** - SSR uyumlu, hidrasyon flash önleme
|
||||||
|
- 🎯 **Kapsamlı Tema** - Uygulamanızın farklı bölümlerine farklı temalar uygulayın
|
||||||
|
- 🧩 **Kullanıma Hazır Bileşenler** - `ThemeSwitcher` ve `ThemeToggle` dahil
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Kurulum
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install reactive-switcher
|
||||||
|
# veya
|
||||||
|
pnpm add reactive-switcher
|
||||||
|
# veya
|
||||||
|
yarn add reactive-switcher
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Hızlı Başlangıç
|
||||||
|
|
||||||
|
### 1. Temalarınızı Tanımlayın
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// themes.ts
|
||||||
|
import { ThemesConfig } from "reactive-switcher";
|
||||||
|
|
||||||
|
export const themes: ThemesConfig = {
|
||||||
|
light: {
|
||||||
|
name: "light",
|
||||||
|
type: "light",
|
||||||
|
colors: {
|
||||||
|
background: "#ffffff",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "#3b82f6",
|
||||||
|
foreground: "#ffffff",
|
||||||
|
50: "#eff6ff",
|
||||||
|
500: "#3b82f6",
|
||||||
|
600: "#2563eb",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "#64748b",
|
||||||
|
foreground: "#ffffff",
|
||||||
|
},
|
||||||
|
surface: {
|
||||||
|
50: "#f8fafc",
|
||||||
|
100: "#f1f5f9",
|
||||||
|
200: "#e2e8f0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
name: "dark",
|
||||||
|
type: "dark",
|
||||||
|
colors: {
|
||||||
|
background: "#020617",
|
||||||
|
foreground: "#f8fafc",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "#60a5fa",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "#94a3b8",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
},
|
||||||
|
surface: {
|
||||||
|
50: "#0f172a",
|
||||||
|
100: "#1e293b",
|
||||||
|
200: "#334155",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Uygulamanızı ThemeProvider ile Sarmalayın
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/layout.tsx (Next.js)
|
||||||
|
import { ThemeProvider } from "reactive-switcher";
|
||||||
|
import { themes } from "./themes";
|
||||||
|
|
||||||
|
export default function RootLayout({ children }) {
|
||||||
|
return (
|
||||||
|
<html lang="tr" suppressHydrationWarning>
|
||||||
|
<body>
|
||||||
|
<ThemeProvider themes={themes} defaultTheme="light">
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Temayı Kullanın
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
"use client";
|
||||||
|
import { useTheme, ThemeToggle } from "reactive-switcher";
|
||||||
|
|
||||||
|
export function Header() {
|
||||||
|
const { theme, setTheme, toggleTheme } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className="bg-background text-foreground">
|
||||||
|
<p>Aktif Tema: {theme}</p>
|
||||||
|
|
||||||
|
{/* Kullanıma hazır toggle */}
|
||||||
|
<ThemeToggle />
|
||||||
|
|
||||||
|
{/* Veya manuel kontrol */}
|
||||||
|
<button onClick={() => setTheme("dark")}>Koyu</button>
|
||||||
|
<button onClick={toggleTheme}>Değiştir</button>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Tailwind CSS v4 Yapılandırması
|
||||||
|
|
||||||
|
```css
|
||||||
|
/* globals.css */
|
||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--color-background: var(--color-background);
|
||||||
|
--color-foreground: var(--color-foreground);
|
||||||
|
--color-primary: var(--color-primary-DEFAULT);
|
||||||
|
--color-primary-foreground: var(--color-primary-foreground);
|
||||||
|
--color-secondary: var(--color-secondary-DEFAULT);
|
||||||
|
--color-surface-50: var(--color-surface-50);
|
||||||
|
--color-surface-100: var(--color-surface-100);
|
||||||
|
--color-surface-200: var(--color-surface-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
body {
|
||||||
|
background-color: var(--color-background);
|
||||||
|
color: var(--color-foreground);
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 API Referansı
|
||||||
|
|
||||||
|
### ThemeProvider Props
|
||||||
|
|
||||||
|
| Prop | Tip | Varsayılan | Açıklama |
|
||||||
|
| --------------- | -------------- | --------------------------- | ----------------------------- |
|
||||||
|
| `themes` | `ThemesConfig` | **zorunlu** | Tema yapılandırma objesi |
|
||||||
|
| `defaultTheme` | `string` | `"light"` | Başlangıç teması |
|
||||||
|
| `enableStorage` | `boolean` | `true` | localStorage'a kaydet |
|
||||||
|
| `storageKey` | `string` | `"reactive-switcher-theme"` | localStorage anahtarı |
|
||||||
|
| `enableSystem` | `boolean` | `true` | Sistem teması algılama |
|
||||||
|
| `selector` | `string` | `":root"` | Kapsamlı tema için CSS seçici |
|
||||||
|
|
||||||
|
### useTheme() Hook
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const {
|
||||||
|
theme, // Aktif tema adı (string)
|
||||||
|
resolvedTheme, // Gerçek tema ("system" çözümlenir)
|
||||||
|
setTheme, // (name: string) => void
|
||||||
|
toggleTheme, // () => void - Temalar arasında geçiş
|
||||||
|
themes, // Mevcut tema adları (string[])
|
||||||
|
systemTheme, // Sistem tercihi ("light" | "dark")
|
||||||
|
} = useTheme();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌐 Demo
|
||||||
|
|
||||||
|
Canlı demoyu inceleyin: [reactive-switcher.vercel.app](https://reactive-switcher.vercel.app)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤝 Katkıda Bulunma
|
||||||
|
|
||||||
|
Katkılarınızı bekliyoruz! Pull Request göndermekten çekinmeyin.
|
||||||
|
|
||||||
|
1. Repoyu fork edin
|
||||||
|
2. Feature branch oluşturun (`git checkout -b feature/harika-ozellik`)
|
||||||
|
3. Değişikliklerinizi commit edin (`git commit -m 'Harika özellik ekle'`)
|
||||||
|
4. Branch'i push edin (`git push origin feature/harika-ozellik`)
|
||||||
|
5. Pull Request açın
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 Lisans
|
||||||
|
|
||||||
|
MIT © [Poyraz Avsever](https://github.com/poyrazavsever)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[](https://www.star-history.com/#poyrazavsever/reactive-switcher&type=date&legend=top-left)
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
Made with ❤️ by <a href="https://poyrazavsever.com">Poyraz Avsever</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Reactive Switcher 🎨
|
||||||
|
|
||||||
|
> Type-safe, modular, and instant theme switching for React & Tailwind CSS v4
|
||||||
|
|
||||||
|
[](https://www.npmjs.com/package/reactive-switcher)
|
||||||
|
[](https://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
## ✨ Features
|
||||||
|
|
||||||
|
- **Zero Runtime Overhead** - Uses CSS variables for instant theme switching
|
||||||
|
- **TypeScript First** - Full type safety with autocomplete support
|
||||||
|
- **Tailwind CSS v4 Ready** - Seamless integration with the new engine
|
||||||
|
- **Persistent Themes** - LocalStorage support out of the box
|
||||||
|
- **System Theme Detection** - Respects `prefers-color-scheme`
|
||||||
|
- **No Flash** - SSR compatible with hydration flash prevention
|
||||||
|
- **Scoped Theming** - Apply different themes to different parts of your app
|
||||||
|
- **Ready-to-use Components** - `ThemeSwitcher` and `ThemeToggle` included
|
||||||
|
|
||||||
|
## 📦 Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install reactive-switcher
|
||||||
|
# or
|
||||||
|
pnpm add reactive-switcher
|
||||||
|
# or
|
||||||
|
yarn add reactive-switcher
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### 1. Define Your Themes
|
||||||
|
|
||||||
|
Create a file to define your theme configurations:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// themes.ts
|
||||||
|
import { ThemesConfig } from "reactive-switcher";
|
||||||
|
|
||||||
|
export const themes: ThemesConfig = {
|
||||||
|
light: {
|
||||||
|
name: "light",
|
||||||
|
type: "light",
|
||||||
|
colors: {
|
||||||
|
background: "#ffffff",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "#3b82f6",
|
||||||
|
foreground: "#ffffff",
|
||||||
|
50: "#eff6ff",
|
||||||
|
100: "#dbeafe",
|
||||||
|
500: "#3b82f6",
|
||||||
|
600: "#2563eb",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "#64748b",
|
||||||
|
foreground: "#ffffff",
|
||||||
|
},
|
||||||
|
surface: {
|
||||||
|
50: "#f8fafc",
|
||||||
|
100: "#f1f5f9",
|
||||||
|
200: "#e2e8f0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
name: "dark",
|
||||||
|
type: "dark",
|
||||||
|
colors: {
|
||||||
|
background: "#020617",
|
||||||
|
foreground: "#f8fafc",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "#60a5fa",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
50: "#172554",
|
||||||
|
100: "#1e3a8a",
|
||||||
|
500: "#3b82f6",
|
||||||
|
600: "#60a5fa",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "#94a3b8",
|
||||||
|
foreground: "#0f172a",
|
||||||
|
},
|
||||||
|
surface: {
|
||||||
|
50: "#0f172a",
|
||||||
|
100: "#1e293b",
|
||||||
|
200: "#334155",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Wrap Your App with ThemeProvider
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/layout.tsx (Next.js) or main.tsx (Vite)
|
||||||
|
import { ThemeProvider } from "reactive-switcher";
|
||||||
|
import { themes } from "./themes";
|
||||||
|
|
||||||
|
export default function RootLayout({ children }) {
|
||||||
|
return (
|
||||||
|
<html lang="en" suppressHydrationWarning>
|
||||||
|
<body>
|
||||||
|
<ThemeProvider themes={themes} defaultTheme="light">
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Use the Theme
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// components/Header.tsx
|
||||||
|
"use client";
|
||||||
|
import { useTheme, ThemeToggle } from "reactive-switcher";
|
||||||
|
|
||||||
|
export function Header() {
|
||||||
|
const { theme, setTheme, toggleTheme } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className="bg-background text-foreground">
|
||||||
|
<h1>Current Theme: {theme}</h1>
|
||||||
|
|
||||||
|
{/* Option 1: Simple toggle button */}
|
||||||
|
<ThemeToggle />
|
||||||
|
|
||||||
|
{/* Option 2: Manual control */}
|
||||||
|
<button onClick={() => setTheme("dark")}>Dark Mode</button>
|
||||||
|
<button onClick={() => setTheme("light")}>Light Mode</button>
|
||||||
|
<button onClick={() => setTheme("system")}>System</button>
|
||||||
|
|
||||||
|
{/* Option 3: Cycle through themes */}
|
||||||
|
<button onClick={toggleTheme}>Toggle Theme</button>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Configure Tailwind CSS v4
|
||||||
|
|
||||||
|
```css
|
||||||
|
/* globals.css */
|
||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--color-background: var(--color-background);
|
||||||
|
--color-foreground: var(--color-foreground);
|
||||||
|
|
||||||
|
--color-primary: var(--color-primary-DEFAULT);
|
||||||
|
--color-primary-foreground: var(--color-primary-foreground);
|
||||||
|
--color-primary-50: var(--color-primary-50);
|
||||||
|
--color-primary-100: var(--color-primary-100);
|
||||||
|
--color-primary-500: var(--color-primary-500);
|
||||||
|
--color-primary-600: var(--color-primary-600);
|
||||||
|
|
||||||
|
--color-secondary: var(--color-secondary-DEFAULT);
|
||||||
|
--color-secondary-foreground: var(--color-secondary-foreground);
|
||||||
|
|
||||||
|
--color-surface-50: var(--color-surface-50);
|
||||||
|
--color-surface-100: var(--color-surface-100);
|
||||||
|
--color-surface-200: var(--color-surface-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
body {
|
||||||
|
background-color: var(--color-background);
|
||||||
|
color: var(--color-foreground);
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can use Tailwind classes like `bg-primary`, `text-foreground`, `bg-surface-100` etc.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 API Reference
|
||||||
|
|
||||||
|
### ThemeProvider
|
||||||
|
|
||||||
|
The main provider component that wraps your application.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<ThemeProvider
|
||||||
|
themes={themes} // Required: Your theme configurations
|
||||||
|
defaultTheme="light" // Default theme name (default: "light")
|
||||||
|
enableStorage={true} // Enable localStorage persistence (default: true)
|
||||||
|
storageKey="theme" // localStorage key (default: "reactive-switcher-theme")
|
||||||
|
enableSystem={true} // Enable system theme detection (default: true)
|
||||||
|
selector=":root" // CSS selector for scoped theming (default: ":root")
|
||||||
|
styleId="theme-styles" // Style tag ID (default: "reactive-switcher-styles")
|
||||||
|
attribute="class" // HTML attribute: "class" | "data-theme" (default: "class")
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
### useTheme Hook
|
||||||
|
|
||||||
|
Access theme state and controls anywhere in your app.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const {
|
||||||
|
theme, // Current theme name (e.g., "light", "dark", "system")
|
||||||
|
resolvedTheme, // Actual theme when "system" is selected
|
||||||
|
setTheme, // Function to set theme by name
|
||||||
|
toggleTheme, // Function to cycle to next theme
|
||||||
|
activeThemeObject, // Full theme object with colors
|
||||||
|
themes, // Array of available theme names
|
||||||
|
systemTheme, // System preference ("light" | "dark")
|
||||||
|
} = useTheme();
|
||||||
|
```
|
||||||
|
|
||||||
|
### ThemeSwitcher Component
|
||||||
|
|
||||||
|
A ready-to-use theme switcher component with multiple variants.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Buttons variant (default)
|
||||||
|
<ThemeSwitcher />
|
||||||
|
|
||||||
|
// Dropdown variant
|
||||||
|
<ThemeSwitcher variant="dropdown" />
|
||||||
|
|
||||||
|
// Toggle variant (cycles through themes)
|
||||||
|
<ThemeSwitcher variant="toggle" />
|
||||||
|
|
||||||
|
// With custom labels
|
||||||
|
<ThemeSwitcher
|
||||||
|
labels={{ light: "☀️ Light", dark: "🌙 Dark", system: "💻 System" }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
// Hide labels, show only icons
|
||||||
|
<ThemeSwitcher showLabels={false} />
|
||||||
|
|
||||||
|
// Custom render function
|
||||||
|
<ThemeSwitcher>
|
||||||
|
{({ theme, setTheme, themes }) => (
|
||||||
|
<div>
|
||||||
|
{themes.map(t => (
|
||||||
|
<button key={t} onClick={() => setTheme(t)}>
|
||||||
|
{t}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ThemeSwitcher>
|
||||||
|
```
|
||||||
|
|
||||||
|
### ThemeToggle Component
|
||||||
|
|
||||||
|
A simple light/dark toggle button.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Default
|
||||||
|
<ThemeToggle />
|
||||||
|
|
||||||
|
// Different sizes
|
||||||
|
<ThemeToggle size="sm" />
|
||||||
|
<ThemeToggle size="md" />
|
||||||
|
<ThemeToggle size="lg" />
|
||||||
|
|
||||||
|
// Custom icons
|
||||||
|
<ThemeToggle
|
||||||
|
lightIcon={<SunIcon />}
|
||||||
|
darkIcon={<MoonIcon />}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Advanced Usage
|
||||||
|
|
||||||
|
### Scoped Theming
|
||||||
|
|
||||||
|
Apply different themes to different parts of your app:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Main app uses light theme
|
||||||
|
<ThemeProvider themes={themes} defaultTheme="light">
|
||||||
|
<main>
|
||||||
|
{/* This section has its own theme */}
|
||||||
|
<ThemeProvider
|
||||||
|
themes={themes}
|
||||||
|
defaultTheme="dark"
|
||||||
|
selector="#preview-section"
|
||||||
|
styleId="preview-theme"
|
||||||
|
enableStorage={false}
|
||||||
|
>
|
||||||
|
<div id="preview-section">{/* This area will have dark theme */}</div>
|
||||||
|
</ThemeProvider>
|
||||||
|
</main>
|
||||||
|
</ThemeProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Theme Type
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Theme, ThemesConfig } from "reactive-switcher";
|
||||||
|
|
||||||
|
// Define your custom theme structure
|
||||||
|
const myTheme: Theme = {
|
||||||
|
name: "ocean",
|
||||||
|
type: "dark",
|
||||||
|
colors: {
|
||||||
|
background: "#042f2e",
|
||||||
|
foreground: "#ccfbf1",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "#2dd4bf",
|
||||||
|
foreground: "#042f2e",
|
||||||
|
},
|
||||||
|
// Add any custom color tokens
|
||||||
|
accent: {
|
||||||
|
DEFAULT: "#facc15",
|
||||||
|
subtle: "#fef3c7",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### System Theme Only
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<ThemeProvider themes={themes} defaultTheme="system" enableSystem={true}>
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Utility Functions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {
|
||||||
|
flattenTheme,
|
||||||
|
createCssString,
|
||||||
|
getSystemTheme,
|
||||||
|
getStoredTheme,
|
||||||
|
setStoredTheme,
|
||||||
|
} from "reactive-switcher";
|
||||||
|
|
||||||
|
// Flatten nested colors to CSS variables
|
||||||
|
const vars = flattenTheme(theme.colors);
|
||||||
|
// { '--color-primary-DEFAULT': '#3b82f6', '--color-primary-500': '#3b82f6' }
|
||||||
|
|
||||||
|
// Create CSS string
|
||||||
|
const css = createCssString(theme);
|
||||||
|
// ":root { --color-primary-DEFAULT: #3b82f6; ... }"
|
||||||
|
|
||||||
|
// Get system preference
|
||||||
|
const systemTheme = getSystemTheme(); // 'light' | 'dark'
|
||||||
|
|
||||||
|
// Storage utilities
|
||||||
|
const stored = getStoredTheme("theme-key");
|
||||||
|
setStoredTheme("theme-key", "dark");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 TypeScript Support
|
||||||
|
|
||||||
|
Full type definitions are included. Enable autocomplete for your theme tokens:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Theme, ThemesConfig } from 'reactive-switcher';
|
||||||
|
|
||||||
|
// Your themes will have full type checking
|
||||||
|
const themes: ThemesConfig = {
|
||||||
|
light: { ... },
|
||||||
|
dark: { ... },
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please read our contributing guidelines first.
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
MIT © [Poyraz Avsever](https://github.com/poyrazavsever)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
Made with ❤️ for the React community
|
||||||
|
</p>
|
||||||
@@ -0,0 +1,413 @@
|
|||||||
|
# Poyraz UI - Usage Guide (Detayli)
|
||||||
|
|
||||||
|
Bu dokuman, `d:/Poyraz/kodlama/poyraz-ui` reposunun guncel kaynak kodu uzerinden hazirlandi.
|
||||||
|
Hedef: UI kitin hem kullanici (consumer) tarafini hem de bu repoyu gelistirme tarafini tek yerde toplamak.
|
||||||
|
|
||||||
|
Versiyon referansi: `2.0.1`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1) Proje Ozeti
|
||||||
|
|
||||||
|
Poyraz UI, React tabanli, Tailwind CSS v4 ile calisan, atomic design yaklasimi kullanan bir UI kit.
|
||||||
|
Repo iki ana amaca hizmet ediyor:
|
||||||
|
|
||||||
|
1. npm paketi olarak dagitilan UI kutuphanesi (`src`, `components/ui`, `dist`)
|
||||||
|
2. Next.js App Router ile yazilmis canli dokumantasyon sitesi (`app`)
|
||||||
|
|
||||||
|
Temel karakter:
|
||||||
|
|
||||||
|
- clean border odakli, minimum shadow
|
||||||
|
- `rounded-sm` kullanimina dayali yalin gorunum
|
||||||
|
- semantic token sistemi (`--poyraz-*`)
|
||||||
|
- dark mode uyumlu
|
||||||
|
- atoms -> molecules -> organisms katmanlamasi
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2) Dizin Yapisi (Gercek Kod Yapisi)
|
||||||
|
|
||||||
|
```txt
|
||||||
|
poyraz-ui/
|
||||||
|
|- app/ # Next.js docs sitesi
|
||||||
|
| |- docs/ # component/template dokumantasyon sayfalari
|
||||||
|
| |- globals.css # docs sitesi global css + dark override
|
||||||
|
| |- layout.tsx # next-themes + Toaster entegrasyonu
|
||||||
|
| `- page.tsx # landing/showcase
|
||||||
|
|- bin/
|
||||||
|
| `- cli.mjs # npx poyraz-ui init
|
||||||
|
|- components/
|
||||||
|
| |- ui/
|
||||||
|
| | |- atoms/ # 17 atom dosyasi
|
||||||
|
| | |- molecules/ # 22 molecule dosyasi
|
||||||
|
| | `- organisms/ # 5 organism dosyasi
|
||||||
|
| |- theme-provider.tsx # docs sitesi next-themes wrapper
|
||||||
|
| `- theme-toggle.tsx # docs sitesi toggle
|
||||||
|
|- lib/
|
||||||
|
| `- navigation.ts # docs nav/registry merkezi config
|
||||||
|
|- src/
|
||||||
|
| |- index.ts # ana export
|
||||||
|
| |- atoms/index.ts # atom export map
|
||||||
|
| |- molecules/index.ts # molecule export map
|
||||||
|
| |- organisms/index.ts # organism export map
|
||||||
|
| |- themes/index.ts # poyrazLightTheme / poyrazDarkTheme
|
||||||
|
| |- preset.css # token layer + @theme bridge
|
||||||
|
| `- utils.ts # cn()
|
||||||
|
|- dist/ # tsup output (publish edilen paket)
|
||||||
|
|- tsup.config.ts # 5 entry point, esm+cjs, dts
|
||||||
|
`- package.json
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3) Kullanici Tarafi Kurulum (Consumer App)
|
||||||
|
|
||||||
|
### 3.1 Paket kurulumu
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm add poyraz-ui
|
||||||
|
# veya
|
||||||
|
npm install poyraz-ui
|
||||||
|
# veya
|
||||||
|
yarn add poyraz-ui
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Zorunlu peer dependencies
|
||||||
|
|
||||||
|
- `react >= 18`
|
||||||
|
- `react-dom >= 18`
|
||||||
|
- `tailwindcss >= 4`
|
||||||
|
|
||||||
|
Opsiyonel peer dependencies:
|
||||||
|
|
||||||
|
- `react-hook-form`, `@hookform/resolvers`, `zod` (Form molecule icin)
|
||||||
|
- `reactive-switcher` (hazir theme objectleriyle dinamik tema gecisi icin)
|
||||||
|
|
||||||
|
### 3.3 CSS import (kritik)
|
||||||
|
|
||||||
|
Root global stylesheet dosyana ekle:
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import "tailwindcss";
|
||||||
|
@import "poyraz-ui/preset.css";
|
||||||
|
```
|
||||||
|
|
||||||
|
`preset.css` olmadan renk/font tokenlari dogru resolve edilmez.
|
||||||
|
|
||||||
|
### 3.4 Hemen kullanim
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Button, Card, CardContent } from "poyraz-ui/atoms";
|
||||||
|
|
||||||
|
export function Demo() {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<Button>Merhaba</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4) Import Stratejisi ve Entry Pointler
|
||||||
|
|
||||||
|
Paket 5 entry point sunuyor:
|
||||||
|
|
||||||
|
- `poyraz-ui`
|
||||||
|
- `poyraz-ui/atoms`
|
||||||
|
- `poyraz-ui/molecules`
|
||||||
|
- `poyraz-ui/organisms`
|
||||||
|
- `poyraz-ui/themes`
|
||||||
|
|
||||||
|
Onerilen yaklasim:
|
||||||
|
|
||||||
|
- Uretim projelerinde alt path importlarini kullan (`/atoms`, `/molecules`, `/organisms`)
|
||||||
|
- Gecis surecinde hiz icin ana barrel (`poyraz-ui`) kullanabilirsin
|
||||||
|
|
||||||
|
Ornek:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Button, Badge } from "poyraz-ui/atoms";
|
||||||
|
import { Dialog } from "poyraz-ui/molecules";
|
||||||
|
import { Navbar } from "poyraz-ui/organisms";
|
||||||
|
import { poyrazLightTheme, poyrazDarkTheme } from "poyraz-ui/themes";
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5) Tema Sistemi (En Onemli Altyapi)
|
||||||
|
|
||||||
|
Tema zinciri su sekilde calisiyor:
|
||||||
|
|
||||||
|
1. Component classlari `bg-background`, `text-foreground`, `border-border` gibi semantic utility kullaniyor.
|
||||||
|
2. `src/preset.css`, `@theme` ile bunlari `--color-*` tokenlarina bagliyor.
|
||||||
|
3. `--color-*` tokenlari, `var(--poyraz-*, fallback)` ile semantic CSS variable'a mapleniyor.
|
||||||
|
4. Sen `--poyraz-*` degistirdiginde tum kit yeni temaya gecer.
|
||||||
|
|
||||||
|
### 5.1 Token katmanlari
|
||||||
|
|
||||||
|
- Base semantic variables: `--poyraz-background`, `--poyraz-foreground`, `--poyraz-primary`, ...
|
||||||
|
- Tailwind v4 bridge: `--color-background`, `--color-foreground`, ...
|
||||||
|
- Utility kullanim: `bg-background`, `text-muted-foreground`, ...
|
||||||
|
|
||||||
|
### 5.2 Dark mode (class tabanli)
|
||||||
|
|
||||||
|
Docs sitesi `next-themes` kullaniyor ve `html.dark` altinda `--poyraz-*` override ediyor (`app/globals.css`).
|
||||||
|
|
||||||
|
### 5.3 reactive-switcher entegrasyonu
|
||||||
|
|
||||||
|
`src/themes/index.ts` icinde hazir theme objectleri var:
|
||||||
|
|
||||||
|
- `poyrazLightTheme`
|
||||||
|
- `poyrazDarkTheme`
|
||||||
|
- `poyrazThemes`
|
||||||
|
|
||||||
|
Ornek:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { ThemeProvider } from "reactive-switcher";
|
||||||
|
import { poyrazThemes } from "poyraz-ui/themes";
|
||||||
|
|
||||||
|
export function AppTheme({ children }: { children: React.ReactNode }) {
|
||||||
|
return <ThemeProvider themes={poyrazThemes}>{children}</ThemeProvider>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6) Component Katalogu
|
||||||
|
|
||||||
|
Bu bolum `src/*/index.ts` export maplerine gore hazirlandi.
|
||||||
|
|
||||||
|
### 6.1 Atoms (17 component dosyasi)
|
||||||
|
|
||||||
|
- Avatar
|
||||||
|
- Badge
|
||||||
|
- Button
|
||||||
|
- Card
|
||||||
|
- Checkbox
|
||||||
|
- Input
|
||||||
|
- Label
|
||||||
|
- Logo
|
||||||
|
- Radio Group
|
||||||
|
- Separator
|
||||||
|
- Skeleton
|
||||||
|
- Switch
|
||||||
|
- Textarea
|
||||||
|
- Typography
|
||||||
|
- Form Fields (`NumberInput`, `SearchInput`, `PhoneInput`, `PasswordInput`, `UrlInput`)
|
||||||
|
- BG Patterns (`PatternDots`, `PatternGrid`, `PatternLines`, `PatternDiagonal`, `PatternCross`, `PatternCheckerboard`, `PatternDiamond`, `PatternZigzag`, `PatternDashedGrid`, `PatternRadial`)
|
||||||
|
- ScrollArea
|
||||||
|
|
||||||
|
### 6.2 Molecules (22 component dosyasi)
|
||||||
|
|
||||||
|
Core molecules:
|
||||||
|
|
||||||
|
- Accordion
|
||||||
|
- Alert
|
||||||
|
- Autocomplete
|
||||||
|
- Breadcrumb
|
||||||
|
- Calendar
|
||||||
|
- Command Palette
|
||||||
|
- Date Picker
|
||||||
|
- Dialog
|
||||||
|
- Drawer
|
||||||
|
- Dropdown Menu
|
||||||
|
- Form
|
||||||
|
- Hover Card
|
||||||
|
- Modal
|
||||||
|
- Pagination
|
||||||
|
- Popover
|
||||||
|
- Select
|
||||||
|
- Sheet
|
||||||
|
- Sonner (`Toaster`, `toast`)
|
||||||
|
- Tabs
|
||||||
|
- Tooltip
|
||||||
|
|
||||||
|
Template molecules (card-templates):
|
||||||
|
|
||||||
|
- ArticleCard
|
||||||
|
- ImageCard
|
||||||
|
- NewsCard
|
||||||
|
- StatsCard
|
||||||
|
- TestimonialCard
|
||||||
|
- PricingCard
|
||||||
|
- ProductCard
|
||||||
|
|
||||||
|
### 6.3 Organisms (5 component dosyasi)
|
||||||
|
|
||||||
|
- Navbar
|
||||||
|
- Sidebar
|
||||||
|
- Footer
|
||||||
|
- AnnouncementBar
|
||||||
|
- DataTable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7) Hazir Template Sayfalari (Docs Icinde)
|
||||||
|
|
||||||
|
`app/docs/templates` altinda 4 kopyalanabilir sayfa semasi var:
|
||||||
|
|
||||||
|
- Hero
|
||||||
|
- Pricing
|
||||||
|
- Dashboard
|
||||||
|
- Auth
|
||||||
|
|
||||||
|
Onemli not:
|
||||||
|
|
||||||
|
- Bunlar npm paketi icinde "template component" olarak export edilmiyor.
|
||||||
|
- Kaynagi kopyalayip projenin ihtiyacina gore duzenleme modeli kullaniliyor.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8) Dokumantasyon Sitesi Mimarisi
|
||||||
|
|
||||||
|
`app/docs` altinda:
|
||||||
|
|
||||||
|
- toplam `53` adet `page.tsx`
|
||||||
|
- atoms: `18`
|
||||||
|
- molecules: `22`
|
||||||
|
- organisms: `6`
|
||||||
|
- templates: `5`
|
||||||
|
|
||||||
|
Merkezi nav/registry:
|
||||||
|
|
||||||
|
- `lib/navigation.ts`
|
||||||
|
- sidebardaki kategori sayilari ve slug donusumu burada yonetiliyor (`toSlug`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9) CLI: `npx poyraz-ui init`
|
||||||
|
|
||||||
|
CLI (`bin/cli.mjs`) su adimlari yapar:
|
||||||
|
|
||||||
|
1. CSS dosyasini otomatik tespit eder (`app/globals.css`, `src/app/globals.css` vb.)
|
||||||
|
2. `@import "poyraz-ui/preset.css";` satirini ekler
|
||||||
|
3. Opsiyonel olarak `reactive-switcher` tema dosyasi scaffold eder
|
||||||
|
4. Layout icin ThemeProvider snippet'i gosterir
|
||||||
|
|
||||||
|
Manual kurulum yerine hizli onboarding icin ideal.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10) Build, Bundle ve Publish Akisi
|
||||||
|
|
||||||
|
### 10.1 Scriptler
|
||||||
|
|
||||||
|
- `pnpm dev`: docs sitesi
|
||||||
|
- `pnpm build`: library + docs production build
|
||||||
|
- `pnpm build:lib`: sadece library (`tsup`)
|
||||||
|
- `pnpm start`: next production serve
|
||||||
|
- `pnpm prepublishOnly`: publish oncesi otomatik `build:lib`
|
||||||
|
|
||||||
|
### 10.2 tsup ozeti
|
||||||
|
|
||||||
|
`tsup.config.ts`:
|
||||||
|
|
||||||
|
- 5 entry point uretir (`index`, `atoms/index`, `molecules/index`, `organisms/index`, `themes/index`)
|
||||||
|
- format: `esm + cjs`
|
||||||
|
- `dts: true`
|
||||||
|
- `splitting + treeshake + clean`
|
||||||
|
- build sonrasi `dist` dosyalarina `"use client"` directive inject eder
|
||||||
|
|
||||||
|
### 10.3 package export haritasi
|
||||||
|
|
||||||
|
`package.json` `exports` alani:
|
||||||
|
|
||||||
|
- alt path importlarini hem ESM hem CJS ile aciklar
|
||||||
|
- `./preset.css` dogrudan `src/preset.css`'e yonlenir
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11) Bu Repoda Yeni Component Ekleme Rehberi
|
||||||
|
|
||||||
|
### 11.1 Kod ekleme
|
||||||
|
|
||||||
|
1. Component dosyasini `components/ui/<layer>/` altina ekle
|
||||||
|
2. Gerekirse type exportlarini component dosyasinda tanimla
|
||||||
|
|
||||||
|
### 11.2 Export haritasi
|
||||||
|
|
||||||
|
3. `src/<layer>/index.ts` icine export satirlarini ekle
|
||||||
|
4. Gerekliyse `src/index.ts` ana barrel kontrol et
|
||||||
|
|
||||||
|
### 11.3 Docs entegrasyonu
|
||||||
|
|
||||||
|
5. `app/docs/<layer>/<component>/page.tsx` olustur
|
||||||
|
6. Kategori index sayfasina link ekle (`app/docs/<layer>/page.tsx`)
|
||||||
|
7. `lib/navigation.ts` icindeki `componentRegistry` listesine ekle
|
||||||
|
|
||||||
|
### 11.4 Dogrulama
|
||||||
|
|
||||||
|
8. `pnpm build:lib`
|
||||||
|
9. `pnpm dev` ile docs sayfasini ve importlarini test et
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12) Sik Kullanilan Kullanim Patternleri
|
||||||
|
|
||||||
|
### 12.1 Form stack
|
||||||
|
|
||||||
|
- Atoms: `Input`, `Label`, `Checkbox`, `Button`
|
||||||
|
- Molecules: `Form`, `Select`, `DatePicker`, `Autocomplete`
|
||||||
|
|
||||||
|
### 12.2 Overlay stack
|
||||||
|
|
||||||
|
- `Dialog`, `Modal`, `Drawer`, `Sheet`, `Popover`, `Tooltip`
|
||||||
|
- Her biri Radix/Vaul primitive uzerinden geldigi icin a11y ve keyboard destegi yuksek
|
||||||
|
|
||||||
|
### 12.3 Navigation stack
|
||||||
|
|
||||||
|
- `Navbar` (desktop + mobile panel)
|
||||||
|
- `Sidebar` (collapsible/floating/mini varyantlar)
|
||||||
|
- `Footer` (layout varyantlari)
|
||||||
|
|
||||||
|
### 12.4 Data stack
|
||||||
|
|
||||||
|
- `DataTable` + `Badge` + `Pagination`
|
||||||
|
- dashboard tarzinda `StatsCard`, `Card`, `Avatar` ile birlikte kullaniliyor
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13) Bilinen Durumlar / Dikkat Noktalari
|
||||||
|
|
||||||
|
1. `Mermaid` dokumantasyon sayfasi var (`app/docs/molecules/mermaid/page.tsx`) ancak su anda `src/molecules/index.ts` icinden export edilmiyor.
|
||||||
|
2. `componentRegistry` molecules listesi ile molecules landing page listesi tam birebir degil (sidebar listesinde Mermaid yok).
|
||||||
|
3. Template sayfalari (Hero/Pricing/Dashboard/Auth) paket exportu degil; kopyala-ozellestir modeli.
|
||||||
|
4. Rehber ve README metinlerinde bilesen sayilari bazen farkli geciyor; son karar noktasi her zaman `src/*/index.ts` export mapidir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14) Hizli Referans
|
||||||
|
|
||||||
|
### 14.1 Consumer app checklist
|
||||||
|
|
||||||
|
1. `poyraz-ui` paketini kur
|
||||||
|
2. `@import "poyraz-ui/preset.css";` ekle
|
||||||
|
3. `poyraz-ui/atoms` veya `poyraz-ui/molecules` uzerinden import et
|
||||||
|
4. Tema gerekiyorsa `--poyraz-*` override et veya `poyraz-ui/themes` kullan
|
||||||
|
|
||||||
|
### 14.2 Repo contributor checklist
|
||||||
|
|
||||||
|
1. component dosyasi ekle (`components/ui`)
|
||||||
|
2. export map guncelle (`src/*/index.ts`)
|
||||||
|
3. docs page ekle (`app/docs/...`)
|
||||||
|
4. navigation registry guncelle (`lib/navigation.ts`)
|
||||||
|
5. `pnpm build:lib` ve `pnpm dev` ile dogrula
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15) Ek Kaynaklar
|
||||||
|
|
||||||
|
- Paket genel tanitim: `README.md`
|
||||||
|
- Genis API referansi: `COMPONENTS.md`
|
||||||
|
- Theme switcher notlari: `theme-switcher.md`
|
||||||
|
- Kurulum sayfasi referansi: `app/docs/installation/page.tsx`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Bu dokuman "proje ici operasyonel guide" amaciyla yazildi.
|
||||||
|
Paketin public-facing README'sini sade tutup, bu dosyayi teknik detay merkezi olarak kullanman tavsiye edilir.
|
||||||
+2
-1
@@ -11,7 +11,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
"react-dom": "19.2.3"
|
"react-dom": "19.2.3",
|
||||||
|
"reactive-switcher": "^1.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
|
|||||||
Generated
+14
@@ -17,6 +17,9 @@ importers:
|
|||||||
react-dom:
|
react-dom:
|
||||||
specifier: 19.2.3
|
specifier: 19.2.3
|
||||||
version: 19.2.3(react@19.2.3)
|
version: 19.2.3(react@19.2.3)
|
||||||
|
reactive-switcher:
|
||||||
|
specifier: ^1.0.3
|
||||||
|
version: 1.0.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@tailwindcss/postcss':
|
'@tailwindcss/postcss':
|
||||||
specifier: ^4
|
specifier: ^4
|
||||||
@@ -1641,6 +1644,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
|
resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
reactive-switcher@1.0.3:
|
||||||
|
resolution: {integrity: sha512-d5kGGUdDZ0z4kdgmBwNOL9Z6qQKYqv6tyifde+6XXbWQZpY5oNbkuA2WNXut6ETwbIbBNa3+dvHWR66XIapqlw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=18.0.0'
|
||||||
|
react-dom: '>=18.0.0'
|
||||||
|
|
||||||
reflect.getprototypeof@1.0.10:
|
reflect.getprototypeof@1.0.10:
|
||||||
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
|
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -3626,6 +3635,11 @@ snapshots:
|
|||||||
|
|
||||||
react@19.2.3: {}
|
react@19.2.3: {}
|
||||||
|
|
||||||
|
reactive-switcher@1.0.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.3
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
|
||||||
reflect.getprototypeof@1.0.10:
|
reflect.getprototypeof@1.0.10:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { poyrazLightTheme, poyrazDarkTheme, poyrazThemes } from "poyraz-ui/themes";
|
||||||
|
|
||||||
|
// You can customise themes by spreading and overriding variables:
|
||||||
|
//
|
||||||
|
// const customLight = {
|
||||||
|
// ...poyrazLightTheme,
|
||||||
|
// name: "custom-light",
|
||||||
|
// variables: {
|
||||||
|
// ...poyrazLightTheme.variables,
|
||||||
|
// "--poyraz-primary": "#2563eb", // blue-600
|
||||||
|
// "--poyraz-primary-foreground": "#ffffff",
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
export { poyrazLightTheme, poyrazDarkTheme, poyrazThemes };
|
||||||
Reference in New Issue
Block a user