nicegui reference updates

This commit is contained in:
John Lancaster
2026-08-27 18:09:10 -05:00
parent f1dd6ab940
commit e999437b93
4 changed files with 163 additions and 213 deletions
+16 -18
View File
@@ -52,26 +52,24 @@ Load [FastAPI and Uvicorn startup](./references/fastapi-uvicorn-startup.md) for:
Load [styling and customization](./references/styling-and-customization.md) for:
- progressive discovery through NiceGUI docs, constructors, and Quasar docs
- Quasar props, slots, events, and NiceGUI customization methods
- app-wide and page-level color themes, dark mode, and semantic CSS tokens
- Tailwind for structural styling and static stylesheets for fine tuning
- responsive layout and static asset conventions
- Tailwind and Quasar breakpoint scales, container queries, and responsive testing
- uniformly scaling dialogs on mobile
- preserving Quasar field proportions
- keeping detached `QSelect` menus anchored
- sizing scrollable dialog cards under CSS `zoom`
- validating zoomed controls with Playwright or a browser
- Tailwind and Quasar utility classes
- scoped CSS properties and stable application classes
- responsive page composition and static asset loading
- cosmetic treatment of controls, surfaces, typography, and visual states
- visual validation at supported viewport sizes
### Special Component Customization
### Component Mechanics And Customization
Load [special component customization](./references/special-component-customization.md) for:
Load [component mechanics and customization](./references/component-mechanics-and-customization.md) for:
- the required source-research gate before generating component customizations
- `ui.select` constructors, Quasar props, slots, detached popups, and option caveats
- `ui.icon` names, icon families, sizing, colors, assets, and Material Symbol variants
- component-specific accessibility, sanitization, and validation checks
- the NiceGUI Python wrapper, element bridge, Quasar component, and Vue runtime boundaries
- deciding between constructors, bindings, Quasar props, events, slots, and frontend methods
- server-client state and event flow
- detached content and external icon assets
- source research against the installed NiceGUI and bundled Quasar versions
- `ui.select` and `ui.icon` mechanics and caveats
- dialog scaling when detached popup geometry must be preserved
### Bindable State
@@ -118,8 +116,8 @@ Load [source documentation](./references/source-documentation.md) when:
### Page Or Component Work
1. Load [application architecture](./references/architecture.md) for page and component ownership decisions.
2. Load [styling and customization](./references/styling-and-customization.md) for layout, responsive behavior, or visual customization.
3. Add [special component customization](./references/special-component-customization.md) when the work targets `ui.select`, `ui.icon`, or another component with specialized Quasar behavior.
2. Load [styling and customization](./references/styling-and-customization.md) for themes, layout, responsive presentation, utility classes, or CSS.
3. Load [component mechanics and customization](./references/component-mechanics-and-customization.md) when behavior must be mapped across NiceGUI, Quasar, and Vue, or when detached content and component-specific behavior are involved.
4. Add [interaction patterns](./references/interaction-patterns.md) or [bindable dataclasses](./references/binding-dataclasses.md) according to the page behavior.
### Debugging Or Production Review
@@ -1,6 +1,52 @@
# NiceGUI Special Component Customization
# NiceGUI Component Mechanics And Customization
Use this reference for components whose NiceGUI wrapper, Quasar implementation, popup behavior, slots, or external assets require component-specific handling. Start with [styling and customization](./styling-and-customization.md) for the general escalation workflow.
Use this reference to understand how customization crosses the NiceGUI Python wrapper, Quasar component, Vue runtime, and browser DOM. It owns constructor behavior, prop translation, events, bindings, slots, frontend methods, detached content, and component-specific caveats. For themes, utility classes, CSS properties, responsive page composition, and other cosmetic work, load [visual styling and CSS](./styling-and-customization.md).
## Framework Boundary Model
A NiceGUI component is not a Python-rendered HTML fragment. Customization passes through several owners:
| Layer | Owns | Inspect when |
| --- | --- | --- |
| NiceGUI Python wrapper | constructor arguments, Python value normalization, validation, bindings, event callbacks, and update helpers | behavior may already have a typed Python API or wrapper-specific state rules |
| NiceGUI element bridge | serialized props, classes, styles, events, slots, and frontend method calls | mapping a supported Vue or Quasar feature through NiceGUI |
| Quasar Vue component | documented props, emitted events, named slots, public methods, popup behavior, accessibility, and internal state | the NiceGUI constructor does not expose a required component feature |
| Vue and browser runtime | reactivity, rendered DOM, teleported content, CSS cascade, fonts, and static assets | diagnosing placement, asset loading, or content rendered outside the element subtree |
Treat the generated DOM beneath a Quasar component as private implementation detail. Work through the highest owning layer that expresses the requirement.
## How The APIs Map
Use this map after confirming the exact API against the installed NiceGUI and bundled Quasar versions:
| Requirement | NiceGUI surface | Underlying mechanic |
| --- | --- | --- |
| Wrapper-supported value or behavior | constructor argument, binding, or helper such as `set_options()` | Python normalizes state and synchronizes the component |
| Additional Quasar option | `.props(...)` | values become props on the wrapped Vue component |
| Browser or Quasar notification | constructor callback or `.on(...)` | an emitted frontend event is forwarded to a Python handler |
| Semantic insertion point | `add_slot(...)` or a wrapper-specific slot API | content renders in a named Vue slot |
| Imperative frontend action | a NiceGUI helper or `run_method(...)` | NiceGUI invokes a public method on the client component |
| Page placement or appearance | `.classes(...)`, `.style(...)`, or an application stylesheet | CSS applies to the rendered element; detached content needs its own class hook |
Do not copy a Vue template into Python. Translate each part according to its owner: constructor data stays in Python, Quasar props go through `.props()`, emitted events go through callbacks or `.on()`, and named Vue slots go through NiceGUI's slot API.
## State And Event Flow
Server-driven changes and user-driven changes cross a client-server boundary:
1. Python creates the wrapper and serializes initial state to the client.
2. Vue renders the Quasar component from those props and slots.
3. A browser interaction causes Quasar to update client state or emit an event.
4. NiceGUI forwards registered events to Python handlers.
5. Python mutations return through bindings, wrapper helpers, or an explicit `update()`.
Use wrapper helpers and bindings when available because they preserve NiceGUI's value model. Directly changing a Python collection or constructing a raw JavaScript object does not imply that the client receives the change.
## Detached Content And Assets
Some Quasar components render menus, dialogs, tooltips, and similar content outside the field or trigger's DOM subtree. A descendant CSS selector beneath the Python-created element will not reach that content. Use the component's documented popup or content class prop, then style that application-owned class separately.
Icons and other externally defined visuals add another boundary: a valid Quasar icon name identifies an asset but does not load its font or stylesheet. Confirm both the naming convention and the application-level asset registration.
## Source Research Gate
@@ -17,6 +63,8 @@ For each component:
Use current upstream source only as a fallback when the target environment is unavailable. If installed and upstream behavior differ, follow the installed version and state the difference.
If the requirement is purely visual after this ownership check, continue in [visual styling and CSS](./styling-and-customization.md).
## `ui.select`
### Source Map
@@ -77,6 +125,67 @@ with item_select.add_slot("prepend"):
Use `.on()` or `run_method()` only after confirming the event or method in the installed Quasar API. Prefer NiceGUI's `on_change`, `set_options()`, value bindings, and `is_showing_popup` when they cover the behavior.
### Worked Example: Responsive Dialog And Detached Select Popup
This example is mechanics-sensitive because a `QSelect` popup is detached from the dialog card. Scale the complete card to preserve Quasar's internal field proportions, but style the popup through its own class without changing its coordinate system.
Use normal field density and attach application classes through supported APIs:
```python
ui.input("Name").props("outlined")
ui.number("Quantity").props("outlined")
ui.select(...).props("outlined popup-content-class=app-item-detail-menu")
ui.textarea("Description").props("outlined autogrow")
ui.card().classes("app-detail-card app-item-detail-card")
```
```css
:root {
--item-dialog-scale: 1;
--item-dialog-max-height: calc(100dvh - 3rem);
}
.app-item-detail-card {
width: min(50rem, 50vw);
max-height: var(--item-dialog-max-height);
overflow-y: auto;
overscroll-behavior: contain;
zoom: var(--item-dialog-scale);
}
/* Restore Quasar's baseline if a global rule overrides it. */
.app-item-detail-card .q-field,
.app-item-detail-menu {
font-size: 14px;
}
@media (max-width: 599px) {
:root {
--item-dialog-scale: 1.2;
/* 75dvh becomes 90dvh after 1.2x zoom. */
--item-dialog-max-height: 75dvh;
}
.app-item-detail-card {
width: 80vw;
}
.app-item-detail-menu {
font-size: 16.8px;
}
}
```
Do not apply `zoom` or `transform: scale()` to `.app-item-detail-menu`. Quasar positions the detached menu from the unscaled anchor geometry; scaling the menu afterward separates it from its field. Enlarging its text preserves the positioning coordinate system.
The card's pre-zoom maximum height must account for the scale:
\[
h_{\mathrm{pre}} = \frac{h_{\mathrm{visible}}}{s}
\]
For a desired visual height of `90dvh` at \(1.2\times\), use `75dvh`. Apply scrolling to the card so the dimmed page remains stationary while the form reaches its final field. The `599px` media query matches the upper edge of Quasar's default extra-small breakpoint; verify it against custom Quasar breakpoint configuration.
## `ui.icon`
### Source Map
@@ -1,75 +1,54 @@
# NiceGUI Styling And Customization
# NiceGUI Visual Styling And CSS
Use this reference to discover how a NiceGUI component can be customized, apply the least invasive supported mechanism, and introduce CSS without fighting Quasar's internal geometry.
Use this reference for cosmetic and presentational work: themes, color roles, utility classes, CSS properties, responsive layout, and static assets. For the mechanics of how a NiceGUI Python element maps to a Quasar Vue component, including props, events, slots, methods, teleported content, and wrapper-owned state, load [component mechanics and customization](./component-mechanics-and-customization.md).
For package boundaries, dependency direction, and page or component ownership, load [application architecture](./architecture.md).
## Progressive Customization Workflow
## Visual Styling Boundary
Increase the customization level only when the previous source does not expose what the design requires:
This page owns how an element looks and fits into a page after the correct component and behavior have been chosen. Typical concerns include:
1. Read the NiceGUI documentation page for the component.
2. Inspect the NiceGUI element function or class constructor.
3. Identify the wrapped Quasar component and read its documentation.
4. Use Quasar props, slots, and events through NiceGUI's native customization APIs.
5. Use Tailwind and Quasar utility classes for the concerns each system expresses best.
6. Add a scoped static stylesheet for stable visual fine tuning.
- application color roles and light or dark presentation
- width, height, spacing, alignment, wrapping, and overflow
- typography, borders, shadows, focus treatments, and state colors
- responsive page composition and stable control dimensions
- reusable application classes, CSS custom properties, and static assets
Stop as soon as the required behavior is supported. Do not begin by targeting Quasar's generated DOM or internal selectors.
The companion [component mechanics and customization](./component-mechanics-and-customization.md) reference owns how behavior crosses framework boundaries. Use it when the question is whether a value belongs in a constructor, Quasar prop, Vue event, slot, method, binding, or teleported popup.
### 1. Start With The NiceGUI Component Page
## Visual Styling Workflow
Find the component in the [NiceGUI documentation](https://nicegui.io/documentation). Check its examples, parameters, methods, events, bindings, and inheritance before writing CSS. The component page establishes the public NiceGUI API and often demonstrates the intended Quasar integration.
Escalate only as far as the visual requirement needs:
Confirm the target project's installed NiceGUI version because the current online documentation can differ from the pinned release.
1. Use a NiceGUI constructor argument when it directly expresses appearance, such as an icon, color, or size.
2. Use documented Quasar appearance props through `.props(...)` for component variants such as `outlined`, `rounded`, or `dense`.
3. Use Tailwind classes for page structure and common visual utilities.
4. Use Quasar utility classes for Quasar spacing, typography, semantic colors, visibility, and positioning.
5. Use `.style(...)` for a calculated runtime value or a short-lived visual probe.
6. Move stable or repeated declarations into a scoped static stylesheet under an application-owned class.
### 2. Inspect The NiceGUI Constructor
Read the signature and implementation of the imported NiceGUI function or element class. The constructor reveals accepted Python parameters, defaults, event callbacks, validation, and values NiceGUI forwards to the frontend.
Use editor navigation or runtime inspection against the project's selected environment:
Stop when the required presentation is achieved. If a proposed rule needs selectors such as `.q-field__control`, changes a popup's mounting or positioning behavior, or depends on generated Vue markup, resolve the component mechanics first instead of compensating with CSS.
```python
from inspect import getsource, signature
from nicegui import ui
print(signature(ui.select))
print(getsource(ui.select))
```
When `ui.<name>` is a factory or alias, follow it to the element class in the [NiceGUI element sources](https://github.com/zauberzeug/nicegui/tree/main/nicegui/elements). Prefer the installed package source when behavior may differ by version.
### 3. Read The Underlying Quasar Component Docs
NiceGUI wraps Quasar components such as [`QInput`](https://quasar.dev/vue-components/input/), [`QSelect`](https://quasar.dev/vue-components/select/), and [`QDialog`](https://quasar.dev/vue-components/dialog/). Use the matching Quasar component page to discover its complete props, slots, events, methods, and behavior notes.
Map Quasar's Vue API onto the NiceGUI wrapper instead of copying a Vue template. Verify that a prop or slot exists in the Quasar version used by the installed NiceGUI release.
### 4. Apply Native Quasar Features Through NiceGUI
Use the NiceGUI element customization methods to reach the supported Quasar surface:
- `.props(...)` for Quasar properties and boolean flags
- `.classes(...)` for Tailwind utilities and stable application class names
- `.style(...)` for dynamic inline values or a quick, local probe
- `.on(...)` for events that are not represented by a constructor callback
- slots or child elements for Quasar extension points exposed by the wrapper
```python
with ui.select(
ui.select(
options=items,
label="Item",
).props(
"outlined clearable options-dense popup-content-class=app-item-menu"
"outlined popup-content-class=app-item-menu"
).classes(
"w-full md:max-w-md"
) as item_select:
with item_select.add_slot("prepend"):
ui.icon("inventory_2")
"app-item-select w-full md:max-w-md"
)
```
Prefer constructor arguments when NiceGUI exposes the behavior directly. Use `.props()` for supported Quasar features that are not constructor parameters. Use slots when the Quasar docs define a semantic insertion point; do not reproduce that content with absolute positioning.
```css
.app-item-select {
border-radius: 0.25rem;
}
.app-item-menu {
max-height: min(24rem, 60dvh);
}
```
## Application Themes With NiceGUI And Quasar
@@ -292,145 +271,9 @@ ui.add_head_html(
)
```
## Worked Example: Responsive Dialog Customization
## Mechanics-Sensitive Visual Cases
This example begins with normal field density and Quasar popup props, then uses an application class and static stylesheet for the remaining responsive fine tuning. Use whole-card scaling when a form dialog must become uniformly larger on mobile while preserving Quasar's internal proportions. Keep detached select menus unscaled and make the card itself scrollable.
### Use Normal Field Density
Normal Quasar fields are approximately `56px` high, while dense fields are approximately `40px` high. Remove `dense` when larger controls are needed.
```python
ui.input("Name").props("outlined")
ui.number("Quantity").props("outlined")
ui.select(...).props("outlined popup-content-class=app-item-detail-menu")
ui.textarea("Description").props("outlined autogrow")
```
Add a scoped class to the dialog card:
```python
ui.card().classes("app-detail-card app-item-detail-card")
```
### Scale The Complete Card
```css
:root {
--item-dialog-scale: 1;
--item-dialog-max-height: calc(100dvh - 3rem);
}
.app-item-detail-card {
width: min(50rem, 50vw);
max-height: var(--item-dialog-max-height);
overflow-y: auto;
overscroll-behavior: contain;
zoom: var(--item-dialog-scale);
}
/* Restore Quasar's baseline if a global rule overrides it. */
.app-item-detail-card .q-field,
.app-item-detail-menu {
font-size: 14px;
}
@media (max-width: 599px) {
:root {
--item-dialog-scale: 1.2;
/* 75dvh becomes 90dvh after 1.2x zoom. */
--item-dialog-max-height: 75dvh;
}
.app-item-detail-card {
width: 80vw;
}
.app-item-detail-menu {
font-size: 16.8px;
}
}
```
The main mobile tuning knob is:
```css
--item-dialog-scale: 1.2;
```
### Keep Detached Popups Unscaled
Do not apply `zoom` or `transform: scale()` to a `QSelect` popup menu. Quasar renders menus outside the dialog and positions them from the unscaled anchor geometry. Scaling the menu container afterward separates it from its field.
Avoid:
```css
.app-item-detail-card,
.app-item-detail-menu {
zoom: 1.2;
}
```
Use:
```css
.app-item-detail-card {
zoom: 1.2;
}
.app-item-detail-menu {
font-size: 16.8px;
}
```
Use `popup-content-class=app-item-detail-menu` to target the detached menu and enlarge its text without changing its coordinate system.
### Account For Zoom When Scrolling
The card's pre-zoom maximum height must account for the scale:
\[
\begin{aligned}
h_{\mathrm{pre}} &= \frac{h_{\mathrm{visible}}}{s} \\
\text{where } s &= \text{the zoom scale}
\end{aligned}
\]
For a desired visual height of `90dvh` at \(1.2\times\):
\[
\frac{90\,\mathrm{dvh}}{1.2} = 75\,\mathrm{dvh}
\]
Therefore:
```css
--item-dialog-max-height: 75dvh;
```
Apply scrolling to the card itself:
```css
.app-item-detail-card {
max-height: var(--item-dialog-max-height);
overflow-y: auto;
overscroll-behavior: contain;
}
```
This keeps the dimmed page stationary while the form scrolls.
### Match The Quasar Breakpoint
Quasar's extra-small breakpoint ends at `599.98px`. A mobile-only rule can use:
```css
@media (max-width: 599px) {
/* Mobile rules. */
}
```
Confirm custom breakpoint values against the target application's Quasar configuration.
Some visual requests depend on framework behavior before CSS can be chosen safely. Use [component mechanics and customization](./component-mechanics-and-customization.md) for detached menus and dialogs, named slots, icon asset families, Quasar internal geometry, frontend methods, and server-client state synchronization. Its responsive dialog example explains why a card can be scaled while a detached `QSelect` popup must remain in its original positioning coordinate system.
## Validation Checklist