El taller de componentes: los 100 componentes de Reflex
·
Resumen del curso
Diseño
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
Tipografía
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
Formularios
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
Visualización de datos
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
Mostrar y ocultar
·
Tabs
·
Accordion
·
Segmented Control
Superposiciones
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
Renderizado dinámico
·
Cond
·
Match
·
Foreach
·
Auto Scroll
Multimedia
·
Image
·
Audio
·
Video
Tablas y cuadrículas de datos
·
Table
·
Data Table
·
Data Editor
Gráficos
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
Piezas de gráficos
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
Otras bibliotecas de gráficos
·
Plotly
·
Pyplot
Elementos HTML
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
Otras herramientas
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
rx.recharts.sankey_chartrx.recharts.sankey_chart.noderx.recharts.sankey_chart.linkDocumentación oficial
Pedido del taller
Muestra con el grosor de los flujos de dónde entran los ingresos del mes y cuánto se va al alquiler, a la comida y al ahorro.
rx.recharts.sankey_chart es un diagrama de Sankey: muestra nodos y la cantidad que fluye entre ellos mediante el grosor de unas bandas. Se usa para ver «flujos», como por qué páginas pasan los visitantes hasta llegar a la compra, o de dónde viene el dinero y adónde va.
data no es una lista sino un dict con la forma {"nodes": [...], "links": [...]}. El source y el target de links son posiciones (desde 0) de la lista nodes, y value es la cantidad de ese flujo. El tooltip se añade como hijo.
sankeychart_data = {
"nodes": [
{"name": "Website"},
{"name": "Landing"},
{"name": "Product"},
{"name": "Checkout"},
{"name": "Purchase"},
],
"links": [
{"source": 0, "target": 1, "value": 1200},
{"source": 1, "target": 2, "value": 900},
{"source": 2, "target": 3, "value": 420},
{"source": 3, "target": 4, "value": 260},
],
}
rx.recharts.sankey_chart(
rx.recharts.graphing_tooltip(),
data=sankeychart_data,
node_padding=24,
node_width=12,
link_curvature=0.55,
width="100%",
height=300,
)Si das un dict a node y a link, todos los nodos y bandas reciben el mismo estilo SVG. Las claves del dict son los nombres de los atributos SVG tal cual (en camelCase, como strokeOpacity). link_curvature es cuánto se curvan las bandas (con 0, rectas).
Prueba las propiedades
node_color
link_opacity
0.35
link_curvature
0.5
sort
rx.recharts.sankey_chart(
rx.recharts.graphing_tooltip(),
data={
"nodes": [{"name": "Ads"}, {"name": "Search"}, {"name": "Signup"}, {"name": "Leave"}, {"name": "Paid"}],
"links": [
{"source": 0, "target": 2, "value": 300},
{"source": 0, "target": 3, "value": 500},
{"source": 1, "target": 2, "value": 600},
{"source": 1, "target": 3, "value": 200},
{"source": 2, "target": 4, "value": 350},
],
},
node={"fill": rx.color("indigo", 9), "stroke": "none"},
link={"stroke": rx.color("gray", 9), "strokeOpacity": 0.35},
link_curvature=0.5,
sort=True,
node_padding=20,
node_width=12,
width="100%",
height=300,
)| Propiedad | Valores | Por defecto | Uso |
|---|---|---|---|
data | {"nodes": [...], "links": [...]} | ninguno | Nodos y flujos. Los enlaces se unen por la posición del nodo |
name_key | cadena | "name" | Clave del nombre del nodo |
data_key | cadena | "value" | Clave de la cantidad del flujo |
node | dict o función @sankey_chart.node | Estilo de los nodos o función que los dibuja | |
link | dict o función @sankey_chart.link | Estilo de las bandas o función que las dibuja | |
node_width | número | 10 | Grosor de la barra del nodo |
node_padding | número | 10 | Espacio entre nodos de la misma columna |
link_curvature | 0~1 | 0.5 | Cuánto se curvan las bandas |
sort | True / False | True | Si se ordenan los nodos de arriba abajo |
iterations | número | 32 | Veces que se repite el cálculo de la disposición |
margin, width, height | dict / número o porcentaje | 5 por lado / "100%" | Margen y tamaño. Si se cortan los nombres de la derecha, amplía margin |
| Eventos | on_click on_mouse_enter on_mouse_leave on_mouse_move | Eventos de ratón sobre el área del gráfico |
Hemos conectado a data un dict de State. Al pulsar el botón se generan nuevos value para los enlaces, y se recalculan el grosor de las bandas y la altura de los nodos. Aquí node y link reciben un dict con color, borde y opacidad.
import random
from typing import Any
class SankeyChartLiveState(rx.State):
data: dict[str, Any] = {
"nodes": [
{"name": "Marketing"},
{"name": "Trial"},
{"name": "Sales"},
{"name": "Support"},
{"name": "Retained"},
],
"links": [
{"source": 0, "target": 1, "value": 600},
{"source": 1, "target": 2, "value": 320},
{"source": 2, "target": 4, "value": 210},
{"source": 1, "target": 3, "value": 180},
{"source": 3, "target": 4, "value": 130},
],
}
@rx.event
def shuffle(self):
self.data = {
"nodes": self.data["nodes"],
"links": [{**link, "value": random.randint(80, 700)} for link in self.data["links"]],
}
rx.vstack(
rx.recharts.sankey_chart(
rx.recharts.graphing_tooltip(),
data=SankeyChartLiveState.data,
node={
"fill": rx.color("accent", 7),
"stroke": rx.color("accent", 10),
"strokeWidth": 2,
},
link={
"stroke": rx.color("gray", 7),
"strokeOpacity": 0.35,
},
node_padding=18,
node_width=14,
width="100%",
height=300,
),
rx.button("Randomize flows", on_click=SankeyChartLiveState.shuffle),
width="100%",
)Si un dict no basta, escribe tú las funciones que dibujan nodos y bandas. Una función decorada con @rx.recharts.sankey_chart.node recibe como Var la información de un nodo (SankeyNodeProps: posición x e y, tamaño width y height, datos originales payload) y devuelve un componente SVG. @rx.recharts.sankey_chart.link recibe la información de una banda (SankeyLinkProps: coordenadas de inicio y fin, grosor linkWidth, payload).
rx.recharts.use_chart_width() es el ancho real del gráfico. Sirve para poner a la izquierda el nombre de los nodos del extremo derecho."fill") se leen convirtiendo a dict, como en payload.to(dict)["fill"].rx.vars.use_id() crea para cada banda un id de degradado que no se repite. Cada banda pasa del color del nodo de origen al del nodo de destino.Las dos funciones se definen una sola vez a nivel de módulo antes de usarlas en la pantalla.
sankeychart_styled = {
"nodes": [
{"name": "Sources", "fill": rx.color("blue", 8)},
{"name": "Direct", "fill": rx.color("green", 8)},
{"name": "Search", "fill": rx.color("grass", 8)},
{"name": "Paid", "fill": rx.color("amber", 8)},
{"name": "Revenue", "fill": rx.color("purple", 8)},
],
"links": [
{"source": 0, "target": 1, "value": 350},
{"source": 0, "target": 2, "value": 500},
{"source": 0, "target": 3, "value": 220},
{"source": 1, "target": 4, "value": 190},
{"source": 2, "target": 4, "value": 260},
{"source": 3, "target": 4, "value": 150},
],
}
@rx.recharts.sankey_chart.node
def sankeychart_node(node: rx.Var[rx.recharts.SankeyNodeProps]) -> rx.Component:
# put the name on the left for the rightmost nodes
is_out = node.x + node.width + 6 > rx.recharts.use_chart_width()
return rx.fragment(
rx.el.svg.text(
node.payload.name,
x=rx.cond(is_out, node.x - 6, node.x + node.width + 6).to(int),
y=(node.y + node.height / 2).to(int),
text_anchor=rx.cond(is_out, "end", "start"),
fill=rx.color("gray", 12),
font_size=10,
),
rx.el.svg.rect(
x=node.x.to(int),
y=node.y.to(int),
width=node.width.to(int),
height=node.height.to(int),
# read the payload's custom key (fill) after converting it to a dict
fill=node.payload.to(dict)["fill"],
stroke=rx.color("gray", 12),
stroke_width=1,
),
)
@rx.recharts.sankey_chart.link
def sankeychart_link(link: rx.Var[rx.recharts.SankeyLinkProps]) -> rx.Component:
link_id = rx.vars.use_id()
source = link.payload.source.to(dict)
target = link.payload.target.to(dict)
return rx.fragment(
rx.el.svg.linear_gradient(
rx.el.svg.stop(offset="0%", stop_color=source["fill"]),
rx.el.svg.stop(offset="100%", stop_color=target["fill"]),
id=link_id,
),
rx.el.svg.path(
d=(
f"M{link.sourceX},{link.sourceY} "
f"C{link.sourceControlX},{link.sourceY} "
f"{link.targetControlX},{link.targetY} "
f"{link.targetX},{link.targetY}"
),
fill="none",
stroke=f"url(#{link_id})",
stroke_opacity=0.35,
stroke_width=link.linkWidth,
),
rx.el.svg.text(
link.payload.value,
x=((link.sourceX + link.targetX) / 2).to(int),
y=((link.sourceY + link.targetY) / 2).to(int),
text_anchor="middle",
fill=rx.color("gray", 12),
font_size=10,
),
)
rx.recharts.sankey_chart(
data=sankeychart_styled,
node=sankeychart_node,
link=sankeychart_link,
width="100%",
height=320,
)Dos fuentes de ingresos se juntan en el nodo «Budget» y luego se dividen en tres ramas. Los nodos van en un color intenso y las bandas en un tono claro del mismo color, para que el flujo parezca salir de los nodos, y ampliamos el margin derecho para que no se corten los nombres de la última columna.
rx.recharts.sankey_chart(
rx.recharts.graphing_tooltip(),
data={
"nodes": [
{"name": "Salary"},
{"name": "Side job"},
{"name": "Budget"},
{"name": "Rent"},
{"name": "Food"},
{"name": "Savings"},
],
"links": [
{"source": 0, "target": 2, "value": 3000},
{"source": 1, "target": 2, "value": 600},
{"source": 2, "target": 3, "value": 1400},
{"source": 2, "target": 4, "value": 900},
{"source": 2, "target": 5, "value": 1300},
],
},
node={"fill": rx.color("accent", 9), "stroke": "none"},
link={"stroke": rx.color("accent", 6), "strokeOpacity": 0.5},
node_padding=28,
node_width=10,
margin={"top": 10, "right": 80, "bottom": 10, "left": 10},
width="100%",
height=300,
)Notas del taller
data es {"nodes": [...], "links": [...]}. El source y el target de cada enlace son posiciones de nodos.
Un dict en node o link da el estilo de todos (atributos SVG en camelCase).
La disposición se ajusta con node_width, node_padding, link_curvature y sort.
Para dibujar con más libertad, devuelve SVG desde funciones @rx.recharts.sankey_chart.node / .link.
Con un dict de State en data, se recalcula cuando cambian los flujos.
Recibe avisos de nuevas lecciones
Te avisaremos por correo cuando este curso tenga lecciones nuevas o se abra un curso de continuación.
R
ReflexKR
Aprende Python y Reflex haciendo. Todos los ejemplos se ejecutaron y verificaron en Reflex 0.10.0.
ReflexKR es gratis y sin banners publicitarios. Si te ayudó, puedes apoyarlo con un café. ☕ Invítanos un café
Aviso de afiliados© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Preguntas y respuestas
Pregunta lo que quieras sobre esta lección. Aquí se reúnen las preguntas de todas las versiones de idioma de esta página.