---
title: "Рамка"
description: "Отображает связанный контент в структурированном фрейме."
order: 0
---
## Frame: отображает связанный контент в структурированном фрейме.



> Обработка ошибки `usage`: ожидался модуль, класс, метод, функция, обратная трассировка, кадр или объект кода, получен кадр


```python
from typing import Any

from reflex.components.component import Component
from reflex.utils.imports import ImportVar
from reflex.vars import FunctionVar, Var
from reflex.vars.base import VarData

PACKAGE_CN = "clsx-for-tailwind@1.0.0"
CN = Var(
    "cn",
    _var_data=VarData(
        imports={
            PACKAGE_CN: ImportVar(tag="cn"),
        },
    ),
).to(FunctionVar)


class CoreComponent(Component):
    unstyled: Var[bool]

    @classmethod
    def set_class_name(
        cls, default_class_name: str | Var[str], props: dict[str, Any]
    ) -> None:

        if "render_" in props:
            return

        props_class_name = props.get("class_name", "")

        if props.pop("unstyled", False):
            props["class_name"] = props_class_name
            return

        props["class_name"] = cn(default_class_name, props_class_name)

    def _exclude_props(self) -> list[str]:
        return [
            *super()._exclude_props(),
            "unstyled",
        ]


def cn(*classes: Var | str | tuple | list | None) -> Var:
    return CN.call(*classes).to(str)
```

