R

ReflexKR

Reflex-Dokumentation

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

Die Komponentenwerkstatt: Reflex' 100 Bibliotheksbausteine
Overlays

Drawer

rx.drawer.rootrx.drawer.triggerrx.drawer.overlayrx.drawer.portalrx.drawer.contentrx.drawer.close

Offizielle 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",
)

Props ausprobieren

Ä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,
)
Größe und Farbe des Panels legen die Style-Props von drawer.content fest. modal gehört an drawer.root.
Prop (root)WerteStandardVerwendung
direction"top" "bottom" "left" "right""bottom"Richtung, aus der er kommt; bestimmt auch die Richtung zum Wegziehen
open · default_openTrue / False-Offen-Zustand über den State steuern (kontrolliert) · anfangs offen
modalTrue / FalseTrueBei False lässt sich bei offenem Drawer außerhalb klicken und scrollen
dismissibleTrue / False-Bei False schließt er weder per Ziehen noch per Klick außerhalb oder Esc (zusammen mit open verwenden)
handle_onlyTrue / False-Bei True nur über drawer.handle ziehbar
snap_pointsListe von Zahlen zwischen 0 und 1 oder "px"-Werten-Höhen, an denen er einrastet (nur Python-Werte, keine State-Werte)
fade_from_indexGanzzahlletzter PunktAb welchem Rastpunkt der Hintergrund abgedunkelt wird
close_threshold0 bis 1-Wie weit man ziehen muss, damit er schließt
scroll_lock_timeoutMillisekunden500Wie lange nach dem Scrollen im Panel das Ziehen gesperrt ist
should_scale_backgroundTrue / False-Effekt, der den Hintergrund leicht verkleinert (braucht vaul-drawer-wrapper)
prevent_scroll_restorationTrue / FalseTrueVerhindert, dass nach dem Schließen die Scrollposition wiederhergestellt wird
on_open_changeEvent-Beim Öffnen oder Schließen; übergibt den neuen Offen-Wert (bool)
on_animation_endEvent-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.

Vier Richtungen

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",
)

Titel, Beschreibung, Griff

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,
)

Öffnen und Schließen über den State: ein Seitenmenü

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.

Section 1

Section 2

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"),
)

Auftrag erledigt

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.

← Zurück

Overlays · Alert Dialog

Weiter →

Overlays · Dropdown Menu

Über neue Lektionen informiert werden

Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.

Erhoben: deine E-Mail-Adresse · Zweck: Hinweise auf neue Lektionen oder den Start dieses Kurses · Speicherdauer: bis du die Löschung verlangst. Keine andere Nutzung, keine Weitergabe. Antworte einfach auf eine Benachrichtigung, dann löschen wir sie sofort.

Fragen & Antworten

Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.

Wird als reiner Text angezeigt, ohne Links oder Formatierung.

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
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex