ソースを参照

Introduce QRating element (#4347)

This PR introduces a Rating element based on Quasars QRating
https://quasar.dev/vue-components/rating

---------

Co-authored-by: Falko Schindler <falko@zauberzeug.com>
Simon Robinson 2 ヶ月 前
コミット
13b63b24c6

+ 52 - 0
nicegui/elements/rating.py

@@ -0,0 +1,52 @@
+from typing import List, Optional, Union
+
+from ..events import Handler, ValueChangeEventArguments
+from .mixins.disableable_element import DisableableElement
+from .mixins.value_element import ValueElement
+
+
+class Rating(ValueElement, DisableableElement):
+
+    def __init__(self,
+                 value: Optional[float] = None,
+                 max: int = 5,  # pylint: disable=redefined-builtin
+                 icon: Optional[str] = None,
+                 icon_selected: Optional[str] = None,
+                 icon_half: Optional[str] = None,
+                 color: Optional[Union[str, List[str]]] = 'primary',
+                 size: Optional[str] = None,
+                 on_change: Optional[Handler[ValueChangeEventArguments]] = None,
+                 ) -> None:
+        """Rating
+
+        This element is based on Quasar's `QRating <https://quasar.dev/vue-components/rating>`_ component.
+
+        *Added in version 2.12.0*
+
+        :param value: initial value (default: ``None``)
+        :param max: maximum rating, number of icons (default: 5)
+        :param icon: name of icons to be displayed (default: star)
+        :param icon_selected: name of an icon to be displayed when selected (default: same as ``icon``)
+        :param icon_half: name of an icon to be displayed when half-selected (default: same as ``icon``)
+        :param color: color(s) of the icons (Quasar, Tailwind, or CSS colors or ``None``, default: "primary")
+        :param size: size in CSS units, including unit name or standard size name (xs|sm|md|lg|xl), examples: 16px, 2rem
+        :param on_change: callback to execute when selection changes
+        """
+        super().__init__(tag='q-rating', value=value, on_value_change=on_change)
+
+        self._props['max'] = max
+
+        if icon:
+            self._props['icon'] = icon
+
+        if color:
+            self._props['color'] = color
+
+        if icon_selected:
+            self._props['icon-selected'] = icon_selected
+
+        if icon_half:
+            self._props['icon-half'] = icon_half
+
+        if size:
+            self._props['size'] = size

+ 2 - 0
nicegui/ui.py

@@ -83,6 +83,7 @@ __all__ = [
     'query',
     'radio',
     'range',
+    'rating',
     'refreshable',
     'refreshable_method',
     'restructured_text',
@@ -192,6 +193,7 @@ from .elements.pyplot import Pyplot as pyplot
 from .elements.query import Query as query
 from .elements.radio import Radio as radio
 from .elements.range import Range as range  # pylint: disable=redefined-builtin
+from .elements.rating import Rating as rating
 from .elements.restructured_text import ReStructuredText as restructured_text
 from .elements.row import Row as row
 from .elements.scene import Scene as scene

+ 18 - 0
tests/test_rating.py

@@ -0,0 +1,18 @@
+from nicegui import ui
+from nicegui.testing import Screen
+
+
+def test_rating_click(screen: Screen):
+    rating = ui.rating(value=2)
+    ui.label().bind_text_from(rating, 'value', lambda x: f'Value: {x}')
+
+    screen.open('/')
+    rating_icons = screen.find_all_by_class('q-rating__icon-container')
+    rating_icons[0].click()
+    screen.should_contain('Value: 1')
+
+    rating_icons[3].click()
+    screen.should_contain('Value: 4')
+
+    rating_icons[3].click()  # already selected, should unselect
+    screen.should_contain('Value: 0')

+ 49 - 0
website/documentation/content/rating_documentation.py

@@ -0,0 +1,49 @@
+from nicegui import ui
+
+from . import doc
+
+
+@doc.demo(ui.rating)
+def main_demo() -> None:
+    ui.rating(value=4)
+
+
+@doc.demo('Customize icons', '''
+    You can customize name and size of the icons.
+    Optionally, unselected, selected or half-selected values can have different icons.
+''')
+def customize_icons():
+    ui.rating(
+        value=3.5,
+        size='lg',
+        icon='sentiment_dissatisfied',
+        icon_selected='sentiment_satisfied',
+        icon_half='sentiment_neutral',
+    )
+    ui.rating(
+        value=3.5,
+        size='lg',
+        icon='star',
+        icon_selected='star',
+        icon_half='star_half',
+    )
+
+
+@doc.demo('Customize color', '''
+    You can customize the color of the rating either by providing a single color or a range of different colors.
+''')
+def rating_color():
+    ui.rating(value=3, color='red-10')
+    ui.rating(value=5, color=['green-2', 'green-4', 'green-6', 'green-8', 'green-10'])
+
+
+@doc.demo('Maximum rating', '''
+    This demo shows how to change the maximum possible rating
+    as well as binding the value to a slider.
+''')
+def rating_scale():
+    slider = ui.slider(value=5, min=0, max=10)
+    ui.rating(max=10, icon='circle').bind_value(slider)
+
+
+doc.reference(ui.range)

+ 2 - 0
website/documentation/content/section_controls.py

@@ -16,6 +16,7 @@ from . import (
     number_documentation,
     radio_documentation,
     range_documentation,
+    rating_documentation,
     select_documentation,
     slider_documentation,
     switch_documentation,
@@ -39,6 +40,7 @@ doc.intro(checkbox_documentation)
 doc.intro(switch_documentation)
 doc.intro(slider_documentation)
 doc.intro(range_documentation)
+doc.intro(rating_documentation)
 doc.intro(joystick_documentation)
 doc.intro(input_documentation)
 doc.intro(textarea_documentation)