Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions docs/app/assets/tailwind-theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -1699,6 +1699,14 @@
/* padding: 0rem 0.125rem 0rem 0.125rem; */
}

/* Override Radix Code (rt-Code) accent coloring so inline code matches slate theme */
code.rt-Code,
code.rt-Code.rt-variant-soft,
.rt-Code.rt-variant-soft {
color: var(--c-slate-11) !important;
background-color: var(--c-slate-3) !important;
}

.code-error-style {
font-family: var(--font-jetbrains);
font-size: 0.835rem;
Expand Down Expand Up @@ -1803,6 +1811,44 @@
}
}

.code-block button,
.code-block > button {
border: none !important;
border-width: 0 !important;
background: transparent !important;
background-color: transparent !important;
opacity: 0 !important;
transition: opacity 0.15s ease-out !important;
pointer-events: none;
display: inline-flex !important;
align-items: center !important;
gap: 0.375rem !important;
font-size: 0.8125rem !important;
font-weight: 500 !important;
color: var(--c-slate-11) !important;
top: 8px !important;
right: 12px !important;
Comment on lines +1829 to +1830
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 top/right without position: absolute

top: 8px !important and right: 12px !important only have an effect on positioned elements (position: absolute/relative/fixed/sticky). The .code-block button rule sets display: inline-flex but no position, so these values are silently ignored unless the Radix UI copy button already carries position: absolute from its own stylesheet. Adding position: absolute !important here makes the intent explicit and ensures the placement survives any future upstream CSS changes.

Suggested change
top: 8px !important;
right: 12px !important;
position: absolute !important;
top: 8px !important;
right: 12px !important;

padding: 6px 8px !important;
}

.code-block button::after,
.code-block > button::after {
content: "Copy";
}

.code-block:hover button,
.code-block:hover > button,
.code-block button:focus-visible {
opacity: 1 !important;
pointer-events: auto;
}

.code-block button:hover,
.code-block > button:hover {
background: var(--c-slate-3) !important;
background-color: var(--c-slate-3) !important;
}


.tab-style {
color: var(--c-slate-9);
Expand All @@ -1814,6 +1860,89 @@
letter-spacing: -0.01094rem;
}

.pill-tab-list {
display: inline-flex !important;
gap: 2px !important;
padding: 4px !important;
background: var(--c-slate-3) !important;
border-radius: 10px !important;
border-bottom: none !important;
box-shadow: none !important;
width: fit-content !important;
max-width: 100%;
overflow-x: auto;
}

.pill-tab-list::before,
.pill-tab-list::after {
display: none !important;
content: none !important;
}

.pill-tab {
appearance: none !important;
background: transparent !important;
background-color: transparent !important;
border: none !important;
padding: 8px 16px !important;
font-size: 0.9375rem !important;
font-weight: 450 !important;
color: var(--c-slate-11) !important;
border-radius: 7px !important;
cursor: pointer;
white-space: nowrap;
transition: color 0.12s, background-color 0.12s, box-shadow 0.12s;
letter-spacing: 0 !important;
line-height: 1.25rem !important;
box-shadow: none !important;
}

.pill-tab::before,
.pill-tab::after,
.pill-tab:hover::before,
.pill-tab:hover::after,
.pill-tab[data-state='active']::before,
.pill-tab[data-state='active']::after,
.pill-tab[data-state='active']:hover::before,
.pill-tab[data-state='active']:hover::after {
background: transparent !important;
background-color: transparent !important;
box-shadow: none !important;
content: none !important;
display: none !important;
}

.pill-tab:hover {
color: var(--c-slate-11) !important;
background: transparent !important;
}

.pill-tab .rt-BaseTabListTriggerInner,
.pill-tab:hover .rt-BaseTabListTriggerInner,
.pill-tab:focus-visible .rt-BaseTabListTriggerInner,
.pill-tab:focus-visible:hover .rt-BaseTabListTriggerInner {
background-color: transparent !important;
background: transparent !important;
}

.pill-tab[data-state='active'],
.pill-tab[data-state='active']:hover {
color: var(--c-slate-12) !important;
font-weight: 500 !important;
background: var(--c-slate-1) !important;
background-color: var(--c-slate-1) !important;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08) !important;
}

:where(.dark, .dark *) .pill-tab[data-state='active'] {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) !important;
}

.tab-style:hover:not([data-state='active'])::before {
background: transparent !important;
background-color: transparent !important;
}

