Skip to content

Enhance login styling and add iframe defenses with dark mode#4

Open
nolderoos wants to merge 11 commits into
mainfrom
feature/login-variables
Open

Enhance login styling and add iframe defenses with dark mode#4
nolderoos wants to merge 11 commits into
mainfrom
feature/login-variables

Conversation

@nolderoos
Copy link
Copy Markdown
Contributor

@nolderoos nolderoos commented May 12, 2026

Adds dark mode + more branding controls to the login screen.

For the admin: three new settings on the Branding page, a link color picker, a light / dark / auto color mode toggle, and a page background image upload. The Branding section splits into "Identity" (logo, brand, colors) and "Appearance" (mode, page, layout) sub-cards, and every settings section is now collapsible.

For visitors: the sign-in screen renders in a curated dark palette when the admin chooses dark, or follows the browser's preference on auto. Any background image sits behind the card, with safe MIME checks, a soft 1 MB warning, and prefers-reduced-data suppression for low-bandwidth users.

A small accessibility guardrail runs at save time, pick a link color that would be unreadable against the card and the change is rejected with an explanation; pick one that's just borderline and it saves with a warning. Same idea catches a brand color that would have a hard-to-see focus ring in dark mode.

Under the hood: a reusable WCAG contrast helper, a memoized settings reader (was being called 7× per login render), and 24 new tests bringing the suite to 165.

Summary by CodeRabbit

  • New Features

    • Collapsible admin settings with a new Appearance panel and expanded branding controls; default UI/theme settings added.
  • UI / Styling

    • Improved disclosure widget styling, adjusted admin spacing, new theme token for links, and explicit dark-mode palettes (including automatic dark mode).
  • Accessibility

    • WCAG contrast checks that warn or block low-contrast branding colors.
  • Security

    • Stronger clickjacking protection (CSP + X-Frame-Options).
  • Tests / Docs

    • New unit tests for contrast and settings sanitization; updated changelog.

Review Change Stack

@nolderoos nolderoos self-assigned this May 12, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d0087791-35e6-49bb-b032-940948ce52d9

📥 Commits

Reviewing files that changed from the base of the PR and between ab13245 and f83f011.

📒 Files selected for processing (1)
  • magicauth.php
✅ Files skipped from review due to trivial changes (1)
  • magicauth.php

📝 Walkthrough

Walkthrough

Adds admin-controlled branding and theming with WCAG contrast utilities, appearance sanitizers, admin collapsible sections, login-shell theme rendering, dark-mode tokens, JS helpers, tests, installer defaults, and login security headers.

Changes

Branding, Theming, and Contrast Validation

Layer / File(s) Summary
Color utilities, settings cache, and contrast tests
includes/helpers.php, tests/phpunit/Model/ContrastRatioTest.php, tests/phpunit/stubs/wp-functions.php
Adds magicauth_hex_to_rgb(), magicauth_contrast_ratio(), and magicauth_contrast_evaluate() plus per-request settings memoization and magicauth_invalidate_settings_cache(); includes unit tests and expanded test stubs for attachments and settings errors.
Settings sanitize(), validators, and admin fields
includes/Admin/Settings.php, tests/phpunit/Model/SettingsSanitizeTest.php
Extends Settings::sanitize() for appearance keys (page_color, card_radius/width, font_stack, link_color, background_attachment_id, color_mode), adds sanitize_link_color() and sanitize_background(), constants/allowlists, refactors select rendering via render_select_field(), and renders new Appearance fields; includes comprehensive sanitizer tests.
Admin CSS, root tokens, JS followers, and login template
assets/css/magicauth-admin.css, assets/css/magicauth.css, assets/js/magicauth-admin.js, templates/login-shell.php
Scoped <details>/<summary> styling with custom chevron and focus-visible outline; changed .magicauth-action-row padding; adds --magicauth-color-link and dark-mode palettes; adds initColorFollowers() mirroring behavior; login-shell computes/clamps theme variables and conditionally emits background-image CSS.
Login screen headers, body mode classes, installer defaults, plugin header, and docs
includes/Frontend/LoginScreen.php, includes/Installer.php, magicauth.php, readme.txt
Enforces X-Frame-Options: DENY and Content-Security-Policy: frame-ancestors 'none'; appends `magicauth-mode-{light

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 I hopped through hex and hue,
Measured contrast, true and new,
Admin panels fold with care,
Dark and light now dance in pair,
The login blooms — a themed debut.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.96% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: enhanced login styling (dark mode, color controls, background images) and iframe defenses (CSP/X-Frame headers).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/login-variables

Comment @coderabbitai help to get the list of available commands and usage tips.

@nolderoos nolderoos added the enhancement New feature or request label May 12, 2026
@nolderoos nolderoos marked this pull request as ready for review May 12, 2026 09:28
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
assets/css/magicauth.css (1)

454-454: ⚡ Quick win

Consider extracting the dark surface constant.

The comment notes that --magicauth-color-surface: #181c22`` must match Admin\Settings::DARK_SURFACE_HEX. Hardcoding the same hex in two places creates a maintenance risk—if the PHP constant is updated but the CSS is overlooked, the contrast validation logic will diverge from the rendered surface. Consider dynamically injecting this value via inline styles (similar to how `templates/login-shell.php` emits other theme variables) or documenting this sync requirement more prominently in both locations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/css/magicauth.css` at line 454, The CSS hardcodes
--magicauth-color-surface: `#181c22` which must match the PHP constant
Admin\Settings::DARK_SURFACE_HEX; extract this value so it’s injected
dynamically instead of duplicated. Update the code that renders theme variables
(e.g., templates/login-shell.php) to emit the surface hex into the stylesheet or
as an inline style variable used by magicauth.css (replace the hardcoded
--magicauth-color-surface), or if injection isn’t possible add a prominent
comment linking to Admin\Settings::DARK_SURFACE_HEX to ensure both places stay
in sync.
includes/Admin/Settings.php (2)

