---
title: "Поле"
description: "Объедините метки, элементы управления и вспомогательный текст, чтобы составить доступные поля формы и сгруппированные входные данные."
order: 0
---
## Поле, объединяйте метки, элементы управления и текст справки для создания доступных полей формы и сгруппированных входных данных.


```python
from components.ui.field import Field
```

```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 ..core.core import CoreComponent

LiteralOrientation = Literal["horizontal", "vertical"]


class ClassNames:
    SEPARATOR = (
        "shrink-0 bg-input "
        "data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full "
        "data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch"
    )


class SeparatorComponent(CoreComponent):
    @classmethod
    def create(cls, *children, **props) -> rx.Component:
        orientation: str = props.pop("orientation", "horizontal")
        decorative = props.pop("decorative", True)
        data_slot = props.pop("data_slot", "separator")

        props["data-slot"] = data_slot
        props["data-orientation"] = orientation

        if decorative:
            props["aria-hidden"] = "true"
        else:
            props["role"] = "separator"
            props["aria-orientation"] = orientation

        cls.set_class_name(ClassNames.SEPARATOR, props)
        return rx.el.div(*children, **props)


separator = SeparatorComponent.create
```

```python
from typing import Literal

from reflex.components.component import ComponentNamespace
from reflex.vars.base import Var
from reflex_components_core.el import elements

from components.ui.separator import separator

LiteralOrientation = Literal["vertical", "horizontal", "responsive"]
LiteralLegendVariant = Literal["legend", "label"]


class ClassNames:
    FIELD_SET = "flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3"

    FIELD_LEGEND = "mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base"

    FIELD_GROUP = "group/field-group @container/field-group flex flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4"

    FIELD_ROOT_BASE = (
        "group/field flex w-full gap-2 data-[invalid=true]:text-destructive"
    )

    FIELD_ROOT_ORIENTATIONS = {
        "vertical": "flex-col *:w-full [&>.sr-only]:w-auto",
        "horizontal": "flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[data-slot=checkbox]]:mt-[2.5px]",
        "responsive": "flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[data-slot=checkbox]]:mt-px",
    }

    FIELD_CONTENT = "group/field-content flex flex-1 flex-col gap-0.5 leading-snug"

    FIELD_LABEL = "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border border-input *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10 has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col"

    FIELD_TITLE = "flex w-fit items-center gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50"

    FIELD_DESCRIPTION = "text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5 last:mt-0 nth-last-2:-mt-1 [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary"

    FIELD_SEPARATOR = (
        "relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2"
    )

    FIELD_ERROR = "text-sm font-normal text-destructive"


class FieldSet(elements.Fieldset):
    @classmethod
    def create(cls, *children, **props) -> elements.Fieldset:
        props["data-slot"] = "field-set"
        props["class_name"] = (
            f"{ClassNames.FIELD_SET} {props.get('class_name', '')}".strip()
        )
        return super().create(*children, **props)


class FieldLegend(elements.Legend):
    variant: Var[LiteralLegendVariant]

    @classmethod
    def create(cls, *children, **props) -> elements.Legend:
        props["data-slot"] = "field-legend"
        variant = props.pop("variant", "legend")
        props["data-variant"] = variant
        props["class_name"] = (
            f"{ClassNames.FIELD_LEGEND} {props.get('class_name', '')}".strip()
        )
        return super().create(*children, **props)


class FieldGroup(elements.Div):
    @classmethod
    def create(cls, *children, **props) -> elements.Div:
        props["data-slot"] = "field-group"
        props["class_name"] = (
            f"{ClassNames.FIELD_GROUP} {props.get('class_name', '')}".strip()
        )
        return super().create(*children, **props)


class FieldRoot(elements.Div):
    orientation: Var[LiteralOrientation]

    @classmethod
    def create(cls, *children, **props) -> elements.Div:
        props["role"] = "group"
        props["data-slot"] = "field"

        orientation = props.pop("orientation", "vertical")
        props["data-orientation"] = orientation

        orientation_styles = ClassNames.FIELD_ROOT_ORIENTATIONS.get(orientation, "")

        props["class_name"] = (
            f"{ClassNames.FIELD_ROOT_BASE} {orientation_styles} {props.get('class_name', '')}".strip()
        )

        return super().create(*children, **props)


class FieldContent(elements.Div):
    @classmethod
    def create(cls, *children, **props) -> elements.Div:
        props["data-slot"] = "field-content"
        props["class_name"] = (
            f"{ClassNames.FIELD_CONTENT} {props.get('class_name', '')}".strip()
        )
        return super().create(*children, **props)


class FieldLabel(elements.Label):
    @classmethod
    def create(cls, *children, **props) -> elements.Label:
        props["data-slot"] = "field-label"
        props["class_name"] = (
            f"{ClassNames.FIELD_LABEL} {props.get('class_name', '')}".strip()
        )
        return super().create(*children, **props)


class FieldTitle(elements.Div):
    @classmethod
    def create(cls, *children, **props) -> elements.Div:
        props["data-slot"] = "field-label"
        props["class_name"] = (
            f"{ClassNames.FIELD_TITLE} {props.get('class_name', '')}".strip()
        )
        return super().create(*children, **props)


class FieldDescription(elements.P):
    @classmethod
    def create(cls, *children, **props) -> elements.P:
        props["data-slot"] = "field-description"
        props["class_name"] = (
            f"{ClassNames.FIELD_DESCRIPTION} {props.get('class_name', '')}".strip()
        )
        return super().create(*children, **props)


class FieldSeparator(elements.Div):
    @classmethod
    def create(cls, *children, **props) -> elements.Div:
        props["data-slot"] = "field-separator"
        props["data-content"] = "true" if children else "false"
        props["class_name"] = (
            f"{ClassNames.FIELD_SEPARATOR} {props.get('class_name', '')}".strip()
        )

        inner_elements = [separator(class_name="absolute inset-0 top-1/2")]
        if children:
            inner_elements.append(
                elements.Span(
                    *children,
                    data_slot="field-separator-content",
                    class_name="relative mx-auto block w-fit bg-background px-2 text-muted-foreground",
                )
            )
        return super().create(*inner_elements, **props)


class FieldError(elements.Div):
    @classmethod
    def create(cls, *children, **props) -> elements.Div:
        props["role"] = "alert"
        props["data-slot"] = "field-error"
        props["class_name"] = (
            f"{ClassNames.FIELD_ERROR} {props.get('class_name', '')}".strip()
        )
        return super().create(*children, **props)


class Field(ComponentNamespace):
    set = staticmethod(FieldSet.create)
    legend = staticmethod(FieldLegend.create)
    group = staticmethod(FieldGroup.create)
    root = staticmethod(FieldRoot.create)
    content = staticmethod(FieldContent.create)
    label = staticmethod(FieldLabel.create)
    title = staticmethod(FieldTitle.create)
    description = staticmethod(FieldDescription.create)
    separator = staticmethod(FieldSeparator.create)
    error = staticmethod(FieldError.create)
    class_names = ClassNames


field = Field()
```

# Состав

## поле.корень

Один элемент управления с меткой, вспомогательным текстом и проверкой.

```python
field.root
├── field.label
├── Input / Textarea / switch.root / select.root
├── field.description
└── field.error
```

## поле.группа

Связанные поля в одной группе. При необходимости используйте `field.separator` между разделами.

```python
field.group
├── field.root
│   ├── field.label
│   ├── Input / Textarea / switch.root / select.root
│   ├── field.description
│   └── field.error
├── field.separator
└── field.root
    ├── field.label
    └── Input / Textarea / switch.root / select.root
```

## поле.набор

Семантическая группировка с легендой и описанием, обычно содержащая `field.group`.

```python
field.set
├── field.legend
├── field.description
└── field.group
    ├── field.root
    │   ├── field.label
    │   ├── Input / Textarea / switch.root / select.root
    │   ├── field.description
    │   └── field.error
    └── field.root
        ├── field.label
        └── Input / Textarea / switch.root / select.root
```


- `field.root` — это основная оболочка для одного поля.

- `field.content` — гибкий столбец, группирующий метку и описание. Не требуется, если у вас нет описания.

- Оберните связанные поля `field.group` и используйте `field.set` с `field.legend` для семантической группировки.

# Примеры

## Общие

Демонстрирует объединение `field.root`, `field.group`, `field.set`, `field.label`, `field.description` и `field.error`.

**Использованный реквизит:** `orientation` на `field.root`; `variant` на `field.legend`; `html_for` на `field.label`; `data_invalid` на `field.root`.

```python
def field_demo() -> rx.Component:
    return rx.el.div(
        rx.el.form(
            field.group(
                field.set(
                    field.legend("Payment Method"),
                    field.description("All transactions are secure and encrypted"),
                    field.group(
                        field.root(
                            field.label("Name on Card", html_for="checkout-card-name"),
                            input(
                                id="checkout-card-name",
                                placeholder="Evil Rabbit",
                                required=True,
                            ),
                        ),
                        field.root(
                            field.label("Card Number", html_for="checkout-card-number"),
                            input(
                                id="checkout-card-number",
                                placeholder="1234 5678 9012 3456",
                                required=True,
                            ),
                            field.description("Enter your 16-digit card number"),
                        ),
                        rx.el.div(
                            field.root(
                                field.label("Month", html_for="checkout-exp-month"),
                                # select.root(
                                #     select.trigger(
                                #         select.value(),
                                #         select.icon(),
                                #         id="checkout-exp-month",
                                #     ),
                                #     select.portal(
                                #         select.positioner(
                                #             select.popup(
                                #                 select.group(
                                #                     *[
                                #                         select.item(
                                #                             select.item_text(
                                #                                 item["label"]
                                #                             ),
                                #                             select.item_indicator(),
                                #                             value=item["value"],
                                #                         )
                                #                         for item in months
                                #                     ]
                                #                 )
                                #             )
                                #         )
                                #     ),
                                #     items=months,
                                #     default_value="MM",
                                # ),
                            ),
                            field.root(
                                field.label("Year", html_for="checkout-exp-year"),
                                # select.root(
                                #     select.trigger(
                                #         select.value(),
                                #         select.icon(),
                                #         id="checkout-exp-year",
                                #     ),
                                #     select.portal(
                                #         select.positioner(
                                #             select.popup(
                                #                 select.group(
                                #                     *[
                                #                         select.item(
                                #                             select.item_text(
                                #                                 item["label"]
                                #                             ),
                                #                             select.item_indicator(),
                                #                             value=item["value"],
                                #                         )
                                #                         for item in years
                                #                     ]
                                #                 )
                                #             )
                                #         )
                                #     ),
                                #     items=years,
                                #     default_value="YYYY",
                                # ),
                            ),
                            field.root(
                                field.label("CVV", html_for="checkout-cvv"),
                                input(
                                    id="checkout-cvv",
                                    placeholder="123",
                                    required=True,
                                ),
                            ),
                            class_name="grid grid-cols-3 gap-4",
                        ),
                    ),
                ),
                field.separator(),
                field.set(
                    field.legend("Billing Address"),
                    field.description(
                        "The billing address associated with your payment method"
                    ),
                    field.group(
                        field.root(
                            checkbox.root(
                                checkbox.indicator(),
                                id="checkout-same-as-shipping",
                                default_checked=True,
                            ),
                            field.label(
                                "Same as shipping address",
                                html_for="checkout-same-as-shipping",
                                class_name="font-normal",
                            ),
                            orientation="horizontal",
                        )
                    ),
                ),
                field.set(
                    field.group(
                        field.root(
                            field.label("Comments", html_for="checkout-comments"),
                            textarea(
                                id="checkout-comments",
                                placeholder="Add any additional comments",
                                class_name="resize-none",
                            ),
                        )
                    )
                ),
                field.root(
                    button("Submit", type="submit"),
                    button("Cancel", variant="outline", type="button"),
                    orientation="horizontal",
                ),
            )
        ),
        class_name="w-full max-w-md my-10",
    )
```

# Адаптивный макет

- **Вертикальные поля**: ориентация по умолчанию объединяет метки, элементы управления и вспомогательный текст — идеально подходит для макетов, ориентированных на мобильные устройства.  

- **Горизонтальные поля**: установите `orientation="horizontal"` в `field.root`, чтобы выровнять метку и элемент управления рядом. Соедините с `field.content`, чтобы описания были согласованными.  

- **Адаптивные поля**: установите `orientation="responsive"` для автоматического макета столбцов внутри родительских элементов с поддержкой контейнеров.

# Проверка и ошибки

- Добавьте `data_invalid="true"` к `field.root`, чтобы перевести весь блок в состояние ошибки.

- Добавьте `aria_invalid="true"` на вход для вспомогательных технологий.

- Отрисовывайте `field.error` сразу после элемента управления или внутри `field.content`, чтобы сообщения об ошибках были выровнены по полю.

```python
field.root(
    field.label("Email", html_for="email"),
    input(id="email", type="email", aria_invalid="true"),
    field.error("Enter a valid email address."),
    data_invalid="true",
)
```

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

## поле.набор

Контейнер, который отображает семантический `fieldset` с предустановками интервалов.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `class_name` | `str` | |

```python
field.set(
    field.legend("Delivery"),
    field.group(),
)
```

## поле.легенда

Элемент легенды для `field.set`. Переключитесь на вариант `"label"`, чтобы обеспечить соответствие стандартному размеру этикетки.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `variant` | `Literal["legend", "label"]` | `"legend"` |
| `class_name` | `str` |  |

```python
field.legend("Notification Preferences", variant="label")
```

`field.legend` имеет два варианта: `legend` и `label`. Вариант `label` применяет стандартные размеры и выравнивание меток ввода, что полезно, если вы объединяете вложенные наборы полей.

## поле.группа

Оболочка макета, которая объединяет компоненты `field.root` и позволяет выполнять запросы к контейнерам для адаптивных ориентаций.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `class_name` | `str` |  |

```python
field.group(
    field.root(),
    field.root(),
    class_name="@container/field-group flex flex-col gap-6",
)
```

## поле.корень

Основная оболочка для одного поля. Обеспечивает управление ориентацией, недопустимые стили состояния и конфигурации интервалов.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `orientation` | `"vertical" | "horizontal" | "responsive"` | `"vertical"` |
| `class_name` | `str` |  |
| `data_invalid` | `str` |  |

```python
field.root(
    field.label("Remember me", html_for="remember"),
    switch.root(id="remember"),
    orientation="horizontal",
)
```

## поле.содержание

Столбец Flex, который группирует элементы управления и описания, когда метка находится рядом с элементом управления. Не требуется, если у вас нет блока описания макета.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `class_name` | `str` |  |

```python
field.root(
    checkbox.root(id="notifications"),
    field.content(
        field.label("Notifications", html_for="notifications"),
        field.description("Email, SMS, and push options."),
    ),
)
```

## поле.метка

Метка, стилизованная как для прямого ввода, так и для вложенных дочерних элементов `field`.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `html_for` | `str` |  |
| `class_name` | `str` |  |

```python
field.label("Email", html_for="email")
```

## поле.заголовок

Отображает отдельный заголовок с соответствующими свойствами оформления метки внутри узла `field.content`.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `class_name` | `str` |  |

```python
field.content(
    field.title("Enable Touch ID"),
    field.description("Unlock your device faster."),
)
```

## поле.описание

Вспомогательный текстовый слот, который автоматически выравнивает длинные строки при использовании в горизонтальных конфигурациях.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `class_name` | `str` |  |

```python
field.description("We never share your email with anyone.")
```

## поле.разделитель

Правило визуального разделителя, используемое для разделения разделов или категорий внутри компонента-обертки `field.group`. Принимает необязательное встроенное дочернее содержимое.

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `class_name` | `str` |  |

```python
field.separator("Or continue with")
```

## поле.ошибка

Доступный блок-контейнер типографии уведомлений об ошибках, настраиваемый автоматически с использованием стандартных переменных макета состояния приложения (`role="alert"`).

| Опора | Тип | По умолчанию |
| --- | --- | --- |
| `class_name` | `str` |  |

```python
field.error("Invalid passcode combination provided.")
```