Browse Source

improve docstrings, add Quasar references

Falko Schindler 1 year ago
parent
commit
2e57811a49

+ 2 - 0
nicegui/elements/audio.py

@@ -17,6 +17,8 @@ class Audio(Element, component='audio.js'):
                  ) -> None:
         """Audio
 
+        Displays an audio player.
+
         :param src: URL or local file path of the audio source
         :param controls: whether to show the audio controls, like play, pause, and volume (default: `True`)
         :param autoplay: whether to start playing the audio automatically (default: `False`)

+ 9 - 1
nicegui/elements/card.py

@@ -21,7 +21,7 @@ class Card(Element):
         self._classes = ['nicegui-card']
 
     def tight(self) -> Self:
-        """Removes padding and gaps between nested elements."""
+        """Remove padding and gaps between nested elements."""
         self._classes.clear()
         self._style.clear()
         return self
@@ -30,10 +30,18 @@ class Card(Element):
 class CardSection(Element):
 
     def __init__(self) -> None:
+        """Card Section
+
+        This element is based on Quasar's `QCardSection <https://quasar.dev/vue-components/card#qcardsection-api>`_ component.
+        """
         super().__init__('q-card-section')
 
 
 class CardActions(Element):
 
     def __init__(self) -> None:
+        """Card Actions
+
+        This element is based on Quasar's `QCardActions <https://quasar.dev/vue-components/card#qcardactions-api>`_ component.
+        """
         super().__init__('q-card-actions')

+ 2 - 0
nicegui/elements/carousel.py

@@ -43,9 +43,11 @@ class Carousel(ValueElement):
             slide.props(f':done={done}')
 
     def next(self) -> None:
+        """Show the next slide."""
         self.run_method('next')
 
     def previous(self) -> None:
+        """Show the previous slide."""
         self.run_method('previous')
 
 

+ 2 - 0
nicegui/elements/checkbox.py

@@ -10,6 +10,8 @@ class Checkbox(TextElement, ValueElement, DisableableElement):
     def __init__(self, text: str = '', *, value: bool = False, on_change: Optional[Callable[..., Any]] = None) -> None:
         """Checkbox
 
+        This element is based on Quasar's `QCheckbox <https://quasar.dev/vue-components/checkbox>`_ component.
+
         :param text: the label to display next to the checkbox
         :param value: whether it should be checked initially (default: `False`)
         :param on_change: callback to execute when value changes

+ 2 - 0
nicegui/elements/color_input.py

@@ -18,6 +18,8 @@ class ColorInput(ValueElement, DisableableElement):
                  ) -> None:
         """Color Input
 
+        This element extends Quasar's `QInput <https://quasar.dev/vue-components/input>`_ component with a color picker.
+
         :param label: displayed label for the color input
         :param placeholder: text to show if no color is selected
         :param value: the current color value

+ 4 - 1
nicegui/elements/color_picker.py

@@ -10,6 +10,9 @@ class ColorPicker(Menu):
     def __init__(self, *, on_pick: Callable[..., Any], value: bool = False) -> None:
         """Color Picker
 
+        This element is based on Quasar's `QMenu <https://quasar.dev/vue-components/menu>`_ and
+        `QColor <https://quasar.dev/vue-components/color>`_ components.
+
         :param on_pick: callback to execute when a color is picked
         :param value: whether the menu is already opened (default: `False`)
         """
@@ -20,7 +23,7 @@ class ColorPicker(Menu):
             self.q_color = Element('q-color').on('change', handle_change)
 
     def set_color(self, color: str) -> None:
-        """Set the color of the picker
+        """Set the color of the picker.
 
         :param color: the color to set
         """

+ 2 - 2
nicegui/elements/column.py

@@ -4,9 +4,9 @@ from ..element import Element
 class Column(Element):
 
     def __init__(self) -> None:
-        '''Column Element
+        """Column Element
 
         Provides a container which arranges its child in a column.
-        '''
+        """
         super().__init__('div')
         self._classes = ['nicegui-column']

+ 1 - 1
nicegui/elements/dialog.py

@@ -9,7 +9,7 @@ class Dialog(ValueElement):
     def __init__(self, *, value: bool = False) -> None:
         """Dialog
 
-        Creates a dialog.
+        Creates a dialog based on Quasar's `QDialog <https://quasar.dev/vue-components/dialog>`_ component.
         By default it is dismissible by clicking or pressing ESC.
         To make it persistent, set `.props('persistent')` on the dialog element.
 

+ 3 - 1
nicegui/elements/expansion.py