.tab-style:hover {
color: var(--c-slate-11);
}
Expand Down
56 changes: 37 additions & 19 deletions docs/app/reflex_docs/docgen_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -666,15 +666,19 @@ def _render_tabs(self, block: DirectiveBlock) -> rx.Component:
rx.tabs.trigger(
title,
value=value,
class_name="tab-style font-base font-semibold text-[1.25rem]",
class_name="pill-tab",
)
)
contents.append(
rx.tabs.content(self._render_children(body_blocks), value=value),
rx.tabs.content(
self._render_children(body_blocks),
value=value,
class_name="pt-6",
),
)

return rx.tabs.root(
rx.tabs.list(*triggers, class_name="mt-4"),
rx.tabs.list(*triggers, class_name="pill-tab-list mt-2"),
*contents,
default_value="tab1",
)
Expand Down Expand Up @@ -702,29 +706,43 @@ def _render_definition(self, block: DirectiveBlock) -> rx.Component:

def _render_section(self, block: DirectiveBlock) -> rx.Component:
"""Render a ``md section`` directive."""
from reflex_ui_shared.styles.colors import c_color

sections = self._split_children_by_heading(block.children)
return rx.box(
rx.vstack(
return rx.el.div(
rx.el.div(
*[
rx.fragment(
rx.text(
rx.text.span(header, font_weight="bold"),
width="100%",
rx.el.div(
rx.el.div(
header,
style={
"fontWeight": "600",
"color": "var(--c-slate-12)",
"fontSize": "1rem",
"lineHeight": "1.5",
},
),
rx.box(self._render_children(body), width="100%"),
rx.el.div(
self._render_children(body),
style={"width": "100%"},
),
style={
"display": "flex",
"flexDirection": "column",
"gap": "0.25rem",
"width": "100%",
},
)
for header, body in sections
],
text_align="left",
margin_y="1em",
width="100%",
style={
"display": "flex",
"flexDirection": "column",
"gap": "1.25rem",
"width": "100%",
"paddingLeft": "1.5rem",
"borderLeft": "1.5px solid var(--c-slate-4)",
},
),
border_left=f"1.5px {c_color('slate', 4)} solid",
padding_left="1em",
width="100%",
align_items="center",
style={"width": "100%", "margin": "1.5rem 0"},
)


Expand Down
6 changes: 3 additions & 3 deletions docs/app/reflex_docs/templates/docpage/docpage.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,8 @@ def wrapper(*args, **kwargs) -> rx.Component:
class_name="lg:mt-0 h-auto",
),
class_name=ui.cn(
"flex-1 h-auto mx-auto lg:max-w-[42rem] px-4 overflow-y-auto",
"lg:max-w-[56rem]" if not show_right_sidebar else "",
"flex-1 h-auto mx-auto lg:max-w-[52rem] px-4 overflow-y-auto",
"lg:max-w-[64rem]" if not show_right_sidebar else "",
),
),
rx.box(
Expand Down Expand Up @@ -611,7 +611,7 @@ def wrapper(*args, **kwargs) -> rx.Component:
),
),
class_name=(
"w-[240px] h-screen sticky top-0 shrink-0 hidden xl:block"
"w-[240px] h-screen sticky top-0 shrink-0 hidden 2xl:block"
),
)
if show_right_sidebar and not pseudo_right_bar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ def get_sidebar_items_learn():
create_item(
"Getting Started",
children=[
getting_started.introduction,
getting_started.installation,
getting_started.introduction,
getting_started.basics,
getting_started.project_structure,
getting_started.dashboard_tutorial,
Expand Down
4 changes: 2 additions & 2 deletions docs/app/reflex_docs/views/docs_navbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def menu_item(text: str, href: str, active_str: str = "") -> rx.Component:
to=href,
),
class_name=ui.cn(
"xl:flex hidden h-full items-center justify-center",
"md:flex hidden h-full items-center justify-center",
rx.cond(active, active_cn, ""),
),
custom_attrs={"role": "menuitem"},
Expand Down Expand Up @@ -111,7 +111,7 @@ def navigation_menu() -> rx.Component:
),
ui.navigation_menu.item(
navbar_sidebar_button(),
class_name="xl:hidden flex",
class_name="md:hidden flex",
unstyled=True,
custom_attrs={"role": "menuitem"},
),
Expand Down
45 changes: 26 additions & 19 deletions docs/getting_started/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import reflex as rx
```

# Reflex Basics
# Basics

This page gives an introduction to the most common concepts that you will use to build Reflex apps.
**~10 min** · An introduction to the most common concepts you'll use to build Reflex apps.

```md section
# You will learn how to:
Expand All @@ -18,13 +18,7 @@ This page gives an introduction to the most common concepts that you will use to
- Create pages and navigate between them
```

[Install](/docs/getting_started/installation) `reflex` with uv before continuing.

```bash
uv add reflex
```

Import the `reflex` library to get started.
If you haven't yet, [install Reflex](/docs/getting_started/installation) before continuing. Every example below imports the library as `rx`:

```python
import reflex as rx
Expand All @@ -46,15 +40,15 @@ Components can be nested inside each other to create complex UIs.
To nest components as children, pass them as positional arguments to the parent component. In the example below, the `rx.text` and `my_button` components are children of the `rx.box` component.

