소스 검색

Merge pull request #783 from zauberzeug/dark-mode

introduce ui.dark_mode
Falko Schindler 2 년 전
부모
커밋
2edd8e1aff
6개의 변경된 파일118개의 추가작업 그리고 0개의 파일을 삭제
  1. 21 0
      nicegui/elements/dark_mode.js
  2. 46 0
      nicegui/elements/dark_mode.py
  3. 1 0
      nicegui/ui.py
  4. 36 0
      tests/test_dark_mode.py
  5. 1 0
      website/documentation.py
  6. 13 0
      website/more_documentation/dark_mode_documentation.py

+ 21 - 0
nicegui/elements/dark_mode.js

@@ -0,0 +1,21 @@
+export default {
+  mounted() {
+    this.update();
+  },
+  updated() {
+    this.update();
+  },
+  methods: {
+    update() {
+      Quasar.Dark.set(this.value === null ? "auto" : this.value);
+      if (window.tailwind) {
+        tailwind.config.darkMode = this.auto ? "media" : "class";
+        if (this.value) document.body.classList.add("dark");
+        else document.body.classList.remove("dark");
+      }
+    },
+  },
+  props: {
+    value: Boolean,
+  },
+};

+ 46 - 0
nicegui/elements/dark_mode.py

@@ -0,0 +1,46 @@
+from typing import Optional
+
+from ..dependencies import register_component
+from .mixins.value_element import ValueElement
+
+register_component('dark_mode', __file__, 'dark_mode.js')
+
+
+class DarkMode(ValueElement):
+    VALUE_PROP = 'value'
+
+    def __init__(self, value: Optional[bool] = False) -> None:
+        """Dark mode
+
+        You can use this element to enable, disable or toggle dark mode on the page.
+        The value `None` represents auto mode, which uses the client's system preference.
+
+        Note that this element overrides the `dark` parameter of the `ui.run` function and page decorators.
+
+        :param value: Whether dark mode is enabled. If None, dark mode is set to auto.
+        """
+        super().__init__(tag='dark_mode', value=value, on_value_change=None)
+
+    def enable(self) -> None:
+        """Enable dark mode."""
+        self.value = True
+
+    def disable(self) -> None:
+        """Disable dark mode."""
+        self.value = False
+
+    def toggle(self) -> None:
+        """Toggle dark mode.
+
+        This method will raise a ValueError if dark mode is set to auto.
+        """
+        if self.value is None:
+            raise ValueError('Cannot toggle dark mode when it is set to auto.')
+        self.value = not self.value
+
+    def auto(self) -> None:
+        """Set dark mode to auto.
+
+        This will use the client's system preference.
+        """
+        self.value = None

+ 1 - 0
nicegui/ui.py

@@ -16,6 +16,7 @@ from .elements.color_input import ColorInput as color_input
 from .elements.color_picker import ColorPicker as color_picker
 from .elements.color_picker import ColorPicker as color_picker
 from .elements.colors import Colors as colors
 from .elements.colors import Colors as colors
 from .elements.column import Column as column
 from .elements.column import Column as column
+from .elements.dark_mode import DarkMode as dark_mode
 from .elements.date import Date as date
 from .elements.date import Date as date
 from .elements.dialog import Dialog as dialog
 from .elements.dialog import Dialog as dialog
 from .elements.expansion import Expansion as expansion
 from .elements.expansion import Expansion as expansion

+ 36 - 0
tests/test_dark_mode.py

@@ -0,0 +1,36 @@
+from nicegui import ui
+
+from .screen import Screen
+
+
+def test_dark_mode(screen: Screen):
+    ui.label('Hello')
+    dark = ui.dark_mode()
+    ui.button('Dark', on_click=dark.enable)
+    ui.button('Light', on_click=dark.disable)
+    ui.button('Auto', on_click=dark.auto)
+    ui.button('Toggle', on_click=dark.toggle)
+
+    screen.open('/')
+    screen.should_contain('Hello')
+    assert screen.find_by_tag('body').get_attribute('class') == 'desktop no-touch body--light'
+
+    screen.click('Dark')
+    screen.wait(0.5)
+    assert screen.find_by_tag('body').get_attribute('class') == 'desktop no-touch body--dark dark'
+
+    screen.click('Auto')
+    screen.wait(0.5)
+    assert screen.find_by_tag('body').get_attribute('class') == 'desktop no-touch body--light'
+
+    screen.click('Toggle')
+    screen.wait(0.5)
+    screen.assert_py_logger('ERROR', 'Cannot toggle dark mode when it is set to auto.')
+
+    screen.click('Light')
+    screen.wait(0.5)
+    assert screen.find_by_tag('body').get_attribute('class') == 'desktop no-touch body--light'
+
+    screen.click('Toggle')
+    screen.wait(0.5)
+    assert screen.find_by_tag('body').get_attribute('class') == 'desktop no-touch body--dark dark'

+ 1 - 0
website/documentation.py

@@ -258,6 +258,7 @@ def create_full() -> None:
 
 
     load_demo(ui.query)
     load_demo(ui.query)
     load_demo(ui.colors)
     load_demo(ui.colors)
+    load_demo(ui.dark_mode)
 
 
     heading('Action')
     heading('Action')
 
 

+ 13 - 0
website/more_documentation/dark_mode_documentation.py

@@ -0,0 +1,13 @@
+from nicegui import ui
+
+
+def main_demo() -> None:
+    dark = ui.dark_mode()
+    # ui.label('Switch mode:')
+    # ui.button('Dark', on_click=dark.enable)
+    # ui.button('Light', on_click=dark.disable)
+    # END OF DEMO
+    l = ui.label('Switch mode:')
+    c = l.parent_slot.parent
+    ui.button('Dark', on_click=lambda: (l.style('color: white'), c.style('background-color: var(--q-dark-page)')))
+    ui.button('Light', on_click=lambda: (l.style('color: default'), c.style('background-color: default')))