⟨/⟩ 40_Arch/Tech/Angular/ADR_UI_020_Buttons.cs

146 строк · в начало

using System;
using Ban.Sdaid.Notation.Documents;
using Ban.Sdaid.Icd;

namespace Ban.Sdaid.Icd.Arch.Tech.Angular
{
    /// <summary>
    /// ADR-UI-020: Кнопки. Базовый компонент (типы, состояния, pill-геометрия) и кросс-срезовые
    /// конвенции размещения в футерах (порядок, стороны, одна primary).
    /// </summary>
    public class ADR_UI_020_Buttons : IAdrDocument, IFolder<ArchAngularFolder>
    {
        public string Name => "ADR-UI-020. Кнопки";

        public string Description =>
            @"Кнопки встречаются по всей системе. Фиксируем базовый компонент кнопки (типы, состояния,
геометрия) и единое правило их размещения в футерах (порядок и стороны), чтобы пользователь выработал
мышечную память, а разработчик/ИИ не решали заново на каждом экране.";

        public string Version => "1.0";
        public string Status => "accepted";
        public string[] Comments => new[]
        {
            "2026-08-11. Принято перед реализацией base-компонента Button. Модалки отложены.",
        };

        public Type? Supersedes => null;

        public static string S1_Context = """
            ## Контекст и постановка задачи

            Кнопки нужны везде: футеры форм, шапки страниц, карточки, действия в строках. Зафиксировать
            надо две вещи:

            - **компонент** — единые типы, состояния и геометрия кнопки;
            - **размещение** — порядок и стороны кнопок в футерах (правило кросс-срезовое: не принадлежит
              ни формам, ни паттерну страницы, поэтому живёт отдельным ADR, на который ссылаются).
            """;

        public static string S2_DecisionDrivers = """
            ## Драйверы решения

            1. **Предсказуемость** — главное действие всегда в одном месте.
            2. **Единообразие** — одинаковые кнопки во всех контекстах.
            3. **Один факт в одном месте** — остальные ADR/страницы ссылаются сюда.
            4. **Готовность к codegen** — генераторы получают однозначное правило.
            """;

        public static string S3_ConsideredOptions = """
            ## Рассмотренные варианты (размещение)

            - **A. Целевая слева, «Отмена» следом** — `[Сохранить] [Отмена]`.
            - **B. «Отмена» слева, целевая справа** — `[Отмена] [Сохранить]`.
            - **C. Не фиксировать** — на усмотрение страницы (ведёт к разнобою).
            """;

        public static string S4_DecisionOutcome = """
            ## Решение

            ### 1. Базовый компонент `Button`

            Base-компонент набора `ui/`. Геометрия едина для всех типов, различаются только цвета.

            - **Типы (variant):** `primary`, `secondary`, `tertiary`, `ghost`, `danger`, `inverse`.
            - **Состояния:** `default`, `hover`, `active`, `disabled`, `focus` (кольцо `4px`).
            - **Геометрия:** высота `40px`, `border-radius: 9999px` (**pill** — полностью скруглённая
              капсула), текст — Body/M · medium; опциональная **иконка слева** (`20px`, gap `6px`),
              вариант **icon-only** — `40×40`.
            - **Цвета** `bg`/`text`/`border` по каждому типу и состоянию — через control-токены
              (`--icd-*`, ADR-UI-004); иконка красится в цвет текста.

            ### 2. Размещение в футерах (выбран вариант A + уточнение по деструктивным)

            Главный принцип — **целевая (главная) кнопка слева**, вторичные и «Отмена» — следом, в левом
            кластере. Деструктивная кнопка ставится справа и оторванно **только если она вторичная**.

            - **Случай A — главное действие неразрушающее + есть отдельное деструктивное** (форма
              редактирования). Футер во всю ширину (space-between):
              `[Главная] [вторичные…] [Отмена]` слева … `[Опасная]` справа-оторвана.
            - **Случай B — деструктивное действие само целевое** (диалог подтверждения удаления):
              `[Удалить] [Отмена]` слева (кластер не растягиваем).

            ### 3. Типы по роли действия

            - **Главное** действие экрана/футера → `primary`. На один футер — **ровно одна** primary.
            - **Отмена / нейтральное вторичное** → `secondary` или `tertiary`; «Отмена» **никогда** не primary.
            - **Деструктивное** → `danger` (не primary): вторичное — справа-оторвано (A), целевое — слева (B).
            - **Третичное** малозначимое → `ghost`.

            ### 4. Выравнивание

            - Футер формы — **во всю ширину**: левый кластер прижат влево, деструктивная — к правому краю.
              Горизонтальный интервал между кнопками — токеном (ADR-UI-004).
            - Футер идёт **сразу под полями формы** (ADR-UI-009), не приклеен к низу.
            - В шапке страницы кнопки действий — справа от заголовка (разметку контейнера задаёт ADR-UI-005).

            Правила подтверждений в модалках/поповерах — отложены вместе с модалками.
            """;

        public static string S5_PositiveConsequences = """
            ## Положительные следствия

            - Пользователь всегда знает, где главное действие.
            - Единый компонент и одно правило размещения — прототип, код и генераторы совпадают.
            - Споры «где кнопка / какой тип» закрыты ссылкой на один ADR.
            """;

        public static string S6_NegativeConsequences = """
            ## Отрицательные следствия и компромиссы

            - Полный набор из 6 типов × 5 состояний — это набор control-токенов, который надо один раз
              завести и поддерживать (наполняем по мере использования типов).
            - Раскладка футера «во всю ширину со space-between» — не дефолт браузера; инкапсулируется в
              компоненте футера формы (появится с формами).
            """;

        public static string S7_Validation = """
            ## Проверка

            - Целевая (главная) кнопка — всегда слева; на форме редактирования «Сохранить» слева,
              «Удалить» (вторичная деструктивная) — справа-оторвана (случай A).
            - В диалоге подтверждения удаления `[Удалить]` (`danger`) — слева, `[Отмена]` следом (случай B).
            - На каждом футере — не больше одной primary-кнопки.
            - Кнопка использует типы `primary/secondary/tertiary/ghost/danger/inverse` и токены control.
            """;

        public static string S8_OpenQuestions = """
            ## Открытые вопросы / отложено

            - **Кнопки подтверждений в модалках/поповерах** — вместе с модалками (отложено). В коде есть
              экспериментальный `ui/confirm-popover` (подтверждение удаления рядом с кнопкой) — проверяем удобство,
              паттерн **не ратифицирован**, возможна замена; правила порядка кнопок при этом соблюдены (случай B).
            - **Адаптив** — стек кнопок футера на узких экранах (< 1280) уточним при вёрстке форм.
            - **Единый словарь подписей** («Создать»/«Сохранить»/«Отмена» без синонимов) — по мере
              появления действий.
            """;

        public static string S99_Related = $"""
            ## Связанные артефакты

            - {nameof(Ban.Sdaid.Icd.Arch.Tech.Angular.ADR_UI_004_Styling)} — control-токены и интервалы.
            - {nameof(Ban.Sdaid.Icd.Arch.Tech.Angular.ADR_UI_009_Forms)} — футер сразу под полями формы.
            """;
    }
}