```python demo exec
def my_page():
def my_container():
return rx.box(
rx.text("This is a page"),
# Reference components defined in other functions.
my_button(),
)
```

You can also use any base HTML element through the [`rx.el`](/docs/library/other/html) namespace. This allows you to use standard HTML elements directly in your Reflex app when you need more control or when a specific component isn't available in the Reflex component library.
You can also use any base HTML element through the [rx.el](/docs/library/other/html) namespace. This allows you to use standard HTML elements directly in your Reflex app when you need more control or when a specific component isn't available in the Reflex component library.

```python demo exec
def my_div():
Expand Down Expand Up @@ -142,7 +136,7 @@ Vars can be referenced in multiple components, and will automatically update whe
So far, we've defined state vars but we haven't shown how to change them. All state changes are handled through functions in the state class, called [event handlers](/docs/events/events_overview).

```md alert
Event handlers are the ONLY way to change state in Reflex.
Event handlers are the **only** way to change state in Reflex.
```

Components have special props, such as `on_click`, called event triggers that can be used to make components interactive. Event triggers connect components to event handlers, which update the state.
Expand Down Expand Up @@ -214,7 +208,7 @@ def text_input():
Make sure that the event handler has the same number of arguments as the event trigger, or an error will be raised.
```

## Compile-time vs. runtime (IMPORTANT)
## Compile-time vs. runtime

Before we dive deeper into state, it's important to understand the difference between compile-time and runtime in Reflex.

Expand Down Expand Up @@ -314,7 +308,7 @@ In the next sections, we will show how to handle these cases.

## Conditional rendering

As mentioned above, you cannot use Python `if/else` statements with state vars in components. Instead, use the [`rx.cond`](/docs/components/conditional_rendering) function to conditionally render components.
As mentioned above, you cannot use Python `if/else` statements with state vars in components. Instead, use the [rx.cond](/docs/components/conditional_rendering) function to conditionally render components.

```python demo exec
class LoginState(rx.State):
Expand All @@ -338,7 +332,7 @@ def show_login():

## Rendering lists

To iterate over a var that is a list, use the [`rx.foreach`](/docs/components/rendering_iterables) function to render a list of components.
To iterate over a var that is a list, use the [rx.foreach](/docs/components/rendering_iterables) function to render a list of components.

Pass the list var and a function that returns a component as arguments to `rx.foreach`.

Expand Down Expand Up @@ -398,13 +392,26 @@ def index():
return rx.text("Root Page")


rx.app = rx.App()
app = rx.App()
app.add_page(index, route="/")
```

## Next Steps

Now that you have a basic understanding of how Reflex works, the next step is to start coding your own apps. Try one of the following tutorials:
You've got the core pieces — components, state, events, compile-time vs. runtime. Time to build.

```md alert info
# Build something real →

- [Dashboard tutorial](/docs/getting_started/dashboard_tutorial) — a data app with tables, forms, and state.
- [Chatapp tutorial](/docs/getting_started/chatapp_tutorial) — streaming AI responses end-to-end.
- [Open-source templates](/docs/getting_started/open_source_templates) — full apps to fork.
```

- [Dashboard Tutorial](/docs/getting_started/dashboard_tutorial)
- [Chatapp Tutorial](/docs/getting_started/chatapp_tutorial)
```md alert info
# Go deeper →

- [Vars](/docs/vars/base_vars) and [var operations](/docs/vars/var-operations) — the full API.
- [Events](/docs/events/events_overview) and [pages](/docs/pages/overview) — routing, triggers, handlers.
- [How Reflex works](/docs/advanced_onboarding/how-reflex-works) — what runs where, and why.
```
Loading
Loading