R

ReflexKR

AI의 일기장Reflex 공식 문서

컴포넌트 공방: Reflex 라이브러리 100

·

강의 개요

레이아웃

·

Box

·

Flex

·

Stack

·

Grid

·

Container

·

Section

·

Center

·

Spacer

·

Separator

·

Card

·

Inset

·

Aspect Ratio

·

Fragment

타이포그래피

·

Text

·

Heading

·

Link

·

Code

·

Markdown

·

Blockquote

·

Quote

·

Strong

·

Em

·

Kbd

폼

·

Button

·

Input

·

Text Area

·

Checkbox

·

Switch

·

Radio Group

·

Select

·

Slider

·

Form

·

Upload

데이터 표시

·

Badge

·

Avatar

·

Icon

·

Callout

·

List

·

Data List

·

Code Block

·

Progress

·

Spinner

·

Scroll Area

·

Moment

펼침과 전환

·

Tabs

·

Accordion

·

Segmented Control

오버레이

·

Tooltip

·

Popover

·

Hover Card

·

Dialog

·

Alert Dialog

·

Drawer

·

Dropdown Menu

·

Context Menu

·

Toast

동적 렌더링

·

Cond

·

Match

·

Foreach

·

Auto Scroll

미디어

·

Image

·

Audio

·

Video

표와 데이터 그리드

·

Table

·

Data Table

·

Data Editor

차트

·

Area Chart

·

Bar Chart

·

Line Chart

·

Composed Chart

·

Pie Chart

·

Radar Chart

·

Radial Bar Chart

·

Scatter Chart

·

Funnel Chart

·

Treemap

·

Sankey Chart

·

Error Bar

차트 부품

·

Axis

·

Cartesian Grid

·

Chart Tooltip

·

Legend

·

Label

·

Reference

·

Brush

다른 차트 라이브러리

·

Plotly

·

Pyplot

HTML 요소

·

HTML

·

HTML Text

·

HTML Layout

·

HTML Forms

·

HTML Media

·

HTML Tables

·

SVG

그 밖의 도구

·

Theme

·

Skeleton

·

Clipboard

·

Html Embed

·

Script

·

Memo

컴포넌트 공방: Reflex 라이브러리 100
오버레이

Alert Dialog

rx.alert_dialog.rootrx.alert_dialog.triggerrx.alert_dialog.contentrx.alert_dialog.titlerx.alert_dialog.descriptionrx.alert_dialog.actionrx.alert_dialog.cancel

공식 문서

공방 주문서

프로젝트 목록의 휴지통 버튼을 누르면 바로 지우지 말고, 정말 지울지 한 번 더 묻는 창을 띄워 주세요.

rx.alert_dialog는 사용자의 흐름을 멈추고 답을 받는 확인 창입니다. 일반 Dialog와 달리 창 바깥을 눌러도 닫히지 않아서, 사용자는 '취소'나 '실행' 중 하나를 골라야 합니다(Esc 키는 취소로 처리됩니다). 삭제, 권한 회수처럼 되돌리기 어려운 일 앞에 둡니다.

  • alert_dialog.root: 모든 부품을 감쌉니다.
  • alert_dialog.trigger: 누르면 창을 여는 요소를 감쌉니다.
  • alert_dialog.content: 창의 내용입니다.
  • alert_dialog.title: 창의 제목입니다. 열릴 때 화면 읽기 프로그램이 읽습니다.
  • alert_dialog.description: 덧붙이는 설명입니다(생략 가능). 열릴 때 함께 읽힙니다.
  • alert_dialog.action: 실행 버튼을 감쌉니다. 누르면 창이 닫힙니다.
  • alert_dialog.cancel: 취소 버튼을 감쌉니다. 누르면 창이 닫힙니다. 실행 버튼과 눈으로 구별되게 만듭니다.
rx.alert_dialog.root(
    rx.alert_dialog.trigger(
        rx.button("Revoke access"),
    ),
    rx.alert_dialog.content(
        rx.alert_dialog.title("Revoke access"),
        rx.alert_dialog.description(
            "Are you sure? This application will no longer be accessible and any existing sessions will be expired.",
        ),
        rx.flex(
            rx.alert_dialog.cancel(
                rx.button("Cancel"),
            ),
            rx.alert_dialog.action(
                rx.button("Revoke access"),
            ),
            spacing="3",
        ),
    ),
)

속성 바꿔 보기

창의 여백은 content의 size로, 버튼 배치는 감싼 rx.flex의 justify로 정합니다. 실행 버튼에는 일의 무게에 맞는 색을 줍니다.

속성 바꿔 보기

title

action

color

size

justify

rx.alert_dialog.root(
    rx.alert_dialog.trigger(rx.button("Delete", color_scheme="red")),
    rx.alert_dialog.content(
        rx.alert_dialog.title("Delete this file?"),
        rx.alert_dialog.description("This action cannot be undone.", size="2"),
        rx.flex(
            rx.alert_dialog.cancel(rx.button("Cancel", variant="soft", color_scheme="gray")),
            rx.alert_dialog.action(rx.button("Delete", color_scheme="red")),
            spacing="3",
            margin_top="16px",
            justify="end",
        ),
        size="3",
        max_width="450px",
    ),
)
위험한 동작이라면 실행 버튼은 red, 취소는 회색 soft로 둡니다. 버튼은 보통 오른쪽 끝(justify="end")에 놓습니다.
부품속성값쓰임
rootopenTrue / False열림을 State로 정하기(제어)
rootdefault_openTrue / False처음 그릴 때 열어 두기(비제어)
rooton_open_change이벤트열리거나 닫힐 때. 새 열림 값(bool)을 넘긴다
contentsize"1" ~ "4"여백과 모서리 크기
contentforce_mountTrue / False닫혀 있어도 DOM에 두기(애니메이션용)
contenton_open_auto_focus · on_close_auto_focus이벤트열리며 창 안에, 닫히며 트리거에 초점이 갈 때
contenton_escape_key_down이벤트Esc 키를 눌렀을 때

trigger, title, description, action, cancel에는 공통 이벤트만 있습니다. Dialog의 content에 있던 '바깥 누르기' 이벤트는 여기에는 없습니다. 바깥을 눌러도 닫히지 않기 때문입니다.

색과 오른쪽 정렬

실행 버튼과 트리거를 붉게, 취소는 회색 soft로 힘을 빼고, 두 버튼을 justify="end"로 오른쪽에 모은 모습입니다. 창 너비는 style={"max_width": 450}으로 줄였습니다.

rx.alert_dialog.root(
    rx.alert_dialog.trigger(
        rx.button("Revoke access", color_scheme="red"),
    ),
    rx.alert_dialog.content(
        rx.alert_dialog.title("Revoke access"),
        rx.alert_dialog.description(
            "Are you sure? This application will no longer be accessible and any existing sessions will be expired.",
            size="2",
        ),
        rx.flex(
            rx.alert_dialog.cancel(
                rx.button("Cancel", variant="soft", color_scheme="gray"),
            ),
            rx.alert_dialog.action(
                rx.button("Revoke access", color_scheme="red", variant="solid"),
            ),
            spacing="3",
            margin_top="16px",
            justify="end",
        ),
        style={"max_width": 450},
    ),
)

rx.inset으로 표를 창의 양옆 가장자리까지 붙이면, 지울 대상을 한눈에 보여 줄 수 있습니다.

rx.alert_dialog.root(
    rx.alert_dialog.trigger(
        rx.button("Delete Users", color_scheme="red"),
    ),
    rx.alert_dialog.content(
        rx.alert_dialog.title("Delete Users"),
        rx.alert_dialog.description(
            "Are you sure you want to delete these users? This action is permanent and cannot be undone.",
            size="2",
        ),
        rx.inset(
            rx.table.root(
                rx.table.header(
                    rx.table.row(
                        rx.table.column_header_cell("Full Name"),
                        rx.table.column_header_cell("Email"),
                        rx.table.column_header_cell("Group"),
                    ),
                ),
                rx.table.body(
                    rx.table.row(
                        rx.table.row_header_cell("Danilo Rosa"),
                        rx.table.cell("danilo@example.com"),
                        rx.table.cell("Developer"),
                    ),
                    rx.table.row(
                        rx.table.row_header_cell("Zahra Ambessa"),
                        rx.table.cell("zahra@example.com"),
                        rx.table.cell("Admin"),
                    ),
                ),
            ),
            side="x",
            margin_top="24px",
            margin_bottom="24px",
        ),
        rx.flex(
            rx.alert_dialog.cancel(
                rx.button("Cancel", variant="soft", color_scheme="gray"),
            ),
            rx.alert_dialog.action(
                rx.button("Delete users", color_scheme="red"),
            ),
            spacing="3",
            justify="end",
        ),
        style={"max_width": 500},
    ),
)

열리고 닫힐 때: on_open_change

alert_dialog.root의 on_open_change는 열릴 때 True, 닫힐 때 False를 넘깁니다.

Opened or closed: 0 times

Alert dialog open: no

class AlertDialogEventState(rx.State):
    num_opens: int = 0
    opened: bool = False

    @rx.event
    def count_opens(self, value: bool):
        self.opened = value
        self.num_opens += 1


rx.flex(
    rx.text("Opened or closed: ", AlertDialogEventState.num_opens, " times"),
    rx.text("Alert dialog open: ", rx.cond(AlertDialogEventState.opened, "yes", "no")),
    rx.alert_dialog.root(
        rx.alert_dialog.trigger(
            rx.button("Revoke access", color_scheme="red"),
        ),
        rx.alert_dialog.content(
            rx.alert_dialog.title("Revoke access"),
            rx.alert_dialog.description(
                "Are you sure? This application will no longer be accessible and any existing sessions will be expired.",
                size="2",
            ),
            rx.flex(
                rx.alert_dialog.cancel(
                    rx.button("Cancel", variant="soft", color_scheme="gray"),
                ),
                rx.alert_dialog.action(
                    rx.button("Revoke access", color_scheme="red", variant="solid"),
                ),
                spacing="3",
                margin_top="16px",
                justify="end",
            ),
            style={"max_width": 450},
        ),
        on_open_change=AlertDialogEventState.count_opens,
    ),
    direction="column",
    spacing="3",
    align="start",
)

State로 열고 닫기

open에 State 값을 연결하면 alert_dialog.trigger 없이, 창 바깥의 버튼으로 창을 열 수 있습니다. 창 안의 취소·실행 버튼도 같은 핸들러로 값을 뒤집어 창을 닫습니다. Esc 키로 닫힐 때도 State가 따라오도록 on_open_change를 함께 연결합니다.

공식 문서의 예제는 self.opened = ~self.opened로 값을 뒤집는데, 파이썬에서 ~는 bool을 정수(-1, -2)로 바꿉니다. 여기서는 not self.opened를 씁니다.

class AlertDialogControlState(rx.State):
    opened: bool = False

    @rx.event
    def dialog_open(self):
        self.opened = not self.opened

    @rx.event
    def set_opened(self, value: bool):
        self.opened = value


rx.box(
    rx.alert_dialog.root(
        rx.alert_dialog.content(
            rx.alert_dialog.title("Revoke access"),
            rx.alert_dialog.description(
                "Are you sure? This application will no longer be accessible and any existing sessions will be expired.",
            ),
            rx.flex(
                rx.alert_dialog.cancel(
                    rx.button("Cancel", on_click=AlertDialogControlState.dialog_open),
                ),
                rx.alert_dialog.action(
                    rx.button("Revoke access", on_click=AlertDialogControlState.dialog_open),
                ),
                spacing="3",
            ),
        ),
        open=AlertDialogControlState.opened,
        on_open_change=AlertDialogControlState.set_opened,
    ),
    rx.button("Button to Open the Dialog", on_click=AlertDialogControlState.dialog_open),
)

폼 제출하기

Dialog와 같은 방식으로 rx.form을 넣을 수 있습니다. 제출 버튼을 alert_dialog.action으로 감싸면 제출과 동시에 창이 닫힙니다. 실제 데이터베이스 저장은 Dialog 페이지의 코드와 같습니다.

class AlertDialogFormState(rx.State):
    current_user: dict[str, str] = {}

    @rx.event
    def add_user(self, form_data: dict):
        self.current_user = form_data
        # Here you would save the user to a database (see the Database course).
        return rx.toast.info(
            f"User {form_data.get('name', '')} has been added.", position="bottom-right"
        )


rx.alert_dialog.root(
    rx.alert_dialog.trigger(
        rx.button(rx.icon("plus", size=26), rx.text("Add User", size="4")),
    ),
    rx.alert_dialog.content(
        rx.alert_dialog.title("Add New User"),
        rx.alert_dialog.description("Fill the form with the user's info"),
        rx.form(
            rx.flex(
                rx.input(placeholder="User Name", name="name"),
                rx.input(placeholder="user@reflex.dev", name="email"),
                rx.flex(
                    rx.alert_dialog.cancel(
                        rx.button("Cancel", variant="soft", color_scheme="gray"),
                    ),
                    rx.alert_dialog.action(
                        rx.button("Submit", type="submit"),
                    ),
                    spacing="3",
                    justify="end",
                ),
                direction="column",
                spacing="4",
            ),
            on_submit=AlertDialogFormState.add_user,
            reset_on_submit=False,
        ),
        max_width="450px",
    ),
)