@@ -14,7 +14,7 @@ class Expansion(ValueElement, DisableableElement):
                  ) -> None:
         """Expansion Element
 
-        Provides an expandable container.
+        Provides an expandable container based on Quasar's `QExpansionItem <https://quasar.dev/vue-components/expansion-item>`_ component.
 
         :param text: title text
         :param icon: optional icon (default: None)
@@ -27,7 +27,9 @@ class Expansion(ValueElement, DisableableElement):
         self._props['icon'] = icon
 
     def open(self) -> None:
+        """Open the expansion."""
         self.value = True
 
     def close(self) -> None:
+        """Close the expansion."""
         self.value = False

+ 2 - 2
nicegui/elements/grid.py

@@ -9,13 +9,13 @@ class Grid(Element):
                  rows: Optional[int] = None,
                  columns: Optional[int] = None,
                  ) -> None:
-        '''Grid Element
+        """Grid Element
 
         Provides a container which arranges its child in a grid.
 
         :param rows: number of rows in the grid
         :param columns: number of columns in the grid
-        '''
+        """
         super().__init__('div')
         self._classes = ['nicegui-grid']
         if rows is not None:

+ 1 - 0
nicegui/elements/image.py

@@ -10,6 +10,7 @@ class Image(SourceElement, component='image.js'):
         """Image
 
         Displays an image.
+        This element is based on Quasar's `QImg <https://quasar.dev/vue-components/img>`_ component.
 
         :param source: the source of the image; can be a URL, local file path or a base64 string
         """

+ 10 - 0
nicegui/elements/line_plot.py

@@ -33,11 +33,21 @@ class LinePlot(Pyplot):
         self.push_counter = 0
 
     def with_legend(self, titles: List[str], **kwargs: Any):
+        """Add a legend to the plot.
+
+        :param titles: list of titles for the lines
+        :param kwargs: additional arguments which should be passed to `pyplot.legend <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html>`_
+        """
         self.fig.gca().legend(titles, **kwargs)
         self._convert_to_html()
         return self
 
     def push(self, x: List[float], Y: List[List[float]]) -> None:
+        """Push new data to the plot.
+
+        :param x: list of x values
+        :param Y: list of lists of y values (one list per line)
+        """
         self.push_counter += 1
 
         self.x = [*self.x, *x][self.slice]

+ 6 - 2
nicegui/elements/log.py

@@ -8,7 +8,7 @@ from ..element import Element
 class Log(Element, component='log.js'):
 
     def __init__(self, max_lines: Optional[int] = None) -> None:
-        """Log view
+        """Log View
 
         Create a log view that allows to add new lines without re-transmitting the whole history to the client.
 
@@ -22,6 +22,10 @@ class Log(Element, component='log.js'):
         self.total_count: int = 0
 
     def push(self, line: Any) -> None:
+        """Add a new line to the log.
+
+        :param line: the line to add (can contain line breaks)
+        """
         new_lines = [urllib.parse.quote(line) for line in str(line).splitlines()]
         self.lines.extend(new_lines)
         self._props['lines'] = '\n'.join(self.lines)
@@ -29,7 +33,7 @@ class Log(Element, component='log.js'):
         self.run_method('push', urllib.parse.quote(str(line)), self.total_count)
 
     def clear(self) -> None:
-        """Clear the log"""
+        """Clear the log."""
         super().clear()
         self._props['lines'] = ''
         self.lines.clear()

+ 2 - 1
nicegui/elements/menu.py

@@ -11,7 +11,7 @@ class Menu(ValueElement):
     def __init__(self, *, value: bool = False) -> None:
         """Menu
 
-        Creates a menu.
+        Creates a menu based on Quasar's `QMenu <https://quasar.dev/vue-components/menu>`_ component.
         The menu should be placed inside the element where it should be shown.
 
         :param value: whether the menu is already opened (default: `False`)
@@ -41,6 +41,7 @@ class MenuItem(TextElement):
         """Menu Item
 
         A menu item to be added to a menu.
+        This element is based on Quasar's `QItem <https://quasar.dev/vue-components/list-and-list-items#qitem-api>`_ component.
 
         :param text: label of the menu item
         :param on_click: callback to be executed when selecting the menu item

+ 2 - 2
nicegui/elements/mermaid.py

@@ -8,13 +8,13 @@ class Mermaid(ContentElement,
     CONTENT_PROP = 'content'
 
     def __init__(self, content: str) -> None:
-        '''Mermaid Diagrams
+        """Mermaid Diagrams
 
         Renders diagrams and charts written in the Markdown-inspired `Mermaid <https://mermaid.js.org/>`_ language.
         The mermaid syntax can also be used inside Markdown elements by providing the extension string 'mermaid' to the ``ui.markdown`` element.
 
         :param content: the Mermaid content to be displayed
-        '''
+        """
         super().__init__(content=content)
 
     def on_content_change(self, content: str) -> None:

+ 1 - 0
nicegui/elements/number.py

@@ -85,6 +85,7 @@ class Number(ValidationElement, DisableableElement):
         return not self.min <= self.value <= self.max
 
     def sanitize(self) -> None:
+        """Sanitize the current value to be within the allowed limits."""
         value = float(self.value or 0)
         value = max(value, self.min)
         value = min(value, self.max)

