Add Light/Dark Mode Theme Switcher with System Preference Support
It would be great if the Contracts Wizard could include the ability for users to switch between light mode and dark mode, or automatically use the system’s theme preference. This feature would improve the user experience, especially for those who prefer a dark interface for readability and eye comfort while also aligning with modern web development standards.
@ericglau, what do you think about this. Can I start working on it ?
Thanks for the suggestion, this makes sense to add.
Currently the Wizard and its styling are spread across many different html pages (e.g. the pages in packages/ui/public when choosing different languages) and Svelte components (the Svelte apps in packages/ui/src).
One challenge here is to come up with a way to track the desired theme (light/dark) and keep it consistent when the user is moving between different parts of the UI.
Feel free to take a look at this, but if you have thoughts on an approach for tracking and applying the theme selection, please share as a first step so that we can ensure it fits with the overall design. Thanks!
@ericglau Hey, can you assign this to me? I want to help
@Patrick-Ehimen Hey, can you assign this to me? I want to help
I already started work on this
Hey @Patrick-Ehimen we have a design for this which I believe may prove useful -
This is the prototype: https://www.figma.com/proto/nG5OZYG8UEyAT2dDJ0nXeJ/Wizard?page-id=1178%3A8494&node-id=1178-8495&p=f&viewport=-295%2C-430%2C0.32&t=LqNZq0CyFrfROINx-1&scaling=min-zoom&content-scaling=fixed&starting-point-node-id=1178%3A8495
you may need reset the prototype by tapping R first.
and this is the dev mode link: https://www.figma.com/design/gVk2uq2Z1U9aNjXv0nVSGP/Wizard%2F-Dark-Mode?node-id=0-1&m=dev
Let me or @ericglau know if we can help in any way.
@makiopen this looks clean and intuitive, thanks for sharing.
Thanks for the suggestion, this makes sense to add.
Currently the Wizard and its styling are spread across many different html pages (e.g. the pages in
packages/ui/publicwhen choosing different languages) and Svelte components (the Svelte apps inpackages/ui/src).One challenge here is to come up with a way to track the desired theme (light/dark) and keep it consistent when the user is moving between different parts of the UI.
Feel free to take a look at this, but if you have thoughts on an approach for tracking and applying the theme selection, please share as a first step so that we can ensure it fits with the overall design. Thanks!
had a busy week, i will try finishing this during the weekend
Proposed Solution for Theme Management
After analyzing the codebase, I'd like to propose a centralized approach for managing themes across the Contracts Wizard UI. This solution ensures consistent theme handling across both Svelte components and static HTML pages.
Key Features
- Global theme state management using Svelte store
- Persistent theme preferences via localStorage
- System theme preference detection
- Consistent theme application across all UI components
- Smooth theme transitions
Implementation Overview
-
Theme Store Create a centralized store
(packages/ui/src/common/stores/themeStore.ts)to manage the theme state. -
Theme Initialization
(packages/ui/src/common/theme-init.ts)Early theme initialization to prevent flash of wrong theme. -
CSS Variables Define theme variables in
packages/ui/src/common/styles/vars.css.
:root {
/* Light theme defaults */
--text-color: #333333;
--background-color: #ffffff;
}
[data-theme="dark"] {
--text-color: #ffffff;
--background-color: #1a1a1a;
}
- Theme Toggle Component Add a reusable theme toggle component that can be included in the navigation
<script lang="ts">
import { theme } from '../stores/themeStore';
</script>
<button on:click={() => theme.toggle()} class="theme-toggle">
{#if $theme === 'dark'}
<svg><!-- Sun icon --></svg>
{:else}
<svg><!-- Moon icon --></svg>
{/if}
</button>
Implementation Plan
- Add theme store and initialization scripts
- Update HTML entry points with theme initialization
- Replace hard-coded colors with theme variables
- Add theme toggle to navigation
- Update build configuration to include theme scripts
@ericglau @makiopen Would love to get feedback on this approach before proceeding with the implementation. Let me know if you'd like me to elaborate on any part of the solution.
@Patrick-Ehimen Thanks for sharing, that approach sounds reasonable. Here are a few notes which may help with the implementation:
-
There may be some updates needed for styles in files other than
packages/ui/src/common/styles/vars.css.- For example, the styles in these files might be relevant:
packages/ui/src/common/styles/global.css,packages/ui/src/solidity/App.svelte(and also App.svelte for the other languages: cairo, stellar, stylus). - If any of these have styles that are not using variables from
packages/ui/src/common/styles/vars.css, it may make sense to change them to do so (if they are relevant for light/dark theme).
- For example, the styles in these files might be relevant:
-
The main HTML entry points which include the navigation bar are static HTML pages:
packages/ui/public/index.html,packages/ui/public/cairo.html,packages/ui/public/stellar.html,packages/ui/public/stylus.html. Due to this, it may be difficult to use the Theme Toggle Component for the toggle button if that is a Svelte component. The Svelte app is only within the embedded<oz-wizard ...>section in those pages. -
Wizard is also embedded in other sites, for example in https://docs.openzeppelin.com/contracts/5.x/wizard. The embedding method is described in https://github.com/OpenZeppelin/contracts-wizard?tab=readme-ov-file#embedding and is also the same method used in the HTML entry points above. The code for the embed is in
packages/ui/src/embed.ts.- When embedded from other sites, it would be good to ignore the locally stored theme preference, as the theme setting should be determined by the site which embeds it. Instead, the site should be able to explicitly set the desired theme, for example by providing a parameter for
<oz-wizard ...>(which relates to the URL parameters idea above, see example).
- When embedded from other sites, it would be good to ignore the locally stored theme preference, as the theme setting should be determined by the site which embeds it. Instead, the site should be able to explicitly set the desired theme, for example by providing a parameter for
Thank you for your inputs @ericglau If there are no objections or additional requirements, I would like to start working on this feature and tackle any arising issues along the way
@Patrick-Ehimen Sounds good, thanks.
@Patrick-Ehimen Sounds good, thanks.
LFG 🚀🚀