Selaa lähdekoodia

Merge pull request #2527 from zauberzeug/add-list

Introduce `ui.list`, `ui.item`, `ui.item_section` and `ui.item_label`
Falko Schindler 1 vuosi sitten
vanhempi
säilyke
be2f2ad3c7

+ 57 - 0
nicegui/elements/list.py

@@ -0,0 +1,57 @@
+from typing import Any, Callable, Optional
+
+from ..element import Element
+from ..events import ClickEventArguments, handle_event
+from .mixins.disableable_element import DisableableElement
+from .mixins.text_element import TextElement
+
+
+class List(Element):
+
+    def __init__(self) -> None:
+        """List
+
+        A list element based on Quasar's `QList <https://quasar.dev/vue-components/list-and-list-items#qlist-api>`_ component.
+        It provides a container for list items.
+        """
+        super().__init__('q-list')
+
+
+class Item(DisableableElement):
+
+    def __init__(self, *, on_click: Optional[Callable[..., Any]] = None) -> None:
+        """List Item
+
+        Creates a list item based on Quasar's `QItem <https://quasar.dev/vue-components/list-and-list-items#qitem-api>`_ component.
+        The item should be placed inside a list element.
+        """
+        super().__init__(tag='q-item')
+
+        if on_click:
+            self._props['clickable'] = True
+            self.on('click', lambda _: handle_event(on_click, ClickEventArguments(sender=self, client=self.client)))
+
+
+class ItemSection(Element):
+
+    def __init__(self) -> None:
+        """
+        List Item Section
+
+        Creates an item section based on Quasar's `QItemList <https://quasar.dev/vue-components/list-and-list-items#qitemsection-api>`_ component.
+        The section should be placed inside a list item element.
+        """
+        super().__init__('q-item-section')
+
+
+class ItemLabel(TextElement):
+
+    def __init__(self, text: str = '') -> None:
+        """
+        List Item Label
+
+        Creates an item label based on Quasar's `QItemLabel <https://quasar.dev/vue-components/list-and-list-items#qitemlabel-api>`_ component.
+
+        :param text: text to be displayed (default: "")
+        """
+        super().__init__(tag='q-item-label', text=text)

+ 8 - 0
nicegui/ui.py