+ 2 - 0
nicegui/elements/radio.py

@@ -14,6 +14,8 @@ class Radio(ChoiceElement, DisableableElement):
                  ) -> None:
         """Radio Selection
 
+        This element is based on Quasar's `QRadio <https://quasar.dev/vue-components/radio>`_ component.
+
         The options can be specified as a list of values, or as a dictionary mapping values to labels.
         After manipulating the options, call `update()` to update the options in the UI.
 

+ 2 - 2
nicegui/elements/row.py

@@ -4,9 +4,9 @@ from ..element import Element
 class Row(Element):
 
     def __init__(self) -> None:
-        '''Row Element
+        """Row Element
 
         Provides a container which arranges its child in a row.
-        '''
+        """
         super().__init__('div')
         self._classes = ['nicegui-row']

+ 22 - 0
nicegui/elements/scene.py

@@ -117,6 +117,11 @@ class Scene(Element,
                 obj.send()
 
     def run_method(self, name: str, *args: Any) -> None:
+        """Run a method on the client.
+
+        :param name: name of the method
+        :param args: arguments to pass to the method
+        """
         if not self.is_initialized:
             return
         super().run_method(name, *args)
@@ -170,6 +175,19 @@ class Scene(Element,
                     up_y: Optional[float] = None,
                     up_z: Optional[float] = None,
                     duration: float = 0.5) -> None:
+        """Move the camera to a new position.
+
+        :param x: camera x position
+        :param y: camera y position
+        :param z: camera z position
+        :param look_at_x: camera look-at x position
+        :param look_at_y: camera look-at y position
+        :param look_at_z: camera look-at z position
+        :param up_x: x component of the camera up vector
+        :param up_y: y component of the camera up vector
+        :param up_z: z component of the camera up vector
+        :param duration: duration of the movement in seconds (default: `0.5`)
+        """
         self.camera.x = self.camera.x if x is None else x
         self.camera.y = self.camera.y if y is None else y
         self.camera.z = self.camera.z if z is None else z
@@ -189,6 +207,10 @@ class Scene(Element,
         super()._on_delete()
 
     def delete_objects(self, predicate: Callable[[Object3D], bool] = lambda _: True) -> None:
+        """Remove objects from the scene.
+
+        :param predicate: function which returns `True` for objects which should be deleted
+        """
         for obj in list(self.objects.values()):
             if predicate(obj):
                 obj.delete()

+ 57 - 11
nicegui/elements/scene_object3d.py

@@ -2,7 +2,9 @@ from __future__ import annotations
 
 import math
 import uuid
-from typing import TYPE_CHECKING, Any, List, Optional, Union
+from typing import TYPE_CHECKING, Any, List, Literal, Optional, Union
+
+from typing_extensions import Self
 
 if TYPE_CHECKING:
     from .scene import Scene, SceneObject
@@ -34,7 +36,8 @@ class Object3D:
         self.sz: float = 1
         self._create()
 
-    def with_name(self, name: str):
+    def with_name(self, name: str) -> Self:
+        """Set the name of the object."""
         self.name = name
         self._name()
         return self
@@ -49,11 +52,11 @@ class Object3D:
         self._visible()
         self._draggable()
 
-    def __enter__(self):
+    def __enter__(self) -> Self:
         self.scene.stack.append(self)
         return self
 
-    def __exit__(self, *_):
+    def __exit__(self, *_) -> None:
         self.scene.stack.pop()
 
     def _create(self) -> None:
@@ -83,7 +86,13 @@ class Object3D:
     def _delete(self) -> None:
         self.scene.run_method('delete', self.id)
 
-    def material(self, color: str = '#ffffff', opacity: float = 1.0, side: str = 'front'):
+    def material(self, color: str = '#ffffff', opacity: float = 1.0, side: Literal['front', 'back', 'both'] = 'front') -> Self:
+        """Set the color and opacity of the object.
+
+        :param color: CSS color string (default: '#ffffff')
+        :param opacity: opacity between 0.0 and 1.0 (default: 1.0)
+        :param side: 'front', 'back', or 'double' (default: 'front')
+        """
         if self.color != color or self.opacity != opacity or self.side_ != side:
             self.color = color
             self.opacity = opacity
@@ -91,7 +100,13 @@ class Object3D:
             self._material()
         return self
 
-    def move(self, x: float = 0.0, y: float = 0.0, z: float = 0.0):
+    def move(self, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> Self:
+        """Move the object.
+
+        :param x: x coordinate
+        :param y: y coordinate
+        :param z: z coordinate
+        """
         if self.x != x or self.y != y or self.z != z:
             self.x = x
             self.y = y
@@ -101,6 +116,12 @@ class Object3D:
 
     @staticmethod
     def rotation_matrix_from_euler(r_x: float, r_y: float, r_z: float) -> List[List[float]]:
+        """Create a rotation matrix from Euler angles.
+
+        :param r_x: rotation around the x axis in radians
+        :param r_y: rotation around the y axis in radians
+        :param r_z: rotation around the z axis in radians
+        """
         sx, cx = math.sin(r_x), math.cos(r_x)
         sy, cy = math.sin(r_y), math.cos(r_y)
         sz, cz = math.sin(r_z), math.cos(r_z)
@@ -110,16 +131,32 @@ class Object3D:
             [-sy, cy * sx, cy * cx],
         ]
 
-    def rotate(self, r_x: float, r_y: float, r_z: float) -> None:
+    def rotate(self, r_x: float, r_y: float, r_z: float) -> Self:
+        """Rotate the object.
+
+        :param r_x: rotation around the x axis in radians
+        :param r_y: rotation around the y axis in radians
+        :param r_z: rotation around the z axis in radians
+        """
         return self.rotate_R(self.rotation_matrix_from_euler(r_x, r_y, r_z))
 
-    def rotate_R(self, R: List[List[float]]):
+    def rotate_R(self, R: List[List[float]]) -> Self:
+        """Rotate the object.
+
+        :param R: 3x3 rotation matrix
+        """
         if self.R != R:
             self.R = R
             self._rotate()
         return self
 
-    def scale(self, sx: float = 1.0, sy: Optional[float] = None, sz: Optional[float] = None):
+    def scale(self, sx: float = 1.0, sy: Optional[float] = None, sz: Optional[float] = None) -> Self:
+        """Scale the object.
+
+        :param sx: scale factor for the x axis
+        :param sy: scale factor for the y axis (default: `sx`)
+        :param sz: scale factor for the z axis (default: `sx`)
+        """
         if sy is None:
             sy = sx
         if sz is None:
@@ -131,19 +168,28 @@ class Object3D:
             self._scale()
         return self
 
-    def visible(self, value: bool = True):
+    def visible(self, value: bool = True) -> Self:
+        """Set the visibility of the object.
+
+        :param value: whether the object should be visible (default: `True`)
+        """
         if self.visible_ != value:
             self.visible_ = value
             self._visible()
         return self
 
-    def draggable(self, value: bool = True):
+    def draggable(self, value: bool = True) -> Self:
+        """Set whether the object should be draggable.
+
+        :param value: whether the object should be draggable (default: `True`)
+        """
         if self.draggable_ != value:
             self.draggable_ = value
             self._draggable()
         return self
 
     def delete(self) -> None:
+        """Delete the object."""
         children = [object for object in self.scene.objects.values() if object.parent == self]
         for child in children:
             child.delete()

+ 143 - 6
nicegui/elements/scene_objects.py

@@ -4,15 +4,14 @@ from typing import List, Optional
 from .scene_object3d import Object3D
 
 
-class Scene(Object3D):
-
-    def __init__(self) -> None:
-        super().__init__('scene')
-
-
 class Group(Object3D):
 
     def __init__(self) -> None:
+        """Group
+
+        This element is based on Three.js' `Group <https://threejs.org/docs/index.html#api/en/objects/Group>`_ object.
+        It is used to group objects together.
+        """
         super().__init__('group')
 
 
@@ -24,6 +23,16 @@ class Box(Object3D):
                  depth: float = 1.0,
                  wireframe: bool = False,
                  ) -> None:
+        """Box
+
+        This element is based on Three.js' `BoxGeometry <https://threejs.org/docs/index.html#api/en/geometries/BoxGeometry>`_ object.
+        It is used to create a box-shaped mesh.
+
+        :param width: width of the box (default: 1.0)
+        :param height: height of the box (default: 1.0)
+        :param depth: depth of the box (default: 1.0)
+        :param wireframe: whether to display the box as a wireframe (default: `False`)
+        """
         super().__init__('box', width, height, depth, wireframe)
 
 
@@ -35,6 +44,16 @@ class Sphere(Object3D):
                  height_segments: int = 16,
                  wireframe: bool = False,
                  ) -> None:
+        """Sphere
+
+        This element is based on Three.js' `SphereGeometry <https://threejs.org/docs/index.html#api/en/geometries/SphereGeometry>`_ object.
+        It is used to create a sphere-shaped mesh.
+
+        :param radius: radius of the sphere (default: 1.0)
+        :param width_segments: number of horizontal segments (default: 32)
+        :param height_segments: number of vertical segments (default: 16)
+        :param wireframe: whether to display the sphere as a wireframe (default: `False`)
+        """
         super().__init__('sphere', radius, width_segments, height_segments, wireframe)
 
 
@@ -48,6 +67,18 @@ class Cylinder(Object3D):
                  height_segments: int = 1,
                  wireframe: bool = False,
                  ) -> None:
+        """Cylinder
+
+        This element is based on Three.js' `CylinderGeometry <https://threejs.org/docs/index.html#api/en/geometries/CylinderGeometry>`_ object.
+        It is used to create a cylinder-shaped mesh.
+
+        :param top_radius: radius of the top (default: 1.0)
+        :param bottom_radius: radius of the bottom (default: 1.0)
+        :param height: height of the cylinder (default: 1.0)
+        :param radial_segments: number of horizontal segments (default: 8)
+        :param height_segments: number of vertical segments (default: 1)
+        :param wireframe: whether to display the cylinder as a wireframe (default: `False`)
+        """
         super().__init__('cylinder', top_radius, bottom_radius, height, radial_segments, height_segments, wireframe)
 
 
@@ -62,6 +93,19 @@ class Ring(Object3D):
                  theta_length: float = 2 * math.pi,
                  wireframe: bool = False,
                  ) -> None:
+        """Ring
+
+        This element is based on Three.js' `RingGeometry <https://threejs.org/docs/index.html#api/en/geometries/RingGeometry>`_ object.
+        It is used to create a ring-shaped mesh.
+
+        :param inner_radius: inner radius of the ring (default: 0.5)
+        :param outer_radius: outer radius of the ring (default: 1.0)
+        :param theta_segments: number of horizontal segments (default: 8, higher means rounder)
+        :param phi_segments: number of vertical segments (default: 1)
+        :param theta_start: start angle in radians (default: 0)
+        :param theta_length: central angle in radians (default: 2π)
+        :param wireframe: whether to display the ring as a wireframe (default: `False`)
+        """
         super().__init__('ring',
                          inner_radius, outer_radius, theta_segments, phi_segments, theta_start, theta_length, wireframe)
 
@@ -78,6 +122,20 @@ class QuadraticBezierTube(Object3D):
                  closed: bool = False,
                  wireframe: bool = False,
                  ) -> None:
+        """Quadratic Bezier Tube
+
+        This element is based on Three.js' `QuadraticBezierCurve3 <https://threejs.org/docs/index.html#api/en/extras/curves/QuadraticBezierCurve3>`_ object.
+        It is used to create a tube-shaped mesh.
+
+        :param start: start point of the curve
+        :param mid: middle point of the curve
+        :param end: end point of the curve
+        :param tubular_segments: number of tubular segments (default: 64)
+        :param radius: radius of the tube (default: 1.0)
+        :param radial_segments: number of radial segments (default: 8)
+        :param closed: whether the tube should be closed (default: `False`)
+        :param wireframe: whether to display the tube as a wireframe (default: `False`)
+        """
         super().__init__('quadratic_bezier_tube',
                          start, mid, end, tubular_segments, radius, radial_segments, closed, wireframe)
 
@@ -89,6 +147,15 @@ class Extrusion(Object3D):
                  height: float,
                  wireframe: bool = False,
                  ) -> None:
+        """Extrusion
+
+        This element is based on Three.js' `ExtrudeGeometry <https://threejs.org/docs/index.html#api/en/geometries/ExtrudeGeometry>`_ object.
+        It is used to create a 3D shape by extruding a 2D shape to a given height.
+
+        :param outline: list of points defining the outline of the 2D shape
+        :param height: height of the extrusion
+        :param wireframe: whether to display the extrusion as a wireframe (default: `False`)
+        """
         super().__init__('extrusion', outline, height, wireframe)
 
 
@@ -98,6 +165,13 @@ class Stl(Object3D):
                  url: str,
                  wireframe: bool = False,
                  ) -> None:
+        """STL
+
+        This element is used to create a mesh from an STL file.
+
+        :param url: URL of the STL file
+        :param wireframe: whether to display the STL as a wireframe (default: `False`)
+        """
         super().__init__('stl', url, wireframe)
 
 
@@ -107,6 +181,14 @@ class Line(Object3D):
                  start: List[float],
                  end: List[float],
                  ) -> None:
+        """Line
+
+        This element is based on Three.js' `Line <https://threejs.org/docs/index.html#api/en/objects/Line>`_ object.
+        It is used to create a line segment.
+
+        :param start: start point of the line
+        :param end: end point of the line
+        """
         super().__init__('line', start, end)
 
 
@@ -119,6 +201,16 @@ class Curve(Object3D):
                  end: List[float],
                  num_points: int = 20,
                  ) -> None:
+        """Curve
+
+        This element is based on Three.js' `CubicBezierCurve3 <https://threejs.org/docs/index.html#api/en/extras/curves/CubicBezierCurve3>`_ object.
+
+        :param start: start point of the curve
+        :param control1: first control point of the curve
+        :param control2: second control point of the curve
+        :param end: end point of the curve
+        :param num_points: number of points to use for the curve (default: 20)
+        """
         super().__init__('curve', start, control1, control2, end, num_points)
 
 
@@ -128,6 +220,14 @@ class Text(Object3D):
                  text: str,
                  style: str = '',
                  ) -> None:
+        """Text
+
+        This element is used to add 2D text to the scene.
+        It can be moved like any other object, but always faces the camera.
+
+        :param text: text to display
+        :param style: CSS style (default: '')
+        """
         super().__init__('text', text, style)
 
 
@@ -137,6 +237,14 @@ class Text3d(Object3D):
                  text: str,
                  style: str = '',
                  ) -> None:
+        """3D Text
+
+        This element is used to add a 3D text mesh to the scene.
+        It can be moved and rotated like any other object.
+
+        :param text: text to display
+        :param style: CSS style (default: '')
+        """
         super().__init__('text3d', text, style)
 
 
@@ -146,13 +254,22 @@ class Texture(Object3D):
                  url: str,
                  coordinates: List[List[Optional[List[float]]]],
                  ) -> None:
+        """Texture
+
+        This element is used to add a texture to a mesh.
+
+        :param url: URL of the texture image
+        :param coordinates: texture coordinates
+        """
         super().__init__('texture', url, coordinates)
 
     def set_url(self, url: str) -> None:
+        """Change the URL of the texture image."""
         self.args[0] = url
         self.scene.run_method('set_texture_url', self.id, url)
 
     def set_coordinates(self, coordinates: List[List[Optional[List[float]]]]) -> None:
+        """Change the texture coordinates."""
         self.args[1] = coordinates
         self.scene.run_method('set_texture_coordinates', self.id, coordinates)
 
@@ -167,6 +284,18 @@ class SpotLight(Object3D):
                  penumbra: float = 0.0,
                  decay: float = 1.0,
                  ) -> None:
+        """Spot Light
+
+        This element is based on Three.js' `SpotLight <https://threejs.org/docs/index.html#api/en/lights/SpotLight>`_ object.
+        It is used to add a spot light to the scene.
+
+        :param color: CSS color string (default: '#ffffff')
+        :param intensity: light intensity (default: 1.0)
+        :param distance: maximum distance of light (default: 0.0)
+        :param angle: maximum angle of light (default: π/3)
+        :param penumbra: penumbra (default: 0.0)
+        :param decay: decay (default: 1.0)
+        """
         super().__init__('spot_light', color, intensity, distance, angle, penumbra, decay)
 
 
@@ -177,4 +306,12 @@ class PointCloud(Object3D):
                  colors: List[List[float]],
                  point_size: float = 1.0,
                  ) -> None:
+        """Point Cloud
+
+        This element is based on Three.js' `Points <https://threejs.org/docs/index.html#api/en/objects/Points>`_ object.
+
+        :param points: list of points
+        :param colors: list of colors (one per point)
+        :param point_size: size of the points (default: 1.0)
+        """
         super().__init__('point_cloud', points, colors, point_size)

+ 3 - 2
nicegui/elements/separator.py

@@ -6,8 +6,9 @@ class Separator(Element):
     def __init__(self) -> None:
         """Separator
 
-        A separator for cards, menus and other component containers.
-        Similar to HTML's <hr> tag.
+        This element is based on Quasar's `QSeparator <https://quasar.dev/vue-components/separator>`_ component.
+
+        It serves as a separator for cards, menus and other component containers and is similar to HTML's <hr> tag.
         """
         super().__init__('q-separator')
         self._classes = ['nicegui-separator']

+ 2 - 0
nicegui/elements/slider.py

@@ -15,6 +15,8 @@ class Slider(ValueElement, DisableableElement):
                  ) -> None:
         """Slider
 
+        This element is based on Quasar's `QSlider <https://quasar.dev/vue-components/slider>`_ component.
+
         :param min: lower bound of the slider
         :param max: upper bound of the slider
         :param step: step size

+ 1 - 1
nicegui/elements/spinner.py

@@ -39,7 +39,7 @@ class Spinner(TextColorElement):
                  ) -> None:
         """Spinner
 
-        See `Quasar Spinner <https://quasar.dev/vue-components/spinners>`_ for more information.
+        This element is based on Quasar's `QSpinner <https://quasar.dev/vue-components/spinners>`_ component.
 
         :param type: type of spinner (e.g. "audio", "ball", "bars", ..., default: "default")
         :param size: size of the spinner (e.g. "3em", "10px", "xl", ..., default: "1em")

+ 6 - 0
nicegui/elements/stepper.py

@@ -42,9 +42,11 @@ class Stepper(ValueElement):
             step.props(f':done={done}')
 
     def next(self) -> None:
+        """Show the next step."""
         self.run_method('next')
 
     def previous(self) -> None:
+        """Show the previous step."""
         self.run_method('previous')
 
 
@@ -73,4 +75,8 @@ class Step(DisableableElement):
 class StepperNavigation(Element):
 
     def __init__(self) -> None:
+        """Stepper Navigation
+
+        This element represents `Quasar's QStepperNavigation https://quasar.dev/vue-components/stepper#qsteppernavigation-api>`_ component.
+        """
         super().__init__('q-stepper-navigation')

+ 2 - 0
nicegui/elements/switch.py

@@ -10,6 +10,8 @@ class Switch(TextElement, ValueElement, DisableableElement):
     def __init__(self, text: str = '', *, value: bool = False, on_change: Optional[Callable[..., Any]] = None) -> None:
         """Switch
 
+        This element is based on Quasar's `QToggle <https://quasar.dev/vue-components/toggle>`_ component.
+
         :param text: the label to display next to the switch
         :param value: whether it should be active initially (default: `False`)
         :param on_change: callback which is invoked when state is changed by the user

+ 16 - 3
nicegui/elements/table.py

@@ -90,15 +90,28 @@ class Table(FilterElement, component='table.js'):
         self.update()
 
     class row(Element):
+
         def __init__(self) -> None:
+            """Row Element
+
+            This element is based on Quasar's `QTr <https://quasar.dev/vue-components/table#qtr-api>`_ component.
+            """
             super().__init__('q-tr')
 
     class header(Element):
+
         def __init__(self) -> None:
+            """Header Element
+
+            This element is based on Quasar's `QTh <https://quasar.dev/vue-components/table#qth-api>`_ component.
+            """
             super().__init__('q-th')
 
     class cell(Element):
-        def __init__(self, key: str = '') -> None:
+
+        def __init__(self) -> None:
+            """Cell Element
+
+            This element is based on Quasar's `QTd <https://quasar.dev/vue-components/table#qtd-api>`_ component.
+            """
             super().__init__('q-td')
-            if key:
-                self._props['key'] = key

+ 2 - 0
nicegui/elements/toggle.py

@@ -15,6 +15,8 @@ class Toggle(ChoiceElement, DisableableElement):
                  ) -> None:
         """Toggle
 
+        This element is based on Quasar's `QBtnToggle <https://quasar.dev/vue-components/button-toggle>`_ component.
+
         The options can be specified as a list of values, or as a dictionary mapping values to labels.
         After manipulating the options, call `update()` to update the options in the UI.
 

+ 2 - 1
nicegui/elements/tooltip.py

@@ -6,7 +6,8 @@ class Tooltip(TextElement):
     def __init__(self, text: str) -> None:
         """Tooltip
 
-        Can be placed in another element to show additional information on hover.
+        This element is based on Quasar's `QTooltip <https://quasar.dev/vue-components/tooltip>`_ component.
+        It be placed in another element to show additional information on hover.
 
         :param text: the content of the tooltip
         """

+ 1 - 0
nicegui/elements/upload.py

@@ -67,6 +67,7 @@ class Upload(DisableableElement, component='upload.js'):
                     args=[])
 
     def reset(self) -> None:
+        """Clear the upload queue."""
         self.run_method('reset')
 
     def _on_delete(self) -> None:

+ 2 - 0
nicegui/elements/video.py

@@ -17,6 +17,8 @@ class Video(Element, component='video.js'):
                  ) -> None:
         """Video
 
+        Displays a video.
+
         :param src: URL or local file path of the video source
         :param controls: whether to show the video controls, like play, pause, and volume (default: `True`)
         :param autoplay: whether to start playing the video automatically (default: `False`)

+ 31 - 21
nicegui/page_layout.py

@@ -28,7 +28,9 @@ class Header(ValueElement):
                  elevated: bool = False,
                  add_scroll_padding: bool = False,  # DEPRECATED: will be True in v1.4
                  ) -> None:
-        '''Header
+        """Header
+
+        This element is based on Quasar's `QHeader <https://quasar.dev/layout/header-and-footer#qheader-api>`_ component.
 
         Note: The header is automatically placed above other layout elements in the DOM to improve accessibility.
         To change the order, use the `move` method.
@@ -38,7 +40,7 @@ class Header(ValueElement):
         :param bordered: whether the header should have a border (default: `False`)
         :param elevated: whether the header should have a shadow (default: `False`)
         :param add_scroll_padding: whether to automatically prevent link targets from being hidden behind the header (default: `False`, will be `True` in v1.4)
-        '''
+        """
         with globals.get_client().layout:
             super().__init__(tag='q-header', value=value, on_value_change=None)
         self._classes = ['nicegui-header']