```python
from typing import Literal

import reflex as rx
from reflex.components.component import ComponentNamespace

from ..core.core import CoreComponent, cn

LiteralVariant = Literal["default", "inverse", "ghost"]
LiteralSpacing = Literal["xs", "sm", "default", "lg"]


class ClassNames:
    ROOT = "relative flex flex-col bg-muted/50 gap-0.75 p-0.75 rounded-xl"
    ROOT_VARIANT_DEFAULT = "border border-border bg-clip-padding"
    ROOT_VARIANT_INVERSE = "border border-border bg-background bg-clip-padding"
    ROOT_VARIANT_GHOST = ""
    PANEL = "relative grow overflow-hidden rounded-xl border border-border bg-card bg-clip-padding shadow-xs p-(--frame-panel-p)"
    HEADER = "flex flex-col px-(--frame-panel-header-px) py-(--frame-panel-header-py)"
    TITLE = "text-sm font-semibold"
    DESCRIPTION = "text-muted-foreground text-sm"
    FOOTER = (
        "flex flex-col gap-1 px-(--frame-panel-footer-px) py-(--frame-panel-footer-py)"
    )


VARIANT_CLASSES: dict[str, str] = {
    "default": ClassNames.ROOT_VARIANT_DEFAULT,
    "inverse": ClassNames.ROOT_VARIANT_INVERSE,
    "ghost": ClassNames.ROOT_VARIANT_GHOST,
}

SPACING_CLASSES: dict[str, str] = {
    "xs": "[--frame-panel-p:--spacing(2)] [--frame-panel-header-px:--spacing(2)] [--frame-panel-header-py:--spacing(1)] [--frame-panel-footer-px:--spacing(2)] [--frame-panel-footer-py:--spacing(1)]",
    "sm": "[--frame-panel-p:--spacing(3)] [--frame-panel-header-px:--spacing(3)] [--frame-panel-header-py:--spacing(2)] [--frame-panel-footer-px:--spacing(3)] [--frame-panel-footer-py:--spacing(2)]",
    "default": "[--frame-panel-p:--spacing(4)] [--frame-panel-header-px:--spacing(4)] [--frame-panel-header-py:--spacing(3)] [--frame-panel-footer-px:--spacing(4)] [--frame-panel-footer-py:--spacing(3)]",
    "lg": "[--frame-panel-p:--spacing(5)] [--frame-panel-header-px:--spacing(5)] [--frame-panel-header-py:--spacing(4)] [--frame-panel-footer-px:--spacing(5)] [--frame-panel-footer-py:--spacing(4)]",
}


class FrameRoot(CoreComponent):
    @classmethod
    def create(cls, *children, **props) -> rx.Component:
        variant: LiteralVariant = props.pop("variant", "default")
        spacing: LiteralSpacing = props.pop("spacing", "default")
        stacked: bool = props.pop("stacked", False)
        dense: bool = props.pop("dense", False)
        class_name: str = props.pop("class_name", "")

        stacked_class = (
            "gap-0 *:has-[+[data-slot=frame-panel]]:rounded-b-none *:[[data-slot=frame-panel]+[data-slot=frame-panel]]:rounded-t-none *:[[data-slot=frame-panel]+[data-slot=frame-panel]]:border-t-0"
            if stacked
            else ""
        )

        dense_class = (
            "p-0 gap-0 [&_[data-slot=frame-panel]]:-mx-px [&_[data-slot=frame-panel]]:before:hidden [&_[data-slot=frame-panel]:last-child]:-mb-px"
            if dense
            else ""
        )

        props["data-slot"] = "frame"
        props["data-spacing"] = spacing

        return rx.el.div(
            *children,
            class_name=cn(
                ClassNames.ROOT,
                VARIANT_CLASSES.get(variant, ""),
                SPACING_CLASSES.get(spacing, ""),
                stacked_class,
                dense_class,
                class_name,
            ),
            **props,
        )


class FramePanel(CoreComponent):
    @classmethod
    def create(cls, *children, **props) -> rx.Component:
        class_name: str = props.pop("class_name", "")
        props["data-slot"] = "frame-panel"
        return rx.el.div(
            *children,
            class_name=cn(ClassNames.PANEL, class_name),
            **props,
        )


class FrameHeader(CoreComponent):
    @classmethod
    def create(cls, *children, **props) -> rx.Component:
        class_name: str = props.pop("class_name", "")
        props["data-slot"] = "frame-panel-header"
        return rx.el.header(
            *children,
            class_name=cn(ClassNames.HEADER, class_name),
            **props,
        )


class FrameTitle(CoreComponent):
    @classmethod
    def create(cls, *children, **props) -> rx.Component:
        class_name: str = props.pop("class_name", "")
        props["data-slot"] = "frame-panel-title"
        return rx.el.div(
            *children,
            class_name=cn(ClassNames.TITLE, class_name),
            **props,
        )


class FrameDescription(CoreComponent):
    @classmethod
    def create(cls, *children, **props) -> rx.Component:
        class_name: str = props.pop("class_name", "")
        props["data-slot"] = "frame-panel-description"
        return rx.el.div(
            *children,
            class_name=cn(ClassNames.DESCRIPTION, class_name),
            **props,
        )


class FrameFooter(CoreComponent):
    @classmethod
    def create(cls, *children, **props) -> rx.Component:
        class_name: str = props.pop("class_name", "")
        props["data-slot"] = "frame-panel-footer"
        return rx.el.footer(
            *children,
            class_name=cn(ClassNames.FOOTER, class_name),
            **props,
        )


class Frame(ComponentNamespace):
    root = staticmethod(FrameRoot.create)
    panel = staticmethod(FramePanel.create)
    header = staticmethod(FrameHeader.create)
    title = staticmethod(FrameTitle.create)
    description = staticmethod(FrameDescription.create)
    footer = staticmethod(FrameFooter.create)
    __call__ = staticmethod(FrameRoot.create)
    class_names = ClassNames


frame = Frame()
```

# Примеры

## Базовые панели

Базовая рама с заголовком и двумя панелями.

**Использованный реквизит:** ничего не требуется, кроме состава по умолчанию `frame.root`.

```python
def frame_basic():
    return frame.root(
        frame.header(
            frame.title("Section header"),
            frame.description("Description for the section"),
        ),
        frame.panel(
            rx.el.h2("Separated Panel", class_name="text-sm font-semibold"),
            rx.el.p("Section description", class_name="text-muted-foreground text-sm"),
        ),
        frame.panel(
            rx.el.h2("Separated Panel", class_name="text-sm font-semibold"),
            rx.el.p("Section description", class_name="text-muted-foreground text-sm"),
        ),
        class_name="w-full max-w-md",
    )
```

## Сложенные панели

Установите `stacked=True`, чтобы объединить границы панели в один непрерывный блок.

**Использованный реквизит:** `stacked` на `frame.root`.

