Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,64 @@
import { Controller } from '@hotwired/stimulus';

const STORAGE_KEY = 'sylius-theme';
const MODES = ['light', 'dark', 'auto'];

export default class extends Controller {
static targets = ['option'];

connect() {
this.onStorage = (event) => {
if (event.key === STORAGE_KEY || event.key === null) {
this.render();
}
};
window.addEventListener('storage', this.onStorage);
this.render();
}

disconnect() {
window.removeEventListener('storage', this.onStorage);
}

select(event) {
const mode = event.params.mode;

if (!MODES.includes(mode)) {
return;
}

this.apply(mode);
}

toggle() {
const current = document.documentElement.getAttribute('data-bs-theme') || 'light';
const next = current === 'dark' ? 'light' : 'dark';
localStorage.setItem('sylius-theme', next);
document.documentElement.setAttribute('data-bs-theme', next);

this.apply(current === 'dark' ? 'light' : 'dark');
}

apply(mode) {
if (mode === 'auto') {
localStorage.removeItem(STORAGE_KEY);
} else {
localStorage.setItem(STORAGE_KEY, mode);
}

const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = mode === 'auto' ? (prefersDark ? 'dark' : 'light') : mode;

document.documentElement.setAttribute('data-theme-mode', mode);
document.documentElement.setAttribute('data-bs-theme', theme);

this.render();
}

render() {
const mode = document.documentElement.getAttribute('data-theme-mode') || 'auto';

this.optionTargets.forEach((option) => {
const active = option.dataset.themeSwitcherModeParam === mode;
option.classList.toggle('active', active);
option.setAttribute('aria-pressed', active ? 'true' : 'false');
});
}
}
19 changes: 11 additions & 8 deletions src/BootstrapAdminUi/assets/styles/_body.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
--bs-tertiary-bg: #{$body-bg};
--bs-body-color: #{$body-color};
}

[data-theme-switch="light"] {
display: none;
}
}

@include color-mode(dark) {
Expand Down Expand Up @@ -67,15 +63,22 @@
border-color: var(--tblr-border-color);
}

[data-theme-switch="dark"] {
display: none;
}

.empty-img img {
filter: invert(0.9) hue-rotate(180deg);
}
}

[data-theme-switch] {
display: none;
}

:root:not([data-theme-mode]) [data-theme-switch="auto"],
[data-theme-mode="light"] [data-theme-switch="light"],
[data-theme-mode="dark"] [data-theme-switch="dark"],
[data-theme-mode="auto"] [data-theme-switch="auto"] {
display: inline-block;
}

a {
text-underline-offset: 0.25em;
}
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapAdminUi/public/app.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/BootstrapAdminUi/public/app.rtl.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/BootstrapAdminUi/public/symfony_ux.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
<div class="nav-item" {{ stimulus_controller('theme-switcher') }}>
<button class="btn btn-icon btn-ghost-secondary" {{ stimulus_action('theme-switcher', 'toggle') }} aria-label="Toggle theme">
{{ ux_icon('tabler:sun', {'class': 'icon', 'data-theme-switch': 'light'}) }}
{{ ux_icon('tabler:moon', {'class': 'icon', 'data-theme-switch': 'dark'}) }}
{% set modes = {
light: 'tabler:sun',
dark: 'tabler:moon',
auto: 'tabler:device-desktop',
} %}

<div class="nav-item dropdown" {{ stimulus_controller('theme-switcher') }}>
<button type="button" class="btn btn-icon btn-ghost-secondary" data-bs-toggle="dropdown" aria-expanded="false" aria-label="{{ 'sylius.ui.toggle_theme'|trans }}" title="{{ 'sylius.ui.toggle_theme'|trans }}">
{% for mode, icon in modes %}
{{ ux_icon(icon, {'class': 'icon', 'data-theme-switch': mode}) }}
{% endfor %}
</button>
<div class="dropdown-menu dropdown-menu-end">
{% for mode, icon in modes %}
<button
type="button"
class="dropdown-item"
{{ stimulus_target('theme-switcher', 'option') }}
{{ stimulus_action('theme-switcher', 'select', 'click', {mode: mode}) }}
{{ sylius_test_html_attribute('theme-switcher-option', mode) }}
>
{{ ux_icon(icon, {'class': 'icon dropdown-item-icon'}) }}
{{ ('sylius.ui.theme_' ~ mode)|trans }}
</button>
{% endfor %}
</div>
</div>
19 changes: 16 additions & 3 deletions src/BootstrapAdminUi/templates/shared/layout/theme.html.twig
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
<script>
(function() {
const stored = localStorage.getItem('sylius-theme');
const theme = stored || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-bs-theme', theme);
const root = document.documentElement;
const media = window.matchMedia('(prefers-color-scheme: dark)');
const getMode = () => {
const stored = localStorage.getItem('sylius-theme');

return stored === 'light' || stored === 'dark' ? stored : 'auto';
};
const apply = () => {
const mode = getMode();
root.setAttribute('data-theme-mode', mode);
root.setAttribute('data-bs-theme', mode === 'auto' ? (media.matches ? 'dark' : 'light') : mode);
};

apply();
media.addEventListener('change', apply);
window.addEventListener('storage', (event) => (event.key === 'sylius-theme' || event.key === null) && apply());
})();
</script>
4 changes: 4 additions & 0 deletions src/UiTranslations/translations/messages.de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ sylius:
show: 'Anzeigen'
starts_with: 'Beginnt mit'
success: 'Erfolgreich'
theme_auto: 'Automatisch'
theme_dark: 'Dunkel'
theme_light: 'Hell'
this_form_contains_errors: 'Dieses Formular enthält Fehler.'
to: 'Bis'
toggle_theme: 'Design wechseln'
unable_to_copy_to_clipboard: 'Kopieren in die Zwischenablage nicht möglich'
update: 'Aktualisieren'
value: 'Wert'
Expand Down
Loading
Loading