瀏覽代碼

Add skeleton element (#3202)

* feat: Add skeleton element to UI module

The skeleton element is added to the UI module to provide a loading placeholder for content.

* code review

---------

Co-authored-by: Falko Schindler <falko@zauberzeug.com>
frankvp 11 月之前
父節點
當前提交
c35a612ba9

+ 77 - 0
nicegui/elements/skeleton.py

@@ -0,0 +1,77 @@
+from typing import Literal, Optional
+
+from ..element import Element
+
+
+class Skeleton(Element):
+
+    def __init__(self,
+                 type: Literal[  # pylint: disable=redefined-builtin
+                     'text',
+                     'rect',
+                     'circle',
+                     'QBtn',
+                     'QBadge',
+                     'QChip',
+                     'QToolbar',
+                     'QCheckbox',
+                     'QRadio',
+                     'QToggle',
+                     'QSlider',
+                     'QRange',
+                     'QInput',
+                     'QAvatar',
+                 ] = 'rect',
+                 *,
+                 tag: str = 'div',
+                 animation: Literal[
+                     'wave',
+                     'pulse',
+                     'pulse-x',
+                     'pulse-y',
+                     'fade',
+                     'blink',
+                     'none',
+                 ] = 'wave',
+                 animation_speed: float = 1.5,
+                 square: bool = False,
+                 bordered: bool = False,
+                 size: Optional[str] = None,
+                 width: Optional[str] = None,
+                 height: Optional[str] = None,
+                 ) -> None:
+        """Skeleton
+
+        This element is based on Quasar's `QSkeleton <https://quasar.dev/vue-components/skeleton>`_ component.
+        It serves as a placeholder for loading content in cards, menus and other component containers.
+        See the `Quasar documentation <https://quasar.dev/vue-components/skeleton/#predefined-types>`_ for a list of available types.
+
+        :param type: type of skeleton to display (default: "rect")
+        :param tag: HTML tag to use for this element (default: "div")
+        :param animation: animation effect of the skeleton placeholder (default: "wave")
+        :param animation_speed: animation speed in seconds (default: 1.5)
+        :param square: whether to remover border-radius so borders are squared (default: ``False``)
+        :param bordered: whether to apply a default border to the component (default: ``False``)
+        :param size: size in CSS units (overrides ``width`` and ``height``)
+        :param width: width in CSS units (overridden by ``size`` if set)
+        :param height: height in CSS units (overridden by ``size`` if set)
+        """
+        super().__init__('q-skeleton')
+        if type != 'rect':
+            self._props['type'] = type
+        if tag != 'div':
+            self._props['tag'] = tag
+        if animation != 'wave':
+            self._props['animation'] = animation
+        if animation_speed != 1.5:
+            self._props['animation-speed'] = animation_speed
+        if square:
+            self._props['square'] = True
+        if bordered:
+            self._props['bordered'] = True
+        if size:
+            self._props['size'] = size
+        if width:
+            self._props['width'] = width
+        if height:
+            self._props['height'] = height

+ 2 - 0
nicegui/ui.py

@@ -75,6 +75,7 @@ __all__ = [
     'scroll_area',
     'scroll_area',
     'select',
     'select',
     'separator',
     'separator',
+    'skeleton',
     'slider',
     'slider',
     'space',
     'space',
     'spinner',
     'spinner',
@@ -200,6 +201,7 @@ from .elements.scene_view import SceneView as scene_view
 from .elements.scroll_area import ScrollArea as scroll_area
 from .elements.scroll_area import ScrollArea as scroll_area
 from .elements.select import Select as select
 from .elements.select import Select as select
 from .elements.separator import Separator as separator
 from .elements.separator import Separator as separator
+from .elements.skeleton import Skeleton as skeleton
 from .elements.slider import Slider as slider
 from .elements.slider import Slider as slider
 from .elements.space import Space as space
 from .elements.space import Space as space
 from .elements.spinner import Spinner as spinner
 from .elements.spinner import Spinner as spinner

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

@@ -17,6 +17,7 @@ from . import (
     row_documentation,
     row_documentation,
     scroll_area_documentation,
     scroll_area_documentation,
     separator_documentation,
     separator_documentation,
+    skeleton_documentation,
     space_documentation,
     space_documentation,
     splitter_documentation,
     splitter_documentation,
     stepper_documentation,
     stepper_documentation,
@@ -86,6 +87,7 @@ doc.intro(expansion_documentation)
 doc.intro(scroll_area_documentation)
 doc.intro(scroll_area_documentation)
 doc.intro(separator_documentation)
 doc.intro(separator_documentation)
 doc.intro(space_documentation)
 doc.intro(space_documentation)
+doc.intro(skeleton_documentation)
 doc.intro(splitter_documentation)
 doc.intro(splitter_documentation)
 doc.intro(tabs_documentation)
 doc.intro(tabs_documentation)
 doc.intro(stepper_documentation)
 doc.intro(stepper_documentation)

+ 32 - 0
website/documentation/content/skeleton_documentation.py

@@ -0,0 +1,32 @@
+from nicegui import ui
+
+from . import doc
+
+
+@doc.demo(ui.skeleton)
+def skeleton():
+    ui.skeleton().classes('w-full')
+
+
+@doc.demo('Styling and animation', '''
+    The `square` and `bordered` parameters can be set to `True` to remove the border-radius and add a border to the skeleton.
+
+    The `animation` parameter can be set to "pulse", "wave", "pulse-x", "pulse-y", "fade", "blink", or "none"
+    to change the animation effect.
+    The default value is "wave".
+''')
+def custom_animations():
+    ui.skeleton('QToolbar', square=True, bordered=True, animation='pulse-y') \
+        .classes('w-full')
+
+
+@doc.demo('YouTube Skeleton', '''
+    Here is an example skeleton for a YouTube video.
+''')
+def youtube_skeleton():
+    with ui.card().tight().classes('w-full'):
+        ui.skeleton(square=True, animation='fade', height='150px', width='100%')
+        with ui.card_section().classes('w-full'):
+            ui.skeleton('text').classes('text-subtitle1')
+            ui.skeleton('text').classes('text-subtitle1 w-1/2')
+            ui.skeleton('text').classes('text-caption')