Skip to content

Commit

Permalink
Introduce QRating element (#4347)
Browse files Browse the repository at this point in the history
This PR introduces a Rating element based on Quasars QRating
https://quasar.dev/vue-components/rating

---------

Co-authored-by: Falko Schindler <[email protected]>
  • Loading branch information
thetableman and falkoschindler authored Feb 18, 2025
1 parent eec322b commit 13b63b2
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 0 deletions.
52 changes: 52 additions & 0 deletions nicegui/elements/rating.py
Original file line number Diff line number Diff line change
@@ -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 changes: 2 additions & 0 deletions nicegui/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
'query',
'radio',
'range',
'rating',
'refreshable',
'refreshable_method',
'restructured_text',
Expand Down Expand Up @@ -192,6 +193,7 @@
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
Expand Down
18 changes: 18 additions & 0 deletions tests/test_rating.py
Original file line number Diff line number Diff line change
@@ -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 changes: 49 additions & 0 deletions website/documentation/content/rating_documentation.py
Original file line number Diff line number Diff line change
@@ -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 changes: 2 additions & 0 deletions website/documentation/content/section_controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
number_documentation,
radio_documentation,
range_documentation,
rating_documentation,
select_documentation,
slider_documentation,
switch_documentation,
Expand All @@ -39,6 +40,7 @@
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)
Expand Down

0 comments on commit 13b63b2

Please sign in to comment.