Ask the assistant
0/400
Your question is processed by an AI service and kept to improve answers. Do not enter personal data.

    REEEL Layout Best Practices

    This page has not been translated into English yet. The Russian original is below.

    Практические правила вёрстки в REEEL-формате, основанные на особенностях рендеринга Flutter.

    Архитектурные правила приложений (поток данных, навигация, генераторы, каркас) — в architecture.md .

    Адаптивная вёрстка сайта — что решает CSS, что рантайм и по чему это видно — в responsive.md .

    Что стоит на стволе страницы — скроллер, липкая шапка, накладки — в page_root.md .

    Border + Padding: зазор между рамкой и контентом

    DecoratedBox рисует border внутрь своих bounds. Padding отодвигает ребёнка от края. Зазор между внутренним краем рамки и ребёнком:

    зазор = padding - borderWidth

    Если padding == borderWidth — зазора нет, рамка вплотную к контенту.

    // borderWidth 4, padding 8 → зазор 4px
    DecoratedBox
      #decoration
        #border fromBorderSide
          #side color:$primaryFocusedColor width:4
      Padding
        #padding all 8
        // child начинается в 8px от края, рамка заканчивается в 4px → 4px зазор
    // borderWidth 4, padding 4 → зазор 0px (рамка вплотную!)
    DecoratedBox
      #decoration
        #border fromBorderSide
          #side color:$primaryFocusedColor width:4
      Padding
        #padding all 4
        // child начинается в 4px от края = внутренний край рамки → зазора нет

    Параллельные скругления

    Чтобы скругление внешней рамки шло параллельно скруглению внутреннего контента:

    outerRadius = innerRadius + padding
    // inner 20 + padding 8 = outer 28
    DecoratedBox
      #decoration
        #borderRadius circular 28
        #border fromBorderSide
          #side color:$color width:4
      Padding
        #padding all 8
        ClipRRect
          #borderRadius circular 20
          // card content

    SizedBox и DecoratedBox с border

    SizedBox с фиксированным размером должен быть внутри Padding , а не снаружи DecoratedBox . Иначе DecoratedBox зажат в размер карточки и не может вырасти для рамки + зазора.

    // Правильно — рамка адаптируется под card + padding
    DecoratedBox
      #decoration
        #border fromBorderSide
          #side color:$color width:4
      Padding
        #padding all 8
        SizedBox width:288 height:512
          ClipRRect
            #borderRadius circular 20
            Stack ...
    
    // Неправильно — рамка зажата в 288x512, padding ещё больше сжимает контент
    SizedBox width:288 height:512
      DecoratedBox
        #decoration
          #border fromBorderSide
            #side color:$color width:4
        Padding
          #padding all 8
          ClipRRect
            Stack ...

    Stack: размер определяется первым non-positioned ребёнком

    Center , Align и Positioned внутри Stack зависят от размера Stack . Размер Stack определяется non-positioned children. Первый такой ребёнок задаёт базовый размер:

    Stack
      SizedBox width:280 height:500       // задаёт размер Stack
        ColoredBox color:$bgColor
      Positioned top:13 right:13          // позиция относительно 280x500
        $Badge "Lable"
      Center                              // центрируется в 280x500
        Icon play_arrow size:30

    Без SizedBox с фиксированным размером Center и Positioned не будут работать как ожидается.

    Фокус: карточки vs кнопки

    Два паттерна управления фокусом:

    Кнопки — собственный фокус через FocusableActionDetector

    @PrimaryButton @isFocused:false onPressed:null text:"button"
      FocusableActionDetector isFocused:$isFocused onPressed:$onPressed
        DecoratedBox
          #decoration
            #border fromBorderSide
              #side color:{isFocused ? primaryFocusedColor : 0x00} width:3
          // button content

    Карточки — фокус приходит извне из ReeelScroll

    Карточки получают isFocused через параметр макроса. В ReeelScroll фокус передаётся через @Macros id:itemBuilder :

    // Определение макроса карточки (без FocusableActionDetector)
    @VerticalCard @isFocused:false rating:"" badge:""
      DecoratedBox
        #decoration
          #border fromBorderSide
            #side color:{isFocused ? primaryFocusedColor : 0x00} width:4
        Padding
          #padding all 8
          // card content
    
    // Использование в ReeelScroll
    ReeelScroll itemCount:6
      @Macros id:itemBuilder index:0 isFocused:false
        $VerticalCard rating:"8.5" badge:"4K"
    DOCS
    dark_mode_baseline
    RU/EN
    menu_baseline