@@ -63,15 +65,15 @@ class Header(ValueElement):
             ''')
 
     def toggle(self):
-        '''Toggle the header'''
+        """Toggle the header"""
         self.value = not self.value
 
     def show(self):
-        '''Show the header'''
+        """Show the header"""
         self.value = True
 
     def hide(self):
-        '''Hide the header'''
+        """Hide the header"""
         self.value = False
 
 
@@ -85,7 +87,9 @@ class Drawer(Element):
                  elevated: bool = False,
                  top_corner: bool = False,
                  bottom_corner: bool = False) -> None:
-        '''Drawer
+        """Drawer
+
+        This element is based on Quasar's `QDrawer <https://quasar.dev/layout/drawer>`_ component.
 
         Note: Depending on the side, the drawer is automatically placed above or below the main page container in the DOM to improve accessibility.
         To change the order, use the `move` method.
@@ -97,7 +101,7 @@ class Drawer(Element):
         :param elevated: whether the drawer should have a shadow (default: `False`)
         :param top_corner: whether the drawer expands into the top corner (default: `False`)
         :param bottom_corner: whether the drawer expands into the bottom corner (default: `False`)
-        '''
+        """
         with globals.get_client().layout:
             super().__init__('q-drawer')
         if value is None:
@@ -118,15 +122,15 @@ class Drawer(Element):
         self.move(target_index=page_container_index if side == 'left' else page_container_index + 1)
 
     def toggle(self) -> None:
