Die Komponentenwerkstatt: Reflex' 100 Bibliotheksbausteine
·
Kursüberblick
Layout
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
Typografie
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
Formulare
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
Datenanzeige
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
Auf- und Zuklappen
·
Tabs
·
Accordion
·
Segmented Control
Overlays
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
Dynamisches Rendern
·
Cond
·
Match
·
Foreach
·
Auto Scroll
Medien
·
Image
·
Audio
·
Video
Tabellen und Datengrids
·
Table
·
Data Table
·
Data Editor
Diagramme
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
Diagrammbausteine
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
Andere Diagrammbibliotheken
·
Plotly
·
Pyplot
HTML-Elemente
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
Weitere Werkzeuge
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
rx.drawer.rootrx.drawer.triggerrx.drawer.overlayrx.drawer.portalrx.drawer.contentrx.drawer.closeOffizielle Doku
Werkstattauftrag
Tippt man in der mobilen Shop-Ansicht auf „Filter“, soll von unten ein Panel hochfahren, in dem man Sortierung und Verfügbarkeit wählt.
rx.drawer ist ein Panel, das vom Bildschirmrand hereingleitet. Man nutzt es, um größere Inhalte vorübergehend hervorzuholen, etwa ein seitliches Menü oder ein Auswahlpanel, das von unten hochfährt. Es lässt sich auch mit Finger oder Maus wegziehen und so schließen. Reflex baut diese Komponente mit der Bibliothek Vaul.
drawer.root: umschließt alle Teile. Hier gibst du Richtung (direction) und Offen-Zustand an.drawer.trigger: umschließt das Element, das den Drawer per Klick öffnet.drawer.overlay: eine halbtransparente Schicht, die den Hintergrund bedeckt, solange der Drawer offen ist.drawer.portal: rendert den Inhalt ganz außen auf der Seite, damit andere Elemente ihn nicht verdecken.drawer.content: das hereingleitende Panel selbst.drawer.close: umschließt ein Element, das den Drawer per Klick schließt.drawer.content liegt standardmäßig so, dass es den ganzen Bildschirm bedeckt (position: fixed, alle vier Seiten 0). Für die Größe des Panels setzt du deshalb die gegenüberliegende Seite auf "auto" und gibst Breite oder Höhe direkt an. Ein Panel von links bekommt also right="auto" und eine width.
rx.drawer.root(
rx.drawer.trigger(rx.button("Open Drawer")),
rx.drawer.overlay(z_index="5"),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.close(rx.box(rx.button("Close"))),
align_items="start",
direction="column",
),
top="auto",
right="auto",
height="100%",
width="20em",
padding="2em",
background_color=rx.color("gray", 2),
)
),
direction="left",
)Ändere Breite und Farbe eines Panels, das von rechts kommt (direction="right", left="auto"). Schaltest du modal aus, kannst du bei geöffnetem Drawer den Hintergrund anklicken und scrollen.
Props ausprobieren
title
width
color
modal
rx.drawer.root(
rx.drawer.trigger(rx.button("Open panel")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.title("Settings"),
rx.drawer.description("Drag it to the right or press Esc to close."),
rx.drawer.close(rx.button("Close", size="1")),
direction="column",
align_items="start",
spacing="3",
),
left="auto",
height="100%",
width="20em",
padding="2em",
background_color=rx.color("gray", 3),
),
),
direction="right",
modal=True,
)| Prop (root) | Werte | Standard | Verwendung |
|---|---|---|---|
direction | "top" "bottom" "left" "right" | "bottom" | Richtung, aus der er kommt; bestimmt auch die Richtung zum Wegziehen |
open · default_open | True / False | - | Offen-Zustand über den State steuern (kontrolliert) · anfangs offen |
modal | True / False | True | Bei False lässt sich bei offenem Drawer außerhalb klicken und scrollen |
dismissible | True / False | - | Bei False schließt er weder per Ziehen noch per Klick außerhalb oder Esc (zusammen mit open verwenden) |
handle_only | True / False | - | Bei True nur über drawer.handle ziehbar |
snap_points | Liste von Zahlen zwischen 0 und 1 oder "px"-Werten | - | Höhen, an denen er einrastet (nur Python-Werte, keine State-Werte) |
fade_from_index | Ganzzahl | letzter Punkt | Ab welchem Rastpunkt der Hintergrund abgedunkelt wird |
close_threshold | 0 bis 1 | - | Wie weit man ziehen muss, damit er schließt |
scroll_lock_timeout | Millisekunden | 500 | Wie lange nach dem Scrollen im Panel das Ziehen gesperrt ist |
should_scale_background | True / False | - | Effekt, der den Hintergrund leicht verkleinert (braucht vaul-drawer-wrapper) |
prevent_scroll_restoration | True / False | True | Verhindert, dass nach dem Schließen die Scrollposition wiederhergestellt wird |
on_open_change | Event | - | Beim Öffnen oder Schließen; übergibt den neuen Offen-Wert (bool) |
on_animation_end | Event | - | Wenn die Öffnen- oder Schließen-Animation endet; übergibt den dann geltenden Offen-Wert |
drawer.content hat die Events on_open_auto_focus, on_close_auto_focus, on_escape_key_down, on_pointer_down_outside und on_interact_outside. Die übrigen Teile nehmen im Wesentlichen nur as_child entgegen.
Je nach direction haftet das Panel an einer anderen Seite, also setzt du die gegenüberliegende Seite auf "auto". Panels von oben und unten bekommen statt einer Breite eine Höhe. Da alle vier Drawer gleich gebaut werden, steckt das in einer kleinen Funktion.
def drawer_edge_demo(side: str, **position):
return rx.drawer.root(
rx.drawer.trigger(rx.button(side, variant="soft")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.title(f"From the {side}"),
rx.drawer.close(rx.button("Close", size="1")),
direction="column",
align_items="start",
spacing="3",
),
padding="2em",
background_color=rx.color("gray", 2),
**position,
),
),
direction=side,
)
rx.flex(
drawer_edge_demo("left", right="auto", width="16em"),
drawer_edge_demo("right", left="auto", width="16em"),
drawer_edge_demo("top", bottom="auto", height="30%"),
drawer_edge_demo("bottom", top="auto", height="30%"),
spacing="3",
wrap="wrap",
)In der Teileliste der offiziellen Doku fehlen sie, aber 0.10 kennt auch drawer.title, drawer.description und drawer.handle. Titel und Beschreibung lesen Screenreader vor, der Griff zeichnet oben auf dem Panel einen Balken zum Ziehen. Mit handle_only=True lässt sich das Panel nur noch am Griff ziehen; so schließt es sich seltener versehentlich, wenn man darin Buttons antippt.
rx.drawer.root(
rx.drawer.trigger(rx.button("Open sheet")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.handle(),
rx.drawer.title("Share this page"),
rx.drawer.description("Drag the handle down to close the sheet."),
rx.flex(
rx.button(rx.icon("link"), "Copy link", variant="soft"),
rx.button(rx.icon("mail"), "Email", variant="soft"),
spacing="3",
),
direction="column",
spacing="3",
width="100%",
),
top="auto",
height="auto",
padding="1.5em",
background_color=rx.color("gray", 2),
border_radius="12px 12px 0 0",
),
),
handle_only=True,
)Verbindest du open mit einem State-Wert, kann der Code den Drawer beim Klick auf einen Link schließen. Mit on_open_change fließen auch Änderungen durch den Trigger-Button, den Close-Button und die Esc-Taste zurück in den State. Wegen modal=False lässt sich die Seite bei offenem Drawer scrollen; ein Klick auf einen Link schließt den Drawer und springt zum jeweiligen Abschnitt.
class DrawerSidebarState(rx.State):
is_open: bool = False
@rx.event
def set_is_open(self, value: bool):
self.is_open = value
@rx.event
def close_drawer(self):
self.is_open = False
rx.vstack(
rx.drawer.root(
rx.drawer.trigger(rx.button("Open Drawer")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.close(rx.button("Close")),
rx.link("Section 1", href="#drawer-section-1", on_click=DrawerSidebarState.close_drawer),
rx.link("Section 2", href="#drawer-section-2", on_click=DrawerSidebarState.close_drawer),
align_items="start",
direction="column",
spacing="3",
),
right="auto",
height="100%",
width="16em",
padding="2em",
background_color=rx.color("grass", 4),
),
),
open=DrawerSidebarState.is_open,
on_open_change=DrawerSidebarState.set_is_open,
direction="left",
modal=False,
),
rx.section(rx.heading("Section 1", size="5"), id="drawer-section-1", height="160px", padding="1em 0"),
rx.section(rx.heading("Section 2", size="5"), id="drawer-section-2", height="160px", padding="1em 0"),
)Ein Filterpanel, das von unten hochfährt. Was per Schalter und Radio gewählt wird, landet sofort im State; ein Klick auf „Show results“ lässt den Handler das Panel mit self.open = False einfahren. Zieht man das Panel herunter, bleiben die Werte ebenso erhalten.
Sort: Newest
class DrawerFilterState(rx.State):
open: bool = False
in_stock: bool = False
sort: str = "Newest"
@rx.event
def set_open(self, value: bool):
self.open = value
@rx.event
def set_in_stock(self, value: bool):
self.in_stock = value
@rx.event
def set_sort(self, value: str):
self.sort = value
@rx.event
def apply(self):
self.open = False
rx.flex(
rx.text("Sort: ", DrawerFilterState.sort, rx.cond(DrawerFilterState.in_stock, " · in stock only", ""), size="2"),
rx.drawer.root(
rx.drawer.trigger(rx.button(rx.icon("sliders-horizontal"), "Filters", variant="outline")),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.handle(),
rx.drawer.title("Filters"),
rx.flex(rx.switch(checked=DrawerFilterState.in_stock, on_change=DrawerFilterState.set_in_stock),
rx.text("In stock only", size="2"), spacing="2", align="center"),
rx.radio(["Newest", "Price: low", "Price: high"], value=DrawerFilterState.sort,
on_change=DrawerFilterState.set_sort, direction="row"),
rx.button("Show results", on_click=DrawerFilterState.apply, width="100%"),
direction="column",
spacing="4",
width="100%",
max_width="480px",
margin="0 auto",
),
top="auto",
height="auto",
padding="1.5em",
background_color=rx.color("gray", 2),
border_radius="12px 12px 0 0",
),
),
open=DrawerFilterState.open,
on_open_change=DrawerFilterState.set_open,
direction="bottom",
),
spacing="3",
align="center",
wrap="wrap",
)Werkstattnotizen
root(direction) > trigger · overlay · portal > content > close. Standardrichtung ist bottom.
content bedeckt den ganzen Bildschirm, also die gegenüberliegende Seite auf "auto" setzen und width oder height festlegen.
Mit open + on_open_change gesteuert, kann der Handler eines Links oder Buttons den Drawer schließen.
modal=False erlaubt die Nutzung des Hintergrunds bei offenem Drawer, handle_only=True erlaubt das Ziehen nur am Griff.
snap_points wird beim Kompilieren festgelegt; State-Werte gehen dort nicht.
Über neue Lektionen informiert werden
Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.
R
ReflexKR
Python und Reflex zum Anfassen. Alle Beispiele wurden mit Reflex 0.10.0 ausgeführt und geprüft.
ReflexKR ist kostenlos und ohne Werbebanner. Wenn es dir geholfen hat, kannst du es mit einem Kaffee unterstützen. ☕ Spendier uns einen Kaffee
Hinweis zu Affiliate-Links© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Fragen & Antworten
Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.