-
-
Notifications
You must be signed in to change notification settings - Fork 492
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1176 from zauberzeug/carousel
Introduce a carousel element
- Loading branch information
Showing
5 changed files
with
104 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
from __future__ import annotations | ||
|
||
from typing import Any, Callable, Optional, Union, cast | ||
|
||
from .. import globals | ||
from .mixins.disableable_element import DisableableElement | ||
from .mixins.value_element import ValueElement | ||
|
||
|
||
class Carousel(ValueElement): | ||
|
||
def __init__(self, *, | ||
value: Union[str, CarouselSlide, None] = None, | ||
on_value_change: Optional[Callable[..., Any]] = None, | ||
animated: bool = False, | ||
arrows: bool = False, | ||
navigation: bool = False, | ||
) -> None: | ||
"""Carousel | ||
This element represents `Quasar's QCarousel <https://quasar.dev/vue-components/carousel#qcarousel-api>`_ component. | ||
It contains individual carousel slides. | ||
:param value: `ui.carousel_slide` or name of the slide to be initially selected (default: `None` meaning the first slide) | ||
:param on_value_change: callback to be executed when the selected slide changes | ||
:param animated: whether to animate slide transitions (default: `False`) | ||
:param arrows: whether to show arrows for manual slide navigation (default: `False`) | ||
:param navigation: whether to show navigation dots for manual slide navigation (default: `False`) | ||
""" | ||
super().__init__(tag='q-carousel', value=value, on_value_change=on_value_change) | ||
self._props['animated'] = animated | ||
self._props['arrows'] = arrows | ||
self._props['navigation'] = navigation | ||
|
||
def _value_to_model_value(self, value: Any) -> Any: | ||
return value._props['name'] if isinstance(value, CarouselSlide) else value | ||
|
||
def on_value_change(self, value: Any) -> None: | ||
super().on_value_change(value) | ||
names = [slide._props['name'] for slide in self] | ||
for i, slide in enumerate(self): | ||
done = i < names.index(value) if value in names else False | ||
slide.props(f':done={done}') | ||
|
||
def next(self) -> None: | ||
self.run_method('next') | ||
|
||
def previous(self) -> None: | ||
self.run_method('previous') | ||
|
||
|
||
class CarouselSlide(DisableableElement): | ||
|
||
def __init__(self, name: Optional[str] = None) -> None: | ||
"""Carousel Slide | ||
This element represents `Quasar's QCarouselSlide <https://quasar.dev/vue-components/carousel#qcarouselslide-api>`_ component. | ||
It is a child of a `ui.carousel` element. | ||
:param name: name of the slide (will be the value of the `ui.carousel` element, auto-generated if `None`) | ||
""" | ||
super().__init__(tag='q-carousel-slide') | ||
self.carousel = cast(ValueElement, globals.get_slot().parent) | ||
name = name or f'slide_{len(self.carousel.default_slot.children)}' | ||
self._props['name'] = name | ||
if self.carousel.value is None: | ||
self.carousel.value = name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from nicegui import ui | ||
|
||
from .screen import Screen | ||
|
||
|
||
def test_carousel(screen: Screen): | ||
with ui.carousel(arrows=True).props('control-color=primary'): | ||
for name in ['Alice', 'Bob', 'Carol']: | ||
with ui.carousel_slide(): | ||
ui.label(name).classes('w-32') | ||
|
||
screen.open('/') | ||
screen.should_contain('Alice') | ||
screen.click('chevron_right') | ||
screen.should_contain('Bob') | ||
screen.click('chevron_right') | ||
screen.should_contain('Carol') | ||
screen.click('chevron_left') | ||
screen.should_contain('Bob') | ||
screen.click('chevron_left') | ||
screen.should_contain('Alice') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from nicegui import ui | ||
|
||
|
||
def main_demo() -> None: | ||
with ui.carousel(animated=True, arrows=True, navigation=True).props('height=180px'): | ||
with ui.carousel_slide().classes('p-0'): | ||
ui.image('https://picsum.photos/id/30/270/180').classes('w-[270px]') | ||
with ui.carousel_slide().classes('p-0'): | ||
ui.image('https://picsum.photos/id/31/270/180').classes('w-[270px]') | ||
with ui.carousel_slide().classes('p-0'): | ||
ui.image('https://picsum.photos/id/32/270/180').classes('w-[270px]') |
a3e1e96
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rodja you're so fast pushing out the awesome updates! love the carousel :)
Did you take some time to set up a way to donate to the project yet?
I've built a nice(GUI) looking webshop using this library and I'd love to support the continued development of it.
a3e1e96
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @frankhuurman. We are on our way to build a saas solution around NiceGUI: https://nicegui.io/documentation#nicegui_on_air
It's quite new and not ready for receiving payments, but it will be done. That's gonna be a great way to support us. And spread the word. There are way too many Python developers still struggling with GUI and web.