-        '''Toggle the drawer'''
+        """Toggle the drawer"""
         self.run_method('toggle')
 
     def show(self) -> None:
-        '''Show the drawer'''
+        """Show the drawer"""
         self.run_method('show')
 
     def hide(self) -> None:
-        '''Hide the drawer'''
+        """Hide the drawer"""
         self.run_method('hide')
 
 
@@ -139,7 +143,9 @@ class LeftDrawer(Drawer):
                  elevated: bool = False,
                  top_corner: bool = False,
                  bottom_corner: bool = False) -> None:
-        '''Left drawer
+        """Left drawer
+
+        This element is based on Quasar's `QDrawer <https://quasar.dev/layout/drawer>`_ component.
 
         Note: The left drawer is automatically placed above the main page container in the DOM to improve accessibility.
         To change the order, use the `move` method.
@@ -150,7 +156,7 @@ class LeftDrawer(Drawer):
         :param elevated: whether the drawer should have a shadow (default: `False`)
         :param top_corner: whether the drawer expands into the top corner (default: `False`)
         :param bottom_corner: whether the drawer expands into the bottom corner (default: `False`)
-        '''
+        """
         super().__init__('left',
                          value=value,
                          fixed=fixed,
@@ -169,7 +175,9 @@ class RightDrawer(Drawer):
                  elevated: bool = False,
                  top_corner: bool = False,
                  bottom_corner: bool = False) -> None:
-        '''Right drawer
+        """Right drawer
+
+        This element is based on Quasar's `QDrawer <https://quasar.dev/layout/drawer>`_ component.
 
         Note: The right drawer is automatically placed below the main page container in the DOM to improve accessibility.
         To change the order, use the `move` method.
