Лучшая практика для переключаемых тем Vaadin 12
В настоящее время я нахожусь в процессе переноса приложения Vaadin 8 на Vaadin 12. Внешний вид должен использоваться пользователем и изменяться при входе в систему или при нажатии кнопки.
В нашем приложении Vaadin 8 у нас было 2 темы (темная и светлая), каждая со своим собственным SASS/CSS и некоторыми общими свойствами. Пользователь смог переключить его с помощью метода setTheme(). Когда произошел щелчок по кнопке переключения, внешний вид просто изменился. В Vaadin 12 Theming следует другому подходу, и я изо всех сил пытаюсь найти хороший способ реализовать эту функцию в Vaadin 12.
Допустим, мы не хотим создавать совершенно новую тему, а просто хотим использовать настроенный LUMO. Я могу установить тему / вариант с помощью аннотации @Theme. Недостаток: тема будет исправлена во время выполнения.
Также я мог бы просто написать код для применения вариантов к моему приложению и компонентам. (например, в главе "Динамическое моделирование": https://vaadin.com/docs/flow/element-api/tutorial-dynamic-styling.html). Недостаток: перебирать каждый элемент и применять вариант.
Мой вопрос сейчас:
Каков наилучший способ добиться переключения между темами во время выполнения? (индивидуальные светлые и темные варианты Lumo или любой другой темы).
Могу ли я просто создать 2 HTML-файла (для совместимости), содержащих CSS, а затем каким-то образом переопределить используемый в настоящее время файл с помощью динамического импорта?
Я надеюсь, что мой вопрос ясен, и кто-то может указать мне правильное направление.
2 ответа
Если вас интересует только переключение между светлым и темным, вы можете просто добавить / удалить dark
на очень высоком месте в DOM. Например, элементом пользовательского интерфейса обычно является body
или, по крайней мере, очень высоко.
Например:
new Checkbox("Use Dark Theme").tap{
addValueChangeListener{ cb ->
getUI().ifPresent(){ ui ->
def themeList = ui.getElement().getThemeList()
if (cb.value) {
themeList.add(Lumo.DARK)
} else {
themeList.remove(Lumo.DARK)
}
}
}
}
редактировать
Как просили в комментариях другой ответ:
Чтобы изменить цвета в теме, вы можете переопределить используемые цвета. Вот пример того, как изменить цвет текста для светлой и темной темы Lumo:
html {
--lumo-body-text-color: red;
}
[theme~="dark"] {
--lumo-body-text-color: yellow;
}
Относительно легко переключаться между двумя разными вариантами одной и той же темы, например темным и светлым вариантами Lumo. Для этого вам нужно всего лишь переключить соответствующий theme
атрибут на <html>
элемент. Прямой доступ к этому элементу с сервера отсутствует, но вы можете сделать это с помощью небольшого фрагмента JavaScript: ui.getPage().executeJavaScript("document.documentElement.setAttribute($0, $1)", "theme", "dark");
В зависимости от обстоятельств вы можете или должны применить изменения к <body>
элемент вместо В этом случае вы можете либо отключить .documentElement
за .body
в фрагменте JS или непосредственно использовать ui.getElement().setAttribute("theme", "dark")
на Яве.
Переключение между двумя различными базовыми темами, например, Lumo vs Material, гораздо сложнее. Для каждого компонента одновременно может быть загружена только одна базовая тема в браузере, и перезагрузка страницы - единственный способ избавиться от уже загруженной. Для каждого компонента, используемого для Flow, платформа заботится о загрузке правильного импорта темы в дополнение к базовому импорту, который не имеет стилей. Чтобы сделать вещи еще сложнее, тема обозначена с помощью @Theme
автоматически включается в производственный пакет приложения. Чтобы иметь возможность использовать несколько базовых тем, вам также нужно как-то создать несколько разных пакетов, а также каким-то образом настроить Flow на использование правильного пакета в зависимости от обстоятельств.