diff --git a/.cspell-project-words.txt b/.cspell-project-words.txt new file mode 100644 index 0000000..c75afa3 --- /dev/null +++ b/.cspell-project-words.txt @@ -0,0 +1,27 @@ +adminlte +colorlib +dropbutton +dropbuttons +tabledrag +treeview +navbar +subnav +fontsource +popperjs +Popper +woff +Frobieter +grevil +DROWL +Bircher +displace +tertiary +subtle +breadcrumb +breadcrumbs +Nightwatch +stylelint +phpcs +phpstan +cspell +eslint diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..1fb0684 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,28 @@ +################ +# GitLabCI template for Drupal projects. +# +# This uses the official GitLabCI template maintained by the Drupal Association, +# which runs the standard contrib test/lint jobs (phpcs, phpstan, eslint, +# stylelint, cspell, phpunit) against this theme. +# +# For information on customising jobs, variables and adding/skipping jobs, see: +# https://project.pages.drupalcode.org/gitlab_templates/ +################ + +include: + - project: $_GITLAB_TEMPLATES_REPO + ref: $_GITLAB_TEMPLATES_REF + file: + - '/includes/include.drupalci.main.yml' + - '/includes/include.drupalci.variables.yml' + - '/includes/include.drupalci.workflows.yml' + +variables: + # Skip Nightwatch/functional-JS jobs by default: this theme ships no custom + # test suite yet, and the lint/static-analysis jobs are the ones tracked in + # https://www.drupal.org/project/adminlte/issues/3607152 + SKIP_ESLINT: '0' + SKIP_STYLELINT: '0' + SKIP_PHPSTAN: '0' + SKIP_PHPCS: '0' + SKIP_CSPELL: '0' diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a1a850..e98dd6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,69 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +### Added + +- **Primary/accent colour picker** in theme settings — recolours links, focus + rings, active states and `.btn-primary` + ([#3608660](https://www.drupal.org/project/adminlte/issues/3608660)). +- **Drag-resizable sidebar** with a localStorage-persisted width and a + configurable default width setting + ([#3609296](https://www.drupal.org/project/adminlte/issues/3609296)). +- **Bootstrap Icons pack** for Drupal's Icon API (`adminlte.icons.yml`) — optional, + activates when `ui_icons` (`ui_icons_font`) is enabled + ([#3609048](https://www.drupal.org/project/adminlte/issues/3609048)). +- **Components demo** at `docs/components.html` + ([#3608677](https://www.drupal.org/project/adminlte/issues/3608677)). +- **Bootstrap-grid layouts** for Layout Builder (`adminlte.layouts.yml`) — one, + two, content+sidebar, three and four column, under the *AdminLTE* category + ([#3609456](https://www.drupal.org/project/adminlte/issues/3609456)). +- **UI Suite integration** — ship `small-box`, `info-box` and `callout` as Single + Directory Components; UI Patterns 2 surfaces them in Layout Builder, Views and + field formatters. Optional (works standalone on core SDC); `drupal/ui_patterns` + added as a Composer *suggest* + ([#3608703](https://www.drupal.org/project/adminlte/issues/3608703)). +- Bundle **Source Sans 3** (the default AdminLTE/Bootstrap body font) locally — + weights 300/400/700, Latin + Latin-Extended, under the SIL OFL. The intended + default typography now renders without a CDN or a system-installed font + ([#3609458](https://www.drupal.org/project/adminlte/issues/3609458)). +- Theme setting **Start with the sidebar collapsed** — first-load `sidebar-collapse` + ([#3608687](https://www.drupal.org/project/adminlte/issues/3608687)). +- Theme setting **Compact mode** — denser shell via `compact-mode` + ([#3608663](https://www.drupal.org/project/adminlte/issues/3608663)). +- Theme setting **Force RTL layout** — `dir="rtl"` + the bundled RTL stylesheet. + (RTL site languages already auto-load `adminlte.rtl.css`.) + ([#3608661](https://www.drupal.org/project/adminlte/issues/3608661)). +- `.gitlab-ci.yml` using the Drupal Association contrib CI template, plus a + cspell project dictionary + ([#3607152](https://www.drupal.org/project/adminlte/issues/3607152)). +- README: navigation-block guidance (frontend vs. admin theme), a CSS Editor + recommendation, and a first-party-by-Colorlib note + ([#3608681](https://www.drupal.org/project/adminlte/issues/3608681), + [#3608659](https://www.drupal.org/project/adminlte/issues/3608659), + [#3608672](https://www.drupal.org/project/adminlte/issues/3608672)). + +### Changed + +- **Base theme is now Bootstrap5** instead of the deprecated Stable9. This + supplies Drupal core-markup glue CSS (fields, forms, tables, pager, messages) + and adds a `drupal/bootstrap5` dependency; AdminLTE keeps its own bundled + Bootstrap build (Bootstrap5's CSS/JS is disabled) + ([#3609244](https://www.drupal.org/project/adminlte/issues/3609244), + [#3608934](https://www.drupal.org/project/adminlte/issues/3608934)). +- **Dark sidebar is now off by default** — the sidebar follows the active + light/dark colour mode unless the setting is enabled + ([#3608682](https://www.drupal.org/project/adminlte/issues/3608682)). +- Login / register / reset-password pages render as a centred, constrained card + instead of spanning the full content width + ([#3608688](https://www.drupal.org/project/adminlte/issues/3608688)). + +### Fixed + +- Lower the `.app-header` / `.app-sidebar` z-index below Drupal's admin toolbar + so the toolbar (and Admin Toolbar Search autocomplete) is no longer hidden + behind the theme chrome + ([#3608932](https://www.drupal.org/project/adminlte/issues/3608932)). + ## [1.0.0-beta1] - 2026-06-29 First public release. Official **AdminLTE 4** admin theme for **Drupal 10.3+ / 11** diff --git a/README.md b/README.md index 6c08132..d5b4234 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ Official **AdminLTE 4** admin theme for **Drupal** — Bootstrap 5.3, vanilla JS (no jQuery), light & dark colour modes. Self-contained: all assets are bundled locally, no CDN required. By [Colorlib](https://colorlib.com). +> ✅ **Officially created and maintained by [Colorlib](https://colorlib.com)** — +> the authors of [AdminLTE](https://github.com/ColorlibHQ/AdminLTE) itself. This +> is the first-party Drupal port, not a third-party reskin. + Verified on **Drupal 11.3** (PHP 8.5): clean install, no errors/warnings in the log, all admin screens render with the AdminLTE shell in both colour modes. @@ -43,6 +47,11 @@ The same AdminLTE 4 dashboard, in the framework you know best — you're looking - Drupal **10.3+** or **11** - PHP 8.1+ (as required by your Drupal core version) +- The [**Bootstrap5**](https://www.drupal.org/project/bootstrap5) base theme + (`drupal/bootstrap5`, `^4.0`). AdminLTE builds on it for Drupal's core-markup + "glue" CSS. Composer pulls it in automatically; for a manual install, download + and place it in `themes/contrib/bootstrap5` as well. AdminLTE still bundles its + own Bootstrap 5.3 build, so Bootstrap5's own CSS/JS is disabled. ## Installation @@ -93,8 +102,38 @@ At `/admin/appearance/settings/adminlte`: - **Default colour mode** — `auto` (follow OS), `light` or `dark`. Visitors can override it with the navbar toggle; their choice is remembered in the browser. -- **Dark sidebar** — render the sidebar dark regardless of page mode (applied via - `data-bs-theme="dark"` on the sidebar). +- **Dark sidebar** — render the sidebar dark regardless of the page colour mode + (applied via `data-bs-theme="dark"` on the sidebar). *Off by default* — the + sidebar follows the active light/dark mode unless you enable this. +- **Start with the sidebar collapsed** — render the sidebar collapsed to icons on + first load (adds `sidebar-collapse sidebar-mini`). Visitors can still expand it. +- **Compact mode** — tighten spacing across the shell (adds `compact-mode`) for + information-heavy admin screens. +- **Force right-to-left (RTL) layout** — force `dir="rtl"` and the bundled RTL + stylesheet on every page. You usually don't need this: for RTL **site + languages** Drupal already loads `adminlte.rtl.css` automatically (via the + `.rtl.css` naming convention). Use the setting only to force RTL on an + LTR-language site. + +For customisation beyond these settings (colours, spacing, etc.), AdminLTE 4 is +driven by [CSS variables](https://adminlte.io/themes/v4/docs/customization.html). +To edit CSS without touching theme files or writing a subtheme, the +[CSS Editor](https://www.drupal.org/project/css_editor) module lets you add +custom CSS straight from the admin UI. + +## Navigation blocks: frontend vs. admin theme + +AdminLTE works both as a **frontend** theme (for applications, intranets and +dashboards) and as an **administration** theme. Two navigation blocks are placed +in the `sidebar` region on install, so you can pick whichever fits your use case: + +- **Main navigation** — your site's own menu. Use this when AdminLTE is the + **default (frontend) theme** for an app-style site. This is the primary use case. +- **Administration** — Drupal's admin menu as a collapsible treeview with + per-section icons. Use this when AdminLTE is set as the **administration + theme** (`/admin/appearance` → *Administration theme*). + +Remove or rearrange either block at `/admin/structure/block` to suit your build. ## What's bundled @@ -104,9 +143,52 @@ At `/admin/appearance/settings/adminlte`: | `js/adminlte.js` | AdminLTE behaviours (sidebar, treeview) | | `js/vendor/bootstrap.bundle.min.js` | Bootstrap 5.3 + Popper | | `css/vendor/bootstrap-icons.min.css` + fonts | Bootstrap Icons 1.13 | +| `css/vendor/source-sans-3.css` + fonts | Source Sans 3 (default body font, weights 300/400/700, [OFL](css/vendor/fonts/OFL.txt)) | Everything is served from the theme — no external CDN calls. +## Icons (Drupal Icon API) + +The theme ships a **Bootstrap Icons** pack for Drupal's [Icon API](https://www.drupal.org/docs/develop/drupal-apis/icon-api) +(`adminlte.icons.yml`, all ~2,000 icons). It's an **optional** integration: install +the [UI Icons](https://www.drupal.org/project/ui_icons) module and enable its +`ui_icons_font` submodule (the Icon API is in core from 11.1; `ui_icons` backports +it to 10.3–11.0), and the pack appears in every icon picker — menu-link icons, +CKEditor, fields, etc. — using the already-bundled font. Nothing extra to download, +and the theme works fine without it. + +## Component reference + +Open [`docs/components.html`](docs/components.html) in a browser (straight from +the theme folder — no Drupal needed) for a self-contained showcase of the +AdminLTE 4 / Bootstrap 5.3 components this theme provides: buttons, cards, +tables, forms, tabs, pagination, alerts, badges and icons, in both colour modes. + +## Site building: layouts & components + +**Bootstrap layouts** — the theme ships five Bootstrap-grid layouts for +**Layout Builder** (and the *Layout* of display modes), grouped under the +**AdminLTE** category: one column, two columns (½ + ½), content + sidebar +(⅔ + ⅓), three columns and four columns. They emit `.row`/`.col-*` markup, so +Layout Builder regions align to the same grid as the rest of the theme — no +extra module required. + +**Components (SDC / UI Suite)** — three signature AdminLTE widgets ship as +[Single Directory Components](https://www.drupal.org/docs/develop/theming-drupal/using-single-directory-components): +`small-box`, `info-box` and `callout`. Use them in any Twig template: + +```twig +{{ include('adminlte:small-box', { + value: '150', label: 'New orders', icon: 'bag', + color: 'primary', url: '/admin/content' +}) }} +``` + +They work standalone on core SDC. Install +[UI Patterns 2](https://www.drupal.org/project/ui_patterns) (`drupal/ui_patterns`) +to surface them — with auto-generated config forms — in **Layout Builder, Views +and field formatters**, integrating the theme with the **UI Suite** ecosystem. + ## Tested Verified against a clean **Drupal 11.3.13** install (standard profile, PHP 8.5): diff --git a/adminlte.icons.yml b/adminlte.icons.yml new file mode 100644 index 0000000..d61eea3 --- /dev/null +++ b/adminlte.icons.yml @@ -0,0 +1,38 @@ +# Bootstrap Icons pack for the Drupal Icon API (core 11.1+, or the ui_icons +# contrib backport on 10.3–11.0). Uses the "font" extractor from the +# ui_icons_font submodule, so this pack activates only when that module is +# enabled — it is an optional integration, not a hard dependency. +# See https://www.drupal.org/project/adminlte/issues/3609048 +bootstrap_icons: + enabled: true + label: 'Bootstrap Icons' + description: 'Bootstrap Icons 1.13, bundled with the AdminLTE theme and rendered as font icons.' + links: + - https://icons.getbootstrap.com + version: 1.13.1 + license: + name: MIT + url: 'https://github.com/twbs/icons/blob/main/LICENSE' + gpl-compatible: true + extractor: font + config: + sources: + - css/vendor/bootstrap-icons.json + settings: + size: + title: 'Size (px)' + type: integer + default: 16 + class: + title: 'Additional CSS class' + type: string + # The class must be exact, so do NOT run icon_id through clean_class here. + template: >- + + # Loads the bundled Bootstrap Icons webfont CSS so the glyphs render. + library: 'adminlte/bootstrap_icons' + preview: >- + diff --git a/adminlte.info.yml b/adminlte.info.yml index 1538ec3..46e06d1 100644 --- a/adminlte.info.yml +++ b/adminlte.info.yml @@ -3,7 +3,11 @@ type: theme description: 'Official AdminLTE 4 admin theme for Drupal — Bootstrap 5.3, vanilla JS (no jQuery), light & dark modes. By Colorlib.' package: AdminLTE core_version_requirement: ^10.3 || ^11 -base theme: stable9 +# Bootstrap5 is a maintained base theme that supplies Drupal "glue" CSS for core +# markup (field--label-inline, forms, tables, pager, messages …) that Stable9 +# (now deprecated) does not. We inherit that glue but keep AdminLTE's own bundled +# Bootstrap build. See #3609244 (replaces Stable9) and #3608934 (base CSS). +base theme: bootstrap5 screenshot: screenshot.png logo: logo.svg @@ -11,6 +15,20 @@ logo: logo.svg libraries: - adminlte/global-styling +# Keep Bootstrap5's core-markup glue (bootstrap5/base + bootstrap5/messages, both +# in the CSS "component" group) but drop its own compiled Bootstrap CSS and JS — +# AdminLTE already bundles Bootstrap 5.3 (css/adminlte.css) and the Bootstrap JS +# bundle. Our theme-group CSS loads after the inherited component-group CSS, so +# the AdminLTE look wins where the two overlap. +libraries-override: + bootstrap5/global-styling: false + bootstrap5/bootstrap5-js-latest: false + +# Style CKEditor 5 content to match the theme rather than inheriting Bootstrap5's +# css/ck5style.css. +ckeditor5-stylesheets: + - css/adminlte.css + regions: page_top: 'Page top' page_bottom: 'Page bottom' diff --git a/adminlte.layouts.yml b/adminlte.layouts.yml new file mode 100644 index 0000000..4a481b8 --- /dev/null +++ b/adminlte.layouts.yml @@ -0,0 +1,82 @@ +# Bootstrap-grid layouts for Layout Builder / Layout Discovery. Provided directly +# by the theme (no contrib module needed); they output Bootstrap 5 .row/.col +# markup so Layout Builder regions align to the grid AdminLTE ships. +# See https://www.drupal.org/project/adminlte/issues/3609456 +adminlte_one_column: + label: 'AdminLTE: One column' + category: 'AdminLTE' + path: templates/layout/layouts + template: adminlte-one-column + library: adminlte/layouts + default_region: content + icon_map: + - [content] + regions: + content: + label: Content + +adminlte_two_column: + label: 'AdminLTE: Two columns (½ + ½)' + category: 'AdminLTE' + path: templates/layout/layouts + template: adminlte-two-column + library: adminlte/layouts + default_region: first + icon_map: + - [first, second] + regions: + first: + label: First + second: + label: Second + +adminlte_two_column_sidebar: + label: 'AdminLTE: Content + sidebar (⅔ + ⅓)' + category: 'AdminLTE' + path: templates/layout/layouts + template: adminlte-two-column-sidebar + library: adminlte/layouts + default_region: main + icon_map: + - [main, sidebar] + regions: + main: + label: Main + sidebar: + label: Sidebar + +adminlte_three_column: + label: 'AdminLTE: Three columns (⅓ + ⅓ + ⅓)' + category: 'AdminLTE' + path: templates/layout/layouts + template: adminlte-three-column + library: adminlte/layouts + default_region: first + icon_map: + - [first, second, third] + regions: + first: + label: First + second: + label: Second + third: + label: Third + +adminlte_four_column: + label: 'AdminLTE: Four columns' + category: 'AdminLTE' + path: templates/layout/layouts + template: adminlte-four-column + library: adminlte/layouts + default_region: first + icon_map: + - [first, second, third, fourth] + regions: + first: + label: First + second: + label: Second + third: + label: Third + fourth: + label: Fourth diff --git a/adminlte.libraries.yml b/adminlte.libraries.yml index e7b3ca9..e081dcb 100644 --- a/adminlte.libraries.yml +++ b/adminlte.libraries.yml @@ -3,6 +3,8 @@ global-styling: css: # Bootstrap 5.3 is bundled inside adminlte.css, so no separate Bootstrap CSS. theme: + # Source Sans 3 (the default AdminLTE/Bootstrap body font), bundled locally. + css/vendor/source-sans-3.css: {} css/vendor/bootstrap-icons.min.css: { minified: true } css/adminlte.css: { minified: false } css/adminlte-drupal.css: {} @@ -15,3 +17,31 @@ global-styling: - core/drupal - core/drupalSettings - core/once + +# Right-to-left overrides. Drupal loads adminlte.rtl.css automatically for RTL +# site languages via the .rtl.css naming convention; this library is only +# attached when the "Force RTL" theme setting is on, to flip the layout on +# LTR-language sites too. Depends on global-styling so it cascades after it. +rtl: + version: 4.0.2 + css: + theme: + css/adminlte.rtl.css: {} + dependencies: + - adminlte/global-styling + +# Loaded on demand by the Bootstrap Icons pack in adminlte.icons.yml when an icon +# is rendered via the Drupal Icon API. (The webfont CSS is already part of +# global-styling for normal page rendering.) +bootstrap_icons: + version: 1.13.1 + css: + component: + css/vendor/bootstrap-icons.min.css: { minified: true } + +# Spacing/helpers for the theme-provided Bootstrap layouts (adminlte.layouts.yml). +layouts: + version: 4.0.2 + css: + layout: + css/layouts.css: {} diff --git a/adminlte.theme b/adminlte.theme index 115501c..c3dd69a 100644 --- a/adminlte.theme +++ b/adminlte.theme @@ -14,20 +14,129 @@ use Drupal\Core\Url; * Returns the theme's layout settings with sane defaults. * * @return array - * Keyed by: default_color_mode, sidebar_dark. + * Keyed by: default_color_mode, sidebar_dark, sidebar_collapsed, + * compact_mode, force_rtl. */ function _adminlte_layout_settings(): array { return [ 'default_color_mode' => theme_get_setting('default_color_mode', 'adminlte') ?? 'auto', - 'sidebar_dark' => (bool) (theme_get_setting('sidebar_dark', 'adminlte') ?? TRUE), + // The sidebar follows the active colour mode by default; a dark override is + // opt-in (see https://www.drupal.org/project/adminlte/issues/3608682). + 'sidebar_dark' => (bool) (theme_get_setting('sidebar_dark', 'adminlte') ?? FALSE), + 'sidebar_collapsed' => (bool) (theme_get_setting('sidebar_collapsed', 'adminlte') ?? FALSE), + 'compact_mode' => (bool) (theme_get_setting('compact_mode', 'adminlte') ?? FALSE), + 'force_rtl' => (bool) (theme_get_setting('force_rtl', 'adminlte') ?? FALSE), + 'primary_color' => theme_get_setting('primary_color', 'adminlte') ?: NULL, + 'sidebar_width' => theme_get_setting('sidebar_width', 'adminlte') ?: NULL, ]; } +/** + * Builds a CSS override block that recolours the primary accent. + * + * Overrides the Bootstrap primary CSS variables (utilities, links, focus rings) + * plus the `.btn-primary` component variables, since Bootstrap bakes the literal + * default colour into compiled components rather than reading `--bs-primary`. + * + * @param string $hex + * A colour as `#rrggbb` (already normalised by the core 'color' element). + * + * @return string|null + * The CSS, or NULL when the colour is missing or malformed. + */ +function _adminlte_primary_color_css(string $hex): ?string { + if (!preg_match('/^#[0-9a-fA-F]{6}$/', $hex)) { + return NULL; + } + $rgb = static function (float $factor) use ($hex): string { + $r = (int) round(hexdec(substr($hex, 1, 2)) * $factor); + $g = (int) round(hexdec(substr($hex, 3, 2)) * $factor); + $b = (int) round(hexdec(substr($hex, 5, 2)) * $factor); + return "$r, $g, $b"; + }; + $shade = static function (float $factor) use ($hex): string { + return sprintf( + '#%02x%02x%02x', + (int) round(hexdec(substr($hex, 1, 2)) * $factor), + (int) round(hexdec(substr($hex, 3, 2)) * $factor), + (int) round(hexdec(substr($hex, 5, 2)) * $factor) + ); + }; + + $base_rgb = $rgb(1.0); + $hover = $shade(0.85); + $active = $shade(0.75); + + return <<setAttribute('dir', 'rtl'); + } + $variables['#attached']['library'][] = 'adminlte/rtl'; + } + + // Tag the authentication pages (log in, register, reset password) so their + // forms can render as a centred, constrained card instead of spanning the + // full content width. See + // https://www.drupal.org/project/adminlte/issues/3608688 + $auth_routes = ['user.login', 'user.register', 'user.pass']; + if (in_array(\Drupal::routeMatch()->getRouteName(), $auth_routes, TRUE)) { + $variables['attributes']['class'][] = 'adminlte-auth-page'; + } + + // Custom primary/accent colour: inject a small