From adf6c00df2f27986f859e8d5d7aae72e43b1352d Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Tue, 17 Feb 2026 07:06:37 -0500 Subject: [PATCH 1/7] Add user guide and developer/designer guide for Modern theme - USER_GUIDE.md: Installation, dashboard features, dark mode, sidebar, customizer panel, color presets, content tracking, layout options, module widgets setup, system info, FAQ - DEVELOPER_GUIDE.md: Architecture overview, request lifecycle, template system, CSS design tokens, JS architecture, widget system internals, data flow diagrams, customization recipes (new colors, charts, sidebar sections, SVG icons, header elements), i18n, performance notes Co-Authored-By: Claude Opus 4.6 --- .../themes/modern/docs/DEVELOPER_GUIDE.md | 1037 +++++++++++++++++ .../system/themes/modern/docs/USER_GUIDE.md | 443 +++++++ 2 files changed, 1480 insertions(+) create mode 100644 htdocs/modules/system/themes/modern/docs/DEVELOPER_GUIDE.md create mode 100644 htdocs/modules/system/themes/modern/docs/USER_GUIDE.md diff --git a/htdocs/modules/system/themes/modern/docs/DEVELOPER_GUIDE.md b/htdocs/modules/system/themes/modern/docs/DEVELOPER_GUIDE.md new file mode 100644 index 000000000..21653e1cd --- /dev/null +++ b/htdocs/modules/system/themes/modern/docs/DEVELOPER_GUIDE.md @@ -0,0 +1,1037 @@ +# Modern Admin Theme — Developer & Designer Guide + +An in-depth technical reference for designers and developers who want to understand, customize, or extend the Modern admin theme. + +## Table of Contents + +- [Architecture Overview](#architecture-overview) +- [File Structure](#file-structure) +- [Request Lifecycle](#request-lifecycle) +- [Template System](#template-system) +- [CSS Architecture](#css-architecture) +- [JavaScript Architecture](#javascript-architecture) +- [The Widget System](#the-widget-system) +- [Data Flow Reference](#data-flow-reference) +- [Customization Recipes](#customization-recipes) +- [Creating a New Color Preset](#creating-a-new-color-preset) +- [Adding a Dashboard Section](#adding-a-dashboard-section) +- [Adding a Sidebar Section](#adding-a-sidebar-section) +- [Replacing Emoji Icons with SVG](#replacing-emoji-icons-with-svg) +- [Adding a New Chart](#adding-a-new-chart) +- [Modifying the Header](#modifying-the-header) +- [Adding a New Template Partial](#adding-a-new-template-partial) +- [Creating Module Widgets](#creating-module-widgets) +- [Internationalization](#internationalization) +- [Performance Considerations](#performance-considerations) +- [Testing](#testing) +- [Compatibility Notes](#compatibility-notes) + +--- + +## Architecture Overview + +The Modern theme is a XOOPS admin GUI theme that extends `XoopsSystemGui`. It consists of: + +``` +┌─────────────────────────────────────────────────┐ +│ PHP Layer (modern.php) │ +│ - Extends XoopsSystemGui │ +│ - Queries DB for stats, charts, widgets │ +│ - Assigns all Smarty template variables │ +├─────────────────────────────────────────────────┤ +│ Template Layer (theme.tpl + xotpl/*.tpl) │ +│ - Smarty 3 with <{ }> delimiters │ +│ - Modular partials (head, sidebar, dashboard) │ +│ - Data bridge: PHP → JSON → JavaScript │ +├─────────────────────────────────────────────────┤ +│ CSS Layer (css/*.css) │ +│ - Design tokens via CSS custom properties │ +│ - Light mode defaults, dark mode overrides │ +│ - fixes.css for XOOPS core !important rules │ +├─────────────────────────────────────────────────┤ +│ JavaScript Layer (js/*.js) │ +│ - jQuery-based, no build step │ +│ - theme.js: sidebar, dark mode, messages │ +│ - charts.js: Chart.js integration │ +│ - customizer.js: settings panel + cookies │ +├─────────────────────────────────────────────────┤ +│ Widget Layer (class/ + widgets/) │ +│ - ModernThemeWidgetInterface contract │ +│ - WidgetLoader: auto-discovery + sort │ +│ - 11 pre-built module widgets │ +└─────────────────────────────────────────────────┘ +``` + +Key design principles: +- **No build tooling** — Plain CSS, plain JS, no Sass/Webpack/npm required +- **CSS custom properties** — All colors, spacing, and shadows use `var()` tokens +- **Progressive enhancement** — Works without JavaScript (charts and customizer degrade gracefully) +- **Cookie-based persistence** — No database tables, no module configs, no server-side storage +- **Auto-discovery** — Widgets load automatically from module directories + +--- + +## File Structure + +``` +modern/ +├── modern.php # Theme class (XoopsGuiModern extends XoopsSystemGui) +├── theme.tpl # Root HTML document template +├── menu.php # System admin menu builder +│ +├── class/ +│ ├── ModuleWidgetInterface.php # Widget contract (3 methods) +│ └── WidgetLoader.php # Widget auto-discovery engine +│ +├── css/ +│ ├── modern.css # Design tokens + full light-mode styles (~1200 lines) +│ ├── dark.css # Dark mode variable overrides (~200 lines) +│ └── fixes.css # !important overrides for XOOPS core CSS (~300 lines) +│ +├── js/ +│ ├── theme.js # Core: sidebar toggle, dark mode, help, messages +│ ├── charts.js # Chart.js initialization, dark mode sync, content filter +│ ├── customizer.js # Settings panel, color presets, cookie management +│ └── dashboard.js # Table hover, refresh button +│ +├── xotpl/ # Smarty template partials +│ ├── xo_metas.tpl # meta tags + $xoops_module_header +│ ├── xo_scripts.tpl # Placeholder for inline scripts +│ ├── xo_head.tpl # Header bar (brand, services, dark mode toggle) +│ ├── xo_sidebar.tpl # Left sidebar navigation +│ ├── xo_toolbar.tpl # Placeholder for breadcrumb/toolbar +│ ├── xo_dashboard.tpl # Dashboard: KPIs, charts, widgets, system info +│ ├── xo_widgets.tpl # Widget card renderer (iterates $module_widgets) +│ ├── xo_page.tpl # Module content area + admin links bar +│ ├── xo_customizer.tpl # Slide-in settings panel + FAB button +│ └── xo_footer.tpl # Footer bar +│ +├── language/english/ +│ ├── main.php # ~63 language constants (_MODERN_* prefix) +│ └── index.php # Security guard +│ +├── widgets/ # Pre-built widget files (copy to module dirs) +│ ├── alumni/class/ModernThemeWidget.php +│ ├── jobs/class/ModernThemeWidget.php +│ ├── newbb/class/ModernThemeWidget.php +│ ├── news/class/ModernThemeWidget.php +│ ├── pedigree/class/ModernThemeWidget.php +│ ├── protector/class/ModernThemeWidget.php +│ ├── publisher/class/ModernThemeWidget.php +│ ├── realestate/class/ModernThemeWidget.php +│ ├── tdmdownloads/class/ModernThemeWidget.php +│ ├── vision2026/class/ModernThemeWidget.php +│ └── xblog/class/ModernThemeWidget.php +│ +├── icons/ # System service icons (PNG) +├── images/ # Theme images +├── docs/ # Documentation +└── tests/ # Compatibility tests +``` + +--- + +## Request Lifecycle + +When an admin page loads, execution flows through: + +``` +1. XOOPS bootstrap (include/common.php) + ↓ +2. admin.php dispatches to the active admin GUI + ↓ +3. XoopsSystemGui loads modern.php + ↓ +4. xoops_loadLanguage('main', 'system/themes/modern') + → Defines all _MODERN_* constants + ↓ +5. XoopsGuiModern::header() + ├── parent::header() → XoopsSystemGui base initialization + ├── Asset injection → Chart.js, jQuery, theme CSS/JS via $xoTheme + ├── getSystemInfo($tpl) → PHP/MySQL/server info → Smarty vars + ├── getEnhancedStats($tpl) → User count queries → 'enhanced_stats' + ├── getUserStats($tpl) → 6-month registration loop → JSON strings + ├── getModuleStats($tpl) → Module count via CriteriaCompo + ├── getContentStats($tpl) → SHOW TABLES + COUNT per module → JSON + ├── loadModuleWidgets($tpl) → WidgetLoader discovery → 'module_widgets' + ├── ComposerInfo::getComposerInfo($tpl) + └── buildMenu($tpl) → Navigation arrays → Smarty vars + ↓ +6. Smarty renders theme.tpl + ├── xo_metas.tpl → with $xoops_module_header (CSS/JS) + ├── xo_head.tpl → Fixed header bar + ├── xo_sidebar.tpl → Left navigation + ├── xo_dashboard.tpl → Dashboard (only on admin.php homepage) + │ └── Emits window.XOOPS_DASHBOARD_DATA (JSON bridge) + ├── xo_page.tpl → Module content + ├── xo_footer.tpl → Footer + └── xo_customizer.tpl → Settings panel + ↓ +7. JavaScript executes (in order): + ├── theme.js → Dark mode, sidebar, help, messages + ├── dashboard.js → Table hover interactions + ├── charts.js → Reads XOOPS_DASHBOARD_DATA, builds Chart.js instances + └── customizer.js → Restores cookie preferences, binds UI controls +``` + +--- + +## Template System + +### Smarty Delimiters + +XOOPS uses custom Smarty delimiters. **Never** use standard `{` `}` delimiters: + +```smarty +<{$variable}> ← Variable output +<{$variable|escape:'html'}> ← Escaped output (XSS prevention) +<{foreach from=$items item=row}> ← Control structure +<{if $condition}>...<{/if}> ← Conditional +<{include file="$theme_tpl/xo_head.tpl"}> ← Partial include +<{$smarty.const._MODERN_LABEL}> ← Language constant +``` + +### Template Hierarchy + +`theme.tpl` is the root document. It includes all partials via the `$theme_tpl` variable: + +```smarty +<{include file="$theme_tpl/xo_metas.tpl"}> +``` + +The `$theme_tpl` variable resolves to the `xotpl/` directory path. All partials are included by name, making it easy to override individual templates. + +### Key Smarty Variables + +These variables are assigned by `modern.php` and available in all templates: + +| Variable | Type | Source | +|----------|------|--------| +| `$xoops_sitename` | string | Site configuration | +| `$xoops_dirname` | string | Current module dirname | +| `$dark_mode` | string | Cookie value ('0' or '1') | +| `$theme_url` | string | URL to theme directory | +| `$enhanced_stats` | array | User statistics | +| `$user_chart_data` | JSON string | Registration chart data | +| `$group_stats` | JSON string | Group distribution data | +| `$content_stats` | JSON string | Content per module | +| `$module_widgets` | array | Widget data keyed by dirname | +| `$control_menu` | array | Control panel nav items | +| `$module_menu` | array | Module nav items | +| `$mod_options` | array | Current module admin icons | +| `$system_services` | array | System admin service icons | +| `$modules` | array | Module list for dashboard grid | +| `$composerPackages` | array | Installed Composer packages | + +### Adding a Template Partial + +1. Create `xotpl/xo_mypartial.tpl` +2. Include it in `theme.tpl`: + +```smarty +<{include file="$theme_tpl/xo_mypartial.tpl"}> +``` + +3. Assign any needed variables in `modern.php`: + +```php +$tpl->assign('my_data', $data); +``` + +--- + +## CSS Architecture + +### Design Token System + +All visual properties flow from CSS custom properties defined in `:root`. This means changing one variable propagates everywhere: + +```css +:root { + /* Layout */ + --sidebar-width: 260px; + --header-height: 64px; + + /* Border Radius */ + --radius-sm: 4px; /* Badges, small elements */ + --radius: 8px; /* Cards, inputs, buttons */ + --radius-lg: 12px; /* Large containers, panels */ + + /* Shadows */ + --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1); + --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1); + --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1); + + /* Brand Colors */ + --primary: #2563eb; /* Main accent (Blue 600) */ + --primary-dark: #1e40af; /* Hover/active (Blue 800) */ + --primary-light: #3b82f6; /* Light accent (Blue 500) */ + --secondary: #64748b; /* Secondary UI (Slate 500) */ + --success: #10b981; /* Success states (Emerald 500) */ + --warning: #f59e0b; /* Warnings (Amber 500) */ + --danger: #ef4444; /* Errors (Red 500) */ + --info: #06b6d4; /* Info (Cyan 500) */ + + /* Backgrounds */ + --bg-primary: #f8fafc; /* Page background (Slate 50) */ + --bg-secondary: #ffffff; /* Cards, sidebar, header */ + --bg-tertiary: #f1f5f9; /* Hover states, alt rows (Slate 100) */ + + /* Text */ + --text-primary: #0f172a; /* Main text (Slate 900) */ + --text-secondary: #475569;/* Subdued text (Slate 600) */ + --text-tertiary: #94a3b8; /* Placeholders (Slate 400) */ + + /* Borders */ + --border: #e2e8f0; /* Standard borders (Slate 200) */ + --border-light: #f1f5f9; /* Subtle separators (Slate 100) */ +} +``` + +### Three-File Strategy + +| File | Purpose | Uses `!important`? | +|------|---------|-------------------| +| `modern.css` | Design tokens, layout, all components | No | +| `dark.css` | Dark mode variable overrides on `body.dark-mode` | No | +| `fixes.css` | Overrides for XOOPS core inline styles | Yes (required) | + +**Why `fixes.css` exists:** XOOPS core and some modules inject inline styles and CSS rules that can't be overridden through normal cascade. `fixes.css` uses `!important` surgically on specific selectors to fix these conflicts. It's organized into numbered sections with comments explaining each override. + +### Dark Mode + +Dark mode is implemented by reassigning all CSS custom properties on the `body.dark-mode` selector in `dark.css`: + +```css +body.dark-mode { + --bg-primary: #0f172a; /* Deep navy */ + --bg-secondary: #1e293b; /* Card backgrounds */ + --bg-tertiary: #334155; /* Hover states */ + --text-primary: #f1f5f9; /* Light text */ + --text-secondary: #cbd5e1; + --text-tertiary: #94a3b8; + --border: #334155; + --border-light: #475569; + /* ... shadows, brand colors adjusted for dark */ +} +``` + +Because all components use `var()` tokens, dark mode works automatically without per-component overrides. + +### Responsive Breakpoints + +| Breakpoint | Behavior | +|------------|----------| +| `> 1024px` | Full desktop layout. Sidebar visible, collapsible to 80px icon-only mode. | +| `≤ 1024px` | Sidebar hidden by default, slides in as overlay via `body.sidebar-open`. Footer and main content span full width. | +| `≤ 768px` | KPIs and charts collapse to single column. Header text shrinks. Customizer panel goes full-width. | + +### Key Layout Selectors + +```css +.modern-header { position: fixed; height: var(--header-height); z-index: 1000; } +.modern-sidebar { width: var(--sidebar-width); position: fixed; z-index: 999; } +.modern-main { margin-left: var(--sidebar-width); padding-top: var(--header-height); } +.modern-footer { margin-left: var(--sidebar-width); } +``` + +When the sidebar collapses (`body.sidebar-open` on desktop), `--sidebar-width` effectively becomes `80px` through explicit rules that override `margin-left`. + +--- + +## JavaScript Architecture + +All JavaScript is vanilla ES5 + jQuery (no ES6 modules, no build step). Each file is a self-contained IIFE or plain script. + +### Load Order + +Scripts are injected by `modern.php` via `$xoTheme->addScript()`: + +1. `jQuery` (from XOOPS core Frameworks) +2. `Chart.js` (local or CDN fallback) +3. `theme.js` — Core UI behaviors +4. `dashboard.js` — Table interactions +5. `charts.js` — Chart initialization +6. `customizer.js` — Settings panel + +### theme.js — Core Behaviors + +``` +initDarkMode() → Reads/writes xoops_dark_mode cookie, toggles body.dark-mode +initSidebarToggle() → Toggles body.sidebar-open on hamburger click +initHelpToggle() → Shows/hides .tips and .xo-help-content, persists in cookie +initMessages() → Moves .errorMsg/.warningMsg to top of .modern-main, + auto-dismisses after 5 seconds +setCookie(name, val, days) → SameSite=Lax, conditional Secure flag +getCookie(name) → Standard cookie reader +``` + +### charts.js — Chart.js Integration + +``` +initCharts() → Entry point, waits for Chart.js to load (500ms retry) +initUserRegistrationChart() → Line chart from window.XOOPS_DASHBOARD_DATA.userChart +initUserGroupChart() → Doughnut chart from .groupStats +initContentChart() → Bar chart from .contentStats (filtered by cookie) +rebuildContentChart(sel) → Live rebuild when customizer changes module selection +updateChartsForTheme() → Updates all chart colors for dark/light mode +``` + +**PHP → JS data bridge:** `xo_dashboard.tpl` emits a `