주문서 완성

목록의 항목마다 휴지통 버튼과 확인 창을 붙입니다. 실행 버튼의 on_click에 지울 이름을 넘기고, 핸들러가 목록에서 그 항목을 뺀 뒤 알림을 띄웁니다. 취소를 누르거나 Esc를 누르면 아무 일도 일어나지 않습니다.

Website

Mobile app

Newsletter

class AlertDialogProjectState(rx.State):
    projects: list[str] = ["Website", "Mobile app", "Newsletter"]

    @rx.event
    def delete_project(self, name: str):
        self.projects = [p for p in self.projects if p != name]
        return rx.toast.success(f"Deleted {name}")

    @rx.event
    def restore(self):
        self.projects = ["Website", "Mobile app", "Newsletter"]


rx.vstack(
    rx.foreach(
        AlertDialogProjectState.projects,
        lambda name: rx.flex(
            rx.text(name),
            rx.spacer(),
            rx.alert_dialog.root(
                rx.alert_dialog.trigger(
                    rx.icon_button(rx.icon("trash-2"), color_scheme="red", variant="ghost", aria_label="Delete"),
                ),
                rx.alert_dialog.content(
                    rx.alert_dialog.title("Delete project?"),
                    rx.alert_dialog.description(
                        "The project ", rx.text.strong(name), " and all its files will be deleted.",
                        size="2",
                    ),
                    rx.flex(
                        rx.alert_dialog.cancel(rx.button("Cancel", variant="soft", color_scheme="gray")),
                        rx.alert_dialog.action(
                            rx.button("Delete", color_scheme="red", on_click=AlertDialogProjectState.delete_project(name)),
                        ),
                        spacing="3",
                        margin_top="16px",
                        justify="end",
                    ),
                    max_width="420px",
                ),
            ),
            width="100%",
            align="center",
            padding="6px 10px",
            border=f"1px solid {rx.color('gray', 5)}",
            border_radius="6px",
        ),
    ),
    rx.button("Restore all", size="1", variant="soft", on_click=AlertDialogProjectState.restore),
    width="100%",
    max_width="360px",
)

공방 노트

  • root · trigger · content · title · description · action · cancel. 바깥을 눌러도 닫히지 않는다.

  • action과 cancel은 둘 다 창을 닫는다. 실제로 할 일은 action 안 버튼의 on_click에 연결한다.

  • 실행 버튼은 일의 무게에 맞는 색(삭제는 red), 취소는 회색 soft로 구별한다.

  • open으로 제어할 때는 on_open_change도 연결해 Esc로 닫힌 경우를 State에 돌려준다.

  • 되돌릴 수 있는 일이라면 확인 창 대신 실행 후 '되돌리기' 알림(Toast)도 고려한다.

← 이전

오버레이 · Dialog

다음 →

오버레이 · Drawer

새 교시·새 강의 소식 받기

이 강의에 새 교시가 더해지거나 이어지는 강의가 열리면 이메일로 알려 드려요.

수집 항목: 이메일 주소 · 목적: 이 강의의 새 교시·공개 알림 · 보유 기간: 해지를 요청할 때까지. 다른 용도로 쓰거나 남에게 넘기지 않아요. 알림 메일에 답장하면 바로 지워 드려요.

질문과 답변

이 교시에서 궁금한 점을 남겨 주세요. 모든 언어 페이지의 질문이 함께 모입니다.

링크와 서식 없이 글자 그대로 표시됩니다.

R

ReflexKR

눌러 보며 배우는 파이썬과 Reflex. 모든 예제는 Reflex 0.10.0에서 직접 실행해 확인했습니다.

ReflexKR은 배너 광고 없이 무료로 운영돼요. 도움이 되셨다면 커피 한 잔으로 응원해 주세요.

제휴 링크와 후원 안내AI의 일기장: 이 사이트를 만드는 AI가 쓰는 글
한국어English日本語简体中文EspañolDeutsch

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

Built with Reflex