@@ -32,6 +32,9 @@ __all__ = [
     'image',
     'image',
     'input',
     'input',
     'interactive_image',
     'interactive_image',
+    'item',
+    'item_label',
+    'item_section',
     'joystick',
     'joystick',
     'json_editor',
     'json_editor',
     'keyboard',
     'keyboard',
@@ -41,6 +44,7 @@ __all__ = [
     'line_plot',
     'line_plot',
     'link',
     'link',
     'link_target',
     'link_target',
+    'list',
     'log',
     'log',
     'markdown',
     'markdown',
     'menu',
     'menu',
@@ -148,6 +152,10 @@ from .elements.leaflet import Leaflet as leaflet
 from .elements.line_plot import LinePlot as line_plot
 from .elements.line_plot import LinePlot as line_plot
 from .elements.link import Link as link
 from .elements.link import Link as link
 from .elements.link import LinkTarget as link_target
 from .elements.link import LinkTarget as link_target
+from .elements.list import Item as item
+from .elements.list import ItemLabel as item_label
+from .elements.list import ItemSection as item_section
+from .elements.list import List as list  # pylint: disable=redefined-builtin
 from .elements.log import Log as log
 from .elements.log import Log as log
 from .elements.markdown import Markdown as markdown
 from .elements.markdown import Markdown as markdown
 from .elements.menu import Menu as menu
 from .elements.menu import Menu as menu

+ 24 - 0
tests/test_list.py

@@ -0,0 +1,24 @@
+from nicegui import ui
+from nicegui.testing import Screen
+
+
+def test_clicking_items(screen: Screen):
+    with ui.list():
+        with ui.item(on_click=lambda: ui.notify('Clicked item 1')):
+            with ui.item_section():
+                ui.item_label('Item 1')
+        with ui.item(on_click=lambda: ui.notify('Clicked item 2')):
+            with ui.item_section():
+                ui.item_label('Item 2')
+            with ui.item_section():
+                ui.button('Button').on('click.stop', lambda: ui.notify('Clicked button!'))
+
+    screen.open('/')
+    screen.click('Item 1')
+    screen.should_contain('Clicked item 1')
+
+    screen.click('Item 2')
+    screen.should_contain('Clicked item 2')
+
+    screen.click('Button')
+    screen.should_contain('Clicked button!')

+ 52 - 0
website/documentation/content/list_documentation.py

@@ -0,0 +1,52 @@
+from nicegui import ui
+
+from . import doc
+
+
+@doc.demo(ui.list)
+def main_demo() -> None:
+    with ui.list().props('dense separator'):
+        with ui.item():
+            with ui.item_section():
+                ui.item_label('3 Apples')
+        with ui.item():
+            with ui.item_section():
+                ui.item_label('5 Bananas')
+        with ui.item():
+            with ui.item_section():
+                ui.item_label('8 Strawberries')
+        with ui.item():
+            with ui.item_section():
+                ui.item_label('13 Walnuts')
+
+
+@doc.demo('Items, Sections and Labels', '''
+    List items use item sections to structure their content.
+    Item labels take different positions depending on their props.
+''')
+def contact_list():
+    with ui.list().props('bordered separator'):
+        ui.item_label('Contacts').props('header').classes('text-bold')
+        ui.separator()
+        with ui.item(on_click=lambda: ui.notify('Selected contact 1')):
+            with ui.item_section().props('avatar'):
+                ui.icon('person')
+            with ui.item_section():
+                ui.item_label('Nice Guy')
+                ui.item_label('name').props('caption')
+            with ui.item_section().props('side'):
+                ui.icon('chat')
+        with ui.item(on_click=lambda: ui.notify('Selected contact 2')):
+            with ui.item_section().props('avatar'):
+                ui.icon('person')
+            with ui.item_section():
+                ui.item_label('Nice Person')
+                ui.item_label('name').props('caption')
+            with ui.item_section().props('side'):
+                ui.icon('chat')
+
+
+doc.reference(ui.list, title='Reference for ui.list')
+doc.reference(ui.item, title='Reference for ui.item')
+doc.reference(ui.item_section, title='Reference for ui.item_section')
+doc.reference(ui.item_label, title='Reference for ui.item_label')

+ 6 - 4
website/documentation/content/section_page_layout.py

@@ -1,10 +1,11 @@
 from nicegui import ui
 from nicegui import ui
 
 
 from . import (card_documentation, carousel_documentation, column_documentation, context_menu_documentation,
 from . import (card_documentation, carousel_documentation, column_documentation, context_menu_documentation,
-               dialog_documentation, doc, expansion_documentation, grid_documentation, menu_documentation,
-               notification_documentation, notify_documentation, pagination_documentation, row_documentation,
-               scroll_area_documentation, separator_documentation, space_documentation, splitter_documentation,
-               stepper_documentation, tabs_documentation, timeline_documentation, tooltip_documentation)
+               dialog_documentation, doc, expansion_documentation, grid_documentation, list_documentation,
+               menu_documentation, notification_documentation, notify_documentation, pagination_documentation,
+               row_documentation, scroll_area_documentation, separator_documentation, space_documentation,
+               splitter_documentation, stepper_documentation, tabs_documentation, timeline_documentation,
+               tooltip_documentation)
 
 
 doc.title('Page *Layout*')
 doc.title('Page *Layout*')
 
 
@@ -33,6 +34,7 @@ doc.intro(card_documentation)
 doc.intro(column_documentation)
 doc.intro(column_documentation)
 doc.intro(row_documentation)
 doc.intro(row_documentation)
 doc.intro(grid_documentation)
 doc.intro(grid_documentation)
+doc.intro(list_documentation)
 
 
 
 
 @doc.demo('Clear Containers', '''
 @doc.demo('Clear Containers', '''