35-38: ⚡ Quick win

Hardcoded surface color must stay synchronized with CSS.

The comment correctly notes that DARK_SURFACE_HEX must match the value in magicauth.css. However, there's no automated check to prevent drift. If the CSS value changes without updating this constant, the dark-mode contrast validation will use stale data.

Consider adding a test assertion that parses the CSS file and verifies the surface color matches this constant, or document the sync requirement in both locations more prominently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@includes/Admin/Settings.php` around lines 35 - 38, Add an automated assertion
that the DARK_SURFACE_HEX constant in Settings (Settings::DARK_SURFACE_HEX)
stays in sync with the CSS by parsing the magicauth.css file at test time and
comparing the extracted body/.magicauth-mode-dark surface color token to
Settings::DARK_SURFACE_HEX; implement this as a unit/integration test that fails
when the colors differ so developers must update the constant when changing the
CSS (or vice versa). Ensure the test locates the magicauth.css resource used in
production, extracts the hex value used for body.magicauth-mode-dark or
.magicauth-mode-auto, and asserts equality to the Settings constant, with a
clear failure message indicating which source needs updating.

648-660: ⚡ Quick win

Extract the 1 MB threshold to a constant.

Lines 649 and 656 both reference 1024 * 1024 (1 MB). Extracting this to a named constant (e.g., BACKGROUND_SIZE_SOFT_LIMIT_BYTES) would improve maintainability and make the threshold more discoverable if it needs adjustment.

♻️ Proposed refactor

Near the top of the class:

 	private const BACKGROUND_MIMES = [
 		'png'      => 'image/png',
 		'jpg|jpeg' => 'image/jpeg',
 		'webp'     => 'image/webp',
 	];
+
+	// Soft warning threshold for background images (bytes). Never blocks.
+	private const BACKGROUND_SIZE_SOFT_LIMIT_BYTES = 1024 * 1024; // 1 MB

Then update the function:

-		$size = (int) `@filesize`( $path );
-		if ( $size > 1024 * 1024 ) {
+		$size = (int) `@filesize`( $path );
+		if ( $size > self::BACKGROUND_SIZE_SOFT_LIMIT_BYTES ) {
 			add_settings_error(
 				self::OPTION_NAME,
 				'magicauth_bg_large',
 				sprintf(
 					/* translators: %s: file size in MB */
 					__( 'Background image saved. File is %s MB — consider compressing for faster page load.', 'magicauth' ),
-					number_format( $size / ( 1024 * 1024 ), 1 )
+					number_format( $size / self::BACKGROUND_SIZE_SOFT_LIMIT_BYTES, 1 )
 				),
 				'warning'
 			);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@includes/Admin/Settings.php` around lines 648 - 660, Extract the numeric 1 MB
literal into a class constant and use it in both places; add a class-level
constant (e.g., BACKGROUND_SIZE_SOFT_LIMIT_BYTES = 1024 * 1024) inside the
Settings class in includes/Admin/Settings.php, then replace the two occurrences
of 1024 * 1024 in the method that checks $size (the comparison $size > 1024 *
1024 and the division number_format( $size / ( 1024 * 1024 ), 1 )) with that
constant (use it for the comparison and for converting bytes to MB by dividing
$size by BACKGROUND_SIZE_SOFT_LIMIT_BYTES) so behavior remains identical but the
threshold is discoverable and configurable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@assets/css/magicauth.css`:
- Line 454: The CSS hardcodes --magicauth-color-surface: `#181c22` which must
match the PHP constant Admin\Settings::DARK_SURFACE_HEX; extract this value so
it’s injected dynamically instead of duplicated. Update the code that renders
theme variables (e.g., templates/login-shell.php) to emit the surface hex into
the stylesheet or as an inline style variable used by magicauth.css (replace the
hardcoded --magicauth-color-surface), or if injection isn’t possible add a
prominent comment linking to Admin\Settings::DARK_SURFACE_HEX to ensure both
places stay in sync.

