Skip to content

Commit e57c9e4

Browse files
committed
feat: 3 states readme EN
1 parent 4b7134c commit e57c9e4

File tree

1 file changed

+229
-0
lines changed
  • scripts/ColorSchemeSwitchThreeStates

1 file changed

+229
-0
lines changed
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# Color Scheme Switch - Three States (Light/Dark/System)
2+
3+
A script for switching between three color schemes: light, dark, and system preference.
4+
5+
> **Icons used** (from [HeroIcons](https://heroicons.com)):
6+
>
7+
> ![View](/../assets/3-states-hero-icons.gif)
8+
9+
## What does this script do?
10+
11+
The script provides functionality for switching between light, dark, and system themes on a website, while preserving user preferences in `localStorage`. It consists of two parts:
12+
13+
### 1. InitScript - Theme initialization on page load
14+
15+
**File:** `init-script.js`
16+
17+
The script runs **before the page renders** (inline in `<head>`) to avoid **FOUC** (Flash of Unstyled Content).
18+
19+
**Behavior:**
20+
- Checks `localStorage.colorScheme` and if the user has previously selected a theme (light or dark), applies it
21+
- If there's no saved preference (system mode), checks system settings (`prefers-color-scheme`)
22+
- Adds the `dark` class to `document.documentElement` when dark theme is active
23+
24+
### 2. SwitchScript - Theme switching
25+
26+
**File:** `switch-script.js`
27+
28+
The script enables cycling between themes via keyboard shortcut (default key `d`).
29+
30+
**Behavior:**
31+
- Exposes the `window.inlineScripts.switchColorScheme()` function for programmatic theme switching
32+
- Listens for keyboard shortcut (default `d`) and cycles through themes: **Dark → Light → System → Dark → ...**
33+
- Saves the selected preference in `localStorage` (or removes it for system mode)
34+
- Intelligently ignores key presses when focus is on input, textarea, select fields or elements with contentEditable
35+
- Dispatches a custom `colorSchemeChanged` event when the theme changes
36+
37+
### 3. View with color scheme icons
38+
39+
A Blade view with light/dark/system theme icons that call the `window.inlineScripts.switchColorScheme()` function when clicked.
40+
41+
## Usage
42+
43+
### Method 1: Using PHP classes
44+
45+
**Step 1:** Add to your `AppServiceProvider`:
46+
47+
```php
48+
use Zmyslny\LaravelInlineScripts\Ready\ColorSchemeSwitchThreeStates\InitScript;
49+
use Zmyslny\LaravelInlineScripts\Ready\ColorSchemeSwitchThreeStates\SwitchScript;
50+
51+
class AppServiceProvider extends ServiceProvider
52+
{
53+
public function boot(): void
54+
{
55+
BladeInlineScripts::take(
56+
new InitScript(), // initializes the theme on page load
57+
new SwitchScript('d') // cycles through themes when 'd' key is pressed
58+
)->registerAs('colorSchemeScripts');
59+
}
60+
}
61+
```
62+
63+
**Step 2:** Insert the Blade directive in your template:
64+
65+
```blade
66+
<html>
67+
<head>
68+
...
69+
@colorSchemeScripts
70+
</head>
71+
<body>
72+
...
73+
```
74+
75+
**Step 3:** Add the view with theme icons:
76+
77+
```bash
78+
php artisan vendor:publish --tag=color-scheme-3-states-views
79+
```
80+
81+
Select the appropriate view and insert it in your template:
82+
- Blade + TailwindCss + Hero icons: `../views/color-scheme-switch-three-states/hero-icons-tailwind.blade.php`
83+
- Livewire/Alpine + TailwindCss + Hero icons: `../views/color-scheme-switch-three-states/hero-icons-tailwind-alpine.blade.php`
84+
85+
### Method 2: Direct JS file usage
86+
87+
**Step 1:** Publish the built-in scripts:
88+
89+
```bash
90+
php artisan vendor:publish --tag=color-scheme-3-states-js
91+
```
92+
93+
This will copy the scripts to `resources/js/color-scheme-switch-three-states/[init-script.js, switch-script.js]`.
94+
95+
**Step 2:** Register the scripts in `AppServiceProvider`:
96+
97+
```php
98+
class AppServiceProvider extends ServiceProvider
99+
{
100+
public function boot(): void
101+
{
102+
BladeInlineScripts::takeFiles(
103+
[
104+
resource_path('js/color-scheme-switch-three-states/init-script.js'),
105+
['__DARK__' => 'dark'], // variables to replace in the script
106+
],
107+
[
108+
resource_path('js/color-scheme-switch-three-states/switch-script.js'),
109+
['__DARK__' => 'dark', '__LIGHT__' => 'light', '__TOGGLE_KEY__' => 'd'],
110+
]
111+
)->registerAs('colorSchemeScripts');
112+
}
113+
}
114+
```
115+
116+
**Step 3:** Insert the Blade directive in your template (same as in Method 1).
117+
118+
## Configuration
119+
120+
### Changing the toggle key
121+
122+
By default, the script uses the `d` key to cycle through themes. You can change this by passing a different key to the `SwitchScript` constructor:
123+
124+
```php
125+
new SwitchScript('t') // use 't' key instead of 'd'
126+
```
127+
128+
**Requirements:** The key must be a single lowercase letter (a-z).
129+
130+
### Changing CSS class names
131+
132+
By default, the script adds the `dark` class to the `<html>` element. You can change this by editing the values in the `SchemeTypeEnum` enum:
133+
134+
```php
135+
enum SchemeTypeEnum: string
136+
{
137+
case DARK = 'dark';
138+
case LIGHT = 'light';
139+
case SYSTEM = 'system';
140+
}
141+
```
142+
143+
Or when using direct JS files, by changing the placeholders:
144+
145+
```php
146+
['__DARK__' => 'dark-mode', '__LIGHT__' => 'light-mode']
147+
```
148+
149+
## Programmatic theme switching
150+
151+
The script exposes a function for programmatic theme switching:
152+
153+
```javascript
154+
window.inlineScripts.switchColorScheme();
155+
```
156+
157+
You can use it, for example, in a button click handler:
158+
159+
```html
160+
<button onclick="window.inlineScripts.switchColorScheme()">
161+
Toggle theme
162+
</button>
163+
```
164+
165+
## Custom event: colorSchemeChanged
166+
167+
The script dispatches a custom event whenever the theme changes, which you can listen to:
168+
169+
```javascript
170+
document.addEventListener('colorSchemeChanged', (event) => {
171+
console.log('Previous scheme:', event.detail.previousScheme);
172+
console.log('Current scheme:', event.detail.currentScheme);
173+
});
174+
```
175+
176+
This is useful if you need to perform additional actions when the theme changes.
177+
178+
## File structure
179+
180+
```
181+
ColorSchemeSwitchThreeStates/
182+
├── InitScript.php # PHP class for theme initialization
183+
├── SwitchScript.php # PHP class for theme switching
184+
├── SchemeTypeEnum.php # Enum with theme values (dark/light/system)
185+
├── js/
186+
│ ├── init-script.js # Initialization script (inline in <head>)
187+
│ └── switch-script.js # Switching script (inline in <head>)
188+
└── view/
189+
├── hero-icons-tailwind.blade.php # View with icons (Blade + Tailwind)
190+
└── hero-icons-tailwind-alpine.blade.php # View with icons (Alpine + Tailwind)
191+
```
192+
193+
## How does it work?
194+
195+
1. **On page load:** `init-script.js` checks the saved preference or system preferences and immediately applies the appropriate theme
196+
2. **Switching:** After pressing the keyboard shortcut or clicking the icons, `switch-script.js` cycles through themes in the order: **Dark → Light → System → Dark**
197+
3. **System mode:** When in system mode, `localStorage.colorScheme` is removed, and the theme follows the operating system's preference
198+
4. **Subsequent visits:** On the next page load, `init-script.js` will read the saved preference (or system settings if no preference is saved) and apply it before the page renders
199+
200+
## Theme cycling explained
201+
202+
The three-state variant cycles through themes in the following order:
203+
204+
1. **Dark** - Explicitly sets dark theme (saves `"dark"` in localStorage)
205+
2. **Light** - Explicitly sets light theme (saves `"light"` in localStorage)
206+
3. **System** - Follows system preference (removes the value from localStorage)
207+
208+
When in system mode, the script checks `prefers-color-scheme` media query to determine which theme to apply.
209+
210+
## Testing
211+
212+
You can publish unit tests for the JS scripts:
213+
214+
```bash
215+
php artisan vendor:publish --tag=color-scheme-3-states-js-tests
216+
```
217+
218+
Or publish everything at once (JS scripts, tests, and views):
219+
220+
```bash
221+
php artisan vendor:publish --tag=color-scheme-3-states-all
222+
```
223+
224+
## Difference between Two States and Three States
225+
226+
- **Two States:** Switching between light and dark theme (2 states)
227+
- **Three States:** Cycling between light, dark, and system theme (3 states)
228+
229+
The three-state variant is useful when you want to give users the option to follow their operating system's color scheme preference, in addition to explicitly choosing light or dark mode.

0 commit comments

Comments
 (0)