@@ -180,7 +188,7 @@ class RightDrawer(Drawer):
         :param elevated: whether the drawer should have a shadow (default: `False`)
         :param top_corner: whether the drawer expands into the top corner (default: `False`)
         :param bottom_corner: whether the drawer expands into the bottom corner (default: `False`)
-        '''
+        """
         super().__init__('right',
                          value=value,
                          fixed=fixed,
@@ -197,7 +205,9 @@ class Footer(ValueElement):
                  fixed: bool = True,
                  bordered: bool = False,
                  elevated: bool = False) -> None:
-        '''Footer
+        """Footer
+
+        This element is based on Quasar's `QFooter <https://quasar.dev/layout/header-and-footer#qfooter-api>`_ component.
 
         Note: The footer is automatically placed below other layout elements in the DOM to improve accessibility.
         To change the order, use the `move` method.
@@ -206,7 +216,7 @@ class Footer(ValueElement):
         :param fixed: whether the footer is fixed or scrolls with the content (default: `True`)
         :param bordered: whether the footer should have a border (default: `False`)
         :param elevated: whether the footer should have a shadow (default: `False`)
-        '''
+        """
         with globals.get_client().layout:
             super().__init__(tag='q-footer', value=value, on_value_change=None)
         self.classes('nicegui-footer')
@@ -219,29 +229,29 @@ class Footer(ValueElement):
         self.move(target_index=-1)
 
     def toggle(self) -> None:
-        '''Toggle the footer'''
+        """Toggle the footer"""
         self.value = not self.value
 
     def show(self) -> None:
-        '''Show the footer'''
+        """Show the footer"""
         self.value = True
 
     def hide(self) -> None:
-        '''Hide the footer'''
+        """Hide the footer"""
         self.value = False
 
 
 class PageSticky(Element):
 
     def __init__(self, position: PageStickyPositions = 'bottom-right', x_offset: float = 0, y_offset: float = 0) -> None:
-        '''Page sticky
+        """Page sticky
 
         A sticky element that is always visible at the bottom of the page.
 
         :param position: position of the sticky element (default: `'bottom-right'`)
         :param x_offset: horizontal offset of the sticky element (default: `0`)
         :param y_offset: vertical offset of the sticky element (default: `0`)
-        '''
+        """
         super().__init__('q-page-sticky')
         self._props['position'] = position
         self._props['offset'] = [x_offset, y_offset]