| @ -0,0 +1,151 @@ | |||
| # Adminator Documentation | |||
| This directory contains the complete documentation for Adminator Bootstrap 5 Admin Template. | |||
| ## ๐ Documentation Structure | |||
| ``` | |||
| docs/ | |||
| โโโ index.md # Homepage | |||
| โโโ _config.yml # GitHub Pages configuration | |||
| โโโ getting-started/ # Installation and setup guides | |||
| โ โโโ installation.md | |||
| โ โโโ project-structure.md | |||
| โ โโโ development.md | |||
| โ โโโ build-deployment.md | |||
| โโโ components/ # Component documentation | |||
| โ โโโ charts.md | |||
| โ โโโ forms.md | |||
| โ โโโ tables.md | |||
| โ โโโ navigation.md | |||
| โ โโโ modals.md | |||
| โโโ customization/ # Theme and styling guides | |||
| โ โโโ theme-system.md | |||
| โ โโโ css-variables.md | |||
| โ โโโ custom-themes.md | |||
| โ โโโ component-theming.md | |||
| โโโ api/ # API reference | |||
| โ โโโ theme-api.md | |||
| โ โโโ component-apis.md | |||
| โ โโโ utilities.md | |||
| โ โโโ events.md | |||
| โโโ examples/ # Practical examples | |||
| โ โโโ basic-setup.md | |||
| โ โโโ custom-components.md | |||
| โ โโโ theme-integration.md | |||
| โ โโโ advanced-patterns.md | |||
| โโโ deployment/ # Production deployment | |||
| โ โโโ production-build.md | |||
| โ โโโ static-hosting.md | |||
| โ โโโ cdn-integration.md | |||
| โ โโโ performance.md | |||
| โโโ contributing/ # Contribution guidelines | |||
| โโโ development-setup.md | |||
| โโโ code-standards.md | |||
| โโโ pull-requests.md | |||
| โโโ issues.md | |||
| ``` | |||
| ## ๐ Hosting Strategy | |||
| ### **GitHub Pages Setup** | |||
| 1. **Main Branch Integration**: Documentation lives in the `docs/` folder of the main branch | |||
| 2. **Automatic Deployment**: GitHub Pages automatically builds and deploys on every commit | |||
| 3. **Custom Domain Support**: Can be configured with custom domains | |||
| 4. **Jekyll Integration**: Uses Jekyll static site generator with the Minima theme | |||
| ### **Benefits of This Approach** | |||
| โ **Version Control**: Docs stay in sync with code releases | |||
| โ **Free Hosting**: GitHub Pages provides free, reliable hosting | |||
| โ **Easy Discovery**: Users find docs directly in the repository | |||
| โ **SEO Friendly**: Searchable and indexable documentation | |||
| โ **Collaboration**: Easy for contributors to update docs | |||
| โ **Professional URLs**: Clean URLs like `username.github.io/repo/` | |||
| ## ๐ Documentation Sections | |||
| ### **๐ Getting Started** | |||
| Complete setup and installation guides for new users. | |||
| ### **๐จ Components** | |||
| Detailed documentation for all UI components and their usage. | |||
| ### **๐ Dark Mode & Theming** | |||
| Comprehensive guide to the theme system and customization options. | |||
| ### **๐ง API Reference** | |||
| Complete API documentation for all JavaScript utilities and components. | |||
| ### **๐ก Examples** | |||
| Practical, copy-paste examples for common use cases. | |||
| ### **๐ Deployment** | |||
| Production deployment guides and performance optimization tips. | |||
| ### **๐ค Contributing** | |||
| Guidelines for contributing to the project. | |||
| ## ๐ง Local Development | |||
| To view the documentation locally: | |||
| ```bash | |||
| # Install Jekyll (if not already installed) | |||
| gem install bundler jekyll | |||
| # Navigate to docs directory | |||
| cd docs | |||
| # Install dependencies | |||
| bundle install | |||
| # Serve locally | |||
| bundle exec jekyll serve | |||
| # Visit http://localhost:4000 | |||
| ``` | |||
| ## ๐ Writing Documentation | |||
| ### **Markdown Guidelines** | |||
| - Use clear, descriptive headings | |||
| - Include code examples for all features | |||
| - Add cross-references between related sections | |||
| - Use emoji for visual appeal (sparingly) | |||
| - Include "Next Steps" sections to guide readers | |||
| ### **Code Examples** | |||
| ```markdown | |||
| \```javascript | |||
| // Always include working code examples | |||
| const example = Theme.current(); | |||
| console.log(example); | |||
| \``` | |||
| ``` | |||
| ### **File Naming** | |||
| - Use lowercase with hyphens: `theme-system.md` | |||
| - Be descriptive but concise | |||
| - Group related files in subdirectories | |||
| ## ๐ Quick Links | |||
| - **[Live Documentation](https://puikinsh.github.io/Adminator-admin-dashboard/)** (Coming Soon) | |||
| - **[GitHub Repository](https://github.com/puikinsh/Adminator-admin-dashboard)** | |||
| - **[Live Demo](https://colorlib.com/polygon/adminator/index.html)** | |||
| ## ๐ Support | |||
| For documentation issues: | |||
| - Open an issue with the `documentation` label | |||
| - Suggest improvements via pull requests | |||
| - Join discussions for larger documentation changes | |||
| --- | |||
| **Happy documenting!** ๐ | |||
| @ -0,0 +1,85 @@ | |||
| # GitHub Pages Configuration for Adminator Documentation | |||
| # Site settings | |||
| title: "Adminator Documentation" | |||
| description: "Complete guide for the Adminator Bootstrap 5 Admin Dashboard Template with Dark Mode" | |||
| url: "https://puikinsh.github.io" | |||
| baseurl: "/Adminator-admin-dashboard" | |||
| # Build settings | |||
| markdown: kramdown | |||
| highlighter: rouge | |||
| theme: minima | |||
| # Plugin settings | |||
| plugins: | |||
| - jekyll-feed | |||
| - jekyll-sitemap | |||
| - jekyll-seo-tag | |||
| # Navigation | |||
| navigation: | |||
| - title: "Getting Started" | |||
| url: "/getting-started/" | |||
| - title: "Components" | |||
| url: "/components/" | |||
| - title: "Dark Mode & Theming" | |||
| url: "/customization/" | |||
| - title: "API Reference" | |||
| url: "/api/" | |||
| - title: "Examples" | |||
| url: "/examples/" | |||
| - title: "Deployment" | |||
| url: "/deployment/" | |||
| # SEO | |||
| author: "Colorlib" | |||
| twitter: | |||
| username: colorlib | |||
| social: | |||
| name: "Colorlib" | |||
| links: | |||
| - https://github.com/puikinsh/Adminator-admin-dashboard | |||
| - https://colorlib.com | |||
| # Exclude from processing | |||
| exclude: | |||
| - Gemfile | |||
| - Gemfile.lock | |||
| - node_modules | |||
| - vendor/bundle/ | |||
| - vendor/cache/ | |||
| - vendor/gems/ | |||
| - vendor/ruby/ | |||
| # Include | |||
| include: | |||
| - _pages | |||
| # Collections | |||
| collections: | |||
| pages: | |||
| output: true | |||
| permalink: /:name/ | |||
| # Defaults | |||
| defaults: | |||
| - scope: | |||
| path: "" | |||
| type: "pages" | |||
| values: | |||
| layout: "page" | |||
| - scope: | |||
| path: "" | |||
| values: | |||
| layout: "default" | |||
| # Code highlighting | |||
| kramdown: | |||
| syntax_highlighter: rouge | |||
| syntax_highlighter_opts: | |||
| css_class: 'highlight' | |||
| span: | |||
| line_numbers: false | |||
| block: | |||
| line_numbers: true | |||
| @ -0,0 +1,489 @@ | |||
| # Theme API Reference | |||
| Complete API documentation for the Adminator Theme utility system. | |||
| ## Overview | |||
| The Theme API provides programmatic control over Adminator's dark mode and theming system. It includes methods for theme management, color retrieval, and event handling. | |||
| ## Theme Object | |||
| The global `Theme` object is available throughout the application: | |||
| ```javascript | |||
| // Available globally | |||
| window.Theme | |||
| // or simply | |||
| Theme | |||
| ``` | |||
| ## Core Methods | |||
| ### `Theme.apply(theme)` | |||
| Applies a specific theme to the application. | |||
| **Parameters:** | |||
| - `theme` (string): The theme to apply (`'light'` or `'dark'`) | |||
| **Returns:** `void` | |||
| **Example:** | |||
| ```javascript | |||
| // Apply dark theme | |||
| Theme.apply('dark'); | |||
| // Apply light theme | |||
| Theme.apply('light'); | |||
| ``` | |||
| **Side Effects:** | |||
| - Sets `data-theme` attribute on `document.documentElement` | |||
| - Updates Chart.js global defaults (if Chart.js is loaded) | |||
| - Saves theme preference to localStorage | |||
| - Dispatches `adminator:themeChanged` event | |||
| --- | |||
| ### `Theme.toggle()` | |||
| Toggles between light and dark themes. | |||
| **Parameters:** None | |||
| **Returns:** `void` | |||
| **Example:** | |||
| ```javascript | |||
| // Switch from current theme to opposite | |||
| Theme.toggle(); | |||
| // If current theme is 'light', switches to 'dark' | |||
| // If current theme is 'dark', switches to 'light' | |||
| ``` | |||
| --- | |||
| ### `Theme.current()` | |||
| Gets the currently active theme. | |||
| **Parameters:** None | |||
| **Returns:** `string` - The current theme (`'light'` or `'dark'`) | |||
| **Example:** | |||
| ```javascript | |||
| const currentTheme = Theme.current(); | |||
| console.log(currentTheme); // 'light' or 'dark' | |||
| // Use in conditional logic | |||
| if (Theme.current() === 'dark') { | |||
| // Dark theme specific logic | |||
| } | |||
| ``` | |||
| --- | |||
| ### `Theme.init()` | |||
| Initializes the theme system. Called automatically on page load. | |||
| **Parameters:** None | |||
| **Returns:** `void` | |||
| **Example:** | |||
| ```javascript | |||
| // Manual initialization (usually not needed) | |||
| Theme.init(); | |||
| ``` | |||
| **Behavior:** | |||
| - Checks for stored theme preference in localStorage | |||
| - If no stored preference, detects OS color scheme preference | |||
| - Applies the determined theme | |||
| - Sets up Chart.js defaults if available | |||
| --- | |||
| ### `Theme.getCSSVar(varName)` | |||
| Retrieves the computed value of a CSS custom property. | |||
| **Parameters:** | |||
| - `varName` (string): The CSS variable name (including `--` prefix) | |||
| **Returns:** `string` - The computed CSS variable value | |||
| **Example:** | |||
| ```javascript | |||
| // Get primary color | |||
| const primaryColor = Theme.getCSSVar('--c-primary'); | |||
| console.log(primaryColor); // '#4b7cf3' | |||
| // Get background color | |||
| const bgColor = Theme.getCSSVar('--c-bkg-body'); | |||
| console.log(bgColor); // '#f8f9fa' or '#181a1f' | |||
| ``` | |||
| ## Specialized Color Methods | |||
| ### `Theme.getChartColors()` | |||
| Gets color values optimized for Chart.js components. | |||
| **Parameters:** None | |||
| **Returns:** `object` - Chart color configuration | |||
| **Return Object:** | |||
| ```javascript | |||
| { | |||
| textColor: string, // Primary text color | |||
| mutedColor: string, // Secondary text color | |||
| borderColor: string, // Border colors | |||
| gridColor: string, // Grid line colors | |||
| tooltipBg: string // Tooltip background | |||
| } | |||
| ``` | |||
| **Example:** | |||
| ```javascript | |||
| const chartColors = Theme.getChartColors(); | |||
| const chart = new Chart(ctx, { | |||
| options: { | |||
| plugins: { | |||
| legend: { | |||
| labels: { | |||
| color: chartColors.textColor | |||
| } | |||
| } | |||
| }, | |||
| scales: { | |||
| y: { | |||
| ticks: { color: chartColors.mutedColor }, | |||
| grid: { color: chartColors.gridColor } | |||
| } | |||
| } | |||
| } | |||
| }); | |||
| ``` | |||
| --- | |||
| ### `Theme.getVectorMapColors()` | |||
| Gets color palette for vector map components. | |||
| **Parameters:** None | |||
| **Returns:** `object` - Vector map color configuration | |||
| **Return Object:** | |||
| ```javascript | |||
| { | |||
| backgroundColor: string, // Map background | |||
| borderColor: string, // Map borders | |||
| regionColor: string, // Default region color | |||
| markerFill: string, // Marker fill color | |||
| markerStroke: string, // Marker stroke color | |||
| hoverColor: string, // Hover state color | |||
| selectedColor: string, // Selected state color | |||
| scaleStart: string, // Color scale start | |||
| scaleEnd: string, // Color scale end | |||
| scaleLight: string, // Light scale color | |||
| scaleDark: string // Dark scale color | |||
| } | |||
| ``` | |||
| **Example:** | |||
| ```javascript | |||
| const mapColors = Theme.getVectorMapColors(); | |||
| $('#world-map').vectorMap({ | |||
| backgroundColor: mapColors.backgroundColor, | |||
| regionStyle: { | |||
| initial: { | |||
| fill: mapColors.regionColor, | |||
| stroke: mapColors.borderColor | |||
| }, | |||
| hover: { | |||
| fill: mapColors.hoverColor | |||
| } | |||
| } | |||
| }); | |||
| ``` | |||
| --- | |||
| ### `Theme.getSparklineColors()` | |||
| Gets color palette for Sparkline chart components. | |||
| **Parameters:** None | |||
| **Returns:** `object` - Sparkline color configuration | |||
| **Return Object:** | |||
| ```javascript | |||
| { | |||
| success: string, // Success state color | |||
| purple: string, // Purple variant | |||
| info: string, // Info state color | |||
| danger: string, // Danger state color | |||
| light: string // Light variant | |||
| } | |||
| ``` | |||
| **Example:** | |||
| ```javascript | |||
| const sparklineColors = Theme.getSparklineColors(); | |||
| $('.sparkline-success').sparkline(data, { | |||
| lineColor: sparklineColors.success, | |||
| fillColor: false | |||
| }); | |||
| ``` | |||
| ## Event System | |||
| ### Theme Change Event | |||
| The theme system dispatches custom events when themes change. | |||
| **Event Name:** `adminator:themeChanged` | |||
| **Event Detail:** | |||
| ```javascript | |||
| { | |||
| theme: string // The new theme ('light' or 'dark') | |||
| } | |||
| ``` | |||
| **Example:** | |||
| ```javascript | |||
| // Listen for theme changes | |||
| window.addEventListener('adminator:themeChanged', (event) => { | |||
| const newTheme = event.detail.theme; | |||
| console.log('Theme changed to:', newTheme); | |||
| // Update custom components | |||
| updateCustomComponent(newTheme); | |||
| }); | |||
| // Alternative using jQuery | |||
| $(window).on('adminator:themeChanged', function(event) { | |||
| const newTheme = event.originalEvent.detail.theme; | |||
| // Handle theme change | |||
| }); | |||
| ``` | |||
| ## Storage Management | |||
| ### Local Storage Key | |||
| The theme preference is stored using the key: `'adminator-theme'` | |||
| **Example:** | |||
| ```javascript | |||
| // Manually check stored theme | |||
| const storedTheme = localStorage.getItem('adminator-theme'); | |||
| console.log(storedTheme); // 'light', 'dark', or null | |||
| // Manually set theme preference | |||
| localStorage.setItem('adminator-theme', 'dark'); | |||
| ``` | |||
| ### Fallback Handling | |||
| The Theme API gracefully handles storage unavailability: | |||
| ```javascript | |||
| // Internal implementation example | |||
| try { | |||
| localStorage.setItem('adminator-theme', theme); | |||
| } catch (_) { | |||
| // Storage not available - theme won't persist | |||
| // But theme will still work for current session | |||
| } | |||
| ``` | |||
| ## Integration Examples | |||
| ### React Integration | |||
| ```javascript | |||
| import { useEffect, useState } from 'react'; | |||
| function useTheme() { | |||
| const [theme, setTheme] = useState(Theme.current()); | |||
| useEffect(() => { | |||
| const handleThemeChange = (event) => { | |||
| setTheme(event.detail.theme); | |||
| }; | |||
| window.addEventListener('adminator:themeChanged', handleThemeChange); | |||
| return () => { | |||
| window.removeEventListener('adminator:themeChanged', handleThemeChange); | |||
| }; | |||
| }, []); | |||
| return { | |||
| theme, | |||
| toggle: Theme.toggle, | |||
| setTheme: Theme.apply | |||
| }; | |||
| } | |||
| ``` | |||
| ### Vue.js Integration | |||
| ```javascript | |||
| export default { | |||
| data() { | |||
| return { | |||
| currentTheme: Theme.current() | |||
| } | |||
| }, | |||
| mounted() { | |||
| window.addEventListener('adminator:themeChanged', this.handleThemeChange); | |||
| }, | |||
| beforeDestroy() { | |||
| window.removeEventListener('adminator:themeChanged', this.handleThemeChange); | |||
| }, | |||
| methods: { | |||
| handleThemeChange(event) { | |||
| this.currentTheme = event.detail.theme; | |||
| }, | |||
| toggleTheme() { | |||
| Theme.toggle(); | |||
| } | |||
| } | |||
| } | |||
| ``` | |||
| ### Custom Component Integration | |||
| ```javascript | |||
| class CustomWidget { | |||
| constructor(element) { | |||
| this.element = element; | |||
| this.currentTheme = Theme.current(); | |||
| this.init(); | |||
| this.bindEvents(); | |||
| } | |||
| init() { | |||
| this.updateTheme(this.currentTheme); | |||
| } | |||
| bindEvents() { | |||
| window.addEventListener('adminator:themeChanged', (event) => { | |||
| this.currentTheme = event.detail.theme; | |||
| this.updateTheme(this.currentTheme); | |||
| }); | |||
| } | |||
| updateTheme(theme) { | |||
| // Update widget based on theme | |||
| if (theme === 'dark') { | |||
| this.element.classList.add('widget-dark'); | |||
| this.element.style.backgroundColor = Theme.getCSSVar('--c-bkg-card'); | |||
| } else { | |||
| this.element.classList.remove('widget-dark'); | |||
| this.element.style.backgroundColor = Theme.getCSSVar('--c-bkg-card'); | |||
| } | |||
| } | |||
| } | |||
| ``` | |||
| ## Error Handling | |||
| ### Browser Compatibility | |||
| ```javascript | |||
| // Check for CSS custom property support | |||
| function supportsCSSVariables() { | |||
| return window.CSS && CSS.supports('color', 'var(--fake-var)'); | |||
| } | |||
| if (!supportsCSSVariables()) { | |||
| console.warn('CSS variables not supported - theme switching limited'); | |||
| } | |||
| ``` | |||
| ### LocalStorage Availability | |||
| ```javascript | |||
| // Check for localStorage support | |||
| function supportsLocalStorage() { | |||
| try { | |||
| return 'localStorage' in window && window['localStorage'] !== null; | |||
| } catch (e) { | |||
| return false; | |||
| } | |||
| } | |||
| if (!supportsLocalStorage()) { | |||
| console.warn('localStorage not available - theme preference won\'t persist'); | |||
| } | |||
| ``` | |||
| ## Performance Considerations | |||
| ### Debounced Theme Changes | |||
| For applications with many theme-aware components: | |||
| ```javascript | |||
| let themeChangeTimeout; | |||
| window.addEventListener('adminator:themeChanged', (event) => { | |||
| clearTimeout(themeChangeTimeout); | |||
| themeChangeTimeout = setTimeout(() => { | |||
| // Expensive theme update operations | |||
| updateManyComponents(event.detail.theme); | |||
| }, 100); | |||
| }); | |||
| ``` | |||
| ### Efficient CSS Variable Reading | |||
| Cache CSS variable values when possible: | |||
| ```javascript | |||
| class ThemeCache { | |||
| constructor() { | |||
| this.cache = new Map(); | |||
| this.cacheTheme = null; | |||
| } | |||
| getCSSVar(varName) { | |||
| const currentTheme = Theme.current(); | |||
| if (this.cacheTheme !== currentTheme) { | |||
| this.cache.clear(); | |||
| this.cacheTheme = currentTheme; | |||
| } | |||
| if (!this.cache.has(varName)) { | |||
| const value = Theme.getCSSVar(varName); | |||
| this.cache.set(varName, value); | |||
| } | |||
| return this.cache.get(varName); | |||
| } | |||
| } | |||
| ``` | |||
| --- | |||
| **Next:** Explore [Component APIs](component-apis.md) or check out [Theme Integration Examples](../examples/theme-integration.md). | |||
| @ -0,0 +1,356 @@ | |||
| # Theme System Overview | |||
| Adminator v2.6.0 introduces a comprehensive dark mode system with intelligent theme switching and component integration. | |||
| ## ๐ Features | |||
| ### Core Capabilities | |||
| - **๐ Smart Toggle**: Bootstrap-based switch with sun/moon icons | |||
| - **๐ OS Detection**: Automatically detects and applies system preference | |||
| - **๐พ Persistent Storage**: Remembers theme choice across browser sessions | |||
| - **โก Instant Switching**: Real-time theme updates without page reload | |||
| - **๐ฏ Component Integration**: All elements are theme-aware | |||
| ### Visual Enhancements | |||
| - **๐จ Semantic Colors**: Consistent color variables across components | |||
| - **๐ Chart Integration**: Dynamic color schemes for Chart.js | |||
| - **๐๏ธ Calendar Support**: Dark-mode aware FullCalendar | |||
| - **๐บ๏ธ Map Theming**: Custom color palettes for vector and Google maps | |||
| ## ๐ Quick Start | |||
| ### Basic Usage | |||
| The theme system is automatically initialized when the page loads: | |||
| ```javascript | |||
| // The theme toggle is automatically injected into the header | |||
| // Users can click the Light/Dark switch to change themes | |||
| ``` | |||
| ### Programmatic Control | |||
| ```javascript | |||
| // Get current theme | |||
| const currentTheme = Theme.current(); // 'light' or 'dark' | |||
| // Switch themes | |||
| Theme.toggle(); | |||
| // Set specific theme | |||
| Theme.apply('dark'); | |||
| Theme.apply('light'); | |||
| // Listen for theme changes | |||
| window.addEventListener('adminator:themeChanged', (event) => { | |||
| console.log('Theme changed to:', event.detail.theme); | |||
| // Your custom logic here | |||
| }); | |||
| ``` | |||
| ## ๐จ CSS Variables | |||
| ### Core Theme Variables | |||
| ```css | |||
| :root { | |||
| /* Backgrounds */ | |||
| --c-bkg-body: #f8f9fa; /* Main page background */ | |||
| --c-bkg-card: #ffffff; /* Card and panel backgrounds */ | |||
| --c-bkg-sidebar: #ffffff; /* Sidebar background */ | |||
| /* Text Colors */ | |||
| --c-text-base: #212529; /* Primary text color */ | |||
| --c-text-muted: #6c757d; /* Secondary text color */ | |||
| /* UI Elements */ | |||
| --c-border: #e2e5e8; /* Border colors */ | |||
| --c-primary: #4b7cf3; /* Primary brand color */ | |||
| --c-success: #2ecc71; /* Success state color */ | |||
| --c-danger: #e74c3c; /* Error state color */ | |||
| } | |||
| /* Dark theme overrides */ | |||
| [data-theme="dark"] { | |||
| --c-bkg-body: #181a1f; | |||
| --c-bkg-card: #20232a; | |||
| --c-bkg-sidebar: #20232a; | |||
| --c-text-base: #e8eaed; | |||
| --c-text-muted: #9ca3af; | |||
| --c-border: #2b2f36; | |||
| /* ... additional dark theme variables */ | |||
| } | |||
| ``` | |||
| ### Component-Specific Variables | |||
| ```css | |||
| :root { | |||
| /* Vector Maps */ | |||
| --vmap-bg-color: #ffffff; | |||
| --vmap-region-color: #e4ecef; | |||
| --vmap-hover-color: #ffffff; | |||
| /* Charts */ | |||
| --sparkline-success: #4caf50; | |||
| --sparkline-info: #03a9f3; | |||
| --sparkline-danger: #f96262; | |||
| /* Maps */ | |||
| --gmap-landscape-hue: #FFBB00; | |||
| --gmap-water-hue: #0078FF; | |||
| } | |||
| ``` | |||
| ## ๐ง Implementation Details | |||
| ### Theme Toggle Component | |||
| The theme toggle is automatically injected into the navigation: | |||
| ```html | |||
| <!-- Automatically generated theme toggle --> | |||
| <li class="theme-toggle d-flex ai-c"> | |||
| <div class="form-check form-switch d-flex ai-c"> | |||
| <label class="form-check-label me-2 text-nowrap c-grey-700" for="theme-toggle"> | |||
| <i class="ti-sun"></i> Light | |||
| </label> | |||
| <input class="form-check-input" type="checkbox" id="theme-toggle"> | |||
| <label class="form-check-label ms-2 text-nowrap c-grey-700" for="theme-toggle"> | |||
| Dark <i class="ti-moon"></i> | |||
| </label> | |||
| </div> | |||
| </li> | |||
| ``` | |||
| ### Theme Detection Logic | |||
| ```javascript | |||
| // Automatic OS preference detection | |||
| if (!localStorage.getItem('adminator-theme')) { | |||
| const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | |||
| Theme.apply(prefersDark ? 'dark' : 'light'); | |||
| } else { | |||
| Theme.apply(Theme.current()); | |||
| } | |||
| ``` | |||
| ## ๐ฏ Component Integration | |||
| ### Chart.js Integration | |||
| Charts automatically update colors when themes change: | |||
| ```javascript | |||
| // Chart colors are automatically updated | |||
| const chartColors = Theme.getChartColors(); | |||
| // Returns: { textColor, mutedColor, borderColor, gridColor, tooltipBg } | |||
| // Custom chart configuration | |||
| const chart = new Chart(ctx, { | |||
| data: data, | |||
| options: { | |||
| plugins: { | |||
| legend: { | |||
| labels: { | |||
| color: chartColors.textColor | |||
| } | |||
| } | |||
| }, | |||
| scales: { | |||
| y: { | |||
| ticks: { | |||
| color: chartColors.mutedColor | |||
| }, | |||
| grid: { | |||
| color: chartColors.gridColor | |||
| } | |||
| } | |||
| } | |||
| } | |||
| }); | |||
| ``` | |||
| ### FullCalendar Integration | |||
| Calendar styling updates automatically: | |||
| ```css | |||
| /* Automatic dark mode calendar styling */ | |||
| .fc { | |||
| background: var(--c-bkg-card); | |||
| color: var(--c-text-base); | |||
| } | |||
| .fc-event { | |||
| border-color: var(--c-border) !important; | |||
| } | |||
| .fc-daygrid-day { | |||
| border-color: var(--c-border) !important; | |||
| } | |||
| ``` | |||
| ### Vector Maps Integration | |||
| Maps use theme-aware color palettes: | |||
| ```javascript | |||
| // Get vector map colors for current theme | |||
| const mapColors = Theme.getVectorMapColors(); | |||
| /* Returns: | |||
| { | |||
| backgroundColor: '#ffffff' | '#20232a', | |||
| regionColor: '#e4ecef' | '#2b2f36', | |||
| hoverColor: '#ffffff' | '#181a1f', | |||
| // ... other map-specific colors | |||
| } | |||
| */ | |||
| ``` | |||
| ## ๐จ Custom Styling | |||
| ### Using CSS Variables | |||
| Style your components with theme-aware variables: | |||
| ```css | |||
| .my-custom-component { | |||
| background: var(--c-bkg-card); | |||
| color: var(--c-text-base); | |||
| border: 1px solid var(--c-border); | |||
| border-radius: 8px; | |||
| padding: 1rem; | |||
| } | |||
| .my-custom-button { | |||
| background: var(--c-primary); | |||
| color: white; | |||
| border: none; | |||
| padding: 0.5rem 1rem; | |||
| border-radius: 4px; | |||
| } | |||
| .my-custom-button:hover { | |||
| background: var(--c-primary); | |||
| opacity: 0.9; | |||
| } | |||
| ``` | |||
| ### Creating Theme-Aware Components | |||
| ```javascript | |||
| class MyCustomComponent { | |||
| constructor(element) { | |||
| this.element = element; | |||
| this.init(); | |||
| // Listen for theme changes | |||
| window.addEventListener('adminator:themeChanged', (event) => { | |||
| this.updateTheme(event.detail.theme); | |||
| }); | |||
| } | |||
| updateTheme(theme) { | |||
| // Update component based on theme | |||
| if (theme === 'dark') { | |||
| this.element.classList.add('dark-mode'); | |||
| } else { | |||
| this.element.classList.remove('dark-mode'); | |||
| } | |||
| } | |||
| } | |||
| ``` | |||
| ## ๐ Advanced Usage | |||
| ### Custom Theme Colors | |||
| Override default theme colors: | |||
| ```css | |||
| :root { | |||
| /* Custom brand colors */ | |||
| --c-primary: #your-brand-color; | |||
| --c-success: #your-success-color; | |||
| } | |||
| [data-theme="dark"] { | |||
| /* Custom dark theme colors */ | |||
| --c-primary: #your-dark-brand-color; | |||
| --c-success: #your-dark-success-color; | |||
| } | |||
| ``` | |||
| ### Theme-Specific Images | |||
| Use different images for light/dark themes: | |||
| ```css | |||
| .logo { | |||
| background-image: url('logo-light.png'); | |||
| } | |||
| [data-theme="dark"] .logo { | |||
| background-image: url('logo-dark.png'); | |||
| } | |||
| ``` | |||
| ### Dynamic Theme Updates | |||
| Create dynamic theme switching animations: | |||
| ```css | |||
| /* Smooth theme transitions */ | |||
| * { | |||
| transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; | |||
| } | |||
| /* Disable transitions during theme switch */ | |||
| .theme-transitioning * { | |||
| transition: none !important; | |||
| } | |||
| ``` | |||
| ## ๐ Troubleshooting | |||
| ### Common Issues | |||
| #### Theme Not Persisting | |||
| ```javascript | |||
| // Check localStorage availability | |||
| if (typeof(Storage) !== "undefined") { | |||
| // localStorage is available | |||
| } else { | |||
| // No web storage support | |||
| console.warn('localStorage not available - theme won\'t persist'); | |||
| } | |||
| ``` | |||
| #### Components Not Updating | |||
| ```javascript | |||
| // Ensure components listen for theme changes | |||
| window.addEventListener('adminator:themeChanged', (event) => { | |||
| // Force component update | |||
| myComponent.refresh(); | |||
| }); | |||
| ``` | |||
| #### CSS Variables Not Working | |||
| ```css | |||
| /* Fallback for older browsers */ | |||
| .my-component { | |||
| background: #ffffff; /* Fallback */ | |||
| background: var(--c-bkg-card); /* Modern */ | |||
| } | |||
| ``` | |||
| ## ๐ Related Documentation | |||
| - **[CSS Variables Reference](css-variables.md)** - Complete variable list | |||
| - **[Custom Theme Creation](custom-themes.md)** - Create your own themes | |||
| - **[Component Theming](component-theming.md)** - Theme individual components | |||
| --- | |||
| **Ready to customize?** Start with the [CSS Variables Reference](css-variables.md) or explore [Custom Theme Creation](custom-themes.md)! | |||
| @ -0,0 +1,664 @@ | |||
| # Theme Integration Examples | |||
| Practical examples for integrating custom components with Adminator's theme system. | |||
| ## Basic Theme-Aware Component | |||
| ### Simple CSS Integration | |||
| Create components that automatically adapt to theme changes: | |||
| ```html | |||
| <!-- HTML --> | |||
| <div class="custom-widget"> | |||
| <h3 class="widget-title">My Custom Widget</h3> | |||
| <div class="widget-content"> | |||
| <p>This widget adapts to the current theme.</p> | |||
| <button class="widget-button">Action</button> | |||
| </div> | |||
| </div> | |||
| ``` | |||
| ```css | |||
| /* CSS using theme variables */ | |||
| .custom-widget { | |||
| background: var(--c-bkg-card); | |||
| color: var(--c-text-base); | |||
| border: 1px solid var(--c-border); | |||
| border-radius: 8px; | |||
| padding: 1.5rem; | |||
| margin-bottom: 1rem; | |||
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | |||
| } | |||
| .widget-title { | |||
| color: var(--c-text-base); | |||
| margin-bottom: 1rem; | |||
| font-size: 1.25rem; | |||
| font-weight: 600; | |||
| } | |||
| .widget-content { | |||
| color: var(--c-text-muted); | |||
| line-height: 1.6; | |||
| } | |||
| .widget-button { | |||
| background: var(--c-primary); | |||
| color: white; | |||
| border: none; | |||
| padding: 0.5rem 1rem; | |||
| border-radius: 4px; | |||
| cursor: pointer; | |||
| transition: opacity 0.2s ease; | |||
| } | |||
| .widget-button:hover { | |||
| opacity: 0.9; | |||
| } | |||
| /* Dark theme specific adjustments */ | |||
| [data-theme="dark"] .custom-widget { | |||
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); | |||
| } | |||
| ``` | |||
| ## JavaScript Integration | |||
| ### Theme-Aware Class Component | |||
| ```javascript | |||
| class ThemeAwareWidget { | |||
| constructor(element, options = {}) { | |||
| this.element = element; | |||
| this.options = { | |||
| autoUpdate: true, | |||
| customColors: {}, | |||
| ...options | |||
| }; | |||
| this.currentTheme = Theme.current(); | |||
| this.init(); | |||
| } | |||
| init() { | |||
| this.render(); | |||
| this.bindEvents(); | |||
| this.updateTheme(this.currentTheme); | |||
| } | |||
| render() { | |||
| this.element.innerHTML = ` | |||
| <div class="theme-widget"> | |||
| <div class="widget-header"> | |||
| <h4>Theme-Aware Widget</h4> | |||
| <span class="theme-indicator">${this.currentTheme}</span> | |||
| </div> | |||
| <div class="widget-body"> | |||
| <div class="color-preview"> | |||
| <div class="color-sample" data-color="primary"></div> | |||
| <div class="color-sample" data-color="success"></div> | |||
| <div class="color-sample" data-color="danger"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| `; | |||
| } | |||
| bindEvents() { | |||
| if (this.options.autoUpdate) { | |||
| window.addEventListener('adminator:themeChanged', (event) => { | |||
| this.currentTheme = event.detail.theme; | |||
| this.updateTheme(this.currentTheme); | |||
| }); | |||
| } | |||
| } | |||
| updateTheme(theme) { | |||
| const widget = this.element.querySelector('.theme-widget'); | |||
| // Update theme indicator | |||
| const indicator = widget.querySelector('.theme-indicator'); | |||
| indicator.textContent = theme; | |||
| indicator.className = `theme-indicator theme-${theme}`; | |||
| // Update color samples | |||
| const samples = widget.querySelectorAll('.color-sample'); | |||
| samples.forEach(sample => { | |||
| const colorType = sample.dataset.color; | |||
| const cssVar = `--c-${colorType}`; | |||
| const color = Theme.getCSSVar(cssVar); | |||
| sample.style.backgroundColor = color; | |||
| }); | |||
| // Apply custom colors if provided | |||
| if (this.options.customColors[theme]) { | |||
| Object.entries(this.options.customColors[theme]).forEach(([property, value]) => { | |||
| widget.style.setProperty(property, value); | |||
| }); | |||
| } | |||
| // Trigger custom update callback | |||
| if (this.options.onThemeChange) { | |||
| this.options.onThemeChange(theme, this); | |||
| } | |||
| } | |||
| // Public methods | |||
| setTheme(theme) { | |||
| Theme.apply(theme); | |||
| } | |||
| getCurrentColors() { | |||
| return { | |||
| primary: Theme.getCSSVar('--c-primary'), | |||
| success: Theme.getCSSVar('--c-success'), | |||
| danger: Theme.getCSSVar('--c-danger'), | |||
| background: Theme.getCSSVar('--c-bkg-card'), | |||
| text: Theme.getCSSVar('--c-text-base') | |||
| }; | |||
| } | |||
| destroy() { | |||
| // Cleanup event listeners | |||
| window.removeEventListener('adminator:themeChanged', this.updateTheme); | |||
| } | |||
| } | |||
| // Usage | |||
| const widget = new ThemeAwareWidget(document.getElementById('my-widget'), { | |||
| customColors: { | |||
| dark: { | |||
| '--custom-accent': '#ff6b6b' | |||
| }, | |||
| light: { | |||
| '--custom-accent': '#4dabf7' | |||
| } | |||
| }, | |||
| onThemeChange: (theme, instance) => { | |||
| console.log(`Widget theme changed to: ${theme}`); | |||
| } | |||
| }); | |||
| ``` | |||
| ## Chart Integration | |||
| ### Theme-Aware Chart.js | |||
| ```javascript | |||
| class ThemeChart { | |||
| constructor(canvas, data, options = {}) { | |||
| this.canvas = canvas; | |||
| this.data = data; | |||
| this.options = options; | |||
| this.chart = null; | |||
| this.init(); | |||
| } | |||
| init() { | |||
| this.createChart(); | |||
| this.bindThemeEvents(); | |||
| } | |||
| createChart() { | |||
| const colors = Theme.getChartColors(); | |||
| const config = { | |||
| type: this.options.type || 'line', | |||
| data: this.processData(this.data, colors), | |||
| options: { | |||
| responsive: true, | |||
| plugins: { | |||
| legend: { | |||
| labels: { | |||
| color: colors.textColor, | |||
| usePointStyle: true | |||
| } | |||
| }, | |||
| tooltip: { | |||
| backgroundColor: colors.tooltipBg, | |||
| titleColor: colors.textColor, | |||
| bodyColor: colors.textColor, | |||
| borderColor: colors.borderColor, | |||
| borderWidth: 1 | |||
| } | |||
| }, | |||
| scales: { | |||
| x: { | |||
| ticks: { | |||
| color: colors.mutedColor | |||
| }, | |||
| grid: { | |||
| color: colors.gridColor | |||
| } | |||
| }, | |||
| y: { | |||
| ticks: { | |||
| color: colors.mutedColor | |||
| }, | |||
| grid: { | |||
| color: colors.gridColor | |||
| } | |||
| } | |||
| }, | |||
| ...this.options.chartOptions | |||
| } | |||
| }; | |||
| this.chart = new Chart(this.canvas, config); | |||
| } | |||
| processData(data, colors) { | |||
| return { | |||
| ...data, | |||
| datasets: data.datasets.map((dataset, index) => ({ | |||
| ...dataset, | |||
| borderColor: dataset.borderColor || this.getDatasetColor(index, colors), | |||
| backgroundColor: dataset.backgroundColor || this.getDatasetColor(index, colors, 0.2) | |||
| })) | |||
| }; | |||
| } | |||
| getDatasetColor(index, colors, alpha = 1) { | |||
| const colorKeys = ['primary', 'success', 'danger', 'info', 'warning']; | |||
| const colorKey = colorKeys[index % colorKeys.length]; | |||
| const color = Theme.getCSSVar(`--c-${colorKey}`); | |||
| if (alpha < 1) { | |||
| // Convert hex to rgba | |||
| const r = parseInt(color.slice(1, 3), 16); | |||
| const g = parseInt(color.slice(3, 5), 16); | |||
| const b = parseInt(color.slice(5, 7), 16); | |||
| return `rgba(${r}, ${g}, ${b}, ${alpha})`; | |||
| } | |||
| return color; | |||
| } | |||
| bindThemeEvents() { | |||
| window.addEventListener('adminator:themeChanged', () => { | |||
| this.updateChart(); | |||
| }); | |||
| } | |||
| updateChart() { | |||
| if (!this.chart) return; | |||
| const colors = Theme.getChartColors(); | |||
| // Update chart options | |||
| this.chart.options.plugins.legend.labels.color = colors.textColor; | |||
| this.chart.options.plugins.tooltip.backgroundColor = colors.tooltipBg; | |||
| this.chart.options.plugins.tooltip.titleColor = colors.textColor; | |||
| this.chart.options.plugins.tooltip.bodyColor = colors.textColor; | |||
| this.chart.options.plugins.tooltip.borderColor = colors.borderColor; | |||
| // Update scales | |||
| this.chart.options.scales.x.ticks.color = colors.mutedColor; | |||
| this.chart.options.scales.x.grid.color = colors.gridColor; | |||
| this.chart.options.scales.y.ticks.color = colors.mutedColor; | |||
| this.chart.options.scales.y.grid.color = colors.gridColor; | |||
| // Update dataset colors | |||
| this.chart.data.datasets.forEach((dataset, index) => { | |||
| dataset.borderColor = this.getDatasetColor(index, colors); | |||
| dataset.backgroundColor = this.getDatasetColor(index, colors, 0.2); | |||
| }); | |||
| this.chart.update(); | |||
| } | |||
| destroy() { | |||
| if (this.chart) { | |||
| this.chart.destroy(); | |||
| } | |||
| } | |||
| } | |||
| // Usage | |||
| const chartData = { | |||
| labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], | |||
| datasets: [{ | |||
| label: 'Sales', | |||
| data: [12, 19, 3, 5, 2, 3] | |||
| }, { | |||
| label: 'Revenue', | |||
| data: [2, 3, 20, 5, 1, 4] | |||
| }] | |||
| }; | |||
| const themeChart = new ThemeChart( | |||
| document.getElementById('myChart'), | |||
| chartData, | |||
| { | |||
| type: 'line', | |||
| chartOptions: { | |||
| tension: 0.4 | |||
| } | |||
| } | |||
| ); | |||
| ``` | |||
| ## Custom Modal Integration | |||
| ### Theme-Aware Modal | |||
| ```javascript | |||
| class ThemeModal { | |||
| constructor(options = {}) { | |||
| this.options = { | |||
| title: 'Modal Title', | |||
| content: '', | |||
| size: 'md', // sm, md, lg, xl | |||
| backdrop: true, | |||
| keyboard: true, | |||
| ...options | |||
| }; | |||
| this.modal = null; | |||
| this.element = null; | |||
| this.currentTheme = Theme.current(); | |||
| this.init(); | |||
| } | |||
| init() { | |||
| this.createElement(); | |||
| this.bindEvents(); | |||
| this.updateTheme(this.currentTheme); | |||
| } | |||
| createElement() { | |||
| const modalId = `modal-${Date.now()}`; | |||
| const modalHTML = ` | |||
| <div class="modal fade theme-modal" id="${modalId}" tabindex="-1"> | |||
| <div class="modal-dialog modal-${this.options.size}"> | |||
| <div class="modal-content"> | |||
| <div class="modal-header"> | |||
| <h5 class="modal-title">${this.options.title}</h5> | |||
| <button type="button" class="btn-close" data-bs-dismiss="modal"></button> | |||
| </div> | |||
| <div class="modal-body"> | |||
| ${this.options.content} | |||
| </div> | |||
| <div class="modal-footer"> | |||
| <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> | |||
| <button type="button" class="btn btn-primary modal-action">Save</button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| `; | |||
| document.body.insertAdjacentHTML('beforeend', modalHTML); | |||
| this.element = document.getElementById(modalId); | |||
| // Initialize Bootstrap modal | |||
| this.modal = new bootstrap.Modal(this.element, { | |||
| backdrop: this.options.backdrop, | |||
| keyboard: this.options.keyboard | |||
| }); | |||
| } | |||
| bindEvents() { | |||
| // Theme change event | |||
| window.addEventListener('adminator:themeChanged', (event) => { | |||
| this.currentTheme = event.detail.theme; | |||
| this.updateTheme(this.currentTheme); | |||
| }); | |||
| // Action button click | |||
| const actionButton = this.element.querySelector('.modal-action'); | |||
| actionButton.addEventListener('click', () => { | |||
| if (this.options.onAction) { | |||
| this.options.onAction(this); | |||
| } | |||
| }); | |||
| // Cleanup on hide | |||
| this.element.addEventListener('hidden.bs.modal', () => { | |||
| if (this.options.autoDestroy !== false) { | |||
| this.destroy(); | |||
| } | |||
| }); | |||
| } | |||
| updateTheme(theme) { | |||
| const content = this.element.querySelector('.modal-content'); | |||
| // Apply theme-specific styles | |||
| content.style.backgroundColor = Theme.getCSSVar('--c-bkg-card'); | |||
| content.style.color = Theme.getCSSVar('--c-text-base'); | |||
| content.style.border = `1px solid ${Theme.getCSSVar('--c-border')}`; | |||
| // Update header | |||
| const header = this.element.querySelector('.modal-header'); | |||
| header.style.borderBottom = `1px solid ${Theme.getCSSVar('--c-border')}`; | |||
| // Update footer | |||
| const footer = this.element.querySelector('.modal-footer'); | |||
| footer.style.borderTop = `1px solid ${Theme.getCSSVar('--c-border')}`; | |||
| // Update close button for dark theme | |||
| const closeButton = this.element.querySelector('.btn-close'); | |||
| if (theme === 'dark') { | |||
| closeButton.classList.add('btn-close-white'); | |||
| } else { | |||
| closeButton.classList.remove('btn-close-white'); | |||
| } | |||
| } | |||
| show() { | |||
| this.modal.show(); | |||
| } | |||
| hide() { | |||
| this.modal.hide(); | |||
| } | |||
| destroy() { | |||
| if (this.modal) { | |||
| this.modal.dispose(); | |||
| } | |||
| if (this.element) { | |||
| this.element.remove(); | |||
| } | |||
| } | |||
| } | |||
| // Usage | |||
| const modal = new ThemeModal({ | |||
| title: 'Theme-Aware Modal', | |||
| content: '<p>This modal adapts to the current theme automatically.</p>', | |||
| size: 'lg', | |||
| onAction: (modalInstance) => { | |||
| console.log('Action button clicked!'); | |||
| modalInstance.hide(); | |||
| } | |||
| }); | |||
| modal.show(); | |||
| ``` | |||
| ## React Hook Integration | |||
| ### useTheme Hook | |||
| ```javascript | |||
| import { useState, useEffect } from 'react'; | |||
| // Custom hook for theme management | |||
| export function useTheme() { | |||
| const [theme, setTheme] = useState(() => { | |||
| // Initialize with current theme | |||
| return window.Theme ? window.Theme.current() : 'light'; | |||
| }); | |||
| const [isLoading, setIsLoading] = useState(!window.Theme); | |||
| useEffect(() => { | |||
| // Wait for Theme object to be available | |||
| if (!window.Theme) { | |||
| const checkTheme = () => { | |||
| if (window.Theme) { | |||
| setTheme(window.Theme.current()); | |||
| setIsLoading(false); | |||
| } else { | |||
| setTimeout(checkTheme, 100); | |||
| } | |||
| }; | |||
| checkTheme(); | |||
| return; | |||
| } | |||
| const handleThemeChange = (event) => { | |||
| setTheme(event.detail.theme); | |||
| }; | |||
| window.addEventListener('adminator:themeChanged', handleThemeChange); | |||
| return () => { | |||
| window.removeEventListener('adminator:themeChanged', handleThemeChange); | |||
| }; | |||
| }, []); | |||
| const toggleTheme = () => { | |||
| if (window.Theme) { | |||
| window.Theme.toggle(); | |||
| } | |||
| }; | |||
| const setSpecificTheme = (newTheme) => { | |||
| if (window.Theme) { | |||
| window.Theme.apply(newTheme); | |||
| } | |||
| }; | |||
| const getThemeColors = () => { | |||
| if (!window.Theme) return {}; | |||
| return { | |||
| primary: window.Theme.getCSSVar('--c-primary'), | |||
| success: window.Theme.getCSSVar('--c-success'), | |||
| danger: window.Theme.getCSSVar('--c-danger'), | |||
| background: window.Theme.getCSSVar('--c-bkg-card'), | |||
| text: window.Theme.getCSSVar('--c-text-base'), | |||
| muted: window.Theme.getCSSVar('--c-text-muted'), | |||
| border: window.Theme.getCSSVar('--c-border') | |||
| }; | |||
| }; | |||
| return { | |||
| theme, | |||
| isLoading, | |||
| isDark: theme === 'dark', | |||
| isLight: theme === 'light', | |||
| toggle: toggleTheme, | |||
| setTheme: setSpecificTheme, | |||
| colors: getThemeColors() | |||
| }; | |||
| } | |||
| // React component using the hook | |||
| export function ThemeAwareCard({ children, title }) { | |||
| const { theme, colors, isDark } = useTheme(); | |||
| const cardStyle = { | |||
| backgroundColor: colors.background, | |||
| color: colors.text, | |||
| border: `1px solid ${colors.border}`, | |||
| borderRadius: '8px', | |||
| padding: '1.5rem', | |||
| boxShadow: isDark | |||
| ? '0 2px 4px rgba(0, 0, 0, 0.3)' | |||
| : '0 2px 4px rgba(0, 0, 0, 0.1)' | |||
| }; | |||
| const titleStyle = { | |||
| color: colors.text, | |||
| marginBottom: '1rem', | |||
| fontSize: '1.25rem', | |||
| fontWeight: '600' | |||
| }; | |||
| return ( | |||
| <div style={cardStyle} className={`theme-card theme-${theme}`}> | |||
| {title && <h3 style={titleStyle}>{title}</h3>} | |||
| <div style={{ color: colors.muted }}> | |||
| {children} | |||
| </div> | |||
| </div> | |||
| ); | |||
| } | |||
| // Theme toggle button component | |||
| export function ThemeToggle() { | |||
| const { theme, toggle, isLoading } = useTheme(); | |||
| if (isLoading) { | |||
| return <div>Loading theme...</div>; | |||
| } | |||
| return ( | |||
| <button | |||
| onClick={toggle} | |||
| className={`btn btn-outline-${theme === 'dark' ? 'light' : 'dark'}`} | |||
| > | |||
| {theme === 'dark' ? 'โ๏ธ Light' : '๐ Dark'} | |||
| </button> | |||
| ); | |||
| } | |||
| ``` | |||
| ## Performance Optimization | |||
| ### Throttled Theme Updates | |||
| For components with expensive rendering: | |||
| ```javascript | |||
| class PerformantThemeComponent { | |||
| constructor(element) { | |||
| this.element = element; | |||
| this.updateTheme = this.throttle(this._updateTheme.bind(this), 100); | |||
| window.addEventListener('adminator:themeChanged', this.updateTheme); | |||
| } | |||
| throttle(func, limit) { | |||
| let inThrottle; | |||
| return function() { | |||
| const args = arguments; | |||
| const context = this; | |||
| if (!inThrottle) { | |||
| func.apply(context, args); | |||
| inThrottle = true; | |||
| setTimeout(() => inThrottle = false, limit); | |||
| } | |||
| } | |||
| } | |||
| _updateTheme(event) { | |||
| // Expensive theme update operations | |||
| this.recalculateLayout(); | |||
| this.updateComplexVisuals(); | |||
| } | |||
| recalculateLayout() { | |||
| // Complex layout calculations | |||
| } | |||
| updateComplexVisuals() { | |||
| // Expensive visual updates | |||
| } | |||
| } | |||
| ``` | |||
| --- | |||
| **Next Steps:** | |||
| - Check out [Component APIs](../api/component-apis.md) for more integration options | |||
| - Explore [Advanced Patterns](advanced-patterns.md) for complex scenarios | |||
| - Review [Performance Optimization](../deployment/performance.md) for production tips | |||
| @ -0,0 +1,180 @@ | |||
| # Installation Guide | |||
| This guide will help you get Adminator up and running on your local machine. | |||
| ## Prerequisites | |||
| Before installing Adminator, ensure you have the following installed: | |||
| ### Required Software | |||
| - **Node.js** (v18.12.0 or higher) | |||
| - Download from [nodejs.org](https://nodejs.org/) | |||
| - Verify installation: `node --version` | |||
| - **npm** (comes with Node.js) or **Yarn** | |||
| - Verify npm: `npm --version` | |||
| - **Git** for version control | |||
| - Download from [git-scm.com](https://git-scm.com/) | |||
| ### System Requirements | |||
| - **Operating System**: Windows 10+, macOS 10.14+, or Linux | |||
| - **RAM**: Minimum 4GB (8GB recommended for development) | |||
| - **Storage**: 500MB free space for dependencies | |||
| ## Installation Methods | |||
| ### Method 1: Clone from GitHub (Recommended) | |||
| ```bash | |||
| # Clone the repository | |||
| git clone https://github.com/puikinsh/Adminator-admin-dashboard.git | |||
| # Navigate to the project directory | |||
| cd Adminator-admin-dashboard | |||
| # Install dependencies | |||
| npm install | |||
| # Start development server | |||
| npm start | |||
| ``` | |||
| ### Method 2: Download ZIP | |||
| 1. Visit the [GitHub repository](https://github.com/puikinsh/Adminator-admin-dashboard) | |||
| 2. Click **"Code"** โ **"Download ZIP"** | |||
| 3. Extract the downloaded file | |||
| 4. Open terminal in the extracted folder | |||
| 5. Run `npm install` and `npm start` | |||
| ### Method 3: Use with Existing Project | |||
| ```bash | |||
| # Add Adminator to your project | |||
| npm install --save adminator | |||
| # Or download specific release | |||
| wget https://github.com/puikinsh/Adminator-admin-dashboard/archive/v2.6.0.zip | |||
| ``` | |||
| ## Verification | |||
| After installation, verify everything works: | |||
| ### 1. Development Server | |||
| ```bash | |||
| npm start | |||
| ``` | |||
| **Expected Output:** | |||
| ``` | |||
| > adminator@2.6.0 start | |||
| > webpack server | |||
| โ Project is running at: http://localhost:4000/ | |||
| โ webpack compiled successfully | |||
| ``` | |||
| ### 2. Build Process | |||
| ```bash | |||
| npm run build | |||
| ``` | |||
| **Expected Output:** | |||
| ``` | |||
| > adminator@2.6.0 build | |||
| > npm run clean && cross-env webpack | |||
| โ webpack compiled successfully in [time]ms | |||
| ``` | |||
| ### 3. Access the Application | |||
| Open your browser and navigate to: | |||
| - **Local**: `http://localhost:4000` | |||
| - **Network**: `http://[your-ip]:4000` | |||
| You should see the Adminator dashboard with: | |||
| - โ Clean interface loading properly | |||
| - โ Dark/Light mode toggle in the header | |||
| - โ All components rendering correctly | |||
| - โ No console errors | |||
| ## Troubleshooting | |||
| ### Common Issues | |||
| #### Port Already in Use | |||
| ```bash | |||
| # Error: EADDRINUSE: address already in use :::4000 | |||
| # Solution: Kill the process using port 4000 | |||
| sudo lsof -ti:4000 | xargs kill -9 | |||
| # Or use a different port | |||
| PORT=3000 npm start | |||
| ``` | |||
| #### Node Version Issues | |||
| ```bash | |||
| # Check your Node.js version | |||
| node --version | |||
| # If version is below 18.12.0, update Node.js | |||
| # Use nvm (recommended): | |||
| nvm install 18 | |||
| nvm use 18 | |||
| ``` | |||
| #### Permission Errors | |||
| ```bash | |||
| # On macOS/Linux, you might need sudo for global packages | |||
| sudo npm install -g npm@latest | |||
| # Better solution: Fix npm permissions | |||
| npm config set prefix ~/.npm-global | |||
| export PATH=~/.npm-global/bin:$PATH | |||
| ``` | |||
| #### Missing Dependencies | |||
| ```bash | |||
| # Clear npm cache and reinstall | |||
| npm cache clean --force | |||
| rm -rf node_modules package-lock.json | |||
| npm install | |||
| ``` | |||
| #### Build Errors | |||
| ```bash | |||
| # Check for conflicting global packages | |||
| npm list -g --depth=0 | |||
| # Update npm and dependencies | |||
| npm update | |||
| npm audit fix | |||
| ``` | |||
| ### Getting Help | |||
| If you encounter issues: | |||
| 1. **Check the [GitHub Issues](https://github.com/puikinsh/Adminator-admin-dashboard/issues)** | |||
| 2. **Search existing solutions** | |||
| 3. **Create a new issue** with: | |||
| - Operating system and version | |||
| - Node.js and npm versions | |||
| - Complete error message | |||
| - Steps to reproduce | |||
| ## Next Steps | |||
| After successful installation: | |||
| 1. **[Explore Project Structure](project-structure.md)** - Understand the codebase | |||
| 2. **[Development Workflow](development.md)** - Learn the development process | |||
| 3. **[Customize Themes](../customization/theme-system.md)** - Set up dark mode and theming | |||
| 4. **[Build for Production](build-deployment.md)** - Deploy your application | |||
| --- | |||
| **Installation Complete!** ๐ You're ready to start building with Adminator. | |||
| @ -0,0 +1,126 @@ | |||
| --- | |||
| title: Adminator Documentation | |||
| description: Complete guide for the Adminator Bootstrap 5 Admin Dashboard Template | |||
| --- | |||
| # Adminator Documentation | |||
| Welcome to the comprehensive documentation for **Adminator**, a modern Bootstrap 5 admin dashboard template with dark mode support. | |||
| ## ๐ Overview | |||
| Adminator is a responsive, feature-rich admin template built with: | |||
| - **Bootstrap 5.3.6** - Latest CSS framework | |||
| - **Dark Mode System** - Complete theme switching with OS detection | |||
| - **Modern Components** - Charts, calendars, maps, and interactive elements | |||
| - **Performance Optimized** - Webpack build system with modern tooling | |||
| ## ๐ Quick Start | |||
| ```bash | |||
| # Clone the repository | |||
| git clone https://github.com/puikinsh/Adminator-admin-dashboard.git | |||
| # Install dependencies | |||
| npm install | |||
| # Start development server | |||
| npm start | |||
| ``` | |||
| Visit `http://localhost:4000` to see Adminator in action. | |||
| ## ๐ Documentation Sections | |||
| ### ๐ [Getting Started](getting-started/) | |||
| - [Installation Guide](getting-started/installation.md) | |||
| - [Project Structure](getting-started/project-structure.md) | |||
| - [Development Workflow](getting-started/development.md) | |||
| - [Build & Deployment](getting-started/build-deployment.md) | |||
| ### ๐จ [Components](components/) | |||
| - [Charts & Data Visualization](components/charts.md) | |||
| - [Forms & Input Elements](components/forms.md) | |||
| - [Tables & Data Display](components/tables.md) | |||
| - [Navigation & Layout](components/navigation.md) | |||
| - [Modals & Overlays](components/modals.md) | |||
| ### ๐ [Dark Mode & Theming](customization/) | |||
| - [Theme System Overview](customization/theme-system.md) | |||
| - [CSS Variables Reference](customization/css-variables.md) | |||
| - [Custom Theme Creation](customization/custom-themes.md) | |||
| - [Component Theming](customization/component-theming.md) | |||
| ### ๐ง [API Reference](api/) | |||
| - [Theme API](api/theme-api.md) | |||
| - [Component APIs](api/component-apis.md) | |||
| - [Utility Functions](api/utilities.md) | |||
| - [Event System](api/events.md) | |||
| ### ๐ก [Examples](examples/) | |||
| - [Basic Setup](examples/basic-setup.md) | |||
| - [Custom Components](examples/custom-components.md) | |||
| - [Theme Integration](examples/theme-integration.md) | |||
| - [Advanced Patterns](examples/advanced-patterns.md) | |||
| ### ๐ [Deployment](deployment/) | |||
| - [Production Build](deployment/production-build.md) | |||
| - [Static Hosting](deployment/static-hosting.md) | |||
| - [CDN Integration](deployment/cdn-integration.md) | |||
| - [Performance Optimization](deployment/performance.md) | |||
| ### ๐ค [Contributing](contributing/) | |||
| - [Development Setup](contributing/development-setup.md) | |||
| - [Code Standards](contributing/code-standards.md) | |||
| - [Pull Request Process](contributing/pull-requests.md) | |||
| - [Issue Templates](contributing/issues.md) | |||
| ## โจ Key Features | |||
| ### ๐ Dark Mode System | |||
| - **Smart Toggle**: Bootstrap-based switch with visual indicators | |||
| - **OS Detection**: Automatically respects user's system preference | |||
| - **Persistent Storage**: Remembers theme choice across sessions | |||
| - **Component Integration**: All elements are theme-aware | |||
| ### ๐ Rich Components | |||
| - **Chart.js Integration**: Line, bar, pie, and radar charts | |||
| - **FullCalendar**: Interactive calendar with event management | |||
| - **DataTables**: Advanced table features with search and pagination | |||
| - **Vector Maps**: Interactive world and regional maps | |||
| - **Google Maps**: Custom styled maps with markers | |||
| ### ๐ ๏ธ Developer Experience | |||
| - **Modern Tooling**: Webpack 5, ESLint 9.x, Sass, PostCSS | |||
| - **Hot Reload**: Instant development feedback | |||
| - **Code Quality**: Automated linting and formatting | |||
| - **Performance**: Optimized builds with code splitting | |||
| ## ๐ Quick Links | |||
| - **[Live Demo](https://colorlib.com/polygon/adminator/index.html)** - See Adminator in action | |||
| - **[GitHub Repository](https://github.com/puikinsh/Adminator-admin-dashboard)** - Source code and issues | |||
| - **[Changelog](https://github.com/puikinsh/Adminator-admin-dashboard/blob/master/CHANGELOG.md)** - Version history | |||
| - **[License](https://github.com/puikinsh/Adminator-admin-dashboard/blob/master/LICENSE)** - MIT License | |||
| ## ๐ What's New in v2.6.0 | |||
| The latest release introduces a comprehensive dark mode system: | |||
| - **๐ Complete Dark Theme** with automatic OS detection | |||
| - **๐จ Theme-Aware Components** for charts, calendars, and maps | |||
| - **โก Instant Switching** without page reload | |||
| - **๐ฏ CSS Variables Architecture** for consistent theming | |||
| - **๐ฑ Responsive Design** across all screen sizes | |||
| [View Full Changelog โ](https://github.com/puikinsh/Adminator-admin-dashboard/blob/master/CHANGELOG.md) | |||
| ## ๐ฌ Support | |||
| - **Issues**: [GitHub Issues](https://github.com/puikinsh/Adminator-admin-dashboard/issues) | |||
| - **Discussions**: [GitHub Discussions](https://github.com/puikinsh/Adminator-admin-dashboard/discussions) | |||
| - **Documentation**: You're here! ๐ | |||
| --- | |||
| **Happy coding with Adminator!** ๐ | |||