컴포넌트 공방: 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
공방 주문서
게시글 아래 '댓글' 버튼을 누르면, 페이지를 떠나지 않고 그 자리에서 짧은 댓글을 쓸 수 있는 작은 창을 띄워 주세요.
rx.popover는 버튼을 누르면 그 옆에 떠오르는 작은 창입니다. 툴팁과 달리 누를 때 열리고, 안에 입력칸이나 버튼 같은 조작할 거리를 넣을 수 있습니다. 네 부품으로 만듭니다.
popover.root: 팝오버의 모든 부품을 감쌉니다.popover.trigger: 누르면 팝오버를 여닫는 버튼을 감쌉니다.popover.content: 열렸을 때 떠오르는 내용입니다.popover.close: 누르면 팝오버를 닫는 버튼을 감쌉니다.rx.popover.root(
rx.popover.trigger(
rx.button("Popover"),
),
rx.popover.content(
rx.flex(
rx.text("Simple Example"),
rx.popover.close(
rx.button("Close"),
),
direction="column",
spacing="3",
),
),
)위치와 크기는 popover.content에, 모달 여부는 popover.root에 줍니다. 값을 바꾼 뒤 Open을 눌러 확인합니다.
속성 바꿔 보기
text
size
side
align
modal
rx.popover.root(
rx.popover.trigger(rx.button("Open")),
rx.popover.content(
rx.flex(
rx.text("Simple Example"),
rx.popover.close(rx.button("Close", size="1")),
direction="column",
spacing="3",
),
size="2",
side="bottom",
align="center",
),
modal=False,
)| 부품 | 속성 | 값 | 쓰임 |
|---|---|---|---|
root | open | True / False | 열림을 State로 정하기(제어). on_open_change와 함께 |
root | default_open | True / False | 처음 그릴 때 열어 두기(비제어) |
root | modal | True / False | 열려 있는 동안 바깥 조작을 막고, 화면 읽기 프로그램에서 바깥을 숨김 |
root | on_open_change | 이벤트 | 열리거나 닫힐 때. 새 열림 값(bool)을 넘긴다 |
content | size | "1" ~ "4" | 여백과 모서리 크기 |
content | side · align | 위치 이름 | 뜨는 쪽과 맞추는 자리(기본 "bottom", "center") |
content | side_offset · align_offset | 숫자(px) | 버튼과의 간격, 정렬 위치에서 더 미는 거리 |
content | avoid_collisions · collision_padding | bool · 숫자 | 화면 끝에 닿을 때 옮기기, 그 여백 |
content | sticky · hide_when_detached | "partial" "always" · bool | 스크롤할 때 붙어 있는 정도, 버튼이 가려지면 숨기기 |
content | on_open_auto_focus · on_close_auto_focus | 이벤트 | 열리며 안쪽에, 닫히며 버튼에 초점이 갈 때 |
content | on_escape_key_down · on_pointer_down_outside | 이벤트 | Esc 키, 바깥 누르기 |
content | on_focus_outside · on_interact_outside | 이벤트 | 초점이나 조작이 바깥으로 나갈 때 |
trigger와 close에는 따로 속성이 없고, 공통 이벤트(on_click 등)만 받습니다.
팝오버 안에는 무엇이든 넣을 수 있습니다. 아바타 옆에 입력칸과 체크박스, 보내기 버튼을 둔 댓글 창입니다. 보내기 버튼을 popover.close로 감싸면 누르는 순간 창이 닫힙니다. 너비는 style={"width": 360}처럼 content에 직접 줍니다.
rx.popover.root(
rx.popover.trigger(
rx.button("Comment", variant="soft"),
),
rx.popover.content(
rx.flex(
rx.avatar("2", fallback="RX", radius="full"),
rx.box(
rx.text_area(placeholder="Write a comment…", style={"height": 80}),
rx.flex(
rx.checkbox("Send to group"),
rx.popover.close(rx.button("Comment", size="1")),
spacing="3",
margin_top="12px",
justify="between",
),
flex_grow="1",
),
spacing="3",
),
style={"width": 360},
),
)rx.inset(side="top")을 content의 첫 자식으로 두면, 팝오버의 위쪽 여백 없이 가장자리까지 꽉 차는 머리 그림을 넣을 수 있습니다.
rx.popover.root(
rx.popover.trigger(
rx.button("Feedback", variant="classic"),
),
rx.popover.content(
rx.inset(
side="top",
background="url('https://picsum.photos/id/29/720/200') center/cover",
height="100px",
),
rx.box(
rx.text_area(placeholder="Write a comment…", style={"height": 80}),
rx.flex(
rx.checkbox("Send to group"),
rx.popover.close(rx.button("Comment", size="1")),
spacing="3",
margin_top="12px",
justify="between",
),
padding_top="12px",
),
style={"width": 360},
),
)버튼 글자로 State 값을 쓸 때는 rx.button(rx.text(State.값))처럼 rx.text로 한 번 감쌉니다. 공식 문서는 rx.button(State.값)처럼 바로 넘기면 기대대로 동작하지 않는다고 안내합니다. 아래에서 언어를 고르면 버튼 글자가 바뀝니다.
class PopoverLanguageState(rx.State):
language: str = "EN"
@rx.event
def set_language(self, value: str):
self.language = value
rx.popover.root(
rx.popover.trigger(
rx.button(rx.text(PopoverLanguageState.language), variant="outline"),
),
rx.popover.content(
rx.flex(
rx.popover.close(rx.button("EN", size="1", variant="soft", on_click=PopoverLanguageState.set_language("EN"))),
rx.popover.close(rx.button("KO", size="1", variant="soft", on_click=PopoverLanguageState.set_language("KO"))),
rx.popover.close(rx.button("JA", size="1", variant="soft", on_click=PopoverLanguageState.set_language("JA"))),
spacing="2",
),
),
)popover.root의 on_open_change는 열릴 때 True, 닫힐 때 False를 핸들러에 넘깁니다.
Opened or closed: 0 times
Popover open: no
class PopoverEventState(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: ", PopoverEventState.num_opens, " times"),
rx.text("Popover open: ", rx.cond(PopoverEventState.opened, "yes", "no")),
rx.popover.root(
rx.popover.trigger(
rx.button("Popover"),
),
rx.popover.content(
rx.flex(
rx.text("Simple Example"),
rx.popover.close(
rx.button("Close"),
),
direction="column",
spacing="3",
),
),
on_open_change=PopoverEventState.count_opens,
),
direction="column",
spacing="3",
align="start",
)open과 on_open_change를 함께 연결하면, 연필 버튼과 바깥 누르기는 평소처럼 동작하고 코드에서도 창을 닫을 수 있습니다. 아래에서 이름을 바꾸고 Rename을 누르면 핸들러가 값을 저장한 뒤 self.open = False로 창을 닫습니다. 열릴 때마다 입력칸에는 지금 이름이 다시 채워집니다.
class PopoverControlState(rx.State):
open: bool = False
name: str = "Untitled"
draft: str = ""
@rx.event
def set_open(self, value: bool):
self.open = value
if value:
self.draft = self.name
@rx.event
def set_draft(self, value: str):
self.draft = value
@rx.event
def rename(self):
self.name = self.draft.strip() or "Untitled"
self.open = False
rx.flex(
rx.heading(PopoverControlState.name, size="4"),
rx.popover.root(
rx.popover.trigger(rx.icon_button(rx.icon("pencil"), variant="soft", size="1", aria_label="Rename")),
rx.popover.content(
rx.flex(
rx.input(value=PopoverControlState.draft, on_change=PopoverControlState.set_draft),
rx.button("Rename", size="1", on_click=PopoverControlState.rename),
spacing="2",
),
),
open=PopoverControlState.open,
on_open_change=PopoverControlState.set_open,
),
align="center",
spacing="3",
)글 아래 '댓글' 버튼에서 열리는 작은 댓글 창입니다. 위쪽에 열리도록 side="top", 버튼 왼쪽 끝에 맞추도록 align="start"를 줍니다.
Shipping is now free over $30.
rx.card(
rx.text("Shipping is now free over $30.", size="2"),
rx.popover.root(
rx.popover.trigger(rx.button(rx.icon("message-circle"), "Comment", variant="ghost", size="1", margin_top="8px")),
rx.popover.content(
rx.flex(
rx.text_area(placeholder="Write a comment…", rows="3"),
rx.flex(
rx.popover.close(rx.button("Cancel", size="1", variant="soft", color_scheme="gray")),
rx.popover.close(rx.button("Post", size="1")),
spacing="2",
justify="end",
),
direction="column",
spacing="2",
),
side="top",
align="start",
width="300px",
),
),
max_width="360px",
)공방 노트
root · trigger · content · close 네 부품으로 만든다. trigger를 누르면 열리고 close나 바깥을 누르면 닫힌다.
위치·크기는 content(side, align, side_offset, size), 모달 여부는 root(modal).
트리거 버튼 글자로 State 값을 쓸 때는 rx.text로 감싼다.
on_open_change는 새 열림 값(bool)을 넘긴다. open으로 제어하면 핸들러에서 창을 닫을 수 있다.
새 교시·새 강의 소식 받기
이 강의에 새 교시가 더해지거나 이어지는 강의가 열리면 이메일로 알려 드려요.
R
ReflexKR
눌러 보며 배우는 파이썬과 Reflex. 모든 예제는 Reflex 0.10.0에서 직접 실행해 확인했습니다.
ReflexKR은 배너 광고 없이 무료로 운영돼요. 도움이 되셨다면 커피 한 잔으로 응원해 주세요.
© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
질문과 답변
이 교시에서 궁금한 점을 남겨 주세요. 모든 언어 페이지의 질문이 함께 모입니다.