```python
def frame_stacked():
    return frame.root(
        frame.header(
            frame.title("Section header"),
            frame.description("Description for the section"),
        ),
        frame.panel(
            rx.el.h2("Separated Panel", class_name="text-sm font-semibold"),
            rx.el.p("Section description", class_name="text-muted-foreground text-sm"),
        ),
        frame.panel(
            rx.el.h2("Separated Panel", class_name="text-sm font-semibold"),
            rx.el.p("Section description", class_name="text-muted-foreground text-sm"),
        ),
        stacked=True,
        class_name="w-full max-w-md",
    )
```

## Плотные панели

Установите `dense=True` для минимального заполнения кадра от края до края.

**Использованный реквизит:** `dense` на `frame.root`.

```python
def frame_dense():
    return frame.root(
        frame.header(
            frame.title("Section header"),
            frame.description("Description for the section"),
        ),
        frame.panel(
            rx.el.h2("Separated Panel", class_name="text-sm font-semibold"),
            rx.el.p("Section description", class_name="text-muted-foreground text-sm"),
        ),
        frame.panel(
            rx.el.h2("Separated Panel", class_name="text-sm font-semibold"),
            rx.el.p("Section description", class_name="text-muted-foreground text-sm"),
        ),
        stacked=True,
        dense=True,
        class_name="w-full max-w-md",
    )
```

## Внешняя граница

Установите `variant="ghost"`, чтобы удалить внешнюю границу кадра.

**Использованный реквизит:** `variant` на `frame.root`.

```python
def frame_no_border():
    return frame.root(
        frame.header(
            frame.title("No Outer Border"),
            frame.description(
                "This frame uses variant='ghost' to remove the outer border."
            ),
        ),
        frame.panel(
            rx.el.p(
                "The outer container of this frame has no border, only the background and panels are visible.",
                class_name="text-muted-foreground text-sm",
            ),
        ),
        stacked=True,
        dense=True,
        variant="ghost",
        class_name="w-full max-w-md",
    )
```

# Справочник по API

## кадр.корень

```python
frame.root(
    frame.panel(
        frame.header(frame.title("Overview")),
        "Panel content",
    ),
    variant="default",
    spacing="default",
)
```

| Опора | Тип | По умолчанию | Описание |
| ------------ | ---------------------------------------------- | ----------- | -------------------------------------------------------------------------------------- |
| `variant` | `Literal["default", "inverse", "ghost"]` | `"default"` | Управляет визуальным стилем контейнера фрейма.                                     |
| `spacing` | `Literal["xs", "sm", "default", "lg"]` | `"default"` | Управляет внутренним заполнением панелей, верхних и нижних колонтитулов с помощью переменных CSS.          |
| `stacked` | `bool` | `False` | Удаляет пробелы и объединяет границы панелей, чтобы они выглядели как один непрерывный блок.         |
| `dense` | `bool` | `False` | Удаляет все отступы/зазоры и растягивает панели от края до края с отрицательными полями.          |
| `class_name` | `str` | `""` | Дополнительные классы объединены в корневую оболочку.                                       |

## фрейм.панель

```python
frame.panel("Panel content")
```

| Опора | Тип | По умолчанию | Описание |
| ------------ | ----- | ------- | ------------------------------------------------------------------ |
| `class_name` | `str` | `""` | Дополнительные классы объединены в панель — переопределяют значения по умолчанию bg/border/padding. |

## фрейм.заголовок

```python
frame.header(frame.title("Overview"))
```

| Опора | Тип | По умолчанию | Описание |
| ------------ | ----- | ------- | ---------------------------------------------- |
| `class_name` | `str` | `""` | Дополнительные классы объединены в заголовок.       |

## кадр.заголовок

```python
frame.title("Overview")
```

| Опора | Тип | По умолчанию | Описание |
| ------------ | ----- | ------- | ---------------------------------------------- |
| `class_name` | `str` | `""` | Дополнительные классы объединены в заголовок.        |

## фрейм.описание

```python
frame.description("A summary of recent activity.")
```

| Опора | Тип | По умолчанию | Описание |
| ------------ | ----- | ------- | ----------------------------------------------------- |
| `class_name` | `str` | `""` | Дополнительные классы добавлены в описание.        |

## фрейм.нижний колонтитул

```python
frame.footer(button("View all", variant="ghost", size="sm"))
```

| Опора | Тип | По умолчанию | Описание |
| ------------ | ----- | ------- | ---------------------------------------------- |
| `class_name` | `str` | `""` | Дополнительные классы объединены в нижний колонтитул.        |