@adyen/bento-mcp 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/dist/assets/components/accordion/accordion.docs.mdx +77 -0
- package/dist/assets/components/accordion/accordion.stories.ts +1 -0
- package/dist/assets/components/accordion/accordion.vue +1 -0
- package/dist/assets/components/accordion/components/accordion-item.stories.ts +1 -0
- package/dist/assets/components/accordion/components/accordion-item.vue +1 -0
- package/dist/assets/components/action-bar/action-bar.docs.mdx +103 -0
- package/dist/assets/components/action-bar/action-bar.stories.ts +1 -0
- package/dist/assets/components/action-bar/action-bar.vue +1 -0
- package/dist/assets/components/alert/alert.docs.mdx +106 -0
- package/dist/assets/components/alert/alert.stories.ts +1 -0
- package/dist/assets/components/alert/alert.vue +1 -0
- package/dist/assets/components/avatar/avatar.docs.mdx +44 -0
- package/dist/assets/components/avatar/avatar.stories.ts +1 -0
- package/dist/assets/components/avatar/avatar.vue +1 -0
- package/dist/assets/components/avatar/components/avatar-image/avatar-image.vue +1 -0
- package/dist/assets/components/button/button.docs.mdx +137 -0
- package/dist/assets/components/button/button.stories.ts +1 -0
- package/dist/assets/components/button/button.vue +1 -0
- package/dist/assets/components/button/components/ai-button/ai-button.docs.mdx +40 -0
- package/dist/assets/components/button/components/ai-button/ai-button.stories.ts +1 -0
- package/dist/assets/components/button/components/ai-button/ai-button.vue +1 -0
- package/dist/assets/components/button/components/button-actions/button-actions.docs.mdx +169 -0
- package/dist/assets/components/button/components/button-actions/button-actions.stories.ts +1 -0
- package/dist/assets/components/button/components/button-actions/button-actions.vue +1 -0
- package/dist/assets/components/button/components/loading-button/loading-button.docs.mdx +106 -0
- package/dist/assets/components/button/components/loading-button/loading-button.stories.ts +1 -0
- package/dist/assets/components/button/components/loading-button/loading-button.vue +1 -0
- package/dist/assets/components/button/components/toggle-button/toggle-button.docs.mdx +81 -0
- package/dist/assets/components/button/components/toggle-button/toggle-button.stories.ts +1 -0
- package/dist/assets/components/button/components/toggle-button/toggle-button.vue +1 -0
- package/dist/assets/components/card/card.docs.mdx +166 -0
- package/dist/assets/components/card/card.stories.ts +1 -0
- package/dist/assets/components/card/card.vue +1 -0
- package/dist/assets/components/checkbox/checkbox.docs.mdx +116 -0
- package/dist/assets/components/checkbox/checkbox.stories.ts +1 -0
- package/dist/assets/components/checkbox/checkbox.vue +1 -0
- package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.docs.mdx +134 -0
- package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.stories.ts +1 -0
- package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.vue +1 -0
- package/dist/assets/components/chip/chip.docs.mdx +51 -0
- package/dist/assets/components/chip/chip.stories.ts +1 -0
- package/dist/assets/components/chip/chip.vue +1 -0
- package/dist/assets/components/click-outside/click-outside.docs.mdx +30 -0
- package/dist/assets/components/click-outside/click-outside.stories.ts +1 -0
- package/dist/assets/components/code-snippet/code-snippet.docs.mdx +73 -0
- package/dist/assets/components/code-snippet/code-snippet.stories.ts +1 -0
- package/dist/assets/components/code-snippet/code-snippet.vue +1 -0
- package/dist/assets/components/country/country.docs.mdx +61 -0
- package/dist/assets/components/country/country.stories.ts +1 -0
- package/dist/assets/components/country/country.vue +1 -0
- package/dist/assets/components/currency/currency.docs.mdx +38 -0
- package/dist/assets/components/currency/currency.stories.ts +1 -0
- package/dist/assets/components/currency/currency.vue +1 -0
- package/dist/assets/components/dashed-underline/dashed-underline.docs.mdx +57 -0
- package/dist/assets/components/dashed-underline/dashed-underline.stories.ts +1 -0
- package/dist/assets/components/dashed-underline/dashed-underline.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-cell/data-grid-cell.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-cell-actions/data-grid-cell-actions.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-columns/data-grid-columns.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-config-settings/components/data-grid-config-settings-column-row/data-grid-config-settings-column-row.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-config-settings/data-grid-config-settings.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-lazy-load/data-grid-lazy-load.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-row/data-grid-row.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-static-icon/data-grid-static-icon.docs.mdx +61 -0
- package/dist/assets/components/data-grid/components/data-grid-static-icon/data-grid-static-icon.stories.ts +1 -0
- package/dist/assets/components/data-grid/components/data-grid-static-icon/data-grid-static-icon.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-summary-cell/data-grid-summary-cell.docs.mdx +56 -0
- package/dist/assets/components/data-grid/components/data-grid-summary-cell/data-grid-summary-cell.stories.ts +1 -0
- package/dist/assets/components/data-grid/components/data-grid-summary-cell/data-grid-summary-cell.vue +1 -0
- package/dist/assets/components/data-grid/components/data-grid-trend-cell/data-grid-trend-cell.docs.mdx +48 -0
- package/dist/assets/components/data-grid/components/data-grid-trend-cell/data-grid-trend-cell.stories.ts +1 -0
- package/dist/assets/components/data-grid/components/data-grid-trend-cell/data-grid-trend-cell.vue +1 -0
- package/dist/assets/components/data-grid/data-grid.docs.mdx +951 -0
- package/dist/assets/components/data-grid/data-grid.stories.ts +1 -0
- package/dist/assets/components/data-grid/data-grid.vue +1 -0
- package/dist/assets/components/date/date.docs.mdx +49 -0
- package/dist/assets/components/date/date.stories.ts +1 -0
- package/dist/assets/components/date/date.vue +1 -0
- package/dist/assets/components/date-picker/date-picker.docs.mdx +69 -0
- package/dist/assets/components/date-picker/date-picker.stories.ts +1 -0
- package/dist/assets/components/date-picker/date-picker.vue +1 -0
- package/dist/assets/components/date-range-picker/components/date-range-picker-calendar/date-range-picker-calendar.vue +1 -0
- package/dist/assets/components/date-range-picker/date-range-picker.docs.mdx +168 -0
- package/dist/assets/components/date-range-picker/date-range-picker.stories.ts +1 -0
- package/dist/assets/components/date-range-picker/date-range-picker.vue +1 -0
- package/dist/assets/components/divider/divider.docs.mdx +27 -0
- package/dist/assets/components/divider/divider.stories.ts +1 -0
- package/dist/assets/components/divider/divider.vue +1 -0
- package/dist/assets/components/dropdown/components/dropdown-base-textbox/dropdown-base-textbox.vue +1 -0
- package/dist/assets/components/dropdown/components/dropdown-default-textbox/dropdown-default-textbox.vue +1 -0
- package/dist/assets/components/dropdown/components/dropdown-options-container/dropdown-options-container.vue +1 -0
- package/dist/assets/components/dropdown/components/dropdown-small-textbox/dropdown-small-textbox.vue +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.stories.ts +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.vue +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.stories.ts +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.vue +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.stories.ts +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.vue +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.stories.ts +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.vue +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.stories.ts +1 -0
- package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.vue +1 -0
- package/dist/assets/components/dropdown/dropdown.docs.mdx +420 -0
- package/dist/assets/components/dropdown/dropdown.stories.ts +1 -0
- package/dist/assets/components/dropdown/dropdown.vue +1 -0
- package/dist/assets/components/empty-state/empty-state.docs.mdx +115 -0
- package/dist/assets/components/empty-state/empty-state.stories.ts +1 -0
- package/dist/assets/components/empty-state/empty-state.vue +1 -0
- package/dist/assets/components/file-uploader/components/file-uploader-file-card/components/file-uploader-file-card-animation/file-uploader-file-card-animation.vue +1 -0
- package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.stories.ts +1 -0
- package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.vue +1 -0
- package/dist/assets/components/file-uploader/components/file-uploader-restrictions/file-uploader-restrictions.stories.ts +1 -0
- package/dist/assets/components/file-uploader/components/file-uploader-restrictions/file-uploader-restrictions.vue +1 -0
- package/dist/assets/components/file-uploader/file-uploader.docs.mdx +117 -0
- package/dist/assets/components/file-uploader/file-uploader.stories.ts +1 -0
- package/dist/assets/components/file-uploader/file-uploader.vue +1 -0
- package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.vue +1 -0
- package/dist/assets/components/filter-bar/components/all-filters-modal/components/all-filters-modal-button/all-filters-modal-button.vue +1 -0
- package/dist/assets/components/filter-bar/components/base-filter/base-filter.docs.mdx +90 -0
- package/dist/assets/components/filter-bar/components/base-filter/base-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/base-filter/base-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/base-filter-button/base-filter-button.vue +1 -0
- package/dist/assets/components/filter-bar/components/boolean-filter/boolean-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/checkbox-group-filter/checkbox-group-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/checkbox-group-filter/checkbox-group-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/date-filter/date-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/date-filter/date-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/date-range-filter/date-range-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/date-range-filter/date-range-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/filter-bar-button/filter-bar-button.vue +1 -0
- package/dist/assets/components/filter-bar/components/filter-bar-button-group/filter-bar-button-group.vue +1 -0
- package/dist/assets/components/filter-bar/components/input-filter/input-filter.docs.mdx +18 -0
- package/dist/assets/components/filter-bar/components/input-filter/input-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/input-filter/input-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/input-with-dropdown-filter/input-with-dropdown-filter.docs.mdx +18 -0
- package/dist/assets/components/filter-bar/components/input-with-dropdown-filter/input-with-dropdown-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/input-with-dropdown-filter/input-with-dropdown-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/radio-group-filter/radio-group-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/radio-group-filter/radio-group-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/range-filter/range-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/components/select-filter-button/select-filter-button.vue +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/components/select-filter-dropdown/select-filter-dropdown.vue +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/select-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/select-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-avatar-filter/select-avatar-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-avatar-filter/select-avatar-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-country-filter/select-country-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-country-filter/select-country-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-currency-filter/select-currency-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-currency-filter/select-currency-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-payment-method-filter/select-payment-method-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-payment-method-filter/select-payment-method-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-tag-filter/select-tag-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-tag-filter/select-tag-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/toggle-filter/toggle-filter.stories.ts +1 -0
- package/dist/assets/components/filter-bar/components/toggle-filter/toggle-filter.vue +1 -0
- package/dist/assets/components/filter-bar/filter-bar.docs.mdx +1005 -0
- package/dist/assets/components/filter-bar/filter-bar.stories.ts +1 -0
- package/dist/assets/components/filter-bar/filter-bar.vue +1 -0
- package/dist/assets/components/focus-trap/focus-trap.docs.mdx +10 -0
- package/dist/assets/components/focus-trap/focus-trap.stories.ts +1 -0
- package/dist/assets/components/focus-trap/focus-trap.vue +1 -0
- package/dist/assets/components/form-layout/components/form-layout-field-tip/form-layout-field-tip.vue +1 -0
- package/dist/assets/components/form-layout/components/form-layout-group/form-layout-group.vue +1 -0
- package/dist/assets/components/form-layout/components/form-layout-title/form-layout-title.vue +1 -0
- package/dist/assets/components/form-layout/form-layout.docs.mdx +452 -0
- package/dist/assets/components/form-layout/form-layout.stories.ts +1 -0
- package/dist/assets/components/form-layout/form-layout.vue +1 -0
- package/dist/assets/components/header/header.docs.mdx +85 -0
- package/dist/assets/components/header/header.stories.ts +1 -0
- package/dist/assets/components/header/header.vue +1 -0
- package/dist/assets/components/header-with-views/components/header-with-views-all-views/header-with-views-all-views.vue +1 -0
- package/dist/assets/components/header-with-views/components/header-with-views-item-edit-form/header-with-views-edit-form.vue +1 -0
- package/dist/assets/components/header-with-views/header-with-views.docs.mdx +103 -0
- package/dist/assets/components/header-with-views/header-with-views.stories.ts +1 -0
- package/dist/assets/components/header-with-views/header-with-views.vue +1 -0
- package/dist/assets/components/image/image.docs.mdx +34 -0
- package/dist/assets/components/image/image.stories.ts +1 -0
- package/dist/assets/components/image/image.vue +1 -0
- package/dist/assets/components/info-icon/info-icon.docs.mdx +57 -0
- package/dist/assets/components/info-icon/info-icon.stories.ts +1 -0
- package/dist/assets/components/info-icon/info-icon.vue +1 -0
- package/dist/assets/components/input-field/input-field.docs.mdx +141 -0
- package/dist/assets/components/input-field/input-field.stories.ts +1 -0
- package/dist/assets/components/input-field/input-field.vue +1 -0
- package/dist/assets/components/input-field-password/input-field-password.docs.mdx +292 -0
- package/dist/assets/components/input-field-password/input-field-password.stories.ts +1 -0
- package/dist/assets/components/input-field-password/input-field-password.vue +1 -0
- package/dist/assets/components/input-field-phone-number/input-field-phone-number.docs.mdx +72 -0
- package/dist/assets/components/input-field-phone-number/input-field-phone-number.stories.ts +1 -0
- package/dist/assets/components/input-field-phone-number/input-field-phone-number.vue +1 -0
- package/dist/assets/components/inspector/inspector.docs.mdx +118 -0
- package/dist/assets/components/inspector/inspector.stories.ts +1 -0
- package/dist/assets/components/inspector/inspector.vue +1 -0
- package/dist/assets/components/internal/base-button/base-button.vue +1 -0
- package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.stories.ts +1 -0
- package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.vue +1 -0
- package/dist/assets/components/internal/calendar/calendar.stories.ts +1 -0
- package/dist/assets/components/internal/calendar/calendar.vue +1 -0
- package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.stories.ts +1 -0
- package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.vue +1 -0
- package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/__test__/calendar-month-day-stub.vue +1 -0
- package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.stories.ts +1 -0
- package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.vue +1 -0
- package/dist/assets/components/internal/calendar/components/calendar-year/calendar-year.vue +1 -0
- package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/__test__/calendar-year-month-stub.vue +1 -0
- package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/calendar-year-month.vue +1 -0
- package/dist/assets/components/internal/checkbox-input/checkbox-input.stories.ts +1 -0
- package/dist/assets/components/internal/checkbox-input/checkbox-input.vue +1 -0
- package/dist/assets/components/internal/controls-group/controls-group.vue +1 -0
- package/dist/assets/components/internal/copy/copy.docs.mdx +43 -0
- package/dist/assets/components/internal/copy/copy.stories.ts +1 -0
- package/dist/assets/components/internal/copy/copy.vue +1 -0
- package/dist/assets/components/internal/decorative-checkbox/decorative-checkbox.vue +1 -0
- package/dist/assets/components/internal/dialog-page/dialog-page.vue +1 -0
- package/dist/assets/components/internal/error-message/error-message.vue +1 -0
- package/dist/assets/components/internal/field-label/field-label.vue +1 -0
- package/dist/assets/components/internal/fixed-scroller/fixed-scroller.docs.mdx +21 -0
- package/dist/assets/components/internal/fixed-scroller/fixed-scroller.stories.ts +1 -0
- package/dist/assets/components/internal/fixed-scroller/fixed-scroller.vue +1 -0
- package/dist/assets/components/internal/footer-actions/footer-actions.vue +1 -0
- package/dist/assets/components/internal/grid-layout/grid-layout.vue +1 -0
- package/dist/assets/components/internal/header-meta/header-meta.vue +1 -0
- package/dist/assets/components/internal/info-icon-with-popover/info-icon-with-popover.vue +1 -0
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/components/listbox-multi-select-category/listbox-multi-select-category.vue +1 -0
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/listbox-multi-select-options.vue +1 -0
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/listbox-multi-select.vue +1 -0
- package/dist/assets/components/internal/listbox/components/listbox-option/listbox-option.vue +1 -0
- package/dist/assets/components/internal/listbox/components/listbox-option-tag/listbox-option-tag.vue +1 -0
- package/dist/assets/components/internal/listbox/components/listbox-single-select/components/listbox-single-select-category/listbox-single-select-category.vue +1 -0
- package/dist/assets/components/internal/listbox/components/listbox-single-select/listbox-single-select.vue +1 -0
- package/dist/assets/components/internal/listbox/components/listbox-single-select-option/listbox-single-select-option.vue +1 -0
- package/dist/assets/components/internal/listbox/listbox.stories.ts +1 -0
- package/dist/assets/components/internal/listbox/listbox.vue +1 -0
- package/dist/assets/components/internal/radio-input/radio-input.stories.ts +1 -0
- package/dist/assets/components/internal/radio-input/radio-input.vue +1 -0
- package/dist/assets/components/internal/teleport/teleport.vue +1 -0
- package/dist/assets/components/internal/tooltip/tooltip.test.vue +1 -0
- package/dist/assets/components/internal/tooltip/tooltip.vue +1 -0
- package/dist/assets/components/layout/components/layout-row/layout-row.stories.ts +1 -0
- package/dist/assets/components/layout/components/layout-row/layout-row.vue +1 -0
- package/dist/assets/components/layout/layout.docs.mdx +108 -0
- package/dist/assets/components/layout/layout.stories.ts +1 -0
- package/dist/assets/components/layout/layout.vue +1 -0
- package/dist/assets/components/link/link.docs.mdx +119 -0
- package/dist/assets/components/link/link.stories.ts +1 -0
- package/dist/assets/components/link/link.vue +1 -0
- package/dist/assets/components/loading-indicator/loading-indicator.docs.mdx +65 -0
- package/dist/assets/components/loading-indicator/loading-indicator.stories.ts +1 -0
- package/dist/assets/components/loading-indicator/loading-indicator.vue +1 -0
- package/dist/assets/components/menu/components/menu-item/menu-item.vue +1 -0
- package/dist/assets/components/menu/components/menu-item-list/menu-item-list.vue +1 -0
- package/dist/assets/components/menu/components/menu-list-container/menu-list-container.vue +1 -0
- package/dist/assets/components/menu/components/sub-menu-item-list/sub-menu-item-list.vue +1 -0
- package/dist/assets/components/menu/menu.docs.mdx +121 -0
- package/dist/assets/components/menu/menu.stories.ts +1 -0
- package/dist/assets/components/menu/menu.vue +1 -0
- package/dist/assets/components/modal/components/base-modal/base-modal.vue +1 -0
- package/dist/assets/components/modal/components/modal-default/modal-default.vue +1 -0
- package/dist/assets/components/modal/components/modal-dialog/modal-dialog.vue +1 -0
- package/dist/assets/components/modal/components/modal-page/modal-page.vue +1 -0
- package/dist/assets/components/modal/modal.docs.mdx +215 -0
- package/dist/assets/components/modal/modal.stories.ts +1 -0
- package/dist/assets/components/modal/modal.vue +1 -0
- package/dist/assets/components/modal-fullscreen/components/modal-fullscreen-page.vue +1 -0
- package/dist/assets/components/modal-fullscreen/modal-fullscreen.docs.mdx +217 -0
- package/dist/assets/components/modal-fullscreen/modal-fullscreen.stories.ts +1 -0
- package/dist/assets/components/modal-fullscreen/modal-fullscreen.vue +1 -0
- package/dist/assets/components/pagination/components/pagination-context/pagination-context.vue +1 -0
- package/dist/assets/components/pagination/components/pagination-controls/pagination-controls.vue +1 -0
- package/dist/assets/components/pagination/components/pagination-results-per-page/pagination-results-per-page.vue +1 -0
- package/dist/assets/components/pagination/pagination.docs.mdx +116 -0
- package/dist/assets/components/pagination/pagination.stories.ts +1 -0
- package/dist/assets/components/pagination/pagination.vue +1 -0
- package/dist/assets/components/payment-method/payment-method.docs.mdx +34 -0
- package/dist/assets/components/payment-method/payment-method.stories.ts +1 -0
- package/dist/assets/components/payment-method/payment-method.vue +1 -0
- package/dist/assets/components/popover/components/popover-dismiss-button/popover-dismiss-button.vue +1 -0
- package/dist/assets/components/popover/components/popover-image/popover-image.vue +1 -0
- package/dist/assets/components/popover/components/popover-title/popover-title.vue +1 -0
- package/dist/assets/components/popover/popover.docs.mdx +89 -0
- package/dist/assets/components/popover/popover.stories.ts +1 -0
- package/dist/assets/components/popover/popover.vue +1 -0
- package/dist/assets/components/popper-container/popper-container.docs.mdx +11 -0
- package/dist/assets/components/popper-container/popper-container.stories.ts +1 -0
- package/dist/assets/components/popper-container/popper-container.vue +1 -0
- package/dist/assets/components/promo-banner/promo-banner.docs.mdx +94 -0
- package/dist/assets/components/promo-banner/promo-banner.stories.ts +1 -0
- package/dist/assets/components/promo-banner/promo-banner.vue +1 -0
- package/dist/assets/components/radio-group/components/radio-button/radio-button.docs.mdx +76 -0
- package/dist/assets/components/radio-group/components/radio-button/radio-button.stories.ts +1 -0
- package/dist/assets/components/radio-group/components/radio-button/radio-button.vue +1 -0
- package/dist/assets/components/radio-group/radio-group.docs.mdx +154 -0
- package/dist/assets/components/radio-group/radio-group.stories.ts +1 -0
- package/dist/assets/components/radio-group/radio-group.vue +1 -0
- package/dist/assets/components/rich-text-editor/components/rich-text-editor-content-area/rich-text-editor-content-area.vue +1 -0
- package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-code-block/rich-text-editor-code-block.vue +1 -0
- package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-inline-code/rich-text-editor-inline-code.vue +1 -0
- package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-link/rich-text-editor-link.vue +1 -0
- package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-list-item/rich-text-editor-list-item.vue +1 -0
- package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-table/rich-text-editor-table.vue +1 -0
- package/dist/assets/components/rich-text-editor/rich-text-editor.docs.mdx +52 -0
- package/dist/assets/components/rich-text-editor/rich-text-editor.stories.ts +1 -0
- package/dist/assets/components/rich-text-editor/rich-text-editor.vue +1 -0
- package/dist/assets/components/search-bar/search-bar.docs.mdx +117 -0
- package/dist/assets/components/search-bar/search-bar.stories.ts +1 -0
- package/dist/assets/components/search-bar/search-bar.vue +1 -0
- package/dist/assets/components/secondary-nav/components/secondary-nav-category/secondary-nav-category.vue +1 -0
- package/dist/assets/components/secondary-nav/components/secondary-nav-item/secondary-nav-item.vue +1 -0
- package/dist/assets/components/secondary-nav/secondary-nav.docs.mdx +40 -0
- package/dist/assets/components/secondary-nav/secondary-nav.stories.ts +1 -0
- package/dist/assets/components/secondary-nav/secondary-nav.vue +1 -0
- package/dist/assets/components/segmented-control/components/segmented-control-button/segmented-control-button.vue +1 -0
- package/dist/assets/components/segmented-control/segmented-control.docs.mdx +90 -0
- package/dist/assets/components/segmented-control/segmented-control.stories.ts +1 -0
- package/dist/assets/components/segmented-control/segmented-control.vue +1 -0
- package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.docs.mdx +119 -0
- package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.stories.ts +1 -0
- package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.vue +1 -0
- package/dist/assets/components/selection-card/selection-card.docs.mdx +108 -0
- package/dist/assets/components/selection-card/selection-card.stories.ts +1 -0
- package/dist/assets/components/selection-card/selection-card.vue +1 -0
- package/dist/assets/components/sidepanel/components/sidepanel-page.stories.ts +1 -0
- package/dist/assets/components/sidepanel/components/sidepanel-page.vue +1 -0
- package/dist/assets/components/sidepanel/sidepanel.docs.mdx +129 -0
- package/dist/assets/components/sidepanel/sidepanel.stories.ts +1 -0
- package/dist/assets/components/sidepanel/sidepanel.vue +1 -0
- package/dist/assets/components/status/status.docs.mdx +62 -0
- package/dist/assets/components/status/status.stories.ts +1 -0
- package/dist/assets/components/status/status.vue +1 -0
- package/dist/assets/components/stepper/components/step/step.stories.ts +1 -0
- package/dist/assets/components/stepper/components/step/step.vue +1 -0
- package/dist/assets/components/stepper/stepper.docs.mdx +127 -0
- package/dist/assets/components/stepper/stepper.stories.ts +1 -0
- package/dist/assets/components/stepper/stepper.vue +1 -0
- package/dist/assets/components/structured-list/components/structered-list-item/structured-list-item.stories.ts +1 -0
- package/dist/assets/components/structured-list/components/structered-list-item/structured-list-item.vue +1 -0
- package/dist/assets/components/structured-list/structured-list.docs.mdx +68 -0
- package/dist/assets/components/structured-list/structured-list.stories.ts +1 -0
- package/dist/assets/components/structured-list/structured-list.vue +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item/summary-grid-item.vue +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-amount/summary-grid-item-amount.stories.ts +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-amount/summary-grid-item-amount.vue +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-custom/summary-grid-item-custom.stories.ts +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-custom/summary-grid-item-custom.vue +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-numeric/summary-grid-item-numeric.stories.ts +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-numeric/summary-grid-item-numeric.vue +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-percentage/summary-grid-item-percentage.stories.ts +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-percentage/summary-grid-item-percentage.vue +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-text/summary-grid-item-text.stories.ts +1 -0
- package/dist/assets/components/summary-grid/components/summary-grid-item-text/summary-grid-item-text.vue +1 -0
- package/dist/assets/components/summary-grid/summary-grid.docs.mdx +152 -0
- package/dist/assets/components/summary-grid/summary-grid.stories.ts +1 -0
- package/dist/assets/components/summary-grid/summary-grid.vue +1 -0
- package/dist/assets/components/tabs/components/tab.vue +1 -0
- package/dist/assets/components/tabs/tabs.docs.mdx +98 -0
- package/dist/assets/components/tabs/tabs.stories.ts +1 -0
- package/dist/assets/components/tabs/tabs.vue +1 -0
- package/dist/assets/components/tag/tag.docs.mdx +137 -0
- package/dist/assets/components/tag/tag.stories.ts +1 -0
- package/dist/assets/components/tag/tag.vue +1 -0
- package/dist/assets/components/textarea/textarea.docs.mdx +53 -0
- package/dist/assets/components/textarea/textarea.stories.ts +1 -0
- package/dist/assets/components/textarea/textarea.vue +1 -0
- package/dist/assets/components/timeline/components/timeline-item/timeline-item.stories.ts +1 -0
- package/dist/assets/components/timeline/components/timeline-item/timeline-item.vue +1 -0
- package/dist/assets/components/timeline/timeline.docs.mdx +131 -0
- package/dist/assets/components/timeline/timeline.stories.ts +1 -0
- package/dist/assets/components/timeline/timeline.vue +1 -0
- package/dist/assets/components/toast/components/toast-item/toast-item.vue +1 -0
- package/dist/assets/components/toast/components/toast-shadow-stack/toast-shadow-stack.vue +1 -0
- package/dist/assets/components/toast/toast.docs.mdx +151 -0
- package/dist/assets/components/toast/toast.stories.ts +1 -0
- package/dist/assets/components/toast/toast.vue +1 -0
- package/dist/assets/components/toggle/toggle.docs.mdx +81 -0
- package/dist/assets/components/toggle/toggle.stories.ts +1 -0
- package/dist/assets/components/toggle/toggle.vue +1 -0
- package/dist/assets/components/tutorial/components/tutorial-popover/components/tutorial-indicator/tutorial-indicator.vue +1 -0
- package/dist/assets/components/tutorial/components/tutorial-popover/tutorial-popover.vue +1 -0
- package/dist/assets/components/tutorial/tutorial.docs.mdx +85 -0
- package/dist/assets/components/tutorial/tutorial.stories.ts +1 -0
- package/dist/assets/components/tutorial/tutorial.vue +1 -0
- package/dist/assets/components/typography/typography.docs.mdx +124 -0
- package/dist/assets/components/typography/typography.stories.ts +1 -0
- package/dist/assets/components/typography/typography.vue +1 -0
- package/dist/assets/composables/use-bento-currency/use-bento-currency.docs.mdx +28 -0
- package/dist/assets/composables/use-bento-currency/use-bento-currency.stories.ts +1 -0
- package/dist/assets/composables/use-click-outside/use-click-outside.docs.mdx +10 -0
- package/dist/assets/composables/use-click-outside/use-click-outside.stories.ts +1 -0
- package/dist/assets/directives/highlight/highlight.docs.mdx +64 -0
- package/dist/assets/directives/highlight/highlight.stories.ts +1 -0
- package/dist/assets/directives/keyboard-navigation/keyboard-navigation.docs.mdx +41 -0
- package/dist/assets/directives/keyboard-navigation/keyboard-navigation.stories.ts +1 -0
- package/dist/assets/directives/tooltip/tooltip.docs.mdx +86 -0
- package/dist/assets/directives/tooltip/tooltip.stories.ts +1 -0
- package/dist/assets/index.ts +1 -0
- package/dist/assets/templates/dashboard-template/components/dashboard-section/dashboard-section.stories.ts +1 -0
- package/dist/assets/templates/dashboard-template/components/dashboard-section/dashboard-section.vue +1 -0
- package/dist/assets/templates/dashboard-template/dashboard-template.docs.mdx +148 -0
- package/dist/assets/templates/dashboard-template/dashboard-template.stories.ts +1 -0
- package/dist/assets/templates/dashboard-template/dashboard-template.vue +1 -0
- package/dist/assets/templates/data-grid-template/data-grid-template.docs.mdx +117 -0
- package/dist/assets/templates/data-grid-template/data-grid-template.stories.ts +1 -0
- package/dist/assets/templates/data-grid-template/data-grid-template.vue +1 -0
- package/dist/main.js +30031 -0
- package/package.json +45 -3
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Canvas, Meta } from '@storybook/blocks';
|
|
2
|
+
import * as DashboardTemplateStories from './dashboard-template.stories';
|
|
3
|
+
import * as DashboardSectionStories from './components/dashboard-section/dashboard-section.stories';
|
|
4
|
+
|
|
5
|
+
<Meta of={DashboardTemplateStories} />
|
|
6
|
+
|
|
7
|
+
# Dashboard Template
|
|
8
|
+
|
|
9
|
+
Dashboard template is to be used when visualizing data on pages such as data dashboards and reports.
|
|
10
|
+
|
|
11
|
+
<Canvas of={DashboardTemplateStories.Default} />
|
|
12
|
+
|
|
13
|
+
## Use Cases
|
|
14
|
+
|
|
15
|
+
Use a DashboardTemplate:
|
|
16
|
+
|
|
17
|
+
- when you need to visualize data such as charts and breakdowns.
|
|
18
|
+
|
|
19
|
+
## Overview of elements
|
|
20
|
+
|
|
21
|
+
## Header
|
|
22
|
+
|
|
23
|
+
Page header holds the page title and a set of actions related to the dashboard. It can be configured to display a
|
|
24
|
+
tooltip and a timestamp when needed.
|
|
25
|
+
|
|
26
|
+
The header is passed to the Dashboard template as a prop, using all the same props as the `Header` component.
|
|
27
|
+
|
|
28
|
+
## Tabs
|
|
29
|
+
|
|
30
|
+
Use tabs to navigate between different but related content within a page.
|
|
31
|
+
|
|
32
|
+
Tabs can be used above or below the filter bar depending on your use case:
|
|
33
|
+
|
|
34
|
+
- Use tabs above the filter bar when filters are related to one tab
|
|
35
|
+
- Use tabs below the filter bar when filters are related to all tabs
|
|
36
|
+
|
|
37
|
+
### Tabs object
|
|
38
|
+
|
|
39
|
+
Tabs are passed to the Dashboard template as a prop, using all the same props as the `Tabs` component.
|
|
40
|
+
|
|
41
|
+
You can then pass the content to the respective tabs by using the template with the tab id, which is `tab-{index}`.
|
|
42
|
+
|
|
43
|
+
### Sticky tabs
|
|
44
|
+
|
|
45
|
+
Tabs can be configured to stick to the top when scrolling so that they are always accessible and visible by using the
|
|
46
|
+
`stickyTabs` prop.
|
|
47
|
+
|
|
48
|
+
<Canvas of={DashboardTemplateStories.WithTabs} />
|
|
49
|
+
|
|
50
|
+
## Filters
|
|
51
|
+
|
|
52
|
+
Use a filter bar when a user needs to filter the dashboard to a specific data story.
|
|
53
|
+
|
|
54
|
+
You can pass the `bento-filter` component to the `filters` slot, which will display above the tabs if they are present
|
|
55
|
+
on the page.
|
|
56
|
+
|
|
57
|
+
If you need to display the filters under the tabs, then it will be passed as part of the tab content slot.
|
|
58
|
+
|
|
59
|
+
### Sticky filters
|
|
60
|
+
|
|
61
|
+
Filters can be configured to stick to the top when scrolling so that they are always accessible and visible by using the
|
|
62
|
+
`stickyFilters` prop. This will only work for filters passed into the `filters` slot.
|
|
63
|
+
|
|
64
|
+
## Content
|
|
65
|
+
|
|
66
|
+
Content will be passed to the `default` slot, if you're using tabs, content will be inside the `tab-{index}` slots
|
|
67
|
+
instead.
|
|
68
|
+
|
|
69
|
+
These are the recommended elements to use inside the Dashboard template:
|
|
70
|
+
|
|
71
|
+
### Summary grid
|
|
72
|
+
|
|
73
|
+
Use a summary grid to highlight key summary data points on your dashboard.
|
|
74
|
+
|
|
75
|
+
### Dashboard section
|
|
76
|
+
|
|
77
|
+
Dashboard section is a child component of the dashboard template to help you render your data, with Lume charts or data
|
|
78
|
+
grids.
|
|
79
|
+
|
|
80
|
+
The component consists of a header, a slot to pass your data controls and slots for the data, you can display the
|
|
81
|
+
content in one `full-width` column, using the `default` slot, or two columns, passing the `content-col-1` and
|
|
82
|
+
`content-col-2` slots.
|
|
83
|
+
|
|
84
|
+
Additionally, the entire section can also be rendered in half-width, by passing the `halfWidth` prop.
|
|
85
|
+
|
|
86
|
+
#### Lume charts
|
|
87
|
+
|
|
88
|
+
Use Lume charts when you need to visualize data points.
|
|
89
|
+
|
|
90
|
+
Charts come in two sizes: one column (by using the `default` slot) or two columns (by using `content-col-1` and
|
|
91
|
+
`content-col-2` slots)
|
|
92
|
+
|
|
93
|
+
Choosing the right chart to display data can be overwhelming. For more information on what chart to use go to
|
|
94
|
+
[Lume](https://lume.is.adyen.com/).
|
|
95
|
+
|
|
96
|
+
<Canvas of={DashboardSectionStories.Graph} />
|
|
97
|
+
|
|
98
|
+
#### Data Grids
|
|
99
|
+
|
|
100
|
+
Use a data grid when you need to display set of data in a way that is easy to scan and analyze.
|
|
101
|
+
|
|
102
|
+
Data Grid should always be used with `full-width` column, so `half-width` or column layout should never be applied when
|
|
103
|
+
using data grids.
|
|
104
|
+
|
|
105
|
+
<Canvas of={DashboardSectionStories.DataGrid} />
|
|
106
|
+
|
|
107
|
+
#### Controls
|
|
108
|
+
|
|
109
|
+
Both charts and data grid can be paired with controls.
|
|
110
|
+
|
|
111
|
+
The amount of controls you can have is dependent on your usecase and user needs.
|
|
112
|
+
|
|
113
|
+
- **Dropdowns**: Use dropdowns when selecting a specific breakdown of the data set or filtering on specific data eg:
|
|
114
|
+
Breaking down the data set by payment methods, acquirer response etc or selecting a date range.
|
|
115
|
+
- **Segmented controls**: Use segmented controls when showing a different view of the same data set eg: Counts,
|
|
116
|
+
amounts and ratios or days, months and weeks.
|
|
117
|
+
- **Tabs**: Use tabs when switching to an entirely different data set eg: API and Webhooks
|
|
118
|
+
|
|
119
|
+
#### Two columns vs half-width
|
|
120
|
+
|
|
121
|
+
Dashboard section can be rendered to take the full width of the page or only half of the page.
|
|
122
|
+
|
|
123
|
+
There's two ways of rendering the content in half of the page:
|
|
124
|
+
|
|
125
|
+
- `content-col-1` and `content-col-2` slots
|
|
126
|
+
- `halfWidth` prop
|
|
127
|
+
|
|
128
|
+
##### `content-col-1` and `content-col-2` slots
|
|
129
|
+
|
|
130
|
+
If you use the slots, you are rendering one single section, with one title and one set of controls that display two
|
|
131
|
+
different graphs.
|
|
132
|
+
|
|
133
|
+
<Canvas of={DashboardSectionStories.TwoColumns} />
|
|
134
|
+
|
|
135
|
+
##### `halfWidth` prop
|
|
136
|
+
|
|
137
|
+
If you use `halfWidth` you are rendering the whole section as half of the page. That means that you have two sections
|
|
138
|
+
side-by-side, with different titles and controls.
|
|
139
|
+
|
|
140
|
+
**Don't use `halfWidth` in isolation. If you're passing `half-width` there should always be two
|
|
141
|
+
`bento-dashboard-sections` using the prop.**
|
|
142
|
+
|
|
143
|
+
<Canvas of={DashboardTemplateStories.HalfWidth} />
|
|
144
|
+
|
|
145
|
+
## Resources
|
|
146
|
+
|
|
147
|
+
- [Figma link](https://www.figma.com/design/lJK6kNN3ClihuCl7ni7v1k/Bento---Templates?node-id=1966-48825&node-type=instance&m=dev)
|
|
148
|
+
- [Lume](https://lume.is.adyen.com/)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { isVue2 } from 'vue-demi'; import { ref } from 'vue'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import type { Meta, StoryObj } from '@storybook/vue'; import { BentoSummaryGrid, BentoSummaryGridItemAmount } from '@/components/summary-grid'; import { BentoDataGrid } from '@/components/data-grid'; import { type BentoDateRangeFilterOptions, BentoFilterBar, type BentoFilterBarModel, BentoFilterItemType, type BentoFilterValues, } from '@/components/filter-bar'; import { BentoDropdown } from '@/components/dropdown'; import { BentoSegmentedControl } from '@/components/segmented-control'; import { LumeLineChart } from '@adyen/lume'; import BentoDashboardTemplate from './dashboard-template.vue'; import BentoDashboardSection from './components/dashboard-section/dashboard-section.vue'; import InfoIcon from '@adyen/ui-assets-icons-16/vue/info'; import Settings from '@adyen/ui-assets-icons-16/vue/settings'; import Download from '@adyen/ui-assets-icons-16/vue/download'; import Share from '@adyen/ui-assets-icons-16/vue/share-2'; import { subDays } from 'date-fns'; import { type BentoDashboardTemplateHeader, type BentoDashboardTemplateTabs } from './dashboard-template.types'; import { type BentoListboxOptions } from '@/types/listbox'; const meta: Meta = { title: 'Dashboard template', component: BentoDashboardTemplate, parameters: { layout: 'fullscreen', }, }; export default meta; type Story = StoryObj<typeof BentoDashboardTemplate>; const HEADER_PROPS: BentoDashboardTemplateHeader = { title: 'Dashboard', lastUpdated: Date.now(), actions: [ { title: 'Glossary', variant: 'secondary', event: () => undefined, icon: InfoIcon }, { title: 'Settings', variant: 'secondary', event: () => undefined, icon: Settings }, { title: 'Download', variant: 'secondary', event: () => undefined, icon: Download }, { title: 'Share', variant: 'secondary', event: () => undefined, icon: Share }, ], infoIconTooltipText: 'Info', }; const TABS_ARGS: BentoDashboardTemplateTabs = { tabs: [{ title: 'Tab 1' }, { title: 'Tab 2' }], }; const HEADER_SECTION_PROPS: BentoDashboardTemplateHeader = { title: 'Section', infoIconTooltipText: 'Extra info about this section', }; const FILTERS_CONFIG: BentoFilterBarModel = [ { field: 'date-range', label: 'Date range', options: { allowTimeInput: true, numberOfMonths: 1, } as BentoDateRangeFilterOptions, type: BentoFilterItemType.DATE_RANGE, visible: true, }, { field: 'company', label: 'Company', options: { listboxItems: [ { label: 'Adyen', value: 'adyen' }, { label: 'Bento', value: 'bento' }, ], multiple: true, }, type: BentoFilterItemType.SELECT, visible: true, }, ]; const FILTER_VALUES: BentoFilterValues = [ { field: 'date-range', value: { startDate: subDays(new Date(), 7), endDate: new Date() }, }, { field: 'company', value: [], }, ]; const SEGMENTED_CONTROL_ITEMS = [ { label: 'Count', value: 'count' }, { label: 'Amount', value: 'amount' }, ]; const DROPDOWN_OPTIONS: BentoListboxOptions = [ { label: 'Monthly', value: 'monthly' }, { label: 'Yearly', value: 'yearly' }, ]; const LUME_DATA = { data: [ { label: 'Skyblue', color: 'skyblue', values: [10, 30, 20, 50, 40], }, { label: 'Green', color: 'green', values: [50, 60, 90, 30, 10], }, ], labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], options: { yAxisOptions: { gridLines: true, title: 'Y-label', }, }, }; const GRID_DATA = [ { id: 1, paymentMethods: 'Visa', amount: '1,234 USD', numeric: '54,213' }, { id: 2, paymentMethods: 'MasterCard', amount: '1,234 USD', numeric: '54,213' }, { id: 3, paymentMethods: 'iDeal', amount: '1,234 USD', numeric: '54,213' }, { id: 4, paymentMethods: 'Klarna', amount: '1,234 USD', numeric: '54,213' }, { id: 5, paymentMethods: 'Apple Pay', amount: '1,234 USD', numeric: '54,213' }, ]; const GRID_COLUMNS = [ { field: 'paymentMethods', label: 'Payment methods', minWidth: 300, mandatory: true }, { field: 'amount', label: 'Amount', numeric: true, minWidth: 300 }, { field: 'numeric', label: 'Numeric', numeric: true, minWidth: 300 }, ]; const DEFAULT_PROPS = { header: HEADER_PROPS, tabs: TABS_ARGS, stickyFilters: true, stickyTabs: true, }; const defaultCode = ` <template> <bento-dashboard-template :header="header" sticky-filters> <template #filters> <bento-filter-bar :config="filterConfig" :filter-values="filterValues" @update:filter-values="filterValues = $event" /> </template> <bento-summary-grid> <template #cell-1-1> <bento-summary-grid-item-amount title="Title" label="€ 220.00" /> </template> <template #cell-1-2> <bento-summary-grid-item-amount title="Title" label="€ 220.00" /> </template> <template #cell-1-3> <bento-summary-grid-item-amount title="Title" label="€ 220.00" /> </template> </bento-summary-grid> <bento-dashboard-section :header="dashboardSectionHeader" half-width> <template #controls> <bento-dropdown :model-value="dropdownValue1" @update:model-value="dropdownValue1 = $event" :items='dropdownOptions' /> <bento-segmented-control :items="segmentedControlItems" :model-value="segmentedControlValue1" @update:model-value="segmentedControlValue1 = $event"/> </template> <lume-line-chart v-bind="lumeData" /> <lume-line-chart v-bind="lumeData" /> </bento-dashboard-section> <bento-dashboard-section :header="dashboardSectionHeader" half-width> <template #controls> <bento-dropdown :model-value="dropdownValue2" @update:model-value="dropdownValue2 = $event" :items='dropdownOptions' /> <bento-segmented-control :items="segmentedControlItems" :model-value="segmentedControlValue2" @update:model-value="segmentedControlValue2 = $event"/> </template> <lume-line-chart v-bind="lumeData" /> <lume-line-chart v-bind="lumeData" /> </bento-dashboard-section> <bento-dashboard-section :header="dashboardSectionHeader"> <lume-line-chart v-bind="lumeData" /> </bento-dashboard-section> <bento-dashboard-section :header="dashboardSectionHeader"> <bento-data-grid :data="gridData" :columns="gridColumns" /> </bento-dashboard-section> </bento-dashboard-template> </template> <script setup lang="ts"> import { BentoDashboardTemplate, BentoDashboardSection, BentoFilterBar, BentoFilterValues, BentoSummaryGrid, BentoSummaryGridItemAmount, BentoDropdown, BentoSegmentedControl, BentoDataGrid } from '@adyen/bento-vue2' import { LumeLineChart } from '@adyen/lume'; import InfoIcon from '@adyen/ui-assets-icons-16/vue/info'; import Settings from '@adyen/ui-assets-icons-16/vue/settings'; import Download from '@adyen/ui-assets-icons-16/vue/download'; const header = { title: 'Dashboard', lastUpdated: Date.now(), actions: [ { title: 'Glossary', variant: 'secondary', event: () => {}, icon: InfoIcon }, { title: 'Settings', variant: 'secondary', event: () => {}, icon: Settings }, { title: 'Download', variant: 'secondary', event: () => {}, icon: Download }, { title: 'Share', variant: 'secondary', event: () => {}, icon: Share }, ], infoIconTooltipText: 'Info', }; const filterConfig = ${JSON.stringify(FILTERS_CONFIG, null, 4)}; const dashboardSectionHeader = ${JSON.stringify(HEADER_SECTION_PROPS, null, 4)}; const dropdownOptions = ${JSON.stringify(DROPDOWN_OPTIONS, null, 4)}; const segmentedControlItems = ${JSON.stringify(SEGMENTED_CONTROL_ITEMS, null, 4)}; const lumeData = ${JSON.stringify(LUME_DATA, null, 4)}; const filterValues = ref<BentoFilterValues>([ { field: 'date-range', value: { startDate: subDays(new Date(), 7), endDate: new Date() }, }, { field: 'company', value: [], }, ]); const gridData = ${JSON.stringify(GRID_DATA, null, 4)}; const gridColumns = ${JSON.stringify(GRID_COLUMNS, null, 4)}; const segmentedControlValue1 = ref('count'); const dropdownValue1 = ref('monthly'); const segmentedControlValue2 = ref('count'); const dropdownValue2 = ref('monthly'); </script> `; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoDashboardTemplate, BentoDashboardSection, BentoFilterBar, BentoSummaryGrid, BentoSummaryGridItemAmount, BentoDropdown, BentoSegmentedControl, BentoDataGrid, LumeLineChart, }, props: Object.keys(argTypes), template: ` <bento-dashboard-template v-bind="args"> <template #filters> <bento-filter-bar :config="FILTERS_CONFIG" :filter-values="filterValues" @update:filter-values="filterValues = $event" /> </template> <bento-summary-grid> <template #cell-1-1> <bento-summary-grid-item-amount title="Title" label="€ 220.00" /> </template> <template #cell-1-2> <bento-summary-grid-item-amount title="Title" label="€ 220.00" /> </template> <template #cell-1-3> <bento-summary-grid-item-amount title="Title" label="€ 220.00" /> </template> </bento-summary-grid> <bento-dashboard-section :header="HEADER_SECTION_PROPS" half-width> <template #controls> <bento-dropdown :model-value="dropdownValue1" @update:model-value="dropdownValue1 = $event" :items='DROPDOWN_OPTIONS' /> <bento-segmented-control :items="SEGMENTED_CONTROL_ITEMS" :model-value="segmentedControlValue1" @update:model-value="segmentedControlValue1 = $event"/> </template> <lume-line-chart v-bind="LUME_DATA" /> <lume-line-chart v-bind="LUME_DATA" /> </bento-dashboard-section> <bento-dashboard-section :header="HEADER_SECTION_PROPS" half-width> <template #controls> <bento-dropdown :model-value="dropdownValue2" @update:model-value="dropdownValue2 = $event" :items='DROPDOWN_OPTIONS' /> <bento-segmented-control :items="SEGMENTED_CONTROL_ITEMS" :model-value="segmentedControlValue2" @update:model-value="segmentedControlValue2 = $event"/> </template> <lume-line-chart v-bind="LUME_DATA" /> <lume-line-chart v-bind="LUME_DATA" /> </bento-dashboard-section> <bento-dashboard-section :header="HEADER_SECTION_PROPS"> <lume-line-chart v-bind="LUME_DATA" /> </bento-dashboard-section> <bento-dashboard-section :header="HEADER_SECTION_PROPS"> <bento-data-grid :data="GRID_DATA" :columns="GRID_COLUMNS" /> </bento-dashboard-section> </bento-dashboard-template> `, setup(props) { const args = isVue2 ? props : _args; const filterValues = ref<BentoFilterValues>(FILTER_VALUES); const segmentedControlValue1 = ref(SEGMENTED_CONTROL_ITEMS[0].value); const dropdownValue1 = ref(DROPDOWN_OPTIONS[0].value); const segmentedControlValue2 = ref(SEGMENTED_CONTROL_ITEMS[0].value); const dropdownValue2 = ref(DROPDOWN_OPTIONS[0].value); return { args, // Values filterValues, segmentedControlValue1, dropdownValue1, segmentedControlValue2, dropdownValue2, // Constants HEADER_SECTION_PROPS, FILTERS_CONFIG, DROPDOWN_OPTIONS, SEGMENTED_CONTROL_ITEMS, LUME_DATA, GRID_DATA, GRID_COLUMNS, }; }, }), args: DEFAULT_PROPS, parameters: storybookDocsParameter(defaultCode), }; const withTabsCode = ` <template> <bento-dashboard-template :header="header" :tabs="tabs" sticky-filters sticky-tabs> <template #filters> <bento-filter-bar :config="filterConfig" :filter-values="filterValues" @update:filter-values="filterValues = $event" /> </template> <template #tab-1> <bento-dashboard-section :header="dashboardSectionHeader"> <template #controls> <bento-dropdown :model-value="dropdownValue1" @update:model-value="dropdownValue1 = $event" :items='dropdownOptions' /> <bento-segmented-control :items="segmentedControlItems" :model-value="segmentedControlValue1" @update:model-value="segmentedControlValue1 = $event"/> </template> <template #content-col-1> <lume-line-chart v-bind="lumeData" /> <lume-line-chart v-bind="lumeData" /> </template> <template #content-col-2> <lume-line-chart v-bind="lumeData" /> <lume-line-chart v-bind="lumeData" /> </template> </bento-dashboard-section> </template> <template #tab-2> <bento-dashboard-section :header="dashboardSectionHeader"> <template #controls> <bento-dropdown :model-value="dropdownValue2" @update:model-value="dropdownValue2 = $event" :items='dropdownOptions' /> <bento-segmented-control :items="segmentedControlItems" :model-value="segmentedControlValue2" @update:model-value="segmentedControlValue2 = $event"/> </template> <template #content-col-1><lume-line-chart v-bind="lumeData" /></template> <template #content-col-2><lume-line-chart v-bind="lumeData" /></template> </bento-dashboard-section> </template> </bento-dashboard-template> </template> <script setup lang="ts"> import { BentoDashboardTemplate, BentoDashboardSection, BentoFilterBar, BentoFilterValues, BentoDropdown, BentoSegmentedControl } from '@adyen/bento-vue2' import { LumeLineChart } from '@adyen/lume'; import InfoIcon from '@adyen/ui-assets-icons-16/vue/info'; import Settings from '@adyen/ui-assets-icons-16/vue/settings'; import Download from '@adyen/ui-assets-icons-16/vue/download'; const header = { title: 'Dashboard', lastUpdated: Date.now(), actions: [ { title: 'Glossary', variant: 'secondary', event: () => {}, icon: InfoIcon }, { title: 'Settings', variant: 'secondary', event: () => {}, icon: Settings }, { title: 'Download', variant: 'secondary', event: () => {}, icon: Download }, { title: 'Share', variant: 'secondary', event: () => {}, icon: Share }, ], infoIconTooltipText: 'Info', }; const tabs = ${JSON.stringify(TABS_ARGS, null, 4)}; const filterConfig = ${JSON.stringify(FILTERS_CONFIG, null, 4)}; const dashboardSectionHeader = ${JSON.stringify(HEADER_SECTION_PROPS, null, 4)}; const dropdownOptions = ${JSON.stringify(DROPDOWN_OPTIONS, null, 4)}; const segmentedControlItems = ${JSON.stringify(SEGMENTED_CONTROL_ITEMS, null, 4)}; const lumeData = ${JSON.stringify(LUME_DATA, null, 4)}; const filterValues = ref<BentoFilterValues>([ { field: 'date-range', value: { startDate: subDays(new Date(), 7), endDate: new Date() }, }, { field: 'company', value: [], }, ]); const segmentedControlValue1 = ref('count'); const dropdownValue1 = ref('monthly'); const segmentedControlValue2 = ref('count'); const dropdownValue2 = ref('monthly'); </script> `; export const WithTabs: Story = { render: (_args, { argTypes }) => ({ components: { BentoDashboardTemplate, BentoDashboardSection, BentoFilterBar, BentoDropdown, BentoSegmentedControl, LumeLineChart, }, props: Object.keys(argTypes), template: ` <bento-dashboard-template v-bind="args"> <template #filters> <bento-filter-bar :config="FILTERS_CONFIG" :filter-values="filterValues" @update:filter-values="filterValues = $event" /> </template> <template #tab-1> <bento-dashboard-section :header="HEADER_SECTION_PROPS"> <template #controls> <bento-dropdown :model-value="dropdownValue" @update:model-value="dropdownValue = $event" :items='DROPDOWN_OPTIONS' /> <bento-segmented-control :items="SEGMENTED_CONTROL_ITEMS" :model-value="segmentedControlValue" @update:model-value="segmentedControlValue = $event"/> </template> <template #content-col-1> <lume-line-chart v-bind="LUME_DATA" /> <lume-line-chart v-bind="LUME_DATA" /> </template> <template #content-col-2> <lume-line-chart v-bind="LUME_DATA" /> <lume-line-chart v-bind="LUME_DATA" /> </template> </bento-dashboard-section> </template> <template #tab-2> <bento-dashboard-section :header="HEADER_SECTION_PROPS"> <template #controls> <bento-dropdown :model-value="dropdownValue" @update:model-value="dropdownValue = $event" :items='DROPDOWN_OPTIONS' /> <bento-segmented-control :items="SEGMENTED_CONTROL_ITEMS" :model-value="segmentedControlValue" @update:model-value="segmentedControlValue = $event"/> </template> <template #content-col-1><lume-line-chart v-bind="LUME_DATA" /></template> <template #content-col-2><lume-line-chart v-bind="LUME_DATA" /></template> </bento-dashboard-section> </template> </bento-dashboard-template> `, setup(props) { const args = isVue2 ? props : _args; const filterValues = ref<BentoFilterValues>(FILTER_VALUES); const segmentedControlValue = ref(SEGMENTED_CONTROL_ITEMS[0].value); const dropdownValue = ref(DROPDOWN_OPTIONS[0].value); return { args, // Values filterValues, segmentedControlValue, dropdownValue, // Constants HEADER_SECTION_PROPS, FILTERS_CONFIG, SEGMENTED_CONTROL_ITEMS, DROPDOWN_OPTIONS, LUME_DATA, }; }, }), args: DEFAULT_PROPS, parameters: storybookDocsParameter(withTabsCode), }; const halfWidthCode = ` <template> <bento-dashboard-template :header="header"> <bento-dashboard-section :header="{ title: 'Section 1'}" half-width> <template #controls> <bento-segmented-control :items="segmentedControlItems" :model-value="segmentedControlValue" @update:model-value="segmentedControlValue = $event"/> </template> <lume-line-chart v-bind="lumeData" /> </bento-dashboard-section> <bento-dashboard-section :header="{ title: 'Section 2'}" half-width> <template #controls> <bento-dropdown :model-value="dropdownValue" @update:model-value="dropdownValue = $event" :items='dropdownOptions' /> </template> <lume-line-chart v-bind="lumeData" /> </bento-dashboard-section> </bento-dashboard-template> </template> <script setup lang="ts"> import { BentoDashboardTemplate, BentoDashboardSection, BentoDropdown, BentoSegmentedControl, } from '@adyen/bento-vue2' import { LumeLineChart } from '@adyen/lume'; import InfoIcon from '@adyen/ui-assets-icons-16/vue/info'; import Settings from '@adyen/ui-assets-icons-16/vue/settings'; import Download from '@adyen/ui-assets-icons-16/vue/download'; const header = { title: 'Dashboard', lastUpdated: Date.now(), actions: [ { title: 'Glossary', variant: 'secondary', event: () => {}, icon: InfoIcon }, { title: 'Settings', variant: 'secondary', event: () => {}, icon: Settings }, { title: 'Download', variant: 'secondary', event: () => {}, icon: Download }, { title: 'Share', variant: 'secondary', event: () => {}, icon: Share }, ], infoIconTooltipText: 'Info', }; const dropdownOptions = ${JSON.stringify(DROPDOWN_OPTIONS, null, 4)}; const segmentedControlItems = ${JSON.stringify(SEGMENTED_CONTROL_ITEMS, null, 4)}; const lumeData = ${JSON.stringify(LUME_DATA, null, 4)}; const segmentedControlValue = ref('count'); const dropdownValue = ref('monthly'); </script> `; export const HalfWidth: Story = { render: (_args, { argTypes }) => ({ components: { BentoDashboardTemplate, BentoDashboardSection, BentoDropdown, BentoSegmentedControl, LumeLineChart, }, props: Object.keys(argTypes), template: ` <bento-dashboard-template v-bind="args"> <bento-dashboard-section :header="{ title: 'Section 1' }" half-width> <template #controls> <bento-segmented-control :items="SEGMENTED_CONTROL_ITEMS" :model-value="segmentedControlValue" @update:model-value="segmentedControlValue = $event"/> </template> <lume-line-chart v-bind="LUME_DATA" /> </bento-dashboard-section> <bento-dashboard-section :header="{ title: 'Section 2' }" half-width> <template #controls> <bento-dropdown :model-value="dropdownValue" @update:model-value="dropdownValue = $event" :items='DROPDOWN_OPTIONS' /> </template> <lume-line-chart v-bind="LUME_DATA" /> </bento-dashboard-section> </bento-dashboard-template> `, setup(props) { const segmentedControlValue = ref(SEGMENTED_CONTROL_ITEMS[0].value); const dropdownValue = ref(DROPDOWN_OPTIONS[0].value); return { // Values args: isVue2 ? props : _args, segmentedControlValue, dropdownValue, // Contants LUME_DATA, SEGMENTED_CONTROL_ITEMS, DROPDOWN_OPTIONS, }; }, }), args: DEFAULT_PROPS, parameters: storybookDocsParameter(halfWidthCode), };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<template> <main class="b-dashboard-template"> <bento-header v-bind="header" variant="page" class="b-dashboard-template__header"> <template v-if="hasSlot('infoIconTooltipContent')" #infoIconTooltipContent> <slot name="infoIconTooltipContent" /> </template> </bento-header> <div class="b-dashboard-template__top-section" :class="dashboardTopSectionConditionalClasses"> <div v-if="hasSlot('filters')" ref="filtersRef" class="b-dashboard-template__filters" :class="dashboardFiltersConditionalClasses" data-testid="filters" > <slot name="filters" /> </div> <bento-tabs v-if="tabsSlots.length > 1" ref="tabsRef" :active-tab-index="tabs.activeTabIndex" :sticky="stickyTabs" :sticky-options="computedTabsOptions" data-testid="tabs" > <bento-tab v-for="(_item, index) in tabsSlots" :key="`tab-${index}`" :title="getTabTitle(index)"> <div class="b-dashboard-template__container b-dashboard-template__container--tabs"> <slot :name="`tab-${index + 1}`" /> </div> </bento-tab> </bento-tabs> <div v-else class="b-dashboard-template__container"> <slot /> </div> </div> </main> </template> <script setup lang="ts"> import { computed, onUnmounted, ref, useSlots, watch } from 'vue'; import { BentoHeader } from '@/components/header'; import { BentoTab, BentoTabs } from '@/components/tabs'; import { useWindowScroll } from '@vueuse/core'; import { observeSizeOfElement } from '@/utils/ts/resize'; import { useHasSlot } from '@/composables'; import type { BentoDashboardTemplateHeader, BentoDashboardTemplateTabs } from './dashboard-template.types'; const props = withDefaults( defineProps<{ /** * The header that goes to the top of the template */ header: BentoDashboardTemplateHeader; /** * All the tab properties that can be set on the inner tab components. * - tabs.activeTabIndex: the currently active tab index. * - tabs.tabs: an array of BentoTab props, the first item in the array will affect the `tab-1` slot and so on. */ tabs?: BentoDashboardTemplateTabs; /** * Renders the tabs with a sticky positioning */ stickyTabs?: boolean; /** * Renders the tabs with a sticky positioning */ stickyFilters?: boolean; }>(), { tabs: undefined, stickyTabs: false, stickyFilters: false, } ); const slots = useSlots(); const hasSlot = useHasSlot(slots); const tabsRef = ref<InstanceType<typeof BentoTabs>>(); const filtersRef = ref<HTMLDivElement>(null); const isFiltersPinned = ref(false); let filtersElementObserver: ResizeObserver | null = null; const tabsPosition = ref(0); const hasStickyFilters = computed(() => filtersRef.value && props.stickyFilters); const hasStickyTabs = computed(() => tabsRef.value && props.stickyTabs); const dashboardFiltersConditionalClasses = computed(() => ({ 'b-dashboard-template__filters--sticky': props.stickyFilters, 'b-dashboard-template__filters--show-border': hasStickyFilters.value && !hasStickyTabs.value && isFiltersPinned.value, })); const dashboardTopSectionConditionalClasses = computed(() => ({ 'b-dashboard-template__top-section--sticky': props.stickyTabs || props.stickyFilters, })); const tabsSlots = computed(() => Object.keys(slots).filter(el => el?.includes('tab-'))); const getTabTitle = (index: number) => props?.tabs.tabs?.[index]?.title ?? `Tab ${index + 1}`; const computedTabsOptions = computed(() => (tabsPosition.value ? { top: tabsPosition.value } : undefined)); const { y } = useWindowScroll(); watch( () => filtersRef.value, () => { if (!filtersElementObserver && filtersRef.value) { filtersElementObserver = observeSizeOfElement(filtersRef.value, () => { if (filtersRef.value && hasStickyTabs.value) { const filtersHeight = filtersRef.value.offsetHeight; tabsPosition.value = hasStickyFilters.value ? filtersHeight : 0; } }); } } ); watch( () => y.value, () => { if (hasStickyFilters.value) { isFiltersPinned.value = filtersRef.value?.getBoundingClientRect().top === 0; } } ); onUnmounted(() => { filtersElementObserver?.disconnect(); }); </script> <script lang="ts"> /** * Dashboard template is a full page template used to visualize data on pages such as data dashboards and reports. * * @example * import { BentoDashboardTemplate, BentoDashboardSection } from '@adyen/bento-vue2'; * * export default { * components: { BentoDashboardTemplate, BentoDashboardSection }, * template: ` * <bento-dashboard-template :header="{ title: 'Dashboard'}" :tabs="tabs: [{ title: 'Tab 1' }, { title: 'Tab 2' }]" sticky-tabs sticky-filters> * <template #tab-1> * <bento-dashboard-section :header="{ title: 'Section'}"> * <template #controls> * // Add your controls here * </template> * // Add your content here * </bento-dashboard-section> * </template> * <template #tab-2> * <bento-dashboard-section :header="{ title: 'Section'}"> * // Add your content here * </bento-dashboard-section> * </template> * </bento-dashboard-template> * ` * } */ export default {}; </script> <style lang="scss" scoped src="./dashboard-template.scss" />
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Canvas, Meta } from '@storybook/blocks';
|
|
2
|
+
import * as DataGridTemplateStories from './data-grid-template.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={DataGridTemplateStories} />
|
|
5
|
+
|
|
6
|
+
# Data Grid Template
|
|
7
|
+
|
|
8
|
+
The data grid template is a restrictive, full-page data grid used to display information from a data set. This data grid
|
|
9
|
+
template shouldn't be confused with the data grid.
|
|
10
|
+
|
|
11
|
+
**Important:** since this is a full-page template, it is important that the container it's inserted in allows the
|
|
12
|
+
template to expand to full width and height. E.g. `html` and `body` need to be 100% height.
|
|
13
|
+
|
|
14
|
+
<Canvas of={DataGridTemplateStories.Default} />
|
|
15
|
+
|
|
16
|
+
## Use Cases
|
|
17
|
+
|
|
18
|
+
You can use a `bento-data-grid-template` when your user needs:
|
|
19
|
+
|
|
20
|
+
- a clear overview of data
|
|
21
|
+
- a way of organizing and analyzing the data in their own way
|
|
22
|
+
|
|
23
|
+
## Overview of elements
|
|
24
|
+
|
|
25
|
+
### Header
|
|
26
|
+
|
|
27
|
+
The header provides a title and optional actions for the page. You can provide a header in two ways:
|
|
28
|
+
|
|
29
|
+
1. **Using the `header` prop:** Pass a configuration object to the `header` prop. This will render a default
|
|
30
|
+
`<bento-header>` component. This is the simplest method and is suitable for most use cases.
|
|
31
|
+
|
|
32
|
+
2. **Using the `#header` slot:** For more complex scenarios, such as when you need to use a different header component
|
|
33
|
+
like `<bento-header-with-views>`, you can use the `#header` slot. This will override the default header and give you
|
|
34
|
+
full control over the header's content and layout. The `header` prop is not required in this case.
|
|
35
|
+
|
|
36
|
+
Below is an example of using the `#header` slot to include a header with view-switching capabilities.
|
|
37
|
+
|
|
38
|
+
<Canvas of={DataGridTemplateStories.withHeaderWithViews} />
|
|
39
|
+
|
|
40
|
+
### Additional content
|
|
41
|
+
|
|
42
|
+
Any additional content that needs to be displayed on the page can be passed via the `additionalContent` slot. This slot
|
|
43
|
+
will be rendered between the header and the tabs.
|
|
44
|
+
|
|
45
|
+
### Tabs
|
|
46
|
+
|
|
47
|
+
When present, tabs are used to navigate between different data grids within a page. Note that each tab can contain one
|
|
48
|
+
data grid only.
|
|
49
|
+
|
|
50
|
+
The option to pass only one data grid to the `bento-data-grid-template` without rendering tabs is possible through the
|
|
51
|
+
`default` slot.
|
|
52
|
+
|
|
53
|
+
<Canvas of={DataGridTemplateStories.singularDataGrid} />
|
|
54
|
+
|
|
55
|
+
### Inspector
|
|
56
|
+
|
|
57
|
+
The `bento-data-grid-template` features an integrated inspector panel for displaying detailed information. You can
|
|
58
|
+
configure and control its behavior by passing props through the main inspector object. The panel inherits most of its
|
|
59
|
+
functionality directly from the `bento-inspector` component.
|
|
60
|
+
|
|
61
|
+
For accessibility, the `bento-inspector` includes built-in focus management. It is designed to handle cases where the
|
|
62
|
+
element that triggers the inspector might be removed from the Document Object Model (DOM), such as with a `v-if`
|
|
63
|
+
condition. However, if this default behavior is not suitable for your specific use case and leads to unexpected focus
|
|
64
|
+
loss when the inspector closes, you can override it.
|
|
65
|
+
|
|
66
|
+
To ensure focus returns to a predictable and stable location, pass a focusable parent element (e.g.,
|
|
67
|
+
`[role="grid-cell"]`) to the pageFocusAnchor prop within the inspector object. This ensures that even if the original
|
|
68
|
+
trigger element is no longer visible, the user's focus returns to the correct context, preventing a disorienting
|
|
69
|
+
experience.
|
|
70
|
+
|
|
71
|
+
<Canvas of={DataGridTemplateStories.withInspector} />
|
|
72
|
+
|
|
73
|
+
### Data grid
|
|
74
|
+
|
|
75
|
+
All rendered data grids are passed via slots and thus support all props and attributes already supported by the
|
|
76
|
+
`bento-data-grid`. For more information, consult the `bento-data-grid` documentation.
|
|
77
|
+
|
|
78
|
+
Every data grid in the `bento-data-grid-template` renders with a sticky pagination, whenever the pagination prop is
|
|
79
|
+
passed.
|
|
80
|
+
|
|
81
|
+
## Variations
|
|
82
|
+
|
|
83
|
+
### Sticky additional content
|
|
84
|
+
|
|
85
|
+
The additonal content in the `bento-data-grid-template` can be made sticky by passing the `sticky-additional-content`
|
|
86
|
+
property.
|
|
87
|
+
|
|
88
|
+
### Sticky tabs
|
|
89
|
+
|
|
90
|
+
The `bento-data-grid-template` can be rendered with sticky tabs by passing the `sticky-tabs` property. These will sit
|
|
91
|
+
just above of the data grid sticky content.
|
|
92
|
+
|
|
93
|
+
## Accessibility
|
|
94
|
+
|
|
95
|
+
The `beto-data-grid-template` is assigned a `main` landmark role and is complementary to the header component since this
|
|
96
|
+
latter one renders an `h1` tag containing the page title.
|
|
97
|
+
|
|
98
|
+
### Keyboard interaction
|
|
99
|
+
|
|
100
|
+
All the sub-element parts of the data grid template are interactable with the keyboard and reachable through keyboard
|
|
101
|
+
navigation following the logical navigation flow of the page. A detailed list of keyboard interactions is provided in
|
|
102
|
+
the table below.
|
|
103
|
+
|
|
104
|
+
| Keyboard interaction | Output |
|
|
105
|
+
| -------------------- | ---------------------------------------------------- |
|
|
106
|
+
| `Tab` | Moves focus to the various sub-elements in the page. |
|
|
107
|
+
| `Arrow keys` | Navigate the items of a sub-element in the page. |
|
|
108
|
+
|
|
109
|
+
### Roles, states and properties
|
|
110
|
+
|
|
111
|
+
| ARIA attribute | is automatic? | fallback used | manual override |
|
|
112
|
+
| --------------- | ------------------------------------------------------------------------- | ------------- | --------------- |
|
|
113
|
+
| `main` HTML tag | Yes, it is the outer tag wrapping the whole `data-grid-template` content. | - | - |
|
|
114
|
+
|
|
115
|
+
## Resources
|
|
116
|
+
|
|
117
|
+
- [Figma link](https://www.figma.com/file/lJK6kNN3ClihuCl7ni7v1k/Bento---Templates?type=design&node-id=499-37908&mode=design&t=RR6YrceXtwOucsil-0)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { BentoButton } from '@/components/button'; import { BentoCountry, BentoCountryCode } from '@/components/country'; import { type BentoColumn, BentoDataGrid, type BentoDatagridData } from '@/components/data-grid'; import { type BentoFilterBarModel, BentoFilterItemType, type BentoFilterValues } from '@/components/filter-bar'; import { BentoHeaderWithViews, type BentoHeaderWithViewsItem } from '@/components/header-with-views'; import { type BentoInspectorProps } from '@/components/inspector'; import { BentoStatus } from '@/components/status'; import { BentoSummaryGrid, BentoSummaryGridItemAmount, BentoSummaryGridItemCustom } from '@/components/summary-grid'; import { BentoTypography } from '@/components/typography'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import type { Meta, StoryObj } from '@storybook/vue'; import { computed, onMounted, ref } from 'vue'; import { isVue2 } from 'vue-demi'; import DataGridTemplateWithHeaderWithViews from './__tests__/data-grid-template-with-header-with-views.vue?raw'; import './data-grid-template.stories.scss?module'; import { type BentoDataGridTemplateTabs } from './data-grid-template.types'; import BentoDataGridTemplate from './data-grid-template.vue'; const meta: Meta = { title: 'Data grid template', component: BentoDataGridTemplate, parameters: { layout: 'fullscreen', }, }; const HEADER_PROPS = { title: 'Payments', actions: [ { title: 'Primary action', event: () => undefined }, { title: 'Secondary action', event: () => undefined }, { title: 'Tetiary action', event: () => undefined }, ], infoIconTooltipText: 'Title Tooltip Text', }; const HEADER_PROPS_DOCS = { title: 'Payments', actions: [ { title: 'Primary action', event: () => undefined }, { title: 'Secondary action', event: () => undefined }, { title: 'Tetiary action', event: () => undefined }, ], infoIconTooltipText: 'Title Tooltip Text', }; const PAGINATION_DOCS = { description: 'datagrid navigation', hasNext: true, size: 10 }; const DEFAULT_COLUMNS: Array<BentoColumn> = [ { field: 'name', label: 'Name', minWidth: 300, mandatory: true }, { field: 'company', label: 'Reference', minWidth: 150 }, { field: 'payment', label: 'Payment', width: 200, minWidth: 150 }, ]; const DATA_GRID_1_DATA: BentoDatagridData = Array.from({ length: 50 }, (_, index) => ({ name: `Name ${index + 1}`, company: `Company ${index + 1}`, payment: `Payment ${index + 1}`, id: `${index + 1}`, })); const FILTERS: BentoFilterBarModel = [ { field: 'name', label: 'Name', type: BentoFilterItemType.INPUT, }, { field: 'company', label: 'Company', type: BentoFilterItemType.INPUT, }, ]; const FILTER_VALUES: BentoFilterValues = [ { field: 'company', value: 'Company 1', }, ]; const FILTERS_DOCS = `[ { field: 'name', label: 'Name', type: BentoFilterItemType.INPUT, }, { field: 'company', label: 'Company', type: BentoFilterItemType.INPUT, }, ]`; const FILTER_VALUES_DOCS = `[ { field: 'company', value: 'Company 1' }, ]`; const TABS_ARGS: BentoDataGridTemplateTabs = { tabs: [{ title: 'Data grid title 1' }, { title: 'Data grid title 2' }], }; const INSPECTOR_ARGS: BentoInspectorProps = { title: 'Title', size: 'large', isOpen: false, activePage: '', expandable: true, }; const DATA_GRID_1_ARGS = { data: DATA_GRID_1_DATA, columns: DEFAULT_COLUMNS, allowColumnDragAndDrop: false, pagination: {}, filterSearchTerm: '', highlightedRows: [DATA_GRID_1_DATA[0].id], selectable: true, selection: [DATA_GRID_1_DATA[2].id], }; const DATA_GRID_2_DATA: BentoDatagridData = Array.from({ length: 30 }, (_, index) => ({ name: `Name ${index + 1}`, company: `Company ${index + 1}`, payment: `Payment ${index + 1}`, })); const DATA_GRID_2_ARGS = { data: DATA_GRID_2_DATA, columns: DEFAULT_COLUMNS, allowColumnDragAndDrop: false, pagination: {}, }; export default meta; type Story = StoryObj<typeof BentoDataGridTemplate>; const defaultCode = ` <template> <bento-data-grid-template :header="header" :tabs="tabs" sticky-tabs> <template #tab-1> <bento-data-grid :columns="columns" :data="dataArray" :pagination.sync="pagination" @navigate="clickNavigate" /> </template> <template #tab-2> <bento-data-grid :columns="columns" :data="dataArray" :filter-search-term.sync="searchTerm" :filters="filtersConfig" :filter-values.sync="filterValues" :sort-by.sync="sortBy" /> </template> </bento-data-grid-template> </template> <script setup lang="ts"> import { BentoCountryCode, type BentoColumn, type BentoDatagridSortByColumn, type BentoDatagridDataItem, BentoDataGridTemplate, BentoDataGrid, type BentoDataGridTemplateHeader, type BentoDatagridPaginationProps, type BentoFilterBarModel, BentoFilterItemType, } from '@adyen/bento-vue2'; import messages from './messages.json'; const { t } = useI18n({ messages }); const header: BentoDataGridTemplateHeader = { title: 'Payments', actions: [ { title: 'Primary action', event: () => {} }, { title: 'Secondary action', event: () => {} }, { title: 'Tetiary action', event: () => {} }, ], infoIconTooltipText: 'Title Tooltip Text', }; const tabs: BentoDataGridTemplateTabs = { tabs: [{ title: 'Data grid title 1' }, { title: 'Data grid title 2' }], }; const columns = computed<BentoColumn[]>(() => [ { field: 'name', label: t('Name'), minWidth: 300, mandatory: true, frozen: true, autoWidth: true, sortable: true, }, { field: 'company', label: t('Reference') }, { field: 'payment', label: t('Payment'), width: 200, minWidth: 150 }, ]); const filtersConfig = computed<BentoFilterBarModel>(() => [ { field: 'company', label: t('Company'), type: BentoFilterItemType.INPUT, }, { field: 'countryCode', label: t('Country'), options: { listboxItems: [ { value: BentoCountryCode.NL, }, { value: BentoCountryCode.BE, }, ], variant: 'name', }, type: BentoFilterItemType.SELECT_COUNTRY, }, ]); // Watch this to keep track if the user filters data const filterValues = ref(); // Watch this to keep track if the user sorts data const sortBy = ref<BentoDatagridSortByColumn[]>([]); // Watch this to keep track if the user searches for data const searchTerm = ref(''); // Watch this to keep track if the user pages through the data const pagination = ref<BentoDatagridPaginationProps>({ description: 'datagrid 1 navigation', hasNext: true, size: 10 }); // This is a contrived example of the dataArray as this will normally be retried via an API const dataArray = ref<BentoDatagridDataItem[]>([ { id: '03c0a799-1ced-4017-aea3-0cebb0106335', name: 'Shepherd Kane', payment: 160405, company: 'VURBO', registered: '2023-06-30T13:56:09.498Z', tags: ['deserunt', 'et', 'esse'], reference: 'UnbQaUncf3eR1D8XUBqn_UnbQaUncf3eR1D8XUBqn_UnbQaUncf3eR1D8XUBqn', paymentStatus: 1, countryCode: BentoCountryCode.NL, }, { id: 'b6d4f1fd-b1f6-40a6-a443-f785c89604ef', name: 'Santos Palmer', payment: 163500, company: 'POLARAX', registered: '2023-04-28T13:11:09.498Z', tags: ['et', 'Lorem', 'sint'], reference: 'IxUZ9FsEPCZ9dFFPpI9C', paymentStatus: 2, countryCode: BentoCountryCode.BE, }, ]); </script> `; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoDataGrid, BentoDataGridTemplate, }, props: Object.keys(argTypes), template: ` <bento-data-grid-template v-bind="args"> <template #infoIconTooltipContent>Test</template> <template #tab-1><bento-data-grid v-bind="dataGrid1Props" :filters="filters" :filter-values.sync="filterValues" column-panel /></template> <template #tab-2><bento-data-grid v-bind="dataGrid2Props" /></template> <template #inspector-content>Hello</template> </bento-data-grid-template> `, setup(props) { const args = isVue2 ? props : _args; const filters = ref<BentoFilterBarModel>(args?.filters ?? FILTERS); const filterValues = ref<BentoFilterValues>(args?.filterValues ?? FILTER_VALUES); const dataGrid1Props = DATA_GRID_1_ARGS; const dataGrid2Props = DATA_GRID_2_ARGS; return { // Values args, dataGrid1Props, dataGrid2Props, filters, filterValues, }; }, }), args: { header: HEADER_PROPS, tabs: TABS_ARGS, inspector: INSPECTOR_ARGS, }, parameters: storybookDocsParameter(defaultCode), }; const additionalContentCode = ` <bento-data-grid-template :header="${JSON.stringify(HEADER_PROPS_DOCS)}" :tabs="${JSON.stringify( TABS_ARGS )}" sticky-tabs> <template #additionalContent> Your additional content/component here </template> <template #tab-1> <bento-data-grid :columns="${JSON.stringify(DEFAULT_COLUMNS)}" :data="dataArray" :pagination="${JSON.stringify(PAGINATION_DOCS)}" @navigate="clickNavigate" /> </template> <template #tab-2> <bento-data-grid :columns="${JSON.stringify(DEFAULT_COLUMNS)}" :data="dataArray" :filter-search-term.sync="searchTerm" :filters="${FILTERS_DOCS}" :filter-values.sync="${FILTER_VALUES_DOCS}" @filter-search-clear="onSearchCleared" @filter-search-input="onSearchInput" /> </template> </bento-data-grid-template> `; export const withAdditionalContent: Story = { render: (_args, { argTypes }) => ({ components: { BentoCountry, BentoDataGrid, BentoDataGridTemplate, BentoStatus, BentoSummaryGrid, BentoSummaryGridItemAmount, BentoSummaryGridItemCustom, }, props: Object.keys(argTypes), template: ` <bento-data-grid-template v-bind="args"> <template #additionalContent> <bento-summary-grid> <template #cell-1-1> <bento-summary-grid-item-custom title="Title" info-icon-tooltip-text="Text for icon" > <bento-status variant="green"> Status </bento-status> </bento-summary-grid-item-custom> </template> <template #cell-1-2> <bento-summary-grid-item-amount title="Title" label="€200.00" secondary-label="/ day" info-icon-tooltip-text="Text for icon" copy="Copy this to clipboard" /> </template> <template #cell-1-3> <bento-summary-grid-item-custom title="Title" info-icon-tooltip-text="Text for icon" > <bento-country :code="BentoCountryCode.NL" /> </bento-summary-grid-item-custom> </template> </bento-summary-grid> </template> <template #tab-1><bento-data-grid v-bind="dataGrid1Props" :filters="filters" :filter-values.sync="filterValues" /></template> <template #tab-2><bento-data-grid v-bind="dataGrid2Props" /></template> </bento-data-grid-template> `, setup(props) { const args = isVue2 ? props : _args; const filters = ref<BentoFilterBarModel>(args?.filters ?? FILTERS); const filterValues = ref<BentoFilterValues>(args?.filterValues ?? FILTER_VALUES); const dataGrid1Props = DATA_GRID_1_ARGS; const dataGrid2Props = DATA_GRID_2_ARGS; return { // Values args, dataGrid1Props, dataGrid2Props, filters, filterValues, // Enums BentoCountryCode, }; }, }), args: { header: HEADER_PROPS, tabs: TABS_ARGS, }, parameters: storybookDocsParameter(additionalContentCode), }; const singularDataGridCode = ` <bento-data-grid-template :header="${JSON.stringify(HEADER_PROPS)}" sticky-tabs> <bento-data-grid :columns="${JSON.stringify(DEFAULT_COLUMNS)}" :data="dataArray" :pagination="${JSON.stringify(PAGINATION_DOCS)}" @navigate="clickNavigate" :filter-search-term.sync="searchTerm" :filters="${FILTERS_DOCS}" :filter-values.sync="${FILTER_VALUES_DOCS}" @filter-search-clear="onSearchCleared" @filter-search-input="onSearchInput" /> </bento-data-grid-template> `; export const singularDataGrid: Story = { render: (_args, { argTypes }) => ({ components: { BentoDataGrid, BentoDataGridTemplate }, props: Object.keys(argTypes), template: ` <bento-data-grid-template v-bind="args"> <bento-data-grid v-bind="dataGridProps" :filters="filters" :filter-values.sync="filterValues" /> </bento-data-grid-template> `, setup(props) { const args = isVue2 ? props : _args; const filters = ref<BentoFilterBarModel>(args?.filters ?? FILTERS); const filterValues = ref<BentoFilterValues>(args?.filterValues ?? FILTER_VALUES); const dataGridProps = DATA_GRID_1_ARGS; return { // Values args, dataGridProps, filters, filterValues, }; }, }), args: { header: HEADER_PROPS, }, parameters: storybookDocsParameter(singularDataGridCode), }; const inspectorCode = ` <template> <bento-data-grid-template :header="header" :inspector="computedInspectorProps" @update:is-open:inspector="isInspectorOpen = $event" @update:active-page:inspector="inspectorActivePage = $event" > <template #default> <bento-data-grid :columns="columns" :data="dataArray" /> </template> <template #inspector-content> <div style="padding: 1rem;"> <bento-typography variant="title" el="h3"> Details for: {{ inspectorTitle }} </bento-typography> </div> </template> </bento-data-grid-template> </template> <script setup lang="ts"> import { ref, computed, onMounted } from 'vue'; import { BentoDataGridTemplate, BentoDataGrid, BentoTypography, } from '@adyen/bento-vue2'; import type { BentoDataGridTemplateHeader, BentoColumn, BentoDatagridDataItem } from '@adyen/bento-vue3'; const isInspectorOpen = ref(true); const inspectorTitle = ref('Shepherd Kane'); const inspectorActivePage = ref('id-1'); const pageFocusAnchorRef = ref<HTMLElement | null>(null); const dataArray = ref([ { id: '1', name: 'Shepherd Kane', company: 'Company 1', payment: 1604.05 }, { id: '2', name: 'Santos Palmer', company: 'Company 2', payment: 1635.00 }, ]); const openInspector = (item) => { inspectorTitle.value = item.name as string; isInspectorOpen.value = true; inspectorActivePage.value = item.id as string; const row = document.querySelector(\`[role="row"][aria-rowindex="\${item.rowIndex + 1}"]\`); pageFocusAnchorRef.value = row?.querySelector('[role="gridcell"]') as HTMLElement; }; const columns = computed<BentoColumn[]>(() => [ { field: 'name', label: 'Name', cellActions: [{ variant: 'open', event: openInspector }], }, { field: 'payment', label: 'Payment (€)', width: 200, }, ]); const header = ref<BentoDataGridTemplateHeader>({ title: 'Payments', infoIconTooltipText: 'Click the > icon on a row to open the inspector.', }); const computedInspectorProps = computed(() => ({ isOpen: isInspectorOpen.value, title: inspectorTitle.value, activePage: inspectorActivePage.value, pageFocusAnchor: pageFocusAnchorRef.value, })); <script> `; export const withInspector: Story = { render: (_args, { argTypes }) => ({ components: { BentoDataGrid, BentoDataGridTemplate, BentoTypography, BentoButton, }, props: Object.keys(argTypes), template: ` <bento-data-grid-template v-bind="args" :inspector="computedInspectorProps" @update:is-open:inspector="isInspectorOpen = $event" @update:active-page:inspector="inspectorActivePage = $event" > <template #default> <bento-data-grid v-bind="dataGridProps" :filters="dataGridFilters" :filter-values.sync="dataGridFilterValues" /> </template> <template #inspector-content> <bento-typography v-for="i in 10" :key="i" style="padding: 5px"> {{ inspectorContent }} </bento-typography> </template> </bento-data-grid-template> `, setup(props) { const args = isVue2 ? props : _args; const isInspectorOpen = ref(args.inspector.isOpen); const inspectorTitle = ref(args.inspector.title); const inspectorActivePage = ref(''); const dataGridFilters = ref<BentoFilterBarModel>(args?.filters ?? FILTERS); const dataGridFilterValues = ref<BentoFilterValues>(args?.filterValues ?? []); const inspectorContent = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; const cellWithActions = { ...DEFAULT_COLUMNS[0], cellActions: [{ variant: 'open', event: item => openInspector(item) }], } satisfies BentoColumn; const columnsWithActions: Array<BentoColumn> = [cellWithActions, ...DEFAULT_COLUMNS.slice(1, 2)]; const dataGridProps = { ...DATA_GRID_1_ARGS, columns: columnsWithActions }; const pageFocusAnchorRef = ref<HTMLElement | null>(null); // Find the element after the component has mounted in the browser onMounted(() => { pageFocusAnchorRef.value = document.body .querySelector('[role="row"][aria-rowindex="1"]') .querySelectorAll('[role="gridcell"]')[0] as HTMLElement; }); const openInspector = item => { inspectorTitle.value = item.name; isInspectorOpen.value = true; inspectorActivePage.value = item.name; pageFocusAnchorRef.value = document.body .querySelector(`[role="row"][aria-rowindex="${item.id}"]`) .querySelectorAll('[role="gridcell"]')[0] as HTMLElement; }; const computedInspectorProps = computed(() => ({ ...args.inspector, isOpen: isInspectorOpen.value, title: inspectorTitle.value, activePage: inspectorActivePage.value, pageFocusAnchor: pageFocusAnchorRef.value, })); return { args, dataGridProps, dataGridFilters, dataGridFilterValues, isInspectorOpen, inspectorActivePage, computedInspectorProps, inspectorContent, openInspector, }; }, }), args: { header: HEADER_PROPS, inspector: { title: DATA_GRID_1_DATA[0].name, isOpen: true, activePage: DATA_GRID_1_DATA[0].name, }, }, parameters: storybookDocsParameter(inspectorCode), }; export const withHeaderWithViews: Story = { render: (_args, { argTypes }) => ({ components: { BentoDataGrid, BentoDataGridTemplate, BentoHeaderWithViews, }, props: Object.keys(argTypes), template: ` <bento-data-grid-template v-bind="args"> <template #header> <bento-header-with-views :actions="headerActions" description="Description" title="Page Title" :hasChanges="false" skipUnsavedChangesText="Don’t show this message again" :views="headerViews" /> </template> <template #infoIconTooltipContent>Test</template> <template #tab-1><bento-data-grid v-bind="dataGrid1Props" :filters="filters" :filter-values.sync="filterValues" column-panel /></template> <template #tab-2><bento-data-grid v-bind="dataGrid2Props" /></template> <template #inspector-content>Hello</template> </bento-data-grid-template> `, setup(props) { const args = isVue2 ? props : _args; const filters = ref<BentoFilterBarModel>(args?.filters ?? FILTERS); const filterValues = ref<BentoFilterValues>(args?.filterValues ?? FILTER_VALUES); const dataGrid1Props = DATA_GRID_1_ARGS; const dataGrid2Props = DATA_GRID_2_ARGS; const headerViews: Array<BentoHeaderWithViewsItem> = [ { icon: 'stack', iconColor: 'primary', label: 'View 1', }, { icon: 'stack', iconColor: 'primary', label: 'View 2', }, ]; const headerActions = [ { title: 'Primary action', }, { title: 'Secondary action', }, ]; return { // Values args, dataGrid1Props, dataGrid2Props, filters, filterValues, headerActions, headerViews, }; }, }), args: { tabs: TABS_ARGS, inspector: INSPECTOR_ARGS, }, parameters: storybookDocsParameter(DataGridTemplateWithHeaderWithViews), };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<template> <main class="b-data-grid-template"> <bento-inspector v-bind="computedInspectorProps" ref="inspectorRef" v-on="inspectorEvents"> <template #page> <div class="b-data-grid-template__header"> <slot name="header"> <bento-header v-bind="header"> <template v-if="hasSlot('infoIconTooltipContent')" #infoIconTooltipContent> <slot name="infoIconTooltipContent" /> </template> </bento-header> </slot> </div> <div v-if="hasSlot('additionalContent')" ref="additionalContentRef" class="b-data-grid-template__additional-content" :class="additionalContentConditionalClasses" > <slot name="additionalContent" /> </div> <bento-tabs v-if="tabsSlots.length > 1" ref="tabsRef" :active-tab-index="tabs.activeTabIndex" :sticky="stickyTabs" :sticky-options="stickyAdditionalContent ? { top: computedStickyAdditionalContentHeight } : null" @update:active-tab-index="emitTabs" > <bento-tab v-for="(_item, index) in tabsSlots" :key="`tab-${index}`" :title="getTabTitle(index)"> <slot :name="`tab-${index + 1}`" /> </bento-tab> </bento-tabs> <slot v-else /> </template> <template #content> <slot name="inspector-content" /> </template> </bento-inspector> </main> </template> <script setup lang="ts"> import { BentoHeader } from '@/components/header'; import { BentoInspector } from '@/components/inspector'; import { BentoTab, BentoTabs } from '@/components/tabs'; import { useHasSlot } from '@/composables'; import { computed, type PropType, provide, type Ref, ref, toRef, type UnwrapRef, useSlots } from 'vue'; import { DATA_GRID_REGISTER_TEMPLATE_INJECTION_KEY } from './data-grid-template.keys'; import type { BentoDataGridTemplateDataGrid, BentoDataGridTemplateHeader, BentoDataGridTemplateInspector, BentoDataGridTemplateTabs, } from './data-grid-template.types'; const props = defineProps({ /** * The header that goes to the top of the template */ header: { type: Object as PropType<BentoDataGridTemplateHeader>, default: undefined, }, /** * All the tab properties that can be set on the inner tab components. * - tabs.activeTabIndex: the currenly active tab index. * - tabs.tabs: an array of BentoTab props, the first item in the array will affect the `tab-1` slot and so on. */ tabs: { type: Object as PropType<BentoDataGridTemplateTabs>, default: undefined, }, /** * Renders the additional content slot with a sticky positioning */ stickyAdditionalContent: { type: Boolean, default: false, }, /** * Renders the tabs with a sticky positioning */ stickyTabs: { type: Boolean, default: false, }, /** * All the inspector properties that can be set on the inner inspector component. */ inspector: { type: Object as PropType<BentoDataGridTemplateInspector>, default: undefined, }, }); const slots = useSlots(); const hasSlot = useHasSlot(slots); const emit = defineEmits<{ /** * Emits update event when activeTabIndex changes internally */ (e: 'update:tabs', value: BentoDataGridTemplateTabs): void; /** * Emits update event when the inspector's `isOpen` state changes */ (e: 'update:is-open:inspector', value: boolean): void; /** * Emits update event when the inspector's `activePage` changes */ (e: 'update:active-page:inspector', value: string): void; /** * Emits event when the inspector's expand button is clicked */ (e: 'expand:inspector', value: boolean): void; }>(); const tabsRef = ref(null); const additionalContentRef = ref(null); const inspectorRef = ref(null); const additionalContentConditionalClasses = computed(() => ({ 'b-data-grid-template__additional-content--sticky': props.stickyAdditionalContent, })); const computedInspectorProps = computed(() => ({ title: '', ...props.inspector, })); const computedStickyAdditionalContentHeight = computed(() => additionalContentRef?.value?.offsetHeight); const computedTabsRef = computed(() => tabsRef.value?.$refs?.tablistwrapper); const tabsSlots = computed(() => Object.keys(slots).filter(el => el?.includes('tab-'))); const inspectorEvents = computed(() => ({ 'update:is-open': (value: boolean) => emit('update:is-open:inspector', value), 'update:active-page': (value: string) => emit('update:active-page:inspector', value), expand: (value: boolean) => emit('expand:inspector', value), })); const emitTabs = (newActiveTabIndex: number) => { emit('update:tabs', { ...props.tabs, activeTabIndex: newActiveTabIndex }); }; const getTabTitle = (index: number) => props?.tabs.tabs?.[index]?.title ?? `Tab ${index + 1}`; const registerDatagridInDataGridTemplate: BentoDataGridTemplateDataGrid = () => { const isDataGridTemplate = true; const stickyTabs: Ref<boolean> = toRef(props, 'stickyTabs'); const stickyAdditionalContent: Ref<boolean> = toRef(props, 'stickyAdditionalContent'); const tabsRef: Ref<UnwrapRef<HTMLDivElement>> | null = computedTabsRef; const additionalContentSlotRef: Ref<UnwrapRef<HTMLDivElement>> | null = additionalContentRef; // return values to the Tab component return { isDataGridTemplate, stickyTabs, tabsRef, stickyAdditionalContent, additionalContentSlotRef, }; }; provide(DATA_GRID_REGISTER_TEMPLATE_INJECTION_KEY, registerDatagridInDataGridTemplate); </script> <script lang="ts"> /** * The data grid template is a restrictive, full-page data grid used to display information from a data set. * You can use this data grid template when your user needs a clear overview of data or a way of organizing and analyzing the data in their own way. * This data grid template shouldn’t be confused with the data grid. * * @example * import { BentoDataGridTemplate } from '@adyen/bento-vue2'; * * export default { * components: { BentoDataGridTemplate }, * template: ` * // If you want to display multiple data grids in the same page (they will be rendered in different tabs) * <bento-data-grid-template> * <template #tab-1><bento-data-grid v-bind="your-data-grid-args" title="Title for tab 1"/></template> * <template #tab-2><bento-data-grid v-bind="your-data-grid-args" title="Title for tab 2"/></template> * </bento-data-grid-template> * // Alternatively, if you only want to pass one data grid to your template: * <bento-data-grid-template> * <template #default><bento-data-grid v-bind="your-data-grid-args"/></template> * </bento-data-grid-template> * ` * } */ export default {}; </script> <style lang="scss" scoped src="./data-grid-template.scss" />
|