In `@includes/Admin/Settings.php`:
- Around line 35-38: Add an automated assertion that the DARK_SURFACE_HEX
constant in Settings (Settings::DARK_SURFACE_HEX) stays in sync with the CSS by
parsing the magicauth.css file at test time and comparing the extracted
body/.magicauth-mode-dark surface color token to Settings::DARK_SURFACE_HEX;
implement this as a unit/integration test that fails when the colors differ so
developers must update the constant when changing the CSS (or vice versa).
Ensure the test locates the magicauth.css resource used in production, extracts
the hex value used for body.magicauth-mode-dark or .magicauth-mode-auto, and
asserts equality to the Settings constant, with a clear failure message
indicating which source needs updating.
- Around line 648-660: Extract the numeric 1 MB literal into a class constant
and use it in both places; add a class-level constant (e.g.,
BACKGROUND_SIZE_SOFT_LIMIT_BYTES = 1024 * 1024) inside the Settings class in
includes/Admin/Settings.php, then replace the two occurrences of 1024 * 1024 in
the method that checks $size (the comparison $size > 1024 * 1024 and the
division number_format( $size / ( 1024 * 1024 ), 1 )) with that constant (use it
for the comparison and for converting bytes to MB by dividing $size by
BACKGROUND_SIZE_SOFT_LIMIT_BYTES) so behavior remains identical but the
threshold is discoverable and configurable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 79d6bced-0008-472a-b110-ef7f0a46163e

📥 Commits

Reviewing files that changed from the base of the PR and between bbee6d7 and 3b70195.

📒 Files selected for processing (11)
  • assets/css/magicauth-admin.css
  • assets/css/magicauth.css
  • includes/Admin/Settings.php
  • includes/Frontend/LoginScreen.php
  • includes/Installer.php
  • includes/helpers.php
  • readme.txt
  • templates/login-shell.php
  • tests/phpunit/Model/ContrastRatioTest.php
  • tests/phpunit/Model/SettingsSanitizeTest.php
  • tests/phpunit/stubs/wp-functions.php

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/js/magicauth-admin.js`:
- Around line 130-151: The swatch follower isn't initialized on first render so
it can show a stale color until input occurs; call mirrorFromSource() once
during setup when the follower is "connected" to the source: after defining
isConnected() and mirrorFromSource(), check if isConnected() is true and if so
invoke mirrorFromSource() (using the same HEX_RE/normalize logic) so that the
swatch and text are synchronized immediately on load; reference the
functions/variables isConnected, mirrorFromSource, text, sourceText, swatch,
HEX_RE, and normalize when adding this initial call.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 969d80af-9493-449b-b958-1ceb75b12c71

📥 Commits

Reviewing files that changed from the base of the PR and between 3b70195 and d9a7e81.

📒 Files selected for processing (3)
  • assets/css/magicauth-admin.css
  • assets/js/magicauth-admin.js
  • includes/Admin/Settings.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • includes/Admin/Settings.php

Comment thread assets/js/magicauth-admin.js
nolderoos and others added 3 commits May 12, 2026 14:59
Updates the Plugin URI header so the "Visit plugin site" link on the
WordPress Plugins screen resolves to the canonical product page instead
of the GitHub source repo.
- Item 4 (Minor): initialize follower swatch on first render so the
  preview matches the source picker before any user input.
  #4 (comment)
- Item 5 (Nitpick): add prominent bidirectional SYNC-LOCK comments
  cross-referencing the duplicated dark-surface hex in both
  assets/css/magicauth.css and includes/Admin/Settings.php. Chose
  option (c) — option (a) would require injecting only one of nine
  dark-mode tokens via PHP, creating asymmetry vs the eight others
  that legitimately live in CSS.
- Item 6 (Nitpick): same SYNC-LOCK comment on the PHP constant side
  names both CSS line numbers and the cascade direction.
- Item 7 (Nitpick): extract magic number into
  private const BACKGROUND_SIZE_SOFT_LIMIT_BYTES = 1024 * 1024 and
  replace both call sites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Point Plugin URI to plugins.ettic.nl/magicauth
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants