Skip to content

docs(ui): the Querya button and control standard (sizes, variants, states, rules) before any code #1332

Closed

Description

@ZhuchkaTriplesix

Part of #1331.

Why first

The review showed that the problem is not a missing widget but missing rules: three heights were chosen per call site. This issue fixes the rules in docs/ui-kit.md (and the Obsidian Единый UI-стандарт) so the components, the migration and the guard tests all implement the same thing. Nothing is built until this is agreed.

The standard (proposal, to confirm in review)

1. Control scale. One scale for every interactive control (buttons, icon buttons, dropdown triggers, search fields, tab strips, toggles), multiplied by uiScale:

size height h-padding label icon icon gap use
sm 28 8 12 / w500 14 6 trees, panel headers, data-grid and staging toolbars, inline row actions
md 32 12 13 / w500 16 6 default: top toolbars, SQL editor, results, ERD, tab bars
lg 36 16 14 / w500 18 8 dialogs, forms, onboarding, empty states

Icon-only controls are square (width = height). One corner radius for controls: 6. Today's QueryaIconButtonDensity (28 / 32) and QueryaDropdownTokens (26 / 36) are folded into this scale.

2. Variants (what the button means, not how it is painted):

variant look use
primary accent fill, onAccent text the one main action of a surface; at most one per dialog / toolbar
secondary (default) transparent, 1 px borderSubtle, foreground text every other action
ghost no border, hover fill cancel / dismiss, quiet toolbar actions, icon-only
destructive destructive fill (primary tone) or red text (secondary / ghost tone) irreversible actions

Selected / toggled (isActive) is a state of any variant: accent 14 % fill + 30 % accent border (as QueryaIconButton does today). No tinted-fill "tonal" variant: the two Mongo _ActionButton copies become secondary.

3. States. rest · hover (fill from muted 35 %, primary +12 % onAccent) · pressed (fill 50 %, no scale) · keyboard-focus (2 px accent ring, only for keyboard focus) · disabled (50 % foreground, basic cursor, no hover) · loading (spinner replaces the leading icon, or the label of an icon-only button; width is reserved so nothing jumps; not pressable) · selected. Colour fades use QueryaMotion.fast / enter and are instant under reduced motion.

4. Anatomy and behaviour. [leading icon] label [trailing: chevron | shortcut hint]. Label is one line with ellipsis, never wraps. Icon-only controls must have a tooltip (kQueryaTooltipWait); labelled controls may. Minimum hit area 28 × 28 even when the visible icon is smaller (an inline tree action keeps a 14 px icon in a 28 px target). A labelled button collapses to icon-only with its label as the tooltip on a narrow toolbar. Enter / Space activate; the control is focusable and has semantics (label, enabled, busy).

5. Layout rules.

  • One row = one size. A toolbar never mixes sm and md controls.
  • Gap between controls 8; inside a group (split button, segmented control) 0 with a shared border and radius only on the outer corners.
  • A split button (action + menu) is one component, not two neighbours.
  • Dialog footer: right-aligned, order secondary actions → cancel (ghost) → primary / destructive, gap 8, all lg; a lone Close is secondary; Retry is secondary, or primary in an empty / error state; destructive confirmation pairs Cancel with destructive, never two filled buttons.
  • Destructive actions sit last in a toolbar or inside its menu, never first.

6. What is not allowed. shadcn button types, Material IconButton / TextButton / ElevatedButton, InkWell / GestureDetector with a Text child used as a button, a literal height / radius / font size on a button, a literal tooltip delay, a hand-made spinner or eye icon.

7. Theme. Colours come from context.workbench and QueryaSemanticPalette; a custom VS Code theme recolours every button. Text on accent / destructive fills must pass the contrast check already in color_contrast.dart.

Deliverables

  • docs/ui-kit.md: Buttons and controls section with the tables above, the do / don't snippets and the shadcn → Querya mapping.
  • Obsidian note Единый UI-стандарт: the same, plus a rationale paragraph.
  • The mapping table for the migration: shadcn ButtonSize.small → sm in panels and md in toolbars, normal → lg in dialogs and md in toolbars; OutlineButton → secondary, GhostButton → ghost, PrimaryButton → primary, DestructiveButton → destructive, QueryaActionButton → secondary md, QueryaActionMenu trigger → menu button.
  • The values above signed off (any change is made here, once).

Out of scope

Inputs, dropdown menus and tab strips keep their own components; they only adopt the scale's heights (see the metrics issue).

Activity

  1. added
    documentationImprovements or additions to documentation
    frontendTheme parser epic label: frontend
    uiUser interface components and widgets
    uxUser experience, keyboard shortcuts and interactions
    P2Medium priority / Parity & Refactoring
    on Oct 10, 2026
  2. ZhuchkaTriplesix commented on Oct 11, 2026

    @ZhuchkaTriplesix
    MemberAuthor

    Done in #1403 (merged into dev).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium priority / Parity & RefactoringdocumentationImprovements or additions to documentationfrontendTheme parser epic label: frontenduiUser interface components and widgetsuxUser experience, keyboard shortcuts and interactions

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions