GrDashboardItem

  • dashboard
  • Дашборд
  • API · 15 props

Берут, когда любой виджет внутри `GrDashboard`.

import { GrDashboardItem } from '@feugene/granularity-dashboard/components/GrDashboardItem'

Обзор

Когда брать

  • любой виджет внутри GrDashboard — вне сетки компонент смысла не имеет: перенос, растягивание и клавиатура идут через её контекст;
  • у содержимого есть минимум — minW/minH объявляются здесь, а не в раскладке: раскладка знает координаты, а «график ниже трёх строк не читается» знает виджет;
  • шапка нужна не всегда — она появляется, только если есть title, #header или #actions; карте и большой цифре шапка ни к чему;
  • один виджет ведёт себя иначе — :draggable="false" или :resizable="false" сужают правило сетки для него одного.

Когда взять другое

НужноБерите
Карточка вне сетки виджетовGrCard
Показатель числом, без рамы виджетаGrStatistic
Сама сеткаGrDashboard
Каталог виджетов для добавленияGrDashboardPalette

Примеры 3 у каждого — живое демо и его код

  • Все части виджета

    title называет виджет в шапке, в именах ручек и в объявлениях сетки. #actions — продуктовые кнопки, они есть всегда; #editActions и show-settings появляются только в режиме правки и шапку не добавляют; #footer стоит внизу, пока тело прокручивается; #skeleton подменяет тело, пока грузится «Refresh».

    Support today
    Waiting longest
    • Invoice shows the old VAT numberT-229142 min
    • Cannot add a second adminT-22941 h 10 min
    • Card declined on renewalT-22972 h 05 min
    • Export to DATEV is emptyT-23013 h 40 min
    Updated 2 min ago
    Agents online
    7 / 9Two on a break until 14:30
    Switch to Edit to see the handle, Remove and the gear.
  • График от края до края, прокручиваемый список, число без шапки

    padding="none" с overflow="hidden" отдаёт тело графику от края до края и убирает и полосу прокрутки, и остановку Tab. Тело по умолчанию прокручивается, и его прокрутка — остановка Tab, поэтому не влезший список остаётся достижим. У виджета без title, #header и #actions шапки нет вовсе — крупному числу рама ни к чему.

    Traffic, today
    Данные графика
    XRequests per second
    00:00180
    01:00180
    02:00180
    03:00180
    04:00180
    05:00180
    06:00180
    07:00207
    08:00234
    09:00258
    10:00279
    11:00296
    12:00309
    13:00317
    14:00320
    15:00317
    16:00309
    17:00296
    18:00279
    19:00258
    20:00234
    21:00207
    22:00180
    23:00180
    99.982%Uptime this month
    Last errors
    • 502 on /v1/invoices · 14:02
    • Timeout to the bank API · 13:47
    • 429 from the mail provider · 13:15
    • 502 on /v1/payments · 12:58
    • Timeout to the bank API · 12:30
  • Закреплённая строка и растущая хроника

    static — про раскладку, поэтому строка статуса стоит на месте и в режиме правки, и её никто не толкает. «Next event» добавляет запись в хронику с auto-height: она сама просит у сетки строки, а сетка сообщает об этом как item-auto-resize — отдельно от item-resize, чтобы приход данных не выглядел правкой раскладки. min-w и max-h — собственные границы виджета.

    Resized by hand: 0 · by content: 0
    INC-0912 · Invoices API returning 502 · started 14:02
    Timeline
    1. 14:02 · Alert: 502 rate above 2 %
    2. 14:05 · Lena acknowledged
    Owner
    Lena Brandt · on call until 18:00

API порождается из пакета · разойтись не может

Props

PropTypeпо умолчаниюОписание
draggableboolean | undefinedundefinedМожно ли этот виджет тащить и растягивать. Не задан — действует правило сетки; `static` сильнее обоих, потому что он про раскладку, а не про интерфейс.
resizableboolean | undefinedundefinedМожно ли растягивать этот виджет уголком. Не задан — действует правило сетки.
size"lg" | "xs" | "sm" | "md" | undefinedundefinedСтупень размера: кегль шапки, отступы шапки, тела и подвала. По умолчанию `md`; берётся из `GrConfigProvider`.
paddingGrDashboardItemPadding | undefinedundefinedОтступы содержимого. Не задан — ступень от `size`; `none` отдаёт виджет содержимому целиком, край в край.
overflowGrDashboardItemOverflow | undefinedundefined`hidden` снимает и полосу прокрутки, и остановку `Tab` у тела.
autoHeightboolean | undefinedundefinedВысоту виджета определяет его содержимое, а не запись раскладки. Округляется вверх до целой строки: сетка целочисленная, и пустота в несколько пикселей внизу лучше обрезанной последней строки. `minH`/`maxH` продолжают действовать, а уголок у такого виджета меняет только ширину.
staticboolean | undefinedundefinedНе двигается сам и не двигается соседями.
showSettingsboolean | undefinedfalseКнопка настроек в действиях режима редактирования. Шапку она не включает.
ariaLabelstring | undefined—Доступное имя виджета вместо `title`. Без того и другого виджет остаётся обычным блоком, без роли `group`.
itemIdобязательныйstring—Идентификатор виджета. Связывает разметку с записью раскладки.
titlestring | undefined—Имя виджета: заголовок, имя ручек, имя в объявлениях.
minWnumber | undefined—Границы размера. Раскладка их может не содержать — знает их виджет.
minHnumber | undefined—Наименьшая высота виджета в строках сетки.
maxWnumber | undefined—Наибольшая ширина виджета в колонках сетки.

Слоты

SlotTypeОписание
defaultanyСодержимое виджета; при `lazy` у сетки монтируется по попаданию в окно.
headeranyСвоя шапка вместо заголовка `title`; включает шапку.
actionsanyПродуктовые кнопки в шапке — видны всегда и включают шапку.
editActionsanyДействия режима редактирования: удалить виджет, открыть настройки.
footeranyПодвал карточки виджета.
skeletonanyЗаглушка на месте содержимого, пока ленивый виджет не попал в окно.

События

EventСигнатураОписание
settings(event: "settings", id: string): void—

Типы

Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.

Импорт
import type { GrDashboardItemConfigurableProps, GrDashboardItemSize, GrDashboardItemPadding } from '@feugene/granularity-dashboard/components/GrDashboardItem'

Файлdist/types/components/GrDashboardItem/config.d.ts

grDashboardItemConfigconst

GrCard объявлен зависимостью потому, что виджет его **рендерит**: поверхность, шапка и подвал уже есть в ядре, и своя копия разошлась бы с карточками остального приложения.

const grDashboardItemConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrDashboardItem">;

Файлdist/types/components/GrDashboardItem/defaults.d.ts

GrDashboardItemConfigurablePropsinterface

Пропы GrDashboardItem, настраиваемые глобально. size здесь — плотность шапки и кегль заголовка, а не размер виджета в сетке: тот задаётся w/h в раскладке и настройкой быть не может.

interface GrDashboardItemConfigurableProps {
    size: GrDashboardItemSize;
    /** Не задан — отступы берутся от `size`. */
    padding: GrDashboardItemPadding;
    overflow: GrDashboardItemOverflow;
    /** Высоту виджета определяет содержимое, а не запись раскладки. */
    autoHeight: boolean;
}

Файлdist/types/components/GrDashboardItem/grDashboardItemStyles.d.ts

GrDashboardItemSizetype
type GrDashboardItemSize = GrComponentSize;
GrDashboardItemPaddingtype

Отступы содержимого, когда виджет задаёт их сам.

type GrDashboardItemPadding = 'none' | GrDashboardItemSize;
GrDashboardItemOverflowtype
type GrDashboardItemOverflow = 'auto' | 'hidden';

Файлdist/types/components/GrDashboardItem/safelist.d.ts

grDashboardItemSafelistconst
const grDashboardItemSafelist: string[];

Файлdist/types/components/GrDashboardItem/GrDashboardItem.vue.d.ts

GrDashboardItemPropsinterface
interface GrDashboardItemProps {
    /** Идентификатор виджета. Связывает разметку с записью раскладки. */
    itemId: string;
    /** Имя виджета: заголовок, имя ручек, имя в объявлениях. */
    title?: string;
    /**
     * Ступень размера: кегль шапки, отступы шапки, тела и подвала. По умолчанию `md`; берётся из
     * `GrConfigProvider`.
     */
    size?: GrDashboardItemSize;
    /**
     * Отступы содержимого. Не задан — ступень от `size`; `none` отдаёт виджет
     * содержимому целиком, край в край.
     */
    padding?: GrDashboardItemPadding;
    /** `hidden` снимает и полосу прокрутки, и остановку `Tab` у тела. */
    overflow?: GrDashboardItemOverflow;
    /**
     * Высоту виджета определяет его содержимое, а не запись раскладки.
     *
     * Округляется вверх до целой строки: сетка целочисленная, и пустота в
     * несколько пикселей внизу лучше обрезанной последней строки. `minH`/`maxH`
     * продолжают действовать, а уголок у такого виджета меняет только ширину.
     */
    autoHeight?: boolean;
    /**
     * Можно ли этот виджет тащить и растягивать. Не задан — действует правило
     * сетки; `static` сильнее обоих, потому что он про раскладку, а не про
     * интерфейс.
     */
    draggable?: boolean;
    /** Можно ли растягивать этот виджет уголком. Не задан — действует правило сетки. */
    resizable?: boolean;
    /** Не двигается сам и не двигается соседями. */
    static?: boolean;
    /** Кнопка настроек в действиях режима редактирования. Шапку она не включает. */
    showSettings?: boolean;
    /** Границы размера. Раскладка их может не содержать — знает их виджет. */
    minW?: number;
    /** Наименьшая высота виджета в строках сетки. */
    minH?: number;
    /** Наибольшая ширина виджета в колонках сетки. */
    maxW?: number;
    /** Наибольшая высота виджета в строках сетки; упёршееся содержимое прокручивается. */
    maxH?: number;
    /**
     * Доступное имя виджета вместо `title`. Без того и другого виджет остаётся обычным блоком, без
     * роли `group`.
     */
    ariaLabel?: string;
}
GrDashboardItemEmitsinterface
interface GrDashboardItemEmits {
    /** Нажата кнопка настроек. Сетка пересылает это наружу как `itemSettings`. */
    (e: 'settings', id: string): void;
}

Использование из прозы библиотеки

static и draggable — про разное

static — про раскладку: виджет не двигается сам и не даёт соседям себя двигать; столкновение с ним отменяет чужой перенос.

draggable и resizable — про интерфейс, и снимаются по отдельности: :resizable="false" убирает уголок растягивания, оставляя перенос.

Запрет проверяет сама сетка, а не только прячет ручку. Защита, которая держится на «кнопку не отрисовали», снималась бы первым же прямым вызовом из клавиатурного контекста.

Ручка не занимает места в потоке

В режиме редактирования шапка не появляется ради ручки — панель лежит поверх верха содержимого. Поэтому переключение режима ничего не сдвигает: виджет остаётся ровно на своём месте, а не подпрыгивает на высоту шапки.

Скрытая панель остаётся в DOM и в таб-порядке: убрать её значило бы убрать ручку из обхода клавиатурой. Там, где наведения не бывает (палец), она видна всё время редактирования.

Авто-высота: содержимое решает, сколько строк занять

auto-height снимает с приложения задачу угадывать h за пользователя. Виджет замеряет своё содержимое и просит у сетки столько строк, сколько нужно:

vue
<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. Иначе переключение режима сдвигало бы содержимое безголового виджета на её высоту — ровно то, ради чего ручка переноса и уехала в панель поверх содержимого.