GrDashboardPalette
Берут, когда набор виджетов выбирает пользователь.
Обзор
Когда брать
- набор виджетов выбирает пользователь — дашборд собирается из каталога, а не приходит готовым;
- доступное зависит от роли или тарифа — список приходит пропом, и недоступное просто не попадает в него;
- карточка каталога нестандартная — слот
itemрисует иконку, описание, превью; - добавлять пока нечего — слот
emptyобъясняет почему, вместо пустого прямоугольника.
Когда взять другое
| Нужно | Берите |
|---|---|
| Выбрать один вариант из списка | GrSelect |
| Найти команду или объект поиском | GrCommandPalette |
| Показать список без добавления | GrList |
| Объяснить, что дашборд пуст | GrEmptyState |
| Сама сетка | GrDashboard |
Несмотря на название, это не GrCommandPalette: там ищут команду по всему
приложению вводом с клавиатуры, здесь выбирают виджет из короткого известного
набора.
Примеры 2 у каждого — живое демо и его код
Доска, собранная из каталога
Добавьте виджет кнопкой или перетащите плитку на сетку:
droppableпоказывает, куда она встанет. Каталог лишь говорит, что добавить, —addдля кнопки,item-dropу сетки с ячейкой и опциями, — а кладёт виджет страница черезaddItem. То, что уже на доске, остаётся в списке как «Added», аminWедет вместе с плиткой.Widgets- Sales today3×2Orders and revenue so far
- Average basket3×2Compared with last week
- Returns3×2Open and processed
- Low stock6×3Needs at least half the width
My store boardSales today€4,812 · 63 ordersПлитки с иконками и тарифами
Слот
itemрисует свою плитку — иконку, описание, бейдж тарифа, — аtransferPropsвешается на её корень, без него плитку не перетащить. Кнопка «Add» остаётся в плитке: это клавиатурный путь, а перетаскивание — лишь усиление. Она зовётaddиз слота, и каталог эмититaddи объявляет виджет, как со своей плиткой.ghostрешает, что тянется за курсором.Add widgetsTeam plan - MRR Recurring revenue and its change
- Overdue invoices Who owes what, oldest first
- Cash forecast BusinessNext 90 days from open invoices
API порождается из пакета · разойтись не может
Props
| Prop | Type | по умолчанию | Описание |
|---|---|---|---|
draggable | boolean | undefined | undefined | Плитку можно перетащить на сетку. Кнопка «Добавить» остаётся при любом значении: она и есть контракт и единственный клавиатурный путь. Сетка, слушающая `itemDrop`, положит брошенное — не слушающая покажет подложку и ничего не сделает. |
size | "lg" | "xs" | "sm" | "md" | undefined | undefined | Ступень размера: кегль плиток и кнопок добавления. По умолчанию `md`; берётся из `GrConfigProvider`. |
disabled | boolean | undefined | false | Каталог недоступен: кнопки «Добавить» выключены, плитки не перетаскиваются. |
ariaLabel | string | undefined | — | Имя списка плиток. Не задано — из локали («Widget catalog»). |
itemsобязательный | GrDashboardPaletteItem[] | — | Каталог доступных виджетов. |
Слоты
| Slot | Type | Описание |
|---|---|---|
item |
| Своя плитка. `transferProps` навешивается на её корень (`v-bind`) — без этого перетащить свою разметку нечем, а слот существует ровно ради неё. |
ghost | { item: GrDashboardPaletteItem; } | Что рисуется под курсором во время переноса. |
empty | any | Что показать, когда каталог пуст. |
События
| Event | Сигнатура | Описание |
|---|---|---|
add | (event: "add", item: GrDashboardPaletteItem): void | — |
Типы
Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.
import type { GrDashboardPaletteConfigurableProps, GrDashboardPaletteSize, GrDashboardPaletteItem } from '@feugene/granularity-dashboard/components/GrDashboardPalette'Файлdist/types/components/GrDashboardPalette/config.d.ts
const grDashboardPaletteConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrDashboardPalette">;Файлdist/types/components/GrDashboardPalette/defaults.d.ts
Пропы GrDashboardPalette, настраиваемые глобально.
interface GrDashboardPaletteConfigurableProps {
size: GrDashboardPaletteSize;
draggable: boolean;
}Файлdist/types/components/GrDashboardPalette/grDashboardPaletteStyles.d.ts
type GrDashboardPaletteSize = GrComponentSize;Один виджет каталога: что добавится в сетку и с каким размером.
interface GrDashboardPaletteItem {
id: string;
title: string;
description?: string;
/** Размер, с которым виджет встаёт в сетку. */
defaultSize?: {
w: number;
h: number;
};
minW?: number;
minH?: number;
maxW?: number;
maxH?: number;
disabled?: boolean;
}Файлdist/types/components/GrDashboardPalette/safelist.d.ts
const grDashboardPaletteSafelist: string[];Файлdist/types/components/GrDashboardPalette/GrDashboardPalette.vue.d.ts
interface GrDashboardPaletteProps {
/** Каталог доступных виджетов. */
items: GrDashboardPaletteItem[];
/**
* Ступень размера: кегль плиток и кнопок добавления. По умолчанию `md`; берётся из
* `GrConfigProvider`.
*/
size?: GrDashboardPaletteSize;
/**
* Плитку можно перетащить на сетку.
*
* Кнопка «Добавить» остаётся при любом значении: она и есть контракт и
* единственный клавиатурный путь. Сетка, слушающая `itemDrop`, положит
* брошенное — не слушающая покажет подложку и ничего не сделает.
*/
draggable?: boolean;
/** Каталог недоступен: кнопки «Добавить» выключены, плитки не перетаскиваются. */
disabled?: boolean;
/** Имя списка плиток. Не задано — из локали («Widget catalog»). */
ariaLabel?: string;
}interface GrDashboardPaletteEmits {
/** Нажата кнопка «Добавить»: положить виджет в раскладку — дело приложения. */
(e: 'add', item: GrDashboardPaletteItem): void;
}Использование из прозы библиотеки
Куда встаёт добавленный виджет — решает приложение
Компонент излучает намерение с описанием виджета, а координаты назначает потребитель: он один знает, добавлять новый виджет вниз, в первое свободное место или на позицию, с которой пользователь начал. Класть его «куда-нибудь» означало бы портить раскладку, которую человек только что собрал.
Перетаскивание — усиление, а не контракт
Плитку можно перетащить на сетку (draggable, включено по умолчанию), но кнопка
«Добавить» при этом остаётся и остаётся единственным клавиатурным путём. Сделай
перетаскивание контрактом — и каталогом нельзя пользоваться с клавиатуры, а
«доступность потом» здесь не наступает.
Куда бросили, сообщает сетка эмитом itemDrop, и кладёт по-прежнему приложение —
ровно как по кнопке. Сетка, которая itemDrop не слушает, покажет подложку и
по отпусканию не сделает ничего: либо обработайте событие, либо выключите
draggable.
Нажатие на саму кнопку переносом не становится: иначе дрогнувшая на пять пикселей рука давала бы перенос вместо добавления.
Своя плитка — слот #item
Слот получает item, dragging, transferProps и add. transferProps
навешивается на корень плитки — без него свою разметку не перетащить. add
— тот же путь, что у встроенной кнопки: эмит add и объявление «добавлено»
скринридеру, у выключенной плитки — ничего. Своя кнопка «Добавить» обязана звать
именно его: она остаётся единственным клавиатурным путём.
<template>
<GrDashboardPalette :items="catalog" @add="place">
<template #item="{ item, transferProps, add }">
<div v-bind="transferProps" class="flex items-center justify-between gap-2">
<span>{{ item.title }}</span>
<GrButton size="sm" :disabled="item.disabled" @click="add">
Добавить
</GrButton>
</div>
</template>
</GrDashboardPalette>
</template>Границы
Пальцем плитка не тащится. Перенос касанием требует touch-action: none на
плитке, а каталог — вертикальный список, который на телефоне обязан
прокручиваться. Отбирать у скроллера вертикальную ось ради жеста, у которого уже
есть работающий эквивалент, — плохой обмен; на сенсорном вводе остаётся кнопка.
Пропы этого примера