From 0a419163a366b1138052efb53f28ad1ff38d5704 Mon Sep 17 00:00:00 2001 From: Dmytro Date: Sat, 3 Oct 2026 16:32:58 +0300 Subject: [PATCH 1/2] Keep the theme switch inline in the utility nav The switch's li was display: flex, which is block-level. ActiveAdmin lays the utility nav out with inline items, so the switch broke the row and stacked the username, theme switch and logout. Use inline-flex, and make css_check fail if any utility-nav item becomes block-level. --- app/assets/stylesheets/wigu/active_admin_theme.scss | 6 ++++-- test/css_check.rb | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/wigu/active_admin_theme.scss b/app/assets/stylesheets/wigu/active_admin_theme.scss index d4ee1aa..fc98e4e 100644 --- a/app/assets/stylesheets/wigu/active_admin_theme.scss +++ b/app/assets/stylesheets/wigu/active_admin_theme.scss @@ -441,8 +441,10 @@ body.active_admin { // $skinMenuTextColor like every other item in the bar. // On the li, not only the anchor: font-size 0 collapses the anchor to the // icon's own 16px, which then sits at the top of the item instead of on - // the line the rest of the bar shares. - > li#theme_toggle { display: flex; align-items: center; } + // the line the rest of the bar shares. inline-flex, not flex: ActiveAdmin + // lays the utility nav out as `li { display: inline }`, and a block-level + // item breaks the row, dropping the items after it onto new lines. + > li#theme_toggle { display: inline-flex; align-items: center; vertical-align: middle; } > li#theme_toggle > a { display: flex; align-items: center; diff --git a/test/css_check.rb b/test/css_check.rb index 47d4b84..ec04c93 100644 --- a/test/css_check.rb +++ b/test/css_check.rb @@ -118,6 +118,16 @@ def self.run "they out-specify $skinMenuTextColor and render invisible on a light panel" end + # ActiveAdmin keeps the utility nav on one line with `li { display: inline }`. + # A block-level item (flex, block, grid) breaks that row and stacks the + # username, theme switch and logout on top of each other. + utility = compile(GOOD["defaults"]).scan(/^[^{}]*#utility_nav\s*>\s*li[^{}\s,]*\s*\{[^}]*\}/m) + blocky = utility.select { |rule| rule =~ /^\s*display:\s*(?:flex|block|grid)\s*;/ } + unless blocky.empty? + failures << "utility nav: #{blocky.size} item rule(s) make the li block-level and break the inline row: " \ + "#{blocky.map { |rule| rule[/\A[^{]*/].strip }.join(", ")}" + end + if failures.empty? drift = readme_table_matches_declarations unless drift.empty? From 0be6cd9685886be36c77ba1608f0d1458d71c527 Mon Sep 17 00:00:00 2001 From: Dmytro Date: Sat, 3 Oct 2026 16:38:51 +0300 Subject: [PATCH 2/2] Make the status tag label colour configurable, white by default Add and use it in the status-tag mixin. --- README.md | 1 + .../stylesheets/wigu/active_admin_theme.scss | 14 ++++++++------ test/css_check.rb | 4 +++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 36ec413..60a5a10 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,7 @@ set variables: | `$skinActiveTabTextColor` / `$skinActiveTabTextColorDark` | `$skinMainSecondColor` / `#7cc0ec` | selected tab label | | `$skinInactiveTabTextColor` / `$skinInactiveTabTextColorDark` | `#5e6469` / `#b0b8c2` | inactive tab label | | `$skinTableHeaderTextColor` / `$skinTableHeaderTextColorDark` | `#5e6469` / `#dde2e8` | index-table column header text | +| `$skinStatusTagTextColor` | `#ffffff` | status tag label; `#000000` passes WCAG AA on every fill | | `$skinTabPaddingY` | `8px` | tab height | | `$skinTabPaddingX` | `15px` | tab label horizontal padding (text → border) | diff --git a/app/assets/stylesheets/wigu/active_admin_theme.scss b/app/assets/stylesheets/wigu/active_admin_theme.scss index fc98e4e..e0220f8 100644 --- a/app/assets/stylesheets/wigu/active_admin_theme.scss +++ b/app/assets/stylesheets/wigu/active_admin_theme.scss @@ -131,6 +131,8 @@ $skinInactiveTabTextColorDark: #b0b8c2!default; // Index-table column header text, one colour for sortable and plain headers. $skinTableHeaderTextColor: #5e6469!default; $skinTableHeaderTextColorDark: #dde2e8!default; +// Status tag label, the same on every filled tag in both modes. +$skinStatusTagTextColor: #ffffff!default; //DARK-MODE PALETTE---------------------------------------------------------------------------------------------------// // Semantic CSS custom properties for runtime light/dark switching. Light values @@ -301,7 +303,8 @@ $theme-icon-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/s skinInactiveTabTextColor: $skinInactiveTabTextColor, skinInactiveTabTextColorDark: $skinInactiveTabTextColorDark, skinTableHeaderTextColor: $skinTableHeaderTextColor, - skinTableHeaderTextColorDark: $skinTableHeaderTextColorDark + skinTableHeaderTextColorDark: $skinTableHeaderTextColorDark, + skinStatusTagTextColor: $skinStatusTagTextColor ) { @if type-of($value) != color { @error "$#{$name} must be a color (use `transparent`, not `none`), got `#{$value}`."; @@ -1415,11 +1418,10 @@ input[type='radio'] { @mixin status-tag-colors($c) { background: $c; border-color: mix($c, #000000, 84%); // = darken($c) — outline in the fill colour - // Black, not white: the five fills below are mid-tone, and white lands - // between 2.35 and 3.78 against them — under the 4.5 WCAG AA asks for text - // this small. Black gives at least 5.56 on every one of them. #1a1d21 was - // the first thing tried and misses by 0.02 on the error red. - color: #000000; + // The five fills below are mid-tone: white lands between 2.35 and 3.78 + // against them, under the 4.5 WCAG AA asks for text this small. Set + // $skinStatusTagTextColor: #000000 for at least 5.56 on every one of them. + color: $skinStatusTagTextColor; } //CONTENT (both modes)-----------------------------------------------------------// diff --git a/test/css_check.rb b/test/css_check.rb index ec04c93..0c1bd93 100644 --- a/test/css_check.rb +++ b/test/css_check.rb @@ -26,6 +26,7 @@ module CssCheck # The panel header pair is documented as taking a custom property, so the # colour guard has to let one through. "panel header as a custom property" => '$skinPanelHeaderColor: var(--aa-surface);', + "black status tag labels" => '$skinStatusTagTextColor: #000000;', "repainted palette" => '$skinPageBgColor: #fafafa; $skinSurfaceColor: #ffffff; $skinTextColor: #202020; $skinLinkColor: #0b5;', }.freeze @@ -45,6 +46,7 @@ module CssCheck "$skinTextColor: none" => '$skinTextColor: none;', "$skinLinkColorDark: none" => '$skinLinkColorDark: none;', "$skinPanelHeaderColor as a length" => '$skinPanelHeaderColor: 10px;', + "$skinStatusTagTextColor: none" => '$skinStatusTagTextColor: none;', }.freeze # The variables table in the README is the public contract people configure @@ -75,7 +77,7 @@ def self.readme_table_matches_declarations end end - DECLARED_ROWS = 52 + DECLARED_ROWS = 53 def self.load_paths activeadmin = Gem::Specification.find_by_name("activeadmin").gem_dir