Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Darkmode Toggle Laravel Package

jeremykenedy/laravel-darkmode-toggle

jeremykenedy/laravel-darkmode-toggle provides a simple, ready-to-use dark mode toggle for Laravel applications. Add a Blade component, configure its appearance, and let users switch between light and dark themes with their preference persisted across visits. Lightweight and easy to integrate.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Build vs. buy for theme switching. A dark mode toggle looks trivial and isn't: preference persistence, following prefers-color-scheme, cross-tab sync, ARIA semantics, and per-framework markup add up to real engineering time plus a permanent maintenance tail. This package reduces that to a config block and a Blade / Livewire / Vue / React / Svelte component.
  • Accessibility roadmap and compliance work. v2.0.0 implements the ARIA menu button pattern across all three CSS frameworks and Livewire — aria-haspopup, aria-expanded, role="menu", role="menuitemradio" with aria-checked, Escape-to-close with focus returned to the trigger, ArrowUp/ArrowDown navigation, visible focus styles, and aria-hidden icons so screen readers read the label rather than the glyph. That is a shippable response to an audit finding or a WCAG 2.1 AA commitment without a bespoke component build.
  • Platform upgrade sequencing. The effective floor is now Laravel 12/13 on PHP 8.2+. That is not merely a package constraint — it surfaces Laravel 10/11 CVE-2026-48019 as a platform decision that has to be scheduled regardless of this package.
  • Internationalization commitments. Every label now comes from the package language files; strings were previously hardcoded English while resources/lang/en/darkmode.php shipped unused. Localized dark mode copy becomes a translation task, not a code change.
  • Multi-surface products. Bootstrap 4, Bootstrap 5, Tailwind, Livewire, Vue, React and Svelte are all genuinely supported, and CI now compiles the JS components rather than grepping them. This supports a portfolio where marketing, app and docs surfaces do not share one frontend stack.
  • Ops and configuration ownership. Every config option now reads from environment variables, matching what the README already documented — deployment-time theming with no code change.
  • Server-side preference persistence. The toggle now honours persist_field (it previously read a hardcoded dark_mode column) and the Livewire toggle respects persist_to_server. "Remember my theme across devices" becomes a supported use case rather than a broken one.
  • Native UI consistency. The opt-in color_scheme option mirrors the theme onto the CSS color-scheme property so form controls and scrollbars match — a small but visible quality signal.

When to Consider This Package

Adopt when:

  • You are on Laravel 12 or 13, PHP 8.2–8.5 — the only combinations Composer will now install.
  • You need a dark mode toggle that is accessible out of the box and would otherwise have to be designed, built and audited once per framework.
  • You ship, or expect to ship, on more than one CSS or JS framework.
  • You want preference persisted to the user profile and kept in step across tabs, not just a localStorage flag.
  • You want an upgrade you can take without touching application code: every config key, class name, public property, Blade alias, view name, publish tag and command signature is unchanged, and all three new options ship off.

Look elsewhere or wait when:

  • You are on Laravel 10 or 11. This is not a package decision — those branches carry an unpatched CVE (CVE-2026-48019). Treat it as a platform upgrade project with its own timeline.
  • You are still on PHP 8.0/8.1.
  • A prefers-color-scheme media query plus a few CSS custom properties genuinely covers your need; adding a dependency and a JS bundle is a bad trade for that.
  • You have a strict custom design system the shipped Blade markup won't match — you would be overriding more than you inherit.
  • You need zero-JS / progressive-enhancement-only theming, or cannot ship client-side storage access at all.
  • You require server-rendered theme decisions with no hydration flash and are unwilling to inline the init script.

Caveats to state plainly:

  • data_attribute, color_scheme and sync_across_tabs all ship off. Upgrading changes nothing — and delivers nothing — until you turn them on. Budget the configuration work as part of the upgrade, not after it.
  • v2.0.0 is a major version bump that is explicitly backwards compatible. The breaking surface is the platform floor, not the public API.
  • composer.json still permits Laravel 10/11 to avoid cutting off existing installs, but Composer will not resolve them. Read the requirements, not the constraint string.

How to Pitch It (Stakeholders)

To executives: This is a small, well-maintained dependency that closes a real accessibility gap and eliminates a recurring class of bug — dark mode that flickers, doesn't stick, or breaks on one page. It ships an ARIA-compliant menu button on every framework we might use, instead of one we would build and maintain ourselves. The release also forces a question we need to answer anyway: Laravel 10 and 11 carry an unpatched CVE, and this package now effectively requires Laravel 12/13. That framework upgrade is the real project; the package upgrade is a side effect and is backwards compatible once we are there. The ask is to sequence the package bump inside the Laravel 12/13 workstream and decide whether to enable the three new opt-in options this cycle or next.

To engineering: v2.0.0 is a low-risk upgrade. Every config key, class name, public property, Blade component alias, view name, publish tag and command signature is unchanged; all new config ships off by default; and a backwards-compatibility contract test now pins the public API. The changelog is mostly fixes to things that were quietly broken: the Vue component used a v-click-outside directive that was never defined and threw on mount, React/Vue/Svelte didn't follow prefers-color-scheme changes in System mode, unguarded localStorage threw on page load, an empty class_name emitted classList.toggle(''), a stored preference outside light/dark/system painted one theme then switched to another, the toggle read a hardcoded column rather than persist_field, the Livewire toggle ignored persist_to_server and sync_across_tabs, darkmode:switch and darkmode:update reported success without changing anything when DARKMODE_CSS/DARKMODE_FRONTEND were set, .env matching was a substring check, and darkmode:install --css=material --no-interaction wrote an unsupported framework. The darkmode-js publish tag now exists, so the Vue/React/Svelte components actually land at the import path the README documents. Tests went from 105 to 355, and CI gained PHPStan level 6, composer validate --strict, composer audit, a real frontend compile job, and PHP 8.5 in the matrix.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource