GrDashboardItem
Берут, когда любой виджет внутри `GrDashboard`.
Когда брать
- любой виджет внутри
GrDashboard— вне сетки компонент смысла не имеет: перенос, растягивание и клавиатура идут через её контекст; - у содержимого есть минимум —
minW/minHобъявляются здесь, а не в раскладке: раскладка знает координаты, а «график ниже трёх строк не читается» знает виджет; - шапка нужна не всегда — она появляется, только если есть
title,#headerили#actions; карте и большой цифре шапка ни к чему; - один виджет ведёт себя иначе —
:draggable="false"или:resizable="false"сужают правило сетки для него одного.
Когда взять другое
| Нужно | Берите |
|---|---|
| Карточка вне сетки виджетов | GrCard |
| Показатель числом, без рамы виджета | GrStatistic |
| Сама сетка | GrDashboard |
| Каталог виджетов для добавления | GrDashboardPalette |
`static` и `draggable` — про разное
static — про раскладку: виджет не двигается сам и не даёт соседям себя
двигать; столкновение с ним отменяет чужой перенос.
draggable и resizable — про интерфейс, и снимаются по отдельности:
:resizable="false" убирает уголок растягивания, оставляя перенос.
Запрет проверяет сама сетка, а не только прячет ручку. Защита, которая держится на «кнопку не отрисовали», снималась бы первым же прямым вызовом из клавиатурного контекста.
Ручка не занимает места в потоке
В режиме редактирования шапка не появляется ради ручки — панель лежит поверх верха содержимого. Поэтому переключение режима ничего не сдвигает: виджет остаётся ровно на своём месте, а не подпрыгивает на высоту шапки.
Скрытая панель остаётся в DOM и в таб-порядке: убрать её значило бы убрать ручку из обхода клавиатурой. Там, где наведения не бывает (палец), она видна всё время редактирования.
Авто-высота: содержимое решает, сколько строк занять
auto-height снимает с приложения задачу угадывать h за пользователя. Виджет
замеряет своё содержимое и просит у сетки столько строк, сколько нужно:
<GrDashboardItem item-id="log" title="События" auto-height>
<ul><li v-for="e in events" :key="e.id">{{ e.text }}</li></ul>
</GrDashboardItem>
Замеряется обёртка вокруг содержимого, а не тело виджета. Высота тела задана
ячейкой сетки, и scrollHeight у него равен max(содержимое, контейнер): виджет
смог бы вырасти под содержимое, но, став выше него, сообщал бы уже собственную
высоту — и не ужался бы обратно никогда. Обёртка появляется в разметке только
при включённом пропе: виджеты без него сохраняют прежний DOM.
Округление вверх. Строка сетки целая (model.md, инвариант 1), и содержимое
в 131 пиксель при строке в 60 занимает три строки, а не две. Пустота в несколько
пикселей внизу заметна и безобидна — обрезанная последняя строка таблицы нет.
Этим авто-высота отличается от растягивания уголком: там пользователь тянет и
ждёт прилипания к ближайшей ячейке, поэтому там округление к ближайшему.
Уголок у такого виджета меняет только ширину. Заданную рукой высоту затёр бы первый же замер, так что вертикаль у жеста и у стрелок отбирается сразу — вместо того чтобы обещать движение и отменять его.
minH и maxH продолжают действовать. Упёрлись в maxH — содержимое
прокручивается по обычным правилам overflow, ради которых он и существует.
static авто-высоте не поддаётся вовсе: он про то, что виджет не двигается ни
сам, ни под давлением соседей.
Сетка сообщает об этом отдельным событием. Изменение высоты уезжает в
update:layout, как любое другое — раскладка остаётся единственной правдой, —
но сетка дополнительно эмитит itemAutoResize. Приложение, которое считает
раскладку грязной по правкам, иначе спрашивало бы «сохранить изменения?» после
загрузки данных в виджет.
На сервере замера нет: действует h из раскладки, а уточнение приходит после
монтирования — как и брейкпоинт (см. ../ssr.md).
Действия разведены по времени жизни
#actions — продуктовые кнопки, видны всегда и включают шапку. #editActions —
действия режима редактирования (удалить виджет, открыть настройки): появляются
только в mode="edit" и едут либо в шапку, либо в панель, если шапки нет.
Настройки в этом ряду — не слот, а проп: showSettings рисует кнопку-шестерёнку
там же, где #editActions, и эмитит settings; сетка пересылает это наружу как
itemSettings. Место, иконка и доступное имя одинаковы на всех дашбордах, а
что показать по нажатию — дело приложения: готовое окно есть,
GrDashboardItemSettings.
Шапку кнопка не включает, в отличие от #actions. Иначе переключение режима
сдвигало бы содержимое безголового виджета на её высоту — ровно то, ради чего
ручка переноса и уехала в панель поверх содержимого.
Установка
npm i @feugene/granularity-dashboardИмпорт
import { GrDashboardItem } from '@feugene/granularity-dashboard/components/GrDashboardItem'API
API этого компонента ещё не посчитан: генератор витрины пока обходит только ядро. Пока его нет, справочник — в документации пакета.
Примеры 1
Slots
<script setup lang="ts">
import { ref } from 'vue'
import { GrBadge } from '@feugene/granularity'
import type { GrDashboardResponsiveLayout } from '@feugene/granularity-dashboard'
/**
* Виджет — не рамка вокруг содержимого, а карточка со своей поверхностью:
* заголовок, действия рядом с ним, подвал. Плюс собственные границы размера:
* их знает виджет, а не раскладка.
*/
const breakpoints = { lg: 680, md: 520, sm: 400, xs: 0 }
const cols = { lg: 12, md: 8, sm: 4, xs: 2 }
const layout = ref<GrDashboardResponsiveLayout>({
lg: [
{ id: 'report', x: 0, y: 0, w: 7, h: 3 },
{ id: 'narrow', x: 7, y: 0, w: 5, h: 3 },
{ id: 'fixed', x: 0, y: 3, w: 6, h: 2 },
{ id: 'pinned', x: 0, y: 5, w: 12, h: 2 },
],
})
</script>
<template>
<GrDashboard
v-model:layout="layout"
mode="edit"
:breakpoints="breakpoints"
:cols="cols"
:row-height="72"
>
<!-- Шапка, действия и подвал — три слота вокруг содержимого. -->
<GrDashboardItem item-id="report" title="Отчёт за квартал">
<template #actions>
<GrBadge tone="info" size="sm">черновик</GrBadge>
</template>
<p class="text-[var(--gr-muted-fg)]">
Слот <code>#actions</code> держит то, что относится к заголовку: статус, счётчик, кнопку меню.
</p>
<template #footer>
<span class="text-[length:var(--gr-text-sm)] leading-[var(--gr-leading-sm)] text-[var(--gr-muted-fg)]">
Обновлён 14 июля, 09:40
</span>
</template>
</GrDashboardItem>
<!--
Границы объявляет сам виджет: раскладка знает координаты, а «ниже двух
строк я нечитаем» знает только он.
-->
<GrDashboardItem item-id="narrow" title="Не сжимается" :min-w="4" :min-h="2">
<p class="text-[var(--gr-muted-fg)]">
<code>min-w="4"</code> и <code>min-h="2"</code>: уголок растягивания дальше этих границ не пустит —
ни мышью, ни с клавиатуры.
</p>
</GrDashboardItem>
<!-- Размер задан вёрсткой содержимого: менять его нечем и незачем. -->
<GrDashboardItem item-id="fixed" title="Размер фиксирован" :resizable="false">
<p class="text-[var(--gr-muted-fg)]">
<code>:resizable="false"</code>: уголка нет вовсе — ни мышью, ни с клавиатуры. Перетащить виджет
при этом можно.
</p>
</GrDashboardItem>
<!-- Статика: ручек у неё нет вовсе, и соседи её обтекают. -->
<GrDashboardItem item-id="pinned" title="Плановые работы" static>
<p class="text-[var(--gr-muted-fg)]">
Закреплённый виджет не двигается ни сам, ни соседями — перемещение, упёршееся в него, отменяется целиком.
</p>
</GrDashboardItem>
</GrDashboard>
</template>