@adyen/bento-mcp 0.11.0 → 0.12.1
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 +36 -0
- package/README.md +24 -2
- package/SKILL.md +37 -7
- package/dist/assets/components/accordion/accordion.stories.ts +1 -1
- package/dist/assets/components/accordion/components/accordion-item.stories.ts +1 -1
- package/dist/assets/components/accordion/components/accordion-item.vue +1 -1
- package/dist/assets/components/action-bar/action-bar.docs.mdx +10 -3
- package/dist/assets/components/action-bar/action-bar.internal.types.ts +1 -0
- package/dist/assets/components/action-bar/action-bar.stories.ts +1 -1
- package/dist/assets/components/action-bar/action-bar.types.ts +1 -1
- package/dist/assets/components/action-bar/action-bar.vue +1 -1
- package/dist/assets/components/ai-tag/ai-tag.stories.ts +1 -1
- package/dist/assets/components/ai-tag/ai-tag.vue +1 -1
- package/dist/assets/components/alert/alert.stories.ts +1 -1
- package/dist/assets/components/alert/alert.types.ts +1 -1
- package/dist/assets/components/anchor-scroller/anchor-scroller.stories.ts +1 -1
- package/dist/assets/components/anchor-scroller/anchor-scroller.vue +1 -1
- package/dist/assets/components/avatar/avatar.internal.types.ts +1 -0
- package/dist/assets/components/avatar/avatar.stories.ts +1 -1
- package/dist/assets/components/avatar/avatar.types.ts +1 -1
- package/dist/assets/components/button/button.docs.mdx +4 -3
- package/dist/assets/components/button/button.stories.ts +1 -1
- package/dist/assets/components/button/button.types.ts +1 -1
- package/dist/assets/components/button/components/ai-button/ai-button.stories.ts +1 -1
- package/dist/assets/components/button/components/ai-button/ai-button.vue +1 -1
- package/dist/assets/components/button/components/button-actions/button-actions.docs.mdx +3 -0
- package/dist/assets/components/button/components/button-actions/button-actions.internal.types.ts +1 -0
- package/dist/assets/components/button/components/button-actions/button-actions.stories.ts +1 -1
- package/dist/assets/components/button/components/button-actions/button-actions.types.ts +1 -1
- package/dist/assets/components/button/components/button-actions/button-actions.vue +1 -1
- package/dist/assets/components/button/components/loading-button/loading-button.docs.mdx +26 -23
- package/dist/assets/components/button/components/loading-button/loading-button.stories.ts +1 -1
- package/dist/assets/components/button/components/loading-button/loading-button.vue +1 -1
- package/dist/assets/components/button/components/toggle-button/toggle-button.stories.ts +1 -1
- package/dist/assets/components/card/card.docs.mdx +18 -1
- package/dist/assets/components/card/card.stories.ts +1 -1
- package/dist/assets/components/card/card.types.ts +1 -1
- package/dist/assets/components/card/card.vue +1 -1
- package/dist/assets/components/checkbox/checkbox.stories.ts +1 -1
- package/dist/assets/components/checkbox/checkbox.types.ts +1 -1
- package/dist/assets/components/checkbox/checkbox.vue +1 -1
- package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.docs.mdx +9 -14
- package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.stories.ts +1 -1
- package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.types.ts +1 -1
- package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.vue +1 -1
- package/dist/assets/components/chip/chip.stories.ts +1 -1
- package/dist/assets/components/chip/chip.vue +1 -1
- package/dist/assets/components/click-outside/click-outside.stories.ts +1 -1
- package/dist/assets/components/code-snippet/code-snippet.types.ts +1 -1
- package/dist/assets/components/code-snippet/code-snippet.vue +1 -1
- package/dist/assets/components/country/country.stories.ts +1 -1
- package/dist/assets/components/country/country.types.ts +1 -1
- package/dist/assets/components/country/country.vue +1 -1
- package/dist/assets/components/currency/currency.stories.ts +1 -1
- package/dist/assets/components/currency/currency.vue +1 -1
- package/dist/assets/components/dashed-underline/dashed-underline.stories.ts +1 -1
- package/dist/assets/components/data-grid/components/data-grid-cell-actions/data-grid-cell-actions.types.ts +1 -1
- package/dist/assets/components/data-grid/components/data-grid-cell-actions/data-grid-cell-actions.vue +1 -1
- package/dist/assets/components/data-grid/components/data-grid-config-settings/data-grid-config-settings.vue +1 -1
- package/dist/assets/components/data-grid/components/data-grid-row/data-grid-row.vue +1 -1
- package/dist/assets/components/data-grid/components/data-grid-static-icon/data-grid-static-icon.stories.ts +1 -1
- package/dist/assets/components/data-grid/components/data-grid-summary-cell/data-grid-summary-cell.stories.ts +1 -1
- package/dist/assets/components/data-grid/components/data-grid-summary-cell/data-grid-summary-cell.vue +1 -1
- package/dist/assets/components/data-grid/components/data-grid-tag-with-text-cell/data-grid-tag-with-text-cell.stories.ts +1 -1
- package/dist/assets/components/data-grid/components/data-grid-trend-cell/data-grid-trend-cell.stories.ts +1 -1
- package/dist/assets/components/data-grid/components/data-grid-trend-cell/data-grid-trend-cell.vue +1 -1
- package/dist/assets/components/data-grid/data-grid.docs.mdx +14 -61
- package/dist/assets/components/data-grid/data-grid.stories.ts +1 -1
- package/dist/assets/components/data-grid/data-grid.vue +1 -1
- package/dist/assets/components/date/date.stories.ts +1 -1
- package/dist/assets/components/date-picker/date-picker.stories.ts +1 -1
- package/dist/assets/components/date-picker/date-picker.types.ts +1 -1
- package/dist/assets/components/date-picker/date-picker.vue +1 -1
- package/dist/assets/components/date-range-picker/components/date-range-picker-calendar/date-range-picker-calendar.vue +1 -1
- package/dist/assets/components/date-range-picker/components/date-time-input/date-time-input.types.ts +1 -1
- package/dist/assets/components/date-range-picker/components/date-time-input/date-time-input.vue +1 -1
- package/dist/assets/components/date-range-picker/date-range-picker.docs.mdx +31 -6
- package/dist/assets/components/date-range-picker/date-range-picker.stories.ts +1 -1
- package/dist/assets/components/date-range-picker/date-range-picker.types.ts +1 -1
- package/dist/assets/components/date-range-picker/date-range-picker.vue +1 -1
- package/dist/assets/components/date-time-picker/date-time-picker.stories.ts +1 -1
- package/dist/assets/components/date-time-picker/date-time-picker.types.ts +1 -1
- package/dist/assets/components/divider/divider.internal.types.ts +1 -0
- package/dist/assets/components/divider/divider.stories.ts +1 -1
- package/dist/assets/components/divider/divider.types.ts +1 -1
- package/dist/assets/components/divider/divider.vue +1 -1
- package/dist/assets/components/draggable/components/draggable-handle/draggable-handle.stories.ts +1 -1
- package/dist/assets/components/draggable/draggable.stories.ts +1 -1
- package/dist/assets/components/draggable/draggable.vue +1 -1
- package/dist/assets/components/drawer/drawer.stories.ts +1 -1
- package/dist/assets/components/dropdown/components/dropdown-base-textbox/dropdown-base-textbox.internal.types.ts +1 -0
- package/dist/assets/components/dropdown/components/dropdown-base-textbox/dropdown-base-textbox.types.ts +1 -1
- package/dist/assets/components/dropdown/components/dropdown-base-textbox/dropdown-base-textbox.vue +1 -1
- package/dist/assets/components/dropdown/components/dropdown-default-textbox/dropdown-default-textbox.vue +1 -1
- package/dist/assets/components/dropdown/components/dropdown-options-container/dropdown-options-container.vue +1 -1
- package/dist/assets/components/dropdown/components/dropdown-small-textbox/dropdown-small-textbox.vue +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.stories.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.types.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.vue +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.stories.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.types.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.vue +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.stories.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.types.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.vue +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.stories.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.types.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.vue +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.stories.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.types.ts +1 -1
- package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.vue +1 -1
- package/dist/assets/components/dropdown/dropdown.docs.mdx +4 -40
- package/dist/assets/components/dropdown/dropdown.internal.types.ts +1 -0
- package/dist/assets/components/dropdown/dropdown.stories.ts +1 -1
- package/dist/assets/components/dropdown/dropdown.types.ts +1 -1
- package/dist/assets/components/dropdown/dropdown.vue +1 -1
- package/dist/assets/components/empty-state/empty-state.stories.ts +1 -1
- package/dist/assets/components/empty-state/empty-state.types.ts +1 -1
- package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.stories.ts +1 -1
- package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.types.ts +1 -1
- package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.vue +1 -1
- package/dist/assets/components/file-uploader/components/file-uploader-restrictions/file-uploader-restrictions.types.ts +1 -1
- package/dist/assets/components/file-uploader/components/file-uploader-restrictions/file-uploader-restrictions.vue +1 -1
- package/dist/assets/components/file-uploader/file-uploader.internal.types.ts +1 -0
- package/dist/assets/components/file-uploader/file-uploader.stories.ts +1 -1
- package/dist/assets/components/file-uploader/file-uploader.types.ts +1 -1
- package/dist/assets/components/file-uploader/file-uploader.vue +1 -1
- package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.stories.ts +1 -1
- package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.types.ts +1 -1
- package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.vue +1 -1
- package/dist/assets/components/filter-bar/components/all-filters-modal/components/all-filters-modal-filter-selection/all-filters-modal-filter-selection.types.ts +1 -0
- package/dist/assets/components/filter-bar/components/all-filters-modal/components/all-filters-modal-filter-selection/all-filters-modal-filter-selection.vue +1 -0
- package/dist/assets/components/filter-bar/components/all-filters-modal/components/all-filters-modal-selected-filter/all-filters-modal-selected-filter.vue +1 -0
- package/dist/assets/components/filter-bar/components/base-filter/base-filter.internal.types.ts +1 -0
- package/dist/assets/components/filter-bar/components/base-filter/base-filter.types.ts +1 -1
- package/dist/assets/components/filter-bar/components/base-filter/base-filter.vue +1 -1
- package/dist/assets/components/filter-bar/components/boolean-filter/boolean-filter.vue +1 -1
- package/dist/assets/components/filter-bar/components/date-filter/date-filter.vue +1 -1
- package/dist/assets/components/filter-bar/components/date-range-filter/date-range-filter.vue +1 -1
- package/dist/assets/components/filter-bar/components/input-filter/input-filter.types.ts +1 -1
- package/dist/assets/components/filter-bar/components/input-filter/input-filter.vue +1 -1
- package/dist/assets/components/filter-bar/components/input-with-dropdown-filter/input-with-dropdown-filter.stories.ts +1 -1
- package/dist/assets/components/filter-bar/components/input-with-dropdown-filter/input-with-dropdown-filter.vue +1 -1
- package/dist/assets/components/filter-bar/components/select-filter/components/select-filter-button/select-filter-button.vue +1 -1
- package/dist/assets/components/filter-bar/components/select-filter/select-filter.vue +1 -1
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-avatar-filter/select-avatar-filter.stories.ts +1 -1
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-country-filter/select-country-filter.stories.ts +1 -1
- package/dist/assets/components/filter-bar/components/select-filter/variants/select-country-filter/select-country-filter.vue +1 -1
- package/dist/assets/components/filter-bar/components/toggle-filter/toggle-filter.vue +1 -1
- package/dist/assets/components/filter-bar/filter-bar.docs.mdx +4 -62
- package/dist/assets/components/filter-bar/filter-bar.stories.ts +1 -1
- package/dist/assets/components/filter-bar/filter-bar.types.ts +1 -1
- package/dist/assets/components/filter-bar/filter-bar.vue +1 -1
- package/dist/assets/components/form-layout/form-layout.docs.mdx +0 -23
- package/dist/assets/components/form-layout/form-layout.stories.ts +1 -1
- package/dist/assets/components/header/header.stories.ts +1 -1
- package/dist/assets/components/header/header.types.ts +1 -1
- package/dist/assets/components/header/header.vue +1 -1
- package/dist/assets/components/header-with-views/components/header-with-views-all-views/header-with-views-all-views.vue +1 -1
- package/dist/assets/components/header-with-views/components/header-with-views-item-edit-form/header-with-views-edit-form.types.ts +1 -1
- package/dist/assets/components/header-with-views/components/header-with-views-item-edit-form/header-with-views-edit-form.vue +1 -1
- package/dist/assets/components/header-with-views/header-with-views.internal.types.ts +1 -0
- package/dist/assets/components/header-with-views/header-with-views.stories.ts +1 -1
- package/dist/assets/components/header-with-views/header-with-views.types.ts +1 -1
- package/dist/assets/components/header-with-views/header-with-views.vue +1 -1
- package/dist/assets/components/image/image.stories.ts +1 -1
- package/dist/assets/components/info-icon/info-icon.stories.ts +1 -1
- package/dist/assets/components/input-field/input-field.docs.mdx +1 -13
- package/dist/assets/components/input-field/input-field.stories.ts +1 -1
- package/dist/assets/components/input-field/input-field.types.ts +1 -1
- package/dist/assets/components/input-field/input-field.vue +1 -1
- package/dist/assets/components/input-field-password/input-field-password.internal.types.ts +1 -0
- package/dist/assets/components/input-field-password/input-field-password.stories.ts +1 -1
- package/dist/assets/components/input-field-password/input-field-password.types.ts +1 -1
- package/dist/assets/components/input-field-password/input-field-password.vue +1 -1
- package/dist/assets/components/input-field-phone-number/input-field-phone-number.stories.ts +1 -1
- package/dist/assets/components/input-field-phone-number/input-field-phone-number.types.ts +1 -1
- package/dist/assets/components/input-field-phone-number/input-field-phone-number.vue +1 -1
- package/dist/assets/components/input-time/input-time.docs.mdx +17 -0
- package/dist/assets/components/input-time/input-time.stories.ts +1 -1
- package/dist/assets/components/input-time/input-time.types.ts +1 -1
- package/dist/assets/components/input-time/input-time.vue +1 -1
- package/dist/assets/components/inspector/inspector.stories.ts +1 -1
- package/dist/assets/components/inspector/inspector.vue +1 -1
- package/dist/assets/components/layout/components/layout-row/layout-row.stories.ts +1 -1
- package/dist/assets/components/layout/components/layout-row/layout-row.vue +1 -1
- package/dist/assets/components/layout/layout.docs.mdx +10 -0
- package/dist/assets/components/layout/layout.internal.types.ts +1 -0
- package/dist/assets/components/layout/layout.stories.ts +1 -1
- package/dist/assets/components/layout/layout.types.ts +1 -1
- package/dist/assets/components/link/link.stories.ts +1 -1
- package/dist/assets/components/link/link.types.ts +1 -1
- package/dist/assets/components/link/link.vue +1 -1
- package/dist/assets/components/list/list.stories.ts +1 -1
- package/dist/assets/components/loading-indicator/loading-indicator.stories.ts +1 -1
- package/dist/assets/components/menu/components/menu-item/menu-item.types.ts +1 -1
- package/dist/assets/components/menu/components/menu-item/menu-item.vue +1 -1
- package/dist/assets/components/menu/components/menu-item-list/menu-item-list.vue +1 -1
- package/dist/assets/components/menu/components/sub-menu-item-list/sub-menu-item-list.vue +1 -1
- package/dist/assets/components/menu/menu.docs.mdx +9 -0
- package/dist/assets/components/menu/menu.stories.ts +1 -1
- package/dist/assets/components/menu/menu.types.ts +1 -1
- package/dist/assets/components/menu/menu.vue +1 -1
- package/dist/assets/components/modal/components/base-modal/base-modal.vue +1 -1
- package/dist/assets/components/modal/components/modal-page/modal-page.vue +1 -1
- package/dist/assets/components/modal/modal.internal.types.ts +1 -0
- package/dist/assets/components/modal/modal.stories.ts +1 -1
- package/dist/assets/components/modal/modal.types.ts +1 -1
- package/dist/assets/components/modal/modal.vue +1 -1
- package/dist/assets/components/modal-fullscreen/components/modal-fullscreen-page.vue +1 -1
- package/dist/assets/components/modal-fullscreen/modal-fullscreen.stories.ts +1 -1
- package/dist/assets/components/modal-fullscreen/modal-fullscreen.vue +1 -1
- package/dist/assets/components/navigation-menu/components/navigation-menu-group/navigation-menu-group.internal.types.ts +1 -0
- package/dist/assets/components/navigation-menu/components/navigation-menu-group/navigation-menu-group.types.ts +1 -1
- package/dist/assets/components/navigation-menu/components/navigation-menu-group/navigation-menu-group.vue +1 -1
- package/dist/assets/components/navigation-menu/components/navigation-menu-item/navigation-menu-item.vue +1 -1
- package/dist/assets/components/navigation-menu/navigation-menu.internal.types.ts +1 -0
- package/dist/assets/components/navigation-menu/navigation-menu.stories.ts +1 -1
- package/dist/assets/components/navigation-menu/navigation-menu.types.ts +1 -1
- package/dist/assets/components/navigation-menu/navigation-menu.vue +1 -1
- package/dist/assets/components/pagination/components/pagination-context/pagination-context.vue +1 -1
- package/dist/assets/components/pagination/components/pagination-results-per-page/pagination-results-per-page.vue +1 -1
- package/dist/assets/components/pagination/pagination.stories.ts +1 -1
- package/dist/assets/components/pagination/pagination.types.ts +1 -1
- package/dist/assets/components/pagination/pagination.vue +1 -1
- package/dist/assets/components/payment-method/payment-method.stories.ts +1 -1
- package/dist/assets/components/payment-method/payment-method.types.ts +1 -1
- package/dist/assets/components/popover/popover.docs.mdx +32 -9
- package/dist/assets/components/popover/popover.stories.ts +1 -1
- package/dist/assets/components/popover/popover.types.ts +1 -1
- package/dist/assets/components/popover/popover.vue +1 -1
- package/dist/assets/components/popper-container/popper-container.types.ts +1 -1
- package/dist/assets/components/popper-container/popper-container.vue +1 -1
- package/dist/assets/components/progress-bar/progress-bar.stories.ts +1 -1
- package/dist/assets/components/progress-bar/progress-bar.vue +1 -1
- package/dist/assets/components/promo-banner/promo-banner.stories.ts +1 -1
- package/dist/assets/components/promo-banner/promo-banner.types.ts +1 -1
- package/dist/assets/components/promo-banner/promo-banner.vue +1 -1
- package/dist/assets/components/radio-group/components/radio-button/radio-button.vue +1 -1
- package/dist/assets/components/radio-group/radio-group.docs.mdx +1 -6
- package/dist/assets/components/radio-group/radio-group.stories.ts +1 -1
- package/dist/assets/components/radio-group/radio-group.types.ts +1 -1
- package/dist/assets/components/radio-group/radio-group.vue +1 -1
- package/dist/assets/components/rich-text-editor/rich-text-editor.internal.types.ts +1 -0
- package/dist/assets/components/rich-text-editor/rich-text-editor.stories.ts +1 -1
- package/dist/assets/components/rich-text-editor/rich-text-editor.types.ts +1 -1
- package/dist/assets/components/rich-text-editor/rich-text-editor.vue +1 -1
- package/dist/assets/components/search-bar/search-bar.stories.ts +1 -1
- package/dist/assets/components/search-bar/search-bar.vue +1 -1
- package/dist/assets/components/secondary-nav/components/secondary-nav-item/secondary-nav-item.vue +1 -1
- package/dist/assets/components/secondary-nav/secondary-nav.stories.ts +1 -1
- package/dist/assets/components/secondary-nav/secondary-nav.vue +1 -1
- package/dist/assets/components/segmented-control/components/segmented-control-button/segmented-control-button.vue +1 -1
- package/dist/assets/components/segmented-control/segmented-control.stories.ts +1 -1
- package/dist/assets/components/segmented-control/segmented-control.types.ts +1 -1
- package/dist/assets/components/segmented-control/segmented-control.vue +1 -1
- package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.docs.mdx +12 -13
- package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.stories.ts +1 -1
- package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.vue +1 -1
- package/dist/assets/components/selection-card/selection-card.stories.ts +1 -1
- package/dist/assets/components/selection-card/selection-card.types.ts +1 -1
- package/dist/assets/components/selection-card/selection-card.vue +1 -1
- package/dist/assets/components/sidepanel/sidepanel.docs.mdx +1 -1
- package/dist/assets/components/sidepanel/sidepanel.stories.ts +1 -1
- package/dist/assets/components/sidepanel/sidepanel.vue +1 -1
- package/dist/assets/components/status/status.stories.ts +1 -1
- package/dist/assets/components/status/status.types.ts +1 -1
- package/dist/assets/components/stepper/components/step/step.vue +1 -1
- package/dist/assets/components/stepper/stepper.stories.ts +1 -1
- package/dist/assets/components/stepper/stepper.vue +1 -1
- package/dist/assets/components/structured-list/structured-list.stories.ts +1 -1
- package/dist/assets/components/structured-list/structured-list.vue +1 -1
- package/dist/assets/components/summary-grid/components/summary-grid-item/summary-grid-item.types.ts +1 -1
- package/dist/assets/components/summary-grid/summary-grid.stories.ts +1 -1
- package/dist/assets/components/summary-grid/summary-grid.types.ts +1 -1
- package/dist/assets/components/table-of-contents/components/table-of-contents-list/table-of-contents-list.vue +1 -1
- package/dist/assets/components/table-of-contents/table-of-contents.internal.types.ts +1 -0
- package/dist/assets/components/table-of-contents/table-of-contents.stories.ts +1 -1
- package/dist/assets/components/table-of-contents/table-of-contents.types.ts +1 -1
- package/dist/assets/components/table-of-contents/table-of-contents.vue +1 -1
- package/dist/assets/components/tabs/components/tab.internal.types.ts +1 -0
- package/dist/assets/components/tabs/components/tab.types.ts +1 -1
- package/dist/assets/components/tabs/components/tab.vue +1 -1
- package/dist/assets/components/tabs/tabs.stories.ts +1 -1
- package/dist/assets/components/tabs/tabs.vue +1 -1
- package/dist/assets/components/tag/tag.docs.mdx +1 -1
- package/dist/assets/components/tag/tag.stories.ts +1 -1
- package/dist/assets/components/tag/tag.types.ts +1 -1
- package/dist/assets/components/tag/tag.vue +1 -1
- package/dist/assets/components/textarea/textarea.docs.mdx +0 -7
- package/dist/assets/components/textarea/textarea.stories.ts +1 -1
- package/dist/assets/components/textarea/textarea.types.ts +1 -1
- package/dist/assets/components/textarea/textarea.vue +1 -1
- package/dist/assets/components/timeline/components/timeline-item/timeline-item.stories.ts +1 -1
- package/dist/assets/components/timeline/components/timeline-item/timeline-item.vue +1 -1
- package/dist/assets/components/timeline/timeline.docs.mdx +0 -10
- package/dist/assets/components/timeline/timeline.internal.types.ts +1 -0
- package/dist/assets/components/timeline/timeline.stories.ts +1 -1
- package/dist/assets/components/timeline/timeline.types.ts +1 -1
- package/dist/assets/components/timeline/timeline.vue +1 -1
- package/dist/assets/components/toast/components/toast-item/toast-item.vue +1 -1
- package/dist/assets/components/toggle/toggle.stories.ts +1 -1
- package/dist/assets/components/toggle/toggle.types.ts +1 -1
- package/dist/assets/components/toggle/toggle.vue +1 -1
- package/dist/assets/components/tutorial/tutorial.stories.ts +1 -1
- package/dist/assets/components/typography/typography.stories.ts +1 -1
- package/dist/assets/components/typography/typography.types.ts +1 -1
- package/dist/assets/components/typography/typography.vue +1 -1
- package/dist/assets/composables/use-bento-base-filter/index.ts +1 -0
- package/dist/assets/composables/use-bento-base-filter/use-bento-base-filter.ts +1 -0
- package/dist/assets/composables/use-bento-base-filter/utils/index.ts +1 -0
- package/dist/assets/composables/use-bento-base-filter/utils/utils.ts +1 -0
- package/dist/assets/composables/use-bento-currency/index.ts +1 -0
- package/dist/assets/composables/use-bento-currency/use-bento-currency.stories.ts +1 -1
- package/dist/assets/composables/use-bento-currency/use-bento-currency.ts +1 -0
- package/dist/assets/composables/use-bento-delayed-hover/index.ts +1 -0
- package/dist/assets/composables/use-bento-delayed-hover/use-bento-delayed-hover.stories.ts +1 -1
- package/dist/assets/composables/use-bento-delayed-hover/use-bento-delayed-hover.ts +1 -0
- package/dist/assets/composables/use-bento-theme/index.ts +1 -0
- package/dist/assets/composables/use-bento-theme/install.ts +1 -1
- package/dist/assets/composables/use-bento-theme/install.types.ts +1 -1
- package/dist/assets/composables/use-bento-theme/use-bento-theme.ts +1 -0
- package/dist/assets/composables/use-bento-toast-controller/index.ts +1 -0
- package/dist/assets/composables/use-bento-toast-controller/toast-stack.ts +1 -0
- package/dist/assets/composables/use-bento-toast-controller/use-bento-toast-controller.ts +1 -0
- package/dist/assets/composables/use-click-outside/index.ts +1 -0
- package/dist/assets/composables/use-click-outside/use-click-outside.stories.ts +1 -1
- package/dist/assets/composables/use-click-outside/use-click-outside.ts +1 -0
- package/dist/assets/composables/use-form-validate/index.ts +1 -0
- package/dist/assets/composables/use-form-validate/use-form.ts +1 -0
- package/dist/assets/composables/use-form-validate/use-form.types.ts +1 -1
- package/dist/assets/composables.json +9 -0
- package/dist/assets/deprecations.md +132 -236
- package/dist/assets/directives/highlight/highlight.stories.ts +1 -1
- package/dist/assets/directives/keyboard-navigation/keyboard-navigation.stories.ts +1 -1
- package/dist/assets/directives/tooltip/tooltip.internal.types.ts +1 -0
- package/dist/assets/directives/tooltip/tooltip.stories.ts +1 -1
- package/dist/assets/directives/tooltip/tooltip.types.ts +1 -1
- package/dist/assets/icons.json +1 -0
- package/dist/assets/install.ts +1 -1
- package/dist/assets/tailwind/README.md +3 -3
- package/dist/assets/templates/dashboard-template/components/dashboard-section/dashboard-section.stories.ts +1 -1
- package/dist/assets/templates/dashboard-template/dashboard-template.stories.ts +1 -1
- package/dist/assets/templates/data-grid-template/data-grid-template.stories.ts +1 -1
- package/dist/assets/usage.json +77 -77
- package/dist/assets/variables.css +113 -101
- package/dist/main.js +228 -34
- package/package.json +2 -2
- package/dist/assets/components/internal/base-button/base-button.types.ts +0 -1
- package/dist/assets/components/internal/base-button/base-button.vue +0 -1
- package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.stories.ts +0 -1
- package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.types.ts +0 -1
- package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.vue +0 -1
- package/dist/assets/components/internal/calendar/calendar.stories.ts +0 -1
- package/dist/assets/components/internal/calendar/calendar.types.ts +0 -1
- package/dist/assets/components/internal/calendar/calendar.vue +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.stories.ts +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.types.ts +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.vue +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/__test__/calendar-month-day-stub.vue +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.stories.ts +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.types.ts +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.vue +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-month/composables/granular-min-max-date.types.ts +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-year/calendar-year.types.ts +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-year/calendar-year.vue +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/__test__/calendar-year-month-stub.vue +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/calendar-year-month.types.ts +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/calendar-year-month.vue +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-year-selector/calendar-year-selector.types.ts +0 -1
- package/dist/assets/components/internal/calendar/components/calendar-year-selector/calendar-year-selector.vue +0 -1
- package/dist/assets/components/internal/calendar/composables/use-granularity-adjustments.types.ts +0 -1
- package/dist/assets/components/internal/checkbox-input/checkbox-input.stories.ts +0 -1
- package/dist/assets/components/internal/checkbox-input/checkbox-input.types.ts +0 -1
- package/dist/assets/components/internal/checkbox-input/checkbox-input.vue +0 -1
- package/dist/assets/components/internal/controls-group/controls-group.vue +0 -1
- package/dist/assets/components/internal/copy/copy.docs.mdx +0 -43
- package/dist/assets/components/internal/copy/copy.stories.ts +0 -1
- package/dist/assets/components/internal/copy/copy.types.ts +0 -1
- package/dist/assets/components/internal/copy/copy.vue +0 -1
- package/dist/assets/components/internal/decorative-checkbox/decorative-checkbox.vue +0 -1
- package/dist/assets/components/internal/dialog-page/dialog-page.types.ts +0 -1
- package/dist/assets/components/internal/dialog-page/dialog-page.vue +0 -1
- package/dist/assets/components/internal/error-message/error-message.vue +0 -1
- package/dist/assets/components/internal/field-label/field-label.vue +0 -1
- package/dist/assets/components/internal/fixed-scroller/fixed-scroller.docs.mdx +0 -21
- package/dist/assets/components/internal/fixed-scroller/fixed-scroller.stories.ts +0 -1
- package/dist/assets/components/internal/fixed-scroller/fixed-scroller.vue +0 -1
- package/dist/assets/components/internal/footer-actions/footer-actions.vue +0 -1
- package/dist/assets/components/internal/grid-layout/grid-layout.types.ts +0 -1
- package/dist/assets/components/internal/grid-layout/grid-layout.vue +0 -1
- package/dist/assets/components/internal/header-meta/header-meta.types.ts +0 -1
- package/dist/assets/components/internal/header-meta/header-meta.vue +0 -1
- package/dist/assets/components/internal/info-icon-with-popover/info-icon-with-popover.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-lazy-load/listbox-lazy-load.types.ts +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-lazy-load/listbox-lazy-load.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/components/listbox-multi-select-category/listbox-multi-select-category.types.ts +0 -1
- 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 +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/components/listbox-multi-select-nested-lazy-load/listbox-multi-select-nested-lazy-load.types.ts +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/components/listbox-multi-select-nested-lazy-load/listbox-multi-select-nested-lazy-load.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/listbox-multi-select-options.types.ts +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/listbox-multi-select-options.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/listbox-multi-select.types.ts +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-multi-select/listbox-multi-select.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-option/listbox-option.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-option-tag/listbox-option-tag.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-single-select/components/listbox-single-select-category/listbox-single-select-category.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-single-select/listbox-single-select.vue +0 -1
- package/dist/assets/components/internal/listbox/components/listbox-single-select-option/listbox-single-select-option.vue +0 -1
- package/dist/assets/components/internal/listbox/listbox.stories.ts +0 -1
- package/dist/assets/components/internal/listbox/listbox.types.ts +0 -1
- package/dist/assets/components/internal/listbox/listbox.vue +0 -1
- package/dist/assets/components/internal/radio-input/radio-input.stories.ts +0 -1
- package/dist/assets/components/internal/radio-input/radio-input.types.ts +0 -1
- package/dist/assets/components/internal/radio-input/radio-input.vue +0 -1
- package/dist/assets/components/internal/teleport/teleport.types.ts +0 -1
- package/dist/assets/components/internal/teleport/teleport.vue +0 -1
- package/dist/assets/components/internal/tooltip/tooltip.test.vue +0 -1
- package/dist/assets/components/internal/tooltip/tooltip.types.ts +0 -1
- package/dist/assets/components/internal/tooltip/tooltip.vue +0 -1
- package/dist/assets/composables/use-form-validate-zod-4/use-form.types.ts +0 -1
- package/dist/assets/composables/use-numeric-input/use-numeric-input.types.ts +0 -1
- package/dist/assets/composables/use-section-navigation-keyboard/use-section-navigation-keyboard.types.ts +0 -1
- package/dist/assets/composables/use-virtual-list/use-virtual-list.types.ts +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
<template> <div class="b-ai-button" :class="conditionalClass"> <div class="b-ai-button__animation" /> <bento-button class="b-ai-button__button" :condensed="condensed" :disabled="disabled" :inverse="inverse" variant="secondary" @click.capture.stop="onClick" > <template #iconLeft> <ai-filled-icon aria-hidden="true" class="b-ai-button__icon" /> </template> <slot></slot> </bento-button> </div> </template> <script setup lang="ts"> import { computed, onMounted, useSlots } from 'vue'; import BentoButton from '../../button.vue'; import AiFilledIcon from '@adyen/ui-assets-icons-16/vue/artificial-intelligence-ai-filled'; import { useHasSlot } from '@/composables/use-has-slot/use-has-slot'; import { printDevelopmentWarning } from '@/utils/ts/print-development-warning'; import { type BentoAiButtonProps } from './ai-button.types'; const props = withDefaults(defineProps<BentoAiButtonProps>(), { link: undefined, type: 'button', condensed: false, disabled: false, inverse: false, }); const emit = defineEmits<{ /** * Click event handler */ (e: 'click', event: MouseEvent): void; }>(); const slots = useSlots(); const hasSlot = useHasSlot(slots); const conditionalClass = computed(() => ({ 'b-ai-button--disabled': props.disabled, })); const onClick = (e: MouseEvent) => { // Prevent Vue3 from triggering event twice e.stopPropagation(); emit('click', e); }; onMounted(() => { if (!hasSlot('default')) { printDevelopmentWarning('An icon-only button cannot be a AI button'); } }); </script> <script lang="ts"> /** * AI Button component is used for cases where pressing a button starts an AI-related action. * * @example * import { BentoAiButton } from '@adyen/bento-vue2'; * * export default { * components: { BentoAiButton }, * template: ` * <bento-ai-button @click="onClick">Generate with AI</bento-ai-button> * ` * } */ export default { name: 'bento-ai-button', }; </script> <style lang="scss" scoped src="./ai-button.scss" />
|
|
1
|
+
<template> <div class="b-ai-button" :class="conditionalClass"> <div class="b-ai-button__animation" /> <bento-button class="b-ai-button__button" :condensed="condensed" :disabled="disabled" :inverse="inverse" variant="secondary" @click.capture.stop="onClick" > <template #iconLeft> <ai-filled-icon aria-hidden="true" class="b-ai-button__icon" /> </template> <slot></slot> </bento-button> </div> </template> <script setup lang="ts"> import { computed, onMounted, useSlots } from 'vue'; import BentoButton from '../../button.vue'; import AiFilledIcon from '@adyen/ui-assets-icons-16/vue/artificial-intelligence-ai-filled'; import { useHasSlot } from '@/composables/use-has-slot/use-has-slot'; import { printDevelopmentWarning } from '@/utils/ts/print-development-warning'; import { type BentoAiButtonProps } from './ai-button.types'; const props = withDefaults(defineProps<BentoAiButtonProps>(), { link: undefined, type: 'button', condensed: false, disabled: false, inverse: false, }); const emit = defineEmits<{ /** * Click event handler */ (e: 'click', event: MouseEvent): void; }>(); const slots = useSlots(); const hasSlot = useHasSlot(slots); const conditionalClass = computed(() => ({ 'b-ai-button--disabled': props.disabled, 'b-ai-button--inverse': props.inverse, })); const onClick = (e: MouseEvent) => { // Prevent Vue3 from triggering event twice e.stopPropagation(); emit('click', e); }; onMounted(() => { if (!hasSlot('default')) { printDevelopmentWarning('An icon-only button cannot be a AI button'); } }); </script> <script lang="ts"> /** * AI Button component is used for cases where pressing a button starts an AI-related action. * * @example * import { BentoAiButton } from '@adyen/bento-vue2'; * * export default { * components: { BentoAiButton }, * template: ` * <bento-ai-button @click="onClick">Generate with AI</bento-ai-button> * ` * } */ export default { name: 'bento-ai-button', }; </script> <style lang="scss" scoped src="./ai-button.scss" />
|
|
@@ -74,6 +74,9 @@ configured:
|
|
|
74
74
|
|
|
75
75
|
}`}/>
|
|
76
76
|
|
|
77
|
+
> **Icon requirement:** Only components from `@adyen/ui-assets-icons-16` are allowed in icon props and icon slots. Icon
|
|
78
|
+
> fonts, custom SVGs, and external icon libraries are not supported.
|
|
79
|
+
|
|
77
80
|
- `title`: the button's text.
|
|
78
81
|
- `condensed` (optional): condensed button.
|
|
79
82
|
- `critical` (optional): the button's red border and color.
|
package/dist/assets/components/button/components/button-actions/button-actions.internal.types.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import type { BentoMenuProps } from '@/components/menu/menu.types'; import type { VueNodeElement } from '@/types/elements'; import type { OmitStrict } from '@/types/omit-strict'; import type { VNodeRef } from 'vue/types/vnode'; /** * Base interface for the Button and Menu objects */ export interface BentoButtonActionBase { title: string; icon?: VueNodeElement; iconLeft?: VueNodeElement; iconRight?: VueNodeElement; /** * Provides a template ref to the underlying component instance. */ elementRef?: Exclude<VNodeRef, string>; } /** * Type for the Menus passed as objects to Button Actions */ export type BentoActionMenu = BentoButtonActionBase & OmitStrict<BentoMenuProps, 'button' | 'data'> & Partial<Pick<BentoMenuProps, 'data'>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { action } from '@storybook/addon-actions'; import { BentoButtonActionsLayout } from '@/components/button';
|
|
1
|
+
import { action } from '@storybook/addon-actions'; import { BentoButtonActionsLayout } from '@/components/button'; const ButtonActionsWithMenu = "<template>\n <bento-button-actions :actions=\"actions\" />\n</template>\n\n<script setup lang=\"ts\">\n import { BentoButtonActions } from '@adyen/bento-vue2';\n\n const actions = [\n {\n title: 'Primary',\n event: () => true,\n },\n {\n title: 'Secondary',\n event: () => true,\n },\n {\n title: 'Tertiary',\n event: () => true,\n disabled: true,\n },\n {\n title: 'Menu',\n data: [\n {\n text: 'Item 1',\n secondaryText: 'Text',\n handler: () => true,\n critical: true,\n },\n {\n text: 'Item 2',\n secondaryText: 'Text',\n handler: () => true,\n },\n ],\n },\n ];\n</script>\n"; import { isVue2 } from 'vue-demi'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoButtonActions from './button-actions.vue'; import MachineLearningIcon from '@adyen/ui-assets-icons-16/vue/machine-learning'; import type { BentoButtonActionsList } from './button-actions.types'; const ButtonActionsCritical = "<template>\n <bento-button-actions :actions=\"actions\" />\n</template>\n\n<script setup lang=\"ts\">\n import { BentoButtonActions } from '@adyen/bento-vue2';\n\n const clickedAction = () => true;\n const actions = [\n {\n title: 'Primary',\n critical: true,\n event: clickedAction,\n },\n {\n title: 'Secondary',\n event: clickedAction,\n },\n ];\n</script>\n"; const ButtonActionsDefault = "<template>\n <bento-button-actions :actions=\"actions\" />\n</template>\n\n<script setup lang=\"ts\">\n import { BentoButtonActions } from '@adyen/bento-vue2';\n import MachineLearningIcon from '@adyen/ui-assets-icons-16/vue/machine-learning';\n\n const clickedAction = () => true;\n const actions = [\n {\n title: 'Primary',\n event: clickedAction,\n icon: MachineLearningIcon,\n },\n {\n title: 'Secondary',\n event: clickedAction,\n },\n {\n title: 'Tertiary',\n event: clickedAction,\n },\n ];\n</script>\n"; const ButtonActionsWithLink = "<template>\n <bento-button-actions :actions=\"actions\" />\n</template>\n\n<script setup lang=\"ts\">\n import { BentoButtonActions } from '@adyen/bento-vue2';\n import MachineLearningIcon from '@adyen/ui-assets-icons-16/vue/machine-learning';\n\n const clickedAction = () => true;\n const actions = [\n {\n title: 'Primary',\n event: clickedAction,\n icon: MachineLearningIcon,\n },\n {\n title: 'Secondary (a link)',\n event: clickedAction,\n link: {\n variant: 'default',\n external: true,\n to: 'https://www.adyen.com/',\n },\n },\n {\n title: 'Tertiary',\n event: clickedAction,\n },\n ];\n</script>\n"; const ButtonActionsWithLoadingButton = "<template>\n <bento-button-actions :actions=\"actions\" />\n</template>\n\n<script setup lang=\"ts\">\n import { BentoButtonActions, BentoLoadingButtonState } from '@adyen/bento-vue2';\n import MachineLearningIcon from '@adyen/ui-assets-icons-16/vue/machine-learning';\n\n const clickedAction = () => true;\n const actions = [\n {\n title: 'Loading Button',\n event: clickedAction,\n state: BentoLoadingButtonState.LOADING,\n icon: MachineLearningIcon,\n },\n {\n title: 'Secondary',\n event: clickedAction,\n state: BentoLoadingButtonState.START,\n icon: MachineLearningIcon,\n },\n ];\n</script>\n"; export default { title: 'Button/Button Actions', component: BentoButtonActions, argTypes: { layout: { options: Object.values(BentoButtonActionsLayout), mapping: BentoButtonActionsLayout, control: { type: 'select', }, }, }, } as Meta; type Story = StoryObj<typeof BentoButtonActions>; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoButtonActions, MachineLearningIcon }, props: Object.keys(argTypes), template: ` <bento-button-actions v-bind="args" :actions="[{ title: 'Primary', event: clickedAction, icon: icon, }, { title: 'Secondary', event: clickedAction, }, { title: 'Tertiary', event: clickedAction, }]" > </bento-button-actions> `, setup(props) { const icon = MachineLearningIcon; return { args: isVue2 ? props : _args, clickedAction: action('input'), icon, }; }, }), parameters: storybookDocsParameter(ButtonActionsDefault), }; export const Critical = { render: (_args, { argTypes }) => ({ components: { BentoButtonActions, MachineLearningIcon }, props: Object.keys(argTypes), template: ` <bento-button-actions v-bind="args" :actions="[{ title: 'Primary', critical: true, event: clickedAction, icon: args.icon, }, { title: 'Secondary', event: clickedAction, }]" > </bento-button-actions> `, setup(props) { return { args: isVue2 ? props : _args, clickedAction: action('input'), }; }, }), parameters: storybookDocsParameter(ButtonActionsCritical), }; export const WithLink: Story = { render: (_args, { argTypes }) => ({ components: { BentoButtonActions, MachineLearningIcon }, props: Object.keys(argTypes), template: ` <bento-button-actions v-bind="args" :actions="[{ title: 'Primary', event: clickedAction, icon: icon, }, { title: 'Secondary (a link)', event: clickedAction, link: { variant: 'default', external: true, to: 'https://www.adyen.com/' }, }, { title: 'Tertiary', event: clickedAction, }]" > </bento-button-actions> `, setup(props) { const icon = MachineLearningIcon; return { args: isVue2 ? props : _args, clickedAction: action('input'), icon, }; }, }), parameters: storybookDocsParameter(ButtonActionsWithLink), }; export const WithLoadingButton: Story = { render: (_args, { argTypes }) => ({ components: { BentoButtonActions, MachineLearningIcon }, props: Object.keys(argTypes), template: ` <bento-button-actions v-bind="args" :actions="[ { title: 'Loading Button', event: clickedAction, state: 'loading', icon, }, { title: 'Secondary', event: clickedAction, state: 'start', icon, }, ]" /> `, setup(props) { const icon = MachineLearningIcon; return { args: isVue2 ? props : _args, clickedAction: action('input'), icon, }; }, }), parameters: storybookDocsParameter(ButtonActionsWithLoadingButton), }; export const WithMenu: Story = { render: (_args, { argTypes }) => ({ components: { BentoButtonActions }, props: Object.keys(argTypes), template: ` <bento-button-actions v-bind="args" /> `, setup(props) { return { args: isVue2 ? props : _args, }; }, }), args: { actions: [ { title: 'Primary', event: () => true, }, { title: 'Secondary', event: () => true, }, { title: 'Tertiary', event: () => true, disabled: true, }, { title: 'Menu', data: [ { text: 'Item 1', secondaryText: 'Text', handler: () => true, critical: true, }, { text: 'Item 2', secondaryText: 'Text', handler: () => true, }, ], }, ] satisfies BentoButtonActionsList, }, parameters: storybookDocsParameter(ButtonActionsWithMenu), };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import type { BentoButtonProps } from '../../button.types'; import type {
|
|
1
|
+
import type { BentoButtonProps } from '../../button.types'; import type { BentoLoadingButtonState } from '../loading-button/loading-button.types'; import type { BentoActionMenu, BentoButtonActionBase } from './button-actions.internal.types'; export interface BentoButtonActionObject extends BentoButtonActionBase, BentoButtonProps { event?: (event: Event) => void; state?: BentoLoadingButtonState | `${BentoLoadingButtonState}`; iconOnly?: boolean; } // TODO: Update to Array<BentoButtonActionButton | BentoButtonActionMenuObject> in v2.0.0 export type BentoButtonActionsList = Array<BentoButtonActionObject & BentoActionMenu>; export enum BentoButtonActionsLayoutBasic { BUTTONS_END = 'buttons-end', FILL_CONTAINER = 'fill-container', SPACE_BETWEEN = 'space-between', VERTICAL_STACK = 'vertical-stack', } export enum BentoButtonActionsLayoutExtended { BUTTONS_START = 'buttons-start', } /** * @deprecated Since v3.0.0. Use string literal instead. */ export const BentoButtonActionsLayout = { ...BentoButtonActionsLayoutBasic, ...BentoButtonActionsLayoutExtended }; export type BentoButtonActionsLayout = BentoButtonActionsLayoutBasic | BentoButtonActionsLayoutExtended; export interface BentoButtonActionsProps { /** * List of actions that will be used to render the buttons. * First element in the list will be rendered as "primary". * All elements after the first will be rendered as "secondary". * * Each object in the list should have a `title`, an `event` and * (optional) a Vue `icon` from the library `@adyen/ui-assets-icons-16`. * * `title`: Button's text. * * `event`: Event triggered when clicking the Button. * * `icon` (optional): Vue Icon from the library `@adyen/ui-assets-icons-16`. * * @see BentoButton for a list of all the other props supported by each button action. * * ``` * [{ * title: 'Primary', * event: () => { ... }, * icon: FourPeopleIcon, * link: { * variant: 'default', * external: true, * to: 'https://www.adyen.com/' * }, * }, { * title: 'Secondary', * event: () => { ... } * disabled: true, * variant: 'secondary', * critical: true * }] * ``` */ actions: BentoButtonActionsList; /** * Sets the Button Actions to color scheme inverse */ inverse?: boolean; /** * Defines the layout in which the button actions is presented. * It can be one of: * * @values BUTTONS_START * @values BUTTONS_END * @values FILL_CONTAINER * @values SPACE_BETWEEN * @values VERTICAL_STACK */ layout?: string; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<template> <div ref="buttonActions" class="b-button-actions"> <div class="b-button-actions__container-wrapper" :class="conditionalClasses" role="group"> <div v-for="(button, index) in reversedActionsList" :key="index" ref="buttons" class="b-button-actions__button-wrapper" > <template v-if="button.data"> <bento-menu :ref="button.elementRef" :data="button.data" :close-menu-on-item-select="button.closeMenuOnItemSelect" :close-on-click-outside-options="button.closeOnClickOutsideOptions" :disable-arrow-down-opening-menu="button.disableArrowDownOpeningMenu" :menu-position="button.menuPosition" :menu-fixed-positioning="button.menuFixedPositioning" :menu-width="button.menuWidth" :revert-focus-to-button="button.revertFocusToButton" :teleport="button.teleport" > <template v-if="button.icon || button.iconLeft" #iconLeft> <component :is="button.icon || button.iconLeft" :svg-title="button.title"></component> </template> <template v-if="!isIconOnly(button)" #default> {{ button.title }} </template> </bento-menu> </template> <template v-else> <bento-loading-button v-if="button.state" :ref="button.elementRef" :condensed="button.condensed" :critical="button.critical" :disabled="button.disabled" :inverse="inverse" :state="button.state" :variant="button.variant || generateButtonVariantByIndex(index)" v-on="generateButtonEvents(button)" > <template v-if="button.icon || button.iconLeft" #iconLeft> <component :is="button.icon || button.iconLeft" :svg-title="button.title"></component> </template> <template v-if="!isIconOnly(button)" #default> {{ button.title }} </template> </bento-loading-button> <bento-button v-else :ref="button.elementRef" :condensed="button.condensed" :critical="button.critical" :disabled="button.disabled" :inverse="inverse" :link="button.link" :variant="button.variant || generateButtonVariantByIndex(index)" v-on="generateButtonEvents(button)" > <template v-if="button.icon || button.iconLeft" #iconLeft> <component :is="button.icon || button.iconLeft" :svg-title="button.title"></component> </template> <template v-if="!isIconOnly(button)" #default> {{ button.title }} </template> <template v-if="button.iconRight" #iconRight> <component :is="button.iconRight" :svg-title="button.title"></component> </template> </bento-button> </template> </div> </div> </div> </template> <script setup lang="ts"> import { computed, ref, toRef } from 'vue'; import BentoButton from '../../button.vue'; import type {
|
|
1
|
+
<template> <div ref="buttonActions" class="b-button-actions"> <div class="b-button-actions__container-wrapper" :class="conditionalClasses" role="group"> <div v-for="(button, index) in reversedActionsList" :key="index" ref="buttons" class="b-button-actions__button-wrapper" > <template v-if="button.data"> <bento-menu :ref="button.elementRef" :data="button.data" :close-menu-on-item-select="button.closeMenuOnItemSelect" :close-on-click-outside-options="button.closeOnClickOutsideOptions" :disable-arrow-down-opening-menu="button.disableArrowDownOpeningMenu" :menu-position="button.menuPosition" :menu-fixed-positioning="button.menuFixedPositioning" :menu-width="button.menuWidth" :revert-focus-to-button="button.revertFocusToButton" :teleport="button.teleport" > <template v-if="button.icon || button.iconLeft" #iconLeft> <component :is="button.icon || button.iconLeft" :svg-title="button.title"></component> </template> <template v-if="!isIconOnly(button)" #default> {{ button.title }} </template> </bento-menu> </template> <template v-else> <bento-loading-button v-if="button.state" :ref="button.elementRef" :condensed="button.condensed" :critical="button.critical" :disabled="button.disabled" :inverse="inverse" :state="button.state" :variant="button.variant || generateButtonVariantByIndex(index)" v-on="generateButtonEvents(button)" > <template v-if="button.icon || button.iconLeft" #iconLeft> <component :is="button.icon || button.iconLeft" :svg-title="button.title"></component> </template> <template v-if="!isIconOnly(button)" #default> {{ button.title }} </template> </bento-loading-button> <bento-button v-else :ref="button.elementRef" :condensed="button.condensed" :critical="button.critical" :disabled="button.disabled" :inverse="inverse" :link="button.link" :variant="button.variant || generateButtonVariantByIndex(index)" v-on="generateButtonEvents(button)" > <template v-if="button.icon || button.iconLeft" #iconLeft> <component :is="button.icon || button.iconLeft" :svg-title="button.title"></component> </template> <template v-if="!isIconOnly(button)" #default> {{ button.title }} </template> <template v-if="button.iconRight" #iconRight> <component :is="button.iconRight" :svg-title="button.title"></component> </template> </bento-button> </template> </div> </div> </div> </template> <script setup lang="ts"> import { computed, ref, toRef } from 'vue'; import BentoButton from '../../button.vue'; import type { BentoButtonActionObject, BentoButtonActionsProps } from './button-actions.types'; import BentoLoadingButton from '../loading-button/loading-button.vue'; import BentoMenu from '@/components/menu/menu.vue'; import { useStackButtons } from './composables/use-stack-buttons/use-stack-buttons'; const props = withDefaults(defineProps<BentoButtonActionsProps>(), { inverse: false, layout: 'buttons-end', }); const buttonActions = ref<HTMLDivElement>(null); const buttons = ref<Array<HTMLDivElement>>(null); const stackButtons = useStackButtons(buttonActions, buttons, toRef(props, 'actions')); const reversedActionsList = computed(() => props.actions.slice().reverse()); const generateButtonVariantByIndex = actionIndex => { const lastActionIndex = props.actions.length - 1; return actionIndex === lastActionIndex ? 'primary' : 'secondary'; }; const conditionalClasses = computed(() => ({ [`b-button-actions--${props.layout}`]: true, [`b-button-actions--stacked-buttons`]: stackButtons.value, })); const generateButtonEvents = (button: BentoButtonActionObject) => button?.event !== undefined ? { click: button.event, } : {}; const isIconOnly = (button: BentoButtonActionObject) => button.iconOnly && (button.iconLeft || button.iconRight || button.icon); </script> <script lang="ts"> /** * ButtonActions component manages a set of actions a user can choose from by displaying a group of buttons. * * @example * import { BentoButtonActions } from '@adyen/bento-vue2'; * import MachineLearningIcon from '@adyen/ui-assets-icons-16/vue/machine-learning'; * * const clickedAction = () => { //your action here } * * <template> * <bento-button-actions * :actions="[{ * title: 'Primary', * event: clickedAction, * icon: MachineLearningIcon, * }, { * title: 'Secondary', * event: clickedAction, * }, { * title: 'Tertiary', * event: clickedAction, * }]" * /> * </template> */ export default {}; </script> <style lang="scss" scoped src="./button-actions.scss" />
|
|
@@ -20,17 +20,17 @@ Note that both the states of the button (`start`, `loading`, `success` or `fail`
|
|
|
20
20
|
manually based on the state of the action you are waiting upon. For example, let's say clicking on this button would
|
|
21
21
|
trigger a `POST` request:
|
|
22
22
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
|
|
23
|
+
- Before the user clicks on the button, this will be shown initially in a `start` state.
|
|
24
|
+
- Once the user clicks on the button, the `POST` request is triggered and the button's state has to be changed to
|
|
25
|
+
`loading` and have a matching text of your liking to represent that state. At this point the button will be rendered
|
|
26
|
+
as disabled and will not trigger any actions on click.
|
|
27
|
+
- Once a response from the request is received, the loading button state has to be updated and its text updated
|
|
28
|
+
accordingly:
|
|
29
|
+
- If the request was successful a `success` state has to be set with a corresponding text that marks success.
|
|
30
|
+
- Otherwise a `fail` state needs to be set with a corresponding text that indicates failure and tells the user they
|
|
31
|
+
can retry the action if the button is clicked again.
|
|
32
|
+
- In these two final states the button will be clickable again, for retrying on `fail` or doing any other action on
|
|
33
|
+
`success`.
|
|
34
34
|
|
|
35
35
|
## Variations
|
|
36
36
|
|
|
@@ -39,22 +39,22 @@ trigger a `POST` request:
|
|
|
39
39
|
This property represents the state of the button and is of type `BentoLoadingButtonState`, which can take up one of the
|
|
40
40
|
following values:
|
|
41
41
|
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
|
|
42
|
+
- `BentoLoadingButtonState.START`: the initial state of the button, this state represents a button that has not
|
|
43
|
+
triggered any action yet.
|
|
44
|
+
- `BentoLoadingButtonState.LOADING`: the state of the button that represents an action in process, during this state the
|
|
45
|
+
button click events will not be emitted.
|
|
46
|
+
- `BentoLoadingButtonState.SUCCESS`: the state of the button that represents that an action has been completed
|
|
47
|
+
successfully.
|
|
48
|
+
- `BentoLoadingButtonState.FAIL`: the state of the button that represents that an action has been completed
|
|
49
|
+
unsuccessfully.
|
|
50
50
|
|
|
51
51
|
### Variant
|
|
52
52
|
|
|
53
53
|
This property represent the variant referenced in the `bento-button` component. It is one of the following values:
|
|
54
54
|
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
55
|
+
- `'primary'`: renders the `bento-loading-button` in the primary variant.
|
|
56
|
+
- `'secondary'`: renders the `bento-loading-button` in the secondary variant.
|
|
57
|
+
- `'tertiary'`: renders the `bento-loading-button` in the tertiary variant.
|
|
58
58
|
|
|
59
59
|
## Slots
|
|
60
60
|
|
|
@@ -64,6 +64,9 @@ You can pass an icon to the `bento-loading-button` the same way you do to `bento
|
|
|
64
64
|
However, the icon will only show in the `start` state, being replaced by the loading button respective icons in the
|
|
65
65
|
other states.
|
|
66
66
|
|
|
67
|
+
> **Icon requirement:** Only components from `@adyen/ui-assets-icons-16` are allowed in icon props and icon slots. Icon
|
|
68
|
+
> fonts, custom SVGs, and external icon libraries are not supported.
|
|
69
|
+
|
|
67
70
|
## Modifiers
|
|
68
71
|
|
|
69
72
|
### Disabled
|
|
@@ -103,4 +106,4 @@ this component are as follows:
|
|
|
103
106
|
|
|
104
107
|
Resources:
|
|
105
108
|
|
|
106
|
-
-
|
|
109
|
+
- [Figma link](https://www.figma.com/file/uLabwF3243jdMDsNSP7U9I/Bento---Components?node-id=1901-27998&t=NHLd9msx8lGq3NNF-0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { ref, watch } from 'vue'; import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { BentoButtonVariant } from '@/components/button'; import { computed, isVue2 } from 'vue-demi'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoLoadingButton from './loading-button.vue'; import DownloadIcon from '@adyen/ui-assets-icons-16/vue/download'; export default { title: 'Button/Loading Button', component: BentoLoadingButton, argTypes: { condensed: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, critical: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, default: { name: 'default', defaultValue: '', description: 'Button text', table: { type: { summary: 'VNode[]' }, }, control: { disable: true }, }, disabled: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, state: { control: { type: 'select', }, table: { type: { summary: 'BentoLoadingButtonState: start, loading, success, fail', }, }, }, variant: { options: Object.values(BentoButtonVariant), control: { type: 'select', }, table: { type: { summary: `BentoButtonVariant: ${Object.values(BentoButtonVariant)}` }, }, }, }, } as Meta; type Story = StoryObj<typeof BentoLoadingButton>; const BUTTON_TEXT = { start: 'Button', loading: 'Loading', success: 'Success', fail: 'Retry', };
|
|
1
|
+
import { ref, watch } from 'vue'; import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { BentoButtonVariant } from '@/components/button'; import { computed, isVue2 } from 'vue-demi'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoLoadingButton from './loading-button.vue'; import DownloadIcon from '@adyen/ui-assets-icons-16/vue/download'; const LoadingButtonDefault = "<template>\n <bento-loading-button state=\"loading\" variant=\"primary\" @click=\"clickedButtonAction\">\n Loading\n </bento-loading-button>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoLoadingButton } from '@adyen/bento-vue2';\n\n const clickedButtonAction = () => true;\n</script>\n"; const LoadingButtonWithIcon = "<template>\n <bento-loading-button :state=\"loadingState\" variant=\"primary\" @click=\"downloadAction\">\n <template #iconLeft>\n <download-icon />\n </template>\n Download\n </bento-loading-button>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoLoadingButton, BentoLoadingButtonState } from '@adyen/bento-vue2';\n import DownloadIcon from '@adyen/ui-assets-icons-16/vue/download';\n\n const loadingState = ref<BentoLoadingButtonState>(BentoLoadingButtonState.START);\n\n const downloadAction = () => {\n loadingState.value = BentoLoadingButtonState.LOADING;\n\n setTimeout(() => {\n loadingState.value = Math.random() < 0.5 ? BentoLoadingButtonState.SUCCESS : BentoLoadingButtonState.FAIL;\n }, 1000);\n };\n</script>\n"; export default { title: 'Button/Loading Button', component: BentoLoadingButton, argTypes: { condensed: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, critical: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, default: { name: 'default', defaultValue: '', description: 'Button text', table: { type: { summary: 'VNode[]' }, }, control: { disable: true }, }, disabled: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, state: { control: { type: 'select', }, table: { type: { summary: 'BentoLoadingButtonState: start, loading, success, fail', }, }, }, variant: { options: Object.values(BentoButtonVariant), control: { type: 'select', }, table: { type: { summary: `BentoButtonVariant: ${Object.values(BentoButtonVariant)}` }, }, }, }, } as Meta; type Story = StoryObj<typeof BentoLoadingButton>; const BUTTON_TEXT = { start: 'Button', loading: 'Loading', success: 'Success', fail: 'Retry', }; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoLoadingButton }, props: Object.keys(argTypes), template: ` <bento-loading-button v-bind="args" @click="clickedButtonAction"> {{ loadingButtonText }} </bento-loading-button> `, setup(props) { const args = isVue2 ? props : _args; const loadingButtonText = computed(() => BUTTON_TEXT[args.state]); return { clickedButtonAction: action('click'), loadingButtonText, args, }; }, }), args: { state: 'loading', variant: 'primary', }, parameters: storybookDocsParameter(LoadingButtonDefault), }; export const WithIcon: Story = { render: (_args, { argTypes }) => ({ components: { BentoLoadingButton, DownloadIcon }, props: Object.keys(argTypes), template: ` <bento-loading-button v-bind="args" @click="downloadAction" :state="loadingState"> <template #iconLeft> <download-icon /> </template> Download </bento-loading-button> `, setup(props) { const args = isVue2 ? props : _args; const loadingState = ref(args.state); const downloadAction = () => { loadingState.value = 'loading'; setTimeout(() => { loadingState.value = Math.random() < 0.5 ? 'success' : 'fail'; }, 1000); }; watch( () => args.state, () => { loadingState.value = args.state; } ); return { downloadAction, loadingState, args, }; }, }), args: { variant: 'primary', state: 'start', }, parameters: storybookDocsParameter(LoadingButtonWithIcon), };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<template> <bento-button :critical="isCritical" :variant="variant" :condensed="condensed" :disabled="disabled" :inverse="inverse" class="b-loading-button" :class="conditionalClasses" @click.capture.stop="onClick" > <slot></slot> <template v-if="state === 'start' && hasSlot('iconLeft')" #iconLeft> <slot name="iconLeft"></slot> </template> <template v-else-if="state !== 'start'" #iconLeft> <span class="b-loading-button__icon" data-testid="loading-button-rotating-icon"> <cross v-if="state === 'fail'" :svg-title="t('failed')" /> <checkmark v-else-if="state === 'success'" :svg-title="t('succeded')" /> <!-- TODO: Replace with new loading-indicator component --> <bento-loading-indicator v-else-if="state === 'loading'" small :inverse="isInverseLoadingIndicator" /> </span> </template> </bento-button> </template> <script setup lang="ts"> import { computed, type PropType, useSlots } from 'vue'; import { BentoLoadingButtonState } from './loading-button.types'; import { BentoLoadingIndicator } from '@/components/loading-indicator'; import BentoButton from '@/components/button/button.vue'; import Cross from '@adyen/ui-assets-icons-16/vue/cross-circle-fill'; import Checkmark from '@adyen/ui-assets-icons-16/vue/checkmark-circle-fill'; import { useHasSlot } from '@/composables/use-has-slot/use-has-slot'; import { useI18n } from '@/utils/ts/i18n'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; const props = defineProps({ /** * Reduces sizing of button */ condensed: { type: BentoButton.props.condensed.type, default: false, }, /** * Displays loading-button as critical */ critical: { type: BentoButton.props.critical.type, default: false, }, /** * Disables button functonality */ disabled: { type: BentoButton.props.disabled.type, default: false, }, /** * Sets color set to inverse */ inverse: { type: Boolean, default: false, }, /** * State of the button. * @values start, loading, success, fail */ state: { type: String as PropType<BentoLoadingButtonState | `${BentoLoadingButtonState}`>, default: BentoLoadingButtonState.START, validator: (value: BentoLoadingButtonState) => Object.values(BentoLoadingButtonState).includes(value), }, /** * Types of flavour of Button */ variant: { type: BentoButton.props.variant.type, default: 'primary', validator: BentoButton.props.variant.validator, }, }); const emit = defineEmits<{ /** * Click event handler */ (e: 'click', event: MouseEvent): void; }>(); const slots = useSlots(); const hasSlot = useHasSlot(slots); const { t } = useI18n<{ message: MessageSchema }>({ messages }); const conditionalClasses = computed(() => ({ [`b-loading-button--${props.variant}-${BentoLoadingButtonState.LOADING}`]: props.state === BentoLoadingButtonState.LOADING && !props.disabled, 'b-loading-button--loading': props.state === BentoLoadingButtonState.LOADING && !props.disabled, [`b-loading-button--${props.variant}-${BentoLoadingButtonState.SUCCESS}`]: props.state === BentoLoadingButtonState.SUCCESS, [`b-loading-button--inverse`]: props.inverse, })); const isInverseLoadingIndicator = computed( () => (props.variant === 'primary' && !props.inverse) || (props.variant !== 'primary' && props.inverse) ); const isCritical = computed( () => (props.critical && props.state === BentoLoadingButtonState.START) || props.state === BentoLoadingButtonState.FAIL ); const onClick = (e: MouseEvent) => { // Prevent Vue3 from triggering event twice e.stopPropagation(); if (props.state !== BentoLoadingButtonState.LOADING) { emit('click', e); } }; </script> <script lang="ts"> /** * Loading Button component is used for cases where pressing a button starts an event that requires a loading state, e.g. when you have any sort of asynchronous action and are waiting for a response * * @example * import { BentoLoadingButton } from '@adyen/bento-vue2'; * * export default { * components: { BentoLoadingButton }, * template: ` * <bento-loading-button state="loading" variant="secondary"> * Loading * </bento-loading button> * ` * } */ export default { i18n: { messages }, }; </script> <style lang="scss" scoped src="./loading-button.scss" />
|
|
1
|
+
<template> <bento-button :critical="isCritical" :variant="variant" :condensed="condensed" :disabled="disabled" :inverse="inverse" class="b-loading-button" :class="conditionalClasses" @click.capture.stop="onClick" > <slot></slot> <template v-if="state === 'start' && hasSlot('iconLeft')" #iconLeft> <slot name="iconLeft"></slot> </template> <template v-else-if="state !== 'start'" #iconLeft> <span class="b-loading-button__icon" data-testid="loading-button-rotating-icon"> <cross v-if="state === 'fail'" :svg-title="t('failed')" /> <checkmark v-else-if="state === 'success'" :svg-title="t('succeded')" /> <!-- TODO: Replace with new loading-indicator component --> <bento-loading-indicator v-else-if="state === 'loading'" small :inverse="isInverseLoadingIndicator" /> </span> </template> </bento-button> </template> <script setup lang="ts"> import { computed, type PropType, useSlots } from 'vue'; import { BentoLoadingButtonState } from './loading-button.types'; import { BentoLoadingIndicator } from '@/components/loading-indicator'; import BentoButton from '@/components/button/button.vue'; import Cross from '@adyen/ui-assets-icons-16/vue/cross-circle-fill'; import Checkmark from '@adyen/ui-assets-icons-16/vue/checkmark-circle-fill'; import { useHasSlot } from '@/composables/use-has-slot/use-has-slot'; import { useI18n } from '@/utils/ts/i18n'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; const props = defineProps({ /** * Reduces sizing of button */ condensed: { type: BentoButton.props.condensed.type, default: false, }, /** * Displays loading-button as critical */ critical: { type: BentoButton.props.critical.type, default: false, }, /** * Disables button functonality */ disabled: { type: BentoButton.props.disabled.type, default: false, }, /** * Sets color set to inverse */ inverse: { type: Boolean, default: false, }, /** * State of the button. * @values start, loading, success, fail */ state: { type: String as PropType<BentoLoadingButtonState | `${BentoLoadingButtonState}`>, default: BentoLoadingButtonState.START, validator: (value: BentoLoadingButtonState) => Object.values(BentoLoadingButtonState).includes(value), }, /** * Types of flavour of Button */ variant: { type: BentoButton.props.variant.type, default: 'primary', validator: BentoButton.props.variant.validator, }, }); const emit = defineEmits<{ /** * Click event handler */ (e: 'click', event: MouseEvent): void; }>(); const slots = useSlots(); const hasSlot = useHasSlot(slots); const { t } = useI18n<{ message: MessageSchema }>({ messages }); const conditionalClasses = computed(() => ({ [`b-loading-button--${props.variant}-${BentoLoadingButtonState.LOADING}`]: props.state === BentoLoadingButtonState.LOADING && !props.disabled, 'b-loading-button--loading': props.state === BentoLoadingButtonState.LOADING && !props.disabled, [`b-loading-button--${props.variant}-${BentoLoadingButtonState.SUCCESS}`]: props.state === BentoLoadingButtonState.SUCCESS, [`b-loading-button--inverse`]: props.inverse, })); const isInverseLoadingIndicator = computed( () => (props.variant === 'primary' && !props.inverse) || (props.variant !== 'primary' && props.inverse) ); const isCritical = computed( () => (props.critical && props.state === BentoLoadingButtonState.START) || props.state === BentoLoadingButtonState.FAIL ); const onClick = (e: MouseEvent) => { // Prevent Vue3 from triggering event twice e.stopPropagation(); if (props.state !== BentoLoadingButtonState.LOADING) { emit('click', e); } }; </script> <script lang="ts"> /** * Loading Button component is used for cases where pressing a button starts an event that requires a loading state, e.g. when you have any sort of asynchronous action and are waiting for a response * * @example * import { BentoLoadingButton } from '@adyen/bento-vue2'; * * export default { * components: { BentoLoadingButton }, * template: ` * <bento-loading-button state="loading" variant="secondary"> * Loading * </bento-loading button> * ` * } */ export default { i18n: { messages }, name: 'bento-loading-button', }; </script> <style lang="scss" scoped src="./loading-button.scss" />
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { isVue2 } from 'vue-demi'; import { computed, ref, watch } from 'vue'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoToggleButton from './toggle-button.vue'; import OptionsVerticalIcon from '@adyen/ui-assets-icons-16/vue/options-vertical'; import CheckmarkCircleFillIcon from '@adyen/ui-assets-icons-16/vue/checkmark-circle-fill'; export default { title: 'Button/Toggle Button', component: BentoToggleButton, argTypes: { condensed: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, default: { name: 'default', defaultValue: '', description: 'Button text', table: { type: { summary: 'VNode[]' }, }, control: { disable: true }, }, disabled: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, variant: { control: { type: 'select', }, table: { type: { summary: 'BentoButtonVariant: primary, secondary, tertiary' }, }, }, }, } as Meta; type Story = StoryObj<typeof BentoToggleButton>;
|
|
1
|
+
import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { isVue2 } from 'vue-demi'; import { computed, ref, watch } from 'vue'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoToggleButton from './toggle-button.vue'; import OptionsVerticalIcon from '@adyen/ui-assets-icons-16/vue/options-vertical'; import CheckmarkCircleFillIcon from '@adyen/ui-assets-icons-16/vue/checkmark-circle-fill'; const ToggleButtonDefault = "<template>\n <bento-toggle-button :toggled=\"toggleState\" variant=\"primary\" @update:toggled=\"updateToggleState\">\n {{ toggleState ? 'Toggled' : 'Un-toggled' }}\n </bento-toggle-button>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoToggleButton } from '@adyen/bento-vue2';\n\n const toggleState = ref(false);\n const updateToggleState = (newToggleState: boolean) => {\n toggleState.value = newToggleState;\n };\n</script>\n"; const ToggleButtonOnlyIcon = "<template>\n <bento-toggle-button :toggled=\"toggleState\" variant=\"primary\" @update:toggled=\"updateToggleState\">\n <template #iconLeft>\n <options-vertical-icon />\n </template>\n </bento-toggle-button>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoToggleButton } from '@adyen/bento-vue2';\n import OptionsVerticalIcon from '@adyen/ui-assets-icons-16/vue/options-vertical';\n\n const toggleState = ref(false);\n const updateToggleState = (newToggleState: boolean) => {\n toggleState.value = newToggleState;\n };\n</script>\n"; const ToggleButtonWithIcons = "<template>\n <bento-toggle-button :toggled=\"toggleState\" variant=\"primary\" @update:toggled=\"updateToggleState\">\n {{ toggleState ? 'Toggled' : 'Un-toggled' }}\n <template #iconLeft>\n <checkmark-circle-fill-icon />\n </template>\n <template #iconRight>\n <checkmark-circle-fill-icon />\n </template>\n </bento-toggle-button>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoToggleButton } from '@adyen/bento-vue2';\n import CheckmarkCircleFillIcon from '@adyen/ui-assets-icons-16/vue/checkmark-circle-fill';\n\n const toggleState = ref(false);\n const updateToggleState = (newToggleState: boolean) => {\n toggleState.value = newToggleState;\n };\n</script>\n"; export default { title: 'Button/Toggle Button', component: BentoToggleButton, argTypes: { condensed: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, default: { name: 'default', defaultValue: '', description: 'Button text', table: { type: { summary: 'VNode[]' }, }, control: { disable: true }, }, disabled: { control: { type: 'boolean', }, table: { type: { summary: 'boolean' }, }, }, variant: { control: { type: 'select', }, table: { type: { summary: 'BentoButtonVariant: primary, secondary, tertiary' }, }, }, }, } as Meta; type Story = StoryObj<typeof BentoToggleButton>; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoToggleButton }, props: Object.keys(argTypes), template: ` <bento-toggle-button v-bind="args" :toggled="toggleState" @click="clickedButtonAction" @update:toggled="updateToggleState" > {{toggleButtonText}} </bento-toggle-button> `, setup(props) { const args = isVue2 ? props : _args; const toggleState = ref<boolean>(args?.toggled); const toggleButtonText = computed(() => (toggleState.value ? 'Toggled' : 'Un-toggled')); const updateToggleState = (newToggleState: boolean) => { action('update:toggled')(newToggleState); toggleState.value = newToggleState; }; watch( () => args.toggled, () => { toggleState.value = args.toggled; } ); return { // Methods clickedButtonAction: action('click'), updateToggleState, // Values toggleButtonText, toggleState, args, }; }, }), args: { toggled: false, variant: 'primary', disabled: false, inverse: false, condensed: false, }, parameters: storybookDocsParameter(ToggleButtonDefault), }; export const WithIcons: Story = { render: (_args, { argTypes }) => ({ components: { BentoToggleButton, CheckmarkCircleFillIcon }, props: Object.keys(argTypes), template: ` <bento-toggle-button v-bind="args" :toggled="toggleState" @click="clickedButtonAction" @update:toggled="updateToggleState" > {{toggleButtonText}} <template #iconLeft> <CheckmarkCircleFillIcon /> </template> <template #iconRight> <CheckmarkCircleFillIcon /> </template> </bento-toggle-button> `, setup(props) { const args = isVue2 ? props : _args; const toggleState = ref<boolean>(args?.toggled); const toggleButtonText = computed(() => (toggleState.value ? 'Toggled' : 'Un-toggled')); const updateToggleState = (newToggleState: boolean) => { action('update:toggled')(newToggleState); toggleState.value = newToggleState; }; watch( () => args.toggled, () => { toggleState.value = args.toggled; } ); return { // Methods clickedButtonAction: action('click'), updateToggleState, // Values toggleButtonText, toggleState, args, }; }, }), args: { toggled: false, variant: 'primary', disabled: false, inverse: false, condensed: false, }, parameters: storybookDocsParameter(ToggleButtonWithIcons), }; export const OnlyIcon: Story = { render: (_args, { argTypes }) => ({ components: { BentoToggleButton, OptionsVerticalIcon }, props: Object.keys(argTypes), template: ` <bento-toggle-button v-bind="args" :toggled="toggleState" @click="clickedButtonAction" @update:toggled="updateToggleState" > <template #iconLeft> <OptionsVerticalIcon /> </template> </bento-toggle-button> `, setup(props) { const args = isVue2 ? props : _args; const toggleState = ref<boolean>(args?.toggled); const updateToggleState = (newToggleState: boolean) => { action('update:toggled')(newToggleState); toggleState.value = newToggleState; }; watch( () => args.toggled, () => { toggleState.value = args.toggled; } ); return { // Methods clickedButtonAction: action('click'), updateToggleState, // Values toggleState, args, }; }, }), args: { toggled: false, variant: 'primary', disabled: false, inverse: false, condensed: false, }, parameters: storybookDocsParameter(ToggleButtonOnlyIcon), };
|
|
@@ -49,6 +49,16 @@ title visible.
|
|
|
49
49
|
|
|
50
50
|
<Canvas of={CardStories.Expandable} />
|
|
51
51
|
|
|
52
|
+
### Linked title
|
|
53
|
+
|
|
54
|
+
Use the `link` property to make the card title a native link. It accepts the same navigation properties as `bento-link`,
|
|
55
|
+
except for `variant`.
|
|
56
|
+
|
|
57
|
+
Do not combine `link` with the `clickable` or `expandable` property. An interactive card containing a nested link
|
|
58
|
+
creates conflicting interactive targets and a confusing experience for keyboard and assistive-technology users.
|
|
59
|
+
|
|
60
|
+
<Canvas of={CardStories.WithLink} />
|
|
61
|
+
|
|
52
62
|
### Clickable
|
|
53
63
|
|
|
54
64
|
A clickable `bento-card` is a card container that can be actionable, similar to a button. It becomes interactive, and it
|
|
@@ -96,6 +106,13 @@ To configure the actions layout, you can use the different modifier options with
|
|
|
96
106
|
detailed information on the modifiers check the
|
|
97
107
|
[Button actions documentation](../?path=/docs/components-button-button-actions--docs#modifiers).
|
|
98
108
|
|
|
109
|
+
## Last updated
|
|
110
|
+
|
|
111
|
+
Use `lastUpdated` to show when card content was last refreshed. Add the optional `reloadButton` configuration to let
|
|
112
|
+
users refresh the card. Last-updated metadata is available only for regular (non-expandable) cards.
|
|
113
|
+
|
|
114
|
+
<Canvas of={CardStories.WithTimestamp} />
|
|
115
|
+
|
|
99
116
|
### Actions as links
|
|
100
117
|
|
|
101
118
|
You can use the `event` prop of the `actions` object to link to another page. Here is an example on how to do this:
|
|
@@ -105,7 +122,7 @@ You can use the `event` prop of the `actions` object to link to another page. He
|
|
|
105
122
|
<Source
|
|
106
123
|
dark
|
|
107
124
|
language="html"
|
|
108
|
-
code={`<bento-card
|
|
125
|
+
code={`<bento-card
|
|
109
126
|
actionsLayout="buttons-start"
|
|
110
127
|
:actions="cardButtonActions"
|
|
111
128
|
>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { action } from '@storybook/addon-actions'; import { BentoButton, BentoButtonActionsLayout } from '@/components/button'; import { BentoTypography } from '@/components/typography'; import { BentoLink } from '@/components/link'; import { BentoImage } from '@/components/image'; import { cardImageSrcStub } from '../../__tests__/img-stub.json'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { BentoCardBackground, BentoCardTitleSize } from '@/components/card/card.types'; import { type Meta, type StoryObj } from '@storybook/vue'; import { isVue2 } from 'vue-demi'; import BentoCard from './card.vue'; import './card.stories.scss?module'; enum CardHeaderSlotType { TEXT = 'text', LINK = 'link', BUTTON = 'button', } export default { components: { BentoTypography, BentoLink }, title: 'Card', component: BentoCard, argTypes: { titleSize: { options: Object.values(BentoCardTitleSize), mapping: BentoCardTitleSize, control: { type: 'select', }, }, default: { name: 'default', defaultValue: '', description: 'Card content', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text' }, }, image: { name: 'image', description: 'Image', table: { type: { summary: 'BentoImage' }, }, control: { disable: true }, }, header: { name: 'header', defaultValue: '', description: 'Header content', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text' }, }, headerSlotExample: { name: 'headerSlotExample', options: Object.values(CardHeaderSlotType), mapping: CardHeaderSlotType, defaultValue: CardHeaderSlotType.TEXT, description: 'Header content', table: { category: 'Storybook controls', }, control: { type: 'select' }, }, click: { name: 'click', defaultValue: '', description: `Click event handler. Transforms the card into a clickable element if there is no content, footer or actions present in the template. `, table: { type: { summary: '($event) => void' }, }, control: { disable: true }, }, description: { name: 'description', defaultValue: '', description: 'Secondary title, below the main one', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text', }, }, actionsLayout: { options: Object.values(BentoButtonActionsLayout), mapping: BentoButtonActionsLayout, control: { type: 'select', }, }, background: { options: Object.values(BentoCardBackground), mapping: BentoCardBackground, control: { type: 'select', }, }, }, } as Meta; type Story = StoryObj<typeof BentoCard>; const CARD_TITLE = 'Card title'; const CARD_HEADER_SLOT = 'Card header slot'; const CARD_DESCRIPTION = 'A little context goes a long way'; const CARD_CONTENT = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis, ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam. Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue. Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.'; const CARD_ACTIONS = [ { title: 'Primary', event: () => action('Primary')(), }, { title: 'Secondary', event: () => action('Secondary')(), }, ]; const IMAGE_SRC = cardImageSrcStub; const IMAGE_ALT = 'Example image'; const DEFAULT_CARD_PROPS = { default: CARD_TITLE, description: CARD_DESCRIPTION, content: CARD_CONTENT, background: 'primary', expandable: false, disabled: false, titleSize: 'default', headerSlotExample: CardHeaderSlotType.TEXT, }; const Template: Story = { render: (_args, { argTypes }) => ({ components: { BentoCard, BentoTypography, BentoLink, BentoButton, BentoImage }, props: Object.keys(argTypes), template: ` <bento-card v-bind="args" class="b-card-story" @click='cardClicked'> <template #default v-if='args.default'> {{ args.default }} </template> <template #image v-if='args.image'> <bento-image :src="args.image.src" :alt="args.image.alt" /> </template> <template #header v-if='args.header'> <bento-typography v-if="args.headerSlotExample === CardHeaderSlotType.TEXT"> {{ args.header }} </bento-typography> <bento-link v-if="args.headerSlotExample === CardHeaderSlotType.LINK" to="https://www.adyen.com/" external> <bento-typography> {{ args.header }} </bento-typography> </bento-link> <template v-if="args.headerSlotExample === CardHeaderSlotType.BUTTON"> <bento-button > {{ args.header }} </bento-button> </template> </template> <template #description v-if='args.description'> {{ args.description }} </template> <template #content> <bento-typography el="div">{{ args.content }}</bento-typography> </template> </bento-card> `, setup(props) { return { // Enums CardHeaderSlotType, // Values args: isVue2 ? props : _args, // Events cardClicked: action('onCardClicked'), }; }, }), }; const defaultCode = ` <bento-card> ${CARD_TITLE} <template #header> ${CARD_HEADER_SLOT} </template> <template #description> ${CARD_DESCRIPTION} </template> <template #content> <bento-typography>${CARD_CONTENT}</bento-typography> </template> </bento-card> `; export const Default = { ...Template, parameters: storybookDocsParameter(defaultCode), args: { ...DEFAULT_CARD_PROPS }, }; const secondaryCode = ` <bento-card background="secondary"> ${CARD_TITLE} <template #description> ${CARD_DESCRIPTION} </template> <template #content> <bento-typography>${CARD_CONTENT}</bento-typography> </template> </bento-card> `; export const SecondaryBackground = { ...Template, parameters: storybookDocsParameter(secondaryCode), args: { ...DEFAULT_CARD_PROPS, background: 'secondary', }, }; const expandableCode = ` <bento-card expandable> ${CARD_TITLE} <template #description> ${CARD_DESCRIPTION} </template> <template #content> <bento-typography>${CARD_CONTENT}</bento-typography> </template> </bento-card> `; export const Expandable = { ...Template, parameters: storybookDocsParameter(expandableCode), args: { ...DEFAULT_CARD_PROPS, expandable: true, }, }; const expandableClosedCode = ` <bento-card expandable closed> ${CARD_TITLE} <template #description> ${CARD_DESCRIPTION} </template> <template #content> <bento-typography>${CARD_CONTENT}</bento-typography> </template> </bento-card> `; export const ExpandableClosed = { ...Template, parameters: storybookDocsParameter(expandableClosedCode), args: { ...DEFAULT_CARD_PROPS, expandable: true, closed: true, }, }; const disabledCode = ` <bento-card expandable disabled> ${CARD_TITLE} <template #description> ${CARD_DESCRIPTION} </template> <template #content> <bento-typography>${CARD_CONTENT}</bento-typography> </template> </bento-card> `; export const Disabled = { ...Template, parameters: storybookDocsParameter(disabledCode), args: { ...DEFAULT_CARD_PROPS, expandable: true, disabled: true, }, }; const withActionsCode = ` <bento-card actionsLayout="${BentoButtonActionsLayout.BUTTONS_START}" actions="${JSON.stringify(CARD_ACTIONS)}" > ${CARD_TITLE} <template #description> ${CARD_DESCRIPTION} </template> <template #content> <bento-typography>${CARD_CONTENT}</bento-typography> </template> </bento-card> `; export const WithActions = { ...Template, parameters: storybookDocsParameter(withActionsCode), args: { ...DEFAULT_CARD_PROPS, actionsLayout: 'buttons-start', actions: CARD_ACTIONS, }, }; export const WithHeaderSlot: Story = { render: (_args, { argTypes }) => ({ components: { BentoCard, BentoTypography, BentoLink, BentoButton }, props: Object.keys(argTypes), template: ` <bento-card v-bind="args" class="b-card-story"> <template #default v-if='args.default'> {{ args.default }} </template> <template #header v-if='args.header'> <bento-typography v-if="headerSlotExample === CardHeaderSlotType.TEXT"> {{ args.header }} </bento-typography> <bento-link v-if="headerSlotExample === CardHeaderSlotType.LINK" to="https://www.adyen.com/" external> <bento-typography> {{ args.header }} </bento-typography> </bento-link> <template v-if="headerSlotExample === CardHeaderSlotType.BUTTON"> <bento-button > {{ args.header }} </bento-button> </template> </template> <template #description> {{ args.description }} </template> <template #content> <bento-typography el="div">{{ args.content }}</bento-typography> </template> </bento-card> `, setup(props) { return { // Enums CardHeaderSlotType, // Values args: isVue2 ? props : _args, }; }, }), args: { ...DEFAULT_CARD_PROPS, header: CARD_HEADER_SLOT, expandable: true, }, }; const withImageCode = ` <bento-card> ${CARD_TITLE} <template #image> <bento-image src="${IMAGE_SRC}" alt="${IMAGE_ALT}" /> </template> <template #description> ${CARD_DESCRIPTION} </template> <template #content> <bento-typography>${CARD_CONTENT}</bento-typography> </template> </bento-card> `; export const WithImage = { components: { BentoImage, }, ...Template, parameters: storybookDocsParameter(withImageCode), args: { ...DEFAULT_CARD_PROPS, image: { src: IMAGE_SRC, alt: IMAGE_ALT }, }, }; const clickableCode = ` <bento-card clickable @click="onClick"> ${CARD_TITLE} <template #description> ${CARD_DESCRIPTION} </template> <template #content> <bento-typography>${CARD_CONTENT}</bento-typography> </template> </bento-card> `; export const Clickable = { ...Template, parameters: storybookDocsParameter(clickableCode), args: { ...DEFAULT_CARD_PROPS, clickable: true, }, };
|
|
1
|
+
import { action } from '@storybook/addon-actions'; import { BentoButton, BentoButtonActionsLayout } from '@/components/button'; import { BentoTypography } from '@/components/typography'; import { BentoLink } from '@/components/link'; import { BentoImage } from '@/components/image'; import { cardImageSrcStub } from '../../__tests__/img-stub.json'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { BentoCardBackground, BentoCardTitleSize } from '@/components/card/card.types'; import { type Meta, type StoryObj } from '@storybook/vue'; import { isVue2 } from 'vue-demi'; import BentoCard from './card.vue'; const CardWithLinkExample = "<template>\n <bento-card :link=\"{ to: '/' }\">\n Card With Link Title\n\n <template #header>\n <bento-typography>Header slot</bento-typography>\n </template>\n\n <template #description>A little context goes a long way</template>\n\n <template #content>\n <bento-typography el=\"div\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const CardClickable = "<template>\n <bento-card clickable @click=\"onClick\">\n Card title\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n\n const onClick = () => true;\n</script>\n"; const CardDefault = "<template>\n <bento-card>\n Card title\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const CardDisabled = "<template>\n <bento-card disabled expandable>\n Card title\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const CardExpandable = "<template>\n <bento-card expandable>\n Card title\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const CardExpandableClosed = "<template>\n <bento-card closed expandable>\n Card title\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const CardSecondaryBackground = "<template>\n <bento-card background=\"secondary\">\n Card title\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const CardWithActions = "<template>\n <bento-card :actions=\"actions\" actions-layout=\"buttons-start\">\n Card title\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { type BentoButtonActionsList, BentoCard, BentoTypography } from '@adyen/bento-vue2';\n\n const actions: BentoButtonActionsList = [\n {\n title: 'Primary',\n event: () => true,\n },\n {\n title: 'Secondary',\n event: () => true,\n },\n ];\n</script>\n"; const CardWithHeaderSlot = "<template>\n <bento-card expandable>\n Card title\n <template #header>\n <bento-typography>Card header slot</bento-typography>\n </template>\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const CardWithImage = "<template>\n <bento-card>\n Card title\n <template #image>\n <bento-image alt=\"Example image\" :src=\"cardImageSrcStub\" />\n </template>\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis,\n ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam.\n Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue.\n Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed\n leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.\n </bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoImage, BentoTypography } from '@adyen/bento-vue2';\n import { cardImageSrcStub } from '../../../__tests__/img-stub.json';\n</script>\n"; const CardWithTimestamp = "<template>\n <bento-card :last-updated=\"lastUpdated\" :reload-button=\"reloadButton\">\n Card with timestamp and reload button\n <template #description>A little context goes a long way</template>\n <template #content>\n <bento-typography>Card content</bento-typography>\n </template>\n </bento-card>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCard, BentoTypography } from '@adyen/bento-vue2';\n\n const lastUpdated = new Date();\n const reloadButton = {\n title: 'Reload',\n event: () => undefined,\n };\n</script>\n"; import './card.stories.scss?module'; enum CardHeaderSlotType { TEXT = 'text', LINK = 'link', BUTTON = 'button', } export default { components: { BentoTypography, BentoLink }, title: 'Card', component: BentoCard, argTypes: { titleSize: { options: Object.values(BentoCardTitleSize), mapping: BentoCardTitleSize, control: { type: 'select', }, }, default: { name: 'default', defaultValue: '', description: 'Card content', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text' }, }, image: { name: 'image', description: 'Image', table: { type: { summary: 'BentoImage' }, }, control: { disable: true }, }, header: { name: 'header', defaultValue: '', description: 'Header content', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text' }, }, headerSlotExample: { name: 'headerSlotExample', options: Object.values(CardHeaderSlotType), mapping: CardHeaderSlotType, defaultValue: CardHeaderSlotType.TEXT, description: 'Header content', table: { category: 'Storybook controls', }, control: { type: 'select' }, }, click: { name: 'click', defaultValue: '', description: `Click event handler. Transforms the card into a clickable element if there is no content, footer or actions present in the template. `, table: { type: { summary: '($event) => void' }, }, control: { disable: true }, }, description: { name: 'description', defaultValue: '', description: 'Secondary title, below the main one', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text', }, }, lastUpdated: { control: { type: 'date', }, }, actionsLayout: { options: Object.values(BentoButtonActionsLayout), mapping: BentoButtonActionsLayout, control: { type: 'select', }, }, background: { options: Object.values(BentoCardBackground), mapping: BentoCardBackground, control: { type: 'select', }, }, }, } as Meta; type Story = StoryObj<typeof BentoCard>; const CARD_TITLE = 'Card title'; const CARD_HEADER_SLOT = 'Card header slot'; const CARD_DESCRIPTION = 'A little context goes a long way'; const CARD_CONTENT = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat, nunc quis aliquam facilisis, ante nulla aliquet tortor, vel feugiat diam turpis ut neque. Sed ut venenatis ante, in iaculis quam. Nulla nisi nisl, semper non tempus vitae, semper vitae nulla. Nam ac nibh eu ipsum lacinia congue. Suspendisse vulputate nisi eu erat venenatis, ac venenatis nisl ullamcorper. Aliquam interdum sem sed leo sodales, vel accumsan purus consequat. Vivamus luctus non tellus vel gravida.'; const CARD_ACTIONS = [ { title: 'Primary', event: () => action('Primary')(), }, { title: 'Secondary', event: () => action('Secondary')(), }, ]; const IMAGE_SRC = cardImageSrcStub; const IMAGE_ALT = 'Example image'; const DEFAULT_CARD_PROPS = { default: CARD_TITLE, description: CARD_DESCRIPTION, content: CARD_CONTENT, background: 'primary', expandable: false, disabled: false, titleSize: 'default', headerSlotExample: CardHeaderSlotType.TEXT, }; const Template: Story = { render: (_args, { argTypes }) => ({ components: { BentoCard, BentoTypography, BentoLink, BentoButton, BentoImage }, props: Object.keys(argTypes), template: ` <bento-card v-bind="args" v-on="args.link ? {} : { click: cardClicked }" class="b-card-story"> <template #default v-if='args.default'> {{ args.default }} </template> <template #image v-if='args.image'> <bento-image :src="args.image.src" :alt="args.image.alt" /> </template> <template #header v-if='args.header'> <bento-typography v-if="args.headerSlotExample === CardHeaderSlotType.TEXT"> {{ args.header }} </bento-typography> <bento-link v-if="args.headerSlotExample === CardHeaderSlotType.LINK" to="https://www.adyen.com/" external> <bento-typography> {{ args.header }} </bento-typography> </bento-link> <template v-if="args.headerSlotExample === CardHeaderSlotType.BUTTON"> <bento-button > {{ args.header }} </bento-button> </template> </template> <template #description v-if='args.description'> {{ args.description }} </template> <template #content> <bento-typography el="div">{{ args.content }}</bento-typography> </template> </bento-card> `, setup(props) { return { // Enums CardHeaderSlotType, // Values args: isVue2 ? props : _args, // Events cardClicked: action('onCardClicked'), }; }, }), }; export const Default = { ...Template, parameters: storybookDocsParameter(CardDefault), args: { ...DEFAULT_CARD_PROPS }, }; export const SecondaryBackground = { ...Template, parameters: storybookDocsParameter(CardSecondaryBackground), args: { ...DEFAULT_CARD_PROPS, background: 'secondary', }, }; export const Expandable = { ...Template, parameters: storybookDocsParameter(CardExpandable), args: { ...DEFAULT_CARD_PROPS, expandable: true, }, }; export const ExpandableClosed = { ...Template, parameters: storybookDocsParameter(CardExpandableClosed), args: { ...DEFAULT_CARD_PROPS, expandable: true, closed: true, }, }; export const Disabled = { ...Template, parameters: storybookDocsParameter(CardDisabled), args: { ...DEFAULT_CARD_PROPS, expandable: true, disabled: true, }, }; export const WithActions = { ...Template, parameters: storybookDocsParameter(CardWithActions), args: { ...DEFAULT_CARD_PROPS, actionsLayout: 'buttons-start', actions: CARD_ACTIONS, }, }; export const WithTimestamp = { ...Template, parameters: storybookDocsParameter(CardWithTimestamp), args: { ...DEFAULT_CARD_PROPS, lastUpdated: new Date(), reloadButton: { title: 'Reload', event: () => action('Reload')(), }, }, }; export const WithHeaderSlot: Story = { render: (_args, { argTypes }) => ({ components: { BentoCard, BentoTypography, BentoLink, BentoButton }, props: Object.keys(argTypes), template: ` <bento-card v-bind="args" class="b-card-story"> <template #default v-if='args.default'> {{ args.default }} </template> <template #header v-if='args.header'> <bento-typography v-if="headerSlotExample === CardHeaderSlotType.TEXT"> {{ args.header }} </bento-typography> <bento-link v-if="headerSlotExample === CardHeaderSlotType.LINK" to="https://www.adyen.com/" external> <bento-typography> {{ args.header }} </bento-typography> </bento-link> <template v-if="headerSlotExample === CardHeaderSlotType.BUTTON"> <bento-button > {{ args.header }} </bento-button> </template> </template> <template #description> {{ args.description }} </template> <template #content> <bento-typography el="div">{{ args.content }}</bento-typography> </template> </bento-card> `, setup(props) { return { // Enums CardHeaderSlotType, // Values args: isVue2 ? props : _args, }; }, }), args: { ...DEFAULT_CARD_PROPS, header: CARD_HEADER_SLOT, expandable: true, }, parameters: storybookDocsParameter(CardWithHeaderSlot), }; export const WithImage = { components: { BentoImage, }, ...Template, parameters: storybookDocsParameter(CardWithImage), args: { ...DEFAULT_CARD_PROPS, image: { src: IMAGE_SRC, alt: IMAGE_ALT }, }, }; export const WithLink = { ...Template, parameters: storybookDocsParameter(CardWithLinkExample), args: { ...DEFAULT_CARD_PROPS, default: 'Card With Link Title', header: 'Header slot', link: { to: '/', }, }, }; export const Clickable = { ...Template, parameters: storybookDocsParameter(CardClickable), args: { ...DEFAULT_CARD_PROPS, clickable: true, }, };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
/** * @deprecated Since
|
|
1
|
+
import { type BentoLinkProps } from '../link'; export { type TitleDetailsReloadButton as BentoCardReloadButton } from '../internal/title-details/title-details.types'; /** * @deprecated Since v3.0.0. Use string literal instead. */ export enum BentoCardBackground { PRIMARY = 'primary', SECONDARY = 'secondary', } /** * @deprecated Since v3.0.0. Use string literal instead. */ export enum BentoCardTitleSize { DEFAULT = 'default', SMALL = 'small', } export type BentoCardLink = Omit<BentoLinkProps, 'variant'>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<template> <div class="b-card" :class="cardConditionalClasses" :tabindex="tabIndex" data-testid="card" @click="onClick" @keydown.enter="onKeyDown" @keydown.space="onKeyDown" > <div v-if="hasSlot('image')" class="b-card__image"> <slot name="image"></slot> </div> <div v-if="showHeader" class="b-card__header" :class="cardHeaderConditionalClasses" :tabindex="headerTabIndex" :aria-controls="expandable && showCardBody ? cardId : null" :aria-expanded="expandable ? `${showContent}` : null" :role="expandable ? 'button' : null" @click="toggleExpansion" @keypress.enter="toggleExpansion" @keypress.space="toggleExpansion" > <div class="b-card__header-wrapper"> <div v-if="showTitleWrapper" class="b-card__header-slot-wrapper"> <div class="b-card__title-wrapper" :class="cardTitleWrapperConditionalClasses"> <div v-if="expandable" class="b-card__toggle" :class="cardToggleConditionalClasses"> <chevron-up-icon v-if="showContent" :svg-title="t('hideContent')" aria-hidden="true" /> <chevron-down-icon v-else :svg-title="t('showContent')" aria-hidden="true" /> </div> <bento-typography v-if="hasSlot('default')" class="b-card__title" v-bind="typography"> <slot /> </bento-typography> </div> <template v-if="hasSlot('header')"> <slot name="header"></slot> </template> </div> <bento-typography v-if="hasSlot('description')" class="b-card__description" el="div" variant="body"> <slot name="description" /> </bento-typography> </div> </div> <Transition name="b-card__animation"> <div v-if="showCardBody" class="b-card__wrapper" :style="contentMaxHeight"> <div :id="expandable ? cardId : null" ref="contentDiv" class="b-card__body" :class="cardBodyConditionalClasses" > <div v-if="hasSlot('content')" class="b-card__content" :class="cardContentConditionalClasses"> <slot name="content" /> </div> <div v-if="actions" class="b-card__actions" :class="cardActionsConditionalClasses"> <bento-button-actions :actions="actions" :layout="actionsLayout"></bento-button-actions> </div> </div> </div> </Transition> </div> </template> <script setup lang="ts"> import { computed, ref, useSlots, watch } from 'vue'; // Components import { BentoTypography } from '@/components/typography'; import { BentoButtonActions, BentoButtonActionsLayout, type BentoButtonActionsList } from '@/components/button'; import { BentoCardBackground, BentoCardTitleSize } from '@/components/card/card.types'; import ChevronDownIcon from '@adyen/ui-assets-icons-16/vue/chevron-down'; import ChevronUpIcon from '@adyen/ui-assets-icons-16/vue/chevron-up'; // Composables import { useExpandableContentHeight } from '@/composables/use-expandable-content-height/use-expandable-content-height'; // Utils import { useHasSlot } from '@/composables'; import { generateUid } from '@/core/utils/ts'; import { useI18n } from '@/utils/ts/i18n'; import messages from './messages.json'; import { deprecate } from '@/utils/ts/deprecate'; type MessageSchema = (typeof messages)['en-US']; const { t } = useI18n<{ message: MessageSchema }>({ messages }); const slots = useSlots(); const hasSlot = useHasSlot(slots); const props = withDefaults( defineProps<{ /** * List of actions that will be used to render the buttons. * First element in the list will be rendered as "primary". * All elements after the first will be rendered as "secondary". * * Each object in the list should have a `title`, an `event` and * (optional) a Vue `icon` from the library `@adyen/ui-assets-icons-16`. * * `title`: Button's text. * * `event`: Event triggered when clicking the Button. * * `icon`: Vue Icon from the library `@adyen/ui-assets-icons-16`. * * ``` * [{ * title: 'Primary', * event: () => { ... }, * icon: FourPeopleIcon * }, { * title: 'Secondary', * event: () => { ... } * }] * ``` */ actions?: BentoButtonActionsList; /** * Defines the layout in which the button actions is presented. * It can be one of: * * @values BUTTONS_START * @values BUTTONS_END * @values FILL_CONTAINER * @values SPACE_BETWEEN * @values VERTICAL_STACK */ actionsLayout?: BentoButtonActionsLayout | `${BentoButtonActionsLayout}`; /** * Defines the color of card background */ background?: BentoCardBackground | `${BentoCardBackground}`; /** * Makes the whole card clickable */ clickable?: boolean; /** * Sets the expandable card in a closed state */ closed?: boolean; /** * Disables the expandable card */ disabled?: boolean; /** * The whole content of the card will be expandable in accordion manner */ expandable?: boolean; /** * Defines the title size of the card header */ titleSize?: BentoCardTitleSize | `${BentoCardTitleSize}`; }>(), { actions: null, actionsLayout: BentoButtonActionsLayout.BUTTONS_END, background: BentoCardBackground.PRIMARY, clickable: false, closed: false, disabled: false, expandable: false, titleSize: BentoCardTitleSize.DEFAULT, } ); const emit = defineEmits<{ (e: 'click'); (e: 'expanded', isExpanded: boolean); }>(); const contentDiv = ref<HTMLDivElement>(null); const cardId = generateUid('card'); const showContent = ref(!props.closed); watch( () => props.closed, value => { showContent.value = !value; } ); const showHeader = computed(() => hasSlot('default') || hasSlot('description') || hasSlot('header')); const showTitleWrapper = computed(() => hasSlot('default') || hasSlot('header')); const showCardBody = computed( () => (hasSlot('content') || props.actions?.length) && (!props.expandable || (props.expandable && showContent.value)) ); const tabIndex = computed(() => (props.clickable && !props.disabled ? 0 : -1)); const headerTabIndex = computed(() => (props.expandable && !props.disabled ? 0 : -1)); const cardConditionalClasses = computed(() => ({ [`b-card--${props.background}`]: props.background, 'b-card--clickable': props.clickable, 'b-card--expandable': props.expandable, 'b-card--disabled': (props.clickable || props.expandable) && props.disabled, })); const cardHeaderConditionalClasses = computed(() => ({ 'b-card__header--expandable': props.expandable, 'b-card__header--without-body': !props.expandable && !showCardBody.value, })); const cardToggleConditionalClasses = computed(() => ({ 'b-card__toggle--small-text': props.titleSize === BentoCardTitleSize.SMALL, })); const cardBodyConditionalClasses = computed(() => ({ 'b-card__body--expandable': props.expandable && hasSlot('content'), 'b-card__body--without-header': !props.expandable && !showHeader.value, })); const cardContentConditionalClasses = computed(() => ({ 'b-card__content--without-header': !props.expandable && !showHeader.value, 'b-card__content--expandable': props.expandable, })); const cardActionsConditionalClasses = computed(() => { const isNotExpandableWithoutContent = !props.expandable && props.actions && !hasSlot('content'); return { 'b-card__actions--without-content': isNotExpandableWithoutContent, 'b-card__actions--without-content-and-with-header': isNotExpandableWithoutContent && showHeader.value, }; }); const cardTitleWrapperConditionalClasses = computed(() => ({ 'b-card__title-wrapper--truncated': hasSlot('header'), })); const typography = computed( () => ({ el: 'div', variant: props.titleSize === BentoCardTitleSize.DEFAULT ? 'title' : 'body', strongest: props.titleSize === BentoCardTitleSize.SMALL, wide: props.titleSize === BentoCardTitleSize.SMALL, }) as InstanceType<typeof BentoTypography>['$props'] ); // Toggle open and close logic and animation const { contentHeight } = useExpandableContentHeight(contentDiv, showContent); const contentMaxHeight = computed(() => props.expandable && contentHeight.value ? { 'max-height': contentHeight.value } : {} ); const toggleExpansion = () => { if (!props.disabled && props.expandable) { showContent.value = !showContent.value; emit('expanded', showContent.value); } }; const onClick = () => { if (!props.disabled) { emit('click'); if (!props.clickable) { deprecate( 'BentoCard "@click" property', `Use the BentoCard "@click" with the "clickable" property to enable accessible styles.`, '2.0.0' ); } } }; const onKeyDown = () => { if (props.clickable && !props.disabled) { emit('click'); } }; </script> <script lang="ts"> /** * A card is a flexible and composable container. * Use cards to represent a single object or to visually group certain content, like legal information within company settings. * * @example * import { BentoCard } from '@adyen/bento-vue2'; * * export default { * components: { BentoCard }, * template: ` * <bento-card> * Title of the Card * </bento-card> * ` * }; */ export default { i18n: { messages }, name: 'bento-card', }; </script> <style lang="scss" scoped src="./card.scss" />
|
|
1
|
+
<template> <div class="b-card" :class="cardConditionalClasses" :tabindex="tabIndex" data-testid="card" @click="onClick" @keydown.enter="onKeyDown" @keydown.space="onKeyDown" > <div v-if="hasSlot('image')" class="b-card__image"> <slot name="image"></slot> </div> <div v-if="showHeader" class="b-card__header" :class="cardHeaderConditionalClasses" :tabindex="headerTabIndex" :aria-controls="expandable && showCardBody ? cardId : null" :aria-expanded="expandable ? `${showContent}` : null" :role="expandable ? 'button' : null" @click="toggleExpansion" @keypress.enter="toggleExpansion" @keypress.space="toggleExpansion" > <div class="b-card__header-wrapper"> <div v-if="showTitleWrapper" class="b-card__header-slot-wrapper"> <div class="b-card__title-wrapper" :class="cardTitleWrapperConditionalClasses"> <div v-if="expandable" class="b-card__toggle" :class="cardToggleConditionalClasses"> <chevron-up-icon v-if="showContent" :svg-title="t('hideContent')" aria-hidden="true" /> <chevron-down-icon v-else :svg-title="t('showContent')" aria-hidden="true" /> </div> <template v-if="hasSlot('default')"> <bento-link v-if="link && isRegularCard" class="b-card__link" v-bind="link" variant="quiet" disable-typography > <bento-typography class="b-card__title" v-bind="typography" el="span"> <slot /> </bento-typography> <chevron-right-small-icon class="b-card__link-icon" aria-hidden="true" /> </bento-link> <bento-typography v-else class="b-card__title" v-bind="typography"> <slot /> </bento-typography> </template> </div> <template v-if="hasSlot('header')"> <slot name="header"></slot> </template> </div> <div v-if="hasSlot('description') || showLastUpdated" class="b-card__title-details"> <title-details :last-updated="showLastUpdated ? lastUpdated : null" :reload-button="showLastUpdated ? reloadButton : null" > <template v-if="hasSlot('description')" #description><slot name="description" /></template> </title-details> </div> </div> </div> <Transition name="b-card__animation"> <div v-if="showCardBody" class="b-card__wrapper" :style="contentMaxHeight"> <div :id="expandable ? cardId : null" ref="contentDiv" class="b-card__body" :class="cardBodyConditionalClasses" > <div v-if="hasSlot('content')" class="b-card__content" :class="cardContentConditionalClasses"> <slot name="content" /> </div> <div v-if="actions" class="b-card__actions" :class="cardActionsConditionalClasses"> <bento-button-actions :actions="actions" :layout="actionsLayout"></bento-button-actions> </div> </div> </div> </Transition> </div> </template> <script setup lang="ts"> import { computed, onMounted, ref, useSlots, watch } from 'vue'; // Components import { BentoTypography } from '@/components/typography'; import { BentoLink } from '@/components/link'; import { BentoButtonActions, BentoButtonActionsLayout, type BentoButtonActionsList } from '@/components/button'; import { BentoCardBackground, type BentoCardLink, type BentoCardReloadButton, BentoCardTitleSize, } from '@/components/card/card.types'; import { TitleDetails } from '@/internal/title-details'; import ChevronDownIcon from '@adyen/ui-assets-icons-16/vue/chevron-down'; import ChevronUpIcon from '@adyen/ui-assets-icons-16/vue/chevron-up'; import ChevronRightSmallIcon from '@adyen/ui-assets-icons-16/vue/chevron-right-small'; // Composables import { useExpandableContentHeight } from '@/composables/use-expandable-content-height/use-expandable-content-height'; // Utils import { useHasSlot } from '@/composables'; import { generateUid } from '@/utils/ts/generate-uid'; import { useI18n } from '@/utils/ts/i18n'; import messages from './messages.json'; import { deprecate } from '@/utils/ts/deprecate'; type MessageSchema = (typeof messages)['en-US']; const { t } = useI18n<{ message: MessageSchema }>({ messages }); const slots = useSlots(); const hasSlot = useHasSlot(slots); const props = withDefaults( defineProps<{ /** * List of actions that will be used to render the buttons. * First element in the list will be rendered as "primary". * All elements after the first will be rendered as "secondary". * * Each object in the list should have a `title`, an `event` and * (optional) a Vue `icon` from the library `@adyen/ui-assets-icons-16`. * * `title`: Button's text. * * `event`: Event triggered when clicking the Button. * * `icon`: Vue Icon from the library `@adyen/ui-assets-icons-16`. * * ``` * [{ * title: 'Primary', * event: () => { ... }, * icon: FourPeopleIcon * }, { * title: 'Secondary', * event: () => { ... } * }] * ``` */ actions?: BentoButtonActionsList; /** * Defines the layout in which the button actions is presented. * It can be one of: * * @values BUTTONS_START * @values BUTTONS_END * @values FILL_CONTAINER * @values SPACE_BETWEEN * @values VERTICAL_STACK */ actionsLayout?: BentoButtonActionsLayout | `${BentoButtonActionsLayout}`; /** * Defines the color of card background */ background?: BentoCardBackground | `${BentoCardBackground}`; /** * Makes the whole card clickable */ clickable?: boolean; /** * Sets the expandable card in a closed state */ closed?: boolean; /** * Disables the expandable card */ disabled?: boolean; /** * The whole content of the card will be expandable in accordion manner */ expandable?: boolean; /** * JavaScript "Date" object for when the content was last updated * * Only supported by regular (non-expandable) cards. */ lastUpdated?: Date | number; /** * Reload button which shows next to the card's timestamp * * Only supported by regular (non-expandable) cards. */ reloadButton?: BentoCardReloadButton; /** * Link properties to make the card title a navigable link. Can only be used with non-expandable cards. */ link?: BentoCardLink; /** * Defines the title size of the card header */ titleSize?: BentoCardTitleSize | `${BentoCardTitleSize}`; }>(), { actions: null, actionsLayout: BentoButtonActionsLayout.BUTTONS_END, background: BentoCardBackground.PRIMARY, clickable: false, closed: false, disabled: false, expandable: false, lastUpdated: null, reloadButton: null, link: undefined, titleSize: BentoCardTitleSize.DEFAULT, } ); const emit = defineEmits<{ (e: 'click'); (e: 'expanded', isExpanded: boolean); }>(); const contentDiv = ref<HTMLDivElement>(null); const cardId = generateUid('card'); const showContent = ref(!props.closed); watch( () => props.closed, value => { showContent.value = !value; } ); const showLastUpdated = computed(() => !props.expandable && Boolean(props.lastUpdated)); const showHeader = computed( () => hasSlot('default') || hasSlot('description') || hasSlot('header') || showLastUpdated.value ); const showTitleWrapper = computed(() => hasSlot('default') || hasSlot('header')); const showCardBody = computed( () => (hasSlot('content') || props.actions?.length) && (!props.expandable || (props.expandable && showContent.value)) ); const tabIndex = computed(() => (props.clickable && !props.disabled ? 0 : -1)); const headerTabIndex = computed(() => (props.expandable && !props.disabled ? 0 : -1)); const isRegularCard = computed(() => !props.expandable); const cardConditionalClasses = computed(() => ({ [`b-card--${props.background}`]: props.background, 'b-card--clickable': props.clickable, 'b-card--expandable': props.expandable, 'b-card--disabled': (props.clickable || props.expandable) && props.disabled, })); const cardHeaderConditionalClasses = computed(() => ({ 'b-card__header--expandable': props.expandable, 'b-card__header--without-body': !props.expandable && !showCardBody.value, })); const cardToggleConditionalClasses = computed(() => ({ 'b-card__toggle--small-text': props.titleSize === BentoCardTitleSize.SMALL, })); const cardBodyConditionalClasses = computed(() => ({ 'b-card__body--expandable': props.expandable && hasSlot('content'), 'b-card__body--without-header': !props.expandable && !showHeader.value, })); const cardContentConditionalClasses = computed(() => ({ 'b-card__content--without-header': !props.expandable && !showHeader.value, 'b-card__content--expandable': props.expandable, })); const cardActionsConditionalClasses = computed(() => { const isNotExpandableWithoutContent = !props.expandable && props.actions && !hasSlot('content'); return { 'b-card__actions--without-content': isNotExpandableWithoutContent, 'b-card__actions--without-content-and-with-header': isNotExpandableWithoutContent && showHeader.value, }; }); const cardTitleWrapperConditionalClasses = computed(() => ({ 'b-card__title-wrapper--truncated': hasSlot('header'), })); const typography = computed( () => ({ el: 'div', variant: props.titleSize === BentoCardTitleSize.DEFAULT ? 'title' : 'body', strongest: props.titleSize === BentoCardTitleSize.SMALL, wide: props.titleSize === BentoCardTitleSize.SMALL, }) as InstanceType<typeof BentoTypography>['$props'] ); // Toggle open and close logic and animation const { contentHeight } = useExpandableContentHeight(contentDiv, showContent); const contentMaxHeight = computed(() => props.expandable && contentHeight.value ? { 'max-height': contentHeight.value } : {} ); const toggleExpansion = () => { if (!props.disabled && props.expandable) { showContent.value = !showContent.value; emit('expanded', showContent.value); } }; const onClick = () => { if (!props.disabled) { emit('click'); if (!props.clickable) { deprecate( 'BentoCard "@click" property', `Use the BentoCard "@click" with the "clickable" property to enable accessible styles.`, '3.0.0' ); } } }; const onKeyDown = () => { if (props.clickable && !props.disabled) { emit('click'); } }; onMounted(() => { if (props.link && props.clickable) { throw new Error( 'Do not combine the BentoCard "link" property with the "clickable" property. Nested interactive controls create a confusing and inaccessible experience for users of assistive technologies.' ); } }); </script> <script lang="ts"> /** * A card is a flexible and composable container. * Use cards to represent a single object or to visually group certain content, like legal information within company settings. * * @example * import { BentoCard } from '@adyen/bento-vue2'; * * export default { * components: { BentoCard }, * template: ` * <bento-card> * Title of the Card * </bento-card> * ` * }; */ export default { i18n: { messages }, name: 'bento-card', }; </script> <style lang="scss" scoped src="./card.scss" />
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { ref } from 'vue'; import { BentoCheckboxEvent } from './checkbox.types'; import { type Meta, type StoryObj } from '@storybook/vue'; import { isVue2 } from 'vue-demi'; import BentoCheckbox from './checkbox.vue'; const DEFAULT_LABEL = 'Label text'; const DEFAULT_SUB_LABEL = 'Description below label'; const ERROR_MESSAGE = 'Error message text'; export default { title: 'Checkbox', component: BentoCheckbox, argTypes: { default: { name: 'default', defaultValue: '', description: 'Label text slot', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text', }, }, description: { name: 'description', defaultValue: '', description: 'Description text slot', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text', }, }, content: { name: 'content', defaultValue: '', description: 'Content slot available via checkbox group only', table: { type: { summary: 'VNode[]' }, }, }, [BentoCheckboxEvent.UPDATE]: { name: BentoCheckboxEvent.UPDATE, defaultValue: '', description: 'Input event handler.', table: { type: { summary: '(newModelValue: BentoCheckboxType | BentoCheckboxGroupItems) => void' }, }, control: { disable: true }, }, [BentoCheckboxEvent.INPUT]: { name: BentoCheckboxEvent.INPUT, defaultValue: '', description: 'Input event handler.', table: { type: { summary: '(newModelValue: BentoCheckboxType | BentoCheckboxGroupItems) => void' }, }, control: { disable: true }, }, }, } as Meta; type Story = StoryObj<typeof BentoCheckbox>; const
|
|
1
|
+
import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { ref } from 'vue'; import { BentoCheckboxEvent } from './checkbox.types'; import { type Meta, type StoryObj } from '@storybook/vue'; import { isVue2 } from 'vue-demi'; import BentoCheckbox from './checkbox.vue'; const CheckboxDefault = "<template>\n <div>\n <!-- With model-value -->\n <bento-checkbox :model-value=\"selectedValue\" @update:model-value=\"selectedValue = $event\">\n Label text\n <template #description>Description below label</template>\n </bento-checkbox>\n\n <!-- With v-model in Vue 2 and Vue 3 -->\n <bento-checkbox v-model=\"selectedValue\">\n Label text\n <template #description>Description below label</template>\n </bento-checkbox>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCheckbox, type BentoCheckboxType } from '@adyen/bento-vue2';\n\n const selectedValue = ref<BentoCheckboxType>(false);\n</script>\n"; const CheckboxDisabled = "<template>\n <bento-checkbox v-model=\"selectedValue\" disabled>I am disabled</bento-checkbox>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCheckbox, type BentoCheckboxType } from '@adyen/bento-vue2';\n\n const selectedValue = ref<BentoCheckboxType>(false);\n</script>\n"; const CheckboxError = "<template>\n <bento-checkbox v-model=\"selectedValue\" has-error>I am in error state</bento-checkbox>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCheckbox, type BentoCheckboxType } from '@adyen/bento-vue2';\n\n const selectedValue = ref<BentoCheckboxType>(false);\n</script>\n"; const CheckboxErrorMessage = "<template>\n <bento-checkbox v-model=\"selectedValue\" error-message=\"Error message text\">\n I have an error message\n </bento-checkbox>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCheckbox, type BentoCheckboxType } from '@adyen/bento-vue2';\n\n const selectedValue = ref<BentoCheckboxType>(false);\n</script>\n"; const CheckboxIndeterminate = "<template>\n <bento-checkbox v-model=\"selectedValue\" indeterminate> I am indeterminate </bento-checkbox>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCheckbox, type BentoCheckboxType } from '@adyen/bento-vue2';\n\n const selectedValue = ref<BentoCheckboxType>(false);\n</script>\n"; const DEFAULT_LABEL = 'Label text'; const DEFAULT_SUB_LABEL = 'Description below label'; const ERROR_MESSAGE = 'Error message text'; export default { title: 'Checkbox', component: BentoCheckbox, argTypes: { default: { name: 'default', defaultValue: '', description: 'Label text slot', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text', }, }, description: { name: 'description', defaultValue: '', description: 'Description text slot', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text', }, }, content: { name: 'content', defaultValue: '', description: 'Content slot available via checkbox group only', table: { type: { summary: 'VNode[]' }, }, }, [BentoCheckboxEvent.UPDATE]: { name: BentoCheckboxEvent.UPDATE, defaultValue: '', description: 'Input event handler.', table: { type: { summary: '(newModelValue: BentoCheckboxType | BentoCheckboxGroupItems) => void' }, }, control: { disable: true }, }, [BentoCheckboxEvent.INPUT]: { name: BentoCheckboxEvent.INPUT, defaultValue: '', description: 'Input event handler.', table: { type: { summary: '(newModelValue: BentoCheckboxType | BentoCheckboxGroupItems) => void' }, }, control: { disable: true }, }, }, } as Meta; type Story = StoryObj<typeof BentoCheckbox>; const Basic: Story = { render: (_args, { argTypes }) => ({ components: { BentoCheckbox }, props: Object.keys(argTypes), template: ` <bento-checkbox v-bind="args" :model-value="selectedValue" @update:model-value="clickedAction"> {{ args.default }} <template #description>{{ args.description }}</template> </bento-checkbox> `, setup(props) { const selectedValue = ref(undefined); const clickedAction = value => { selectedValue.value = value; action(BentoCheckboxEvent.UPDATE)(value); }; return { // Values selectedValue, args: isVue2 ? props : _args, // Events clickedAction, }; }, }), }; export const Default: Story = { ...Basic, args: { default: DEFAULT_LABEL, description: DEFAULT_SUB_LABEL, }, parameters: storybookDocsParameter(CheckboxDefault), }; export const Disabled: Story = { ...Basic, args: { default: 'I am disabled', disabled: true, }, parameters: storybookDocsParameter(CheckboxDisabled), }; export const Indeterminate = { ...Basic, args: { default: 'I am indeterminate', indeterminate: true, }, parameters: storybookDocsParameter(CheckboxIndeterminate), }; export const Error = { ...Basic, args: { default: 'I am in error state', hasError: true, }, parameters: storybookDocsParameter(CheckboxError), }; export const ErrorMessage = { ...Basic, args: { default: 'I have an error message', errorMessage: ERROR_MESSAGE, }, parameters: storybookDocsParameter(CheckboxErrorMessage), };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import type { BentoTagProps } from '../tag/tag.types';
|
|
1
|
+
import type { BentoTagProps } from '../tag/tag.types'; export enum BentoCheckboxEvent { UPDATE = 'update:model-value', INPUT = 'input', } export type BentoCheckboxTag = BentoTagProps;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<template> <label class="b-checkbox" :class="conditionalClass" v-bind="styleAttrs" :aria-hidden="getAriaHidden($attrs)"> <checkbox-input v-bind="$attrs" ref="input" :aria-label="computedAriaLabel" :aria-describedby="ariaDescribedBy" :aria-required="required" :disabled="disabled" :has-error="shouldShowError" :indeterminate="isIndeterminate" :value="value" :model-value="modelValue" :readonly="readonly" @update:model-value="onChange" /> <span v-if="hasSlot('default') || shouldShowErrorMessage" class="b-checkbox__text"> <bento-typography v-if="hasSlot('default')" class="b-checkbox__label" el="span" variant="body"> <span><slot /></span> <bento-typography v-if="optional" class="b-checkbox__label-requirement" el="span" >({{ t('optional') }})</bento-typography > <bento-typography v-else-if="required" class="b-checkbox__label-requirement" el="span" >*</bento-typography > <bento-tag v-if="tag" class="b-checkbox__label-tag" v-bind="tag" /> </bento-typography> <bento-typography v-if="hasSlot('default') && hasSlot('description')" :id="descriptionId" class="b-checkbox__description" el="span" variant="body" > <slot name="description"></slot> </bento-typography> <error-message v-if="shouldShowErrorMessage" :id="errorId" :error-message="errorMessage" /> <bento-typography v-if="contentSlotAvailable" class="b-checkbox__content" el="span" variant="body"> <slot name="content"></slot> </bento-typography> </span> </label> </template> <script lang="ts"> import { computed, defineComponent, type HTMLAttributes, onMounted, type PropType, ref, toRefs, useAttrs, } from 'vue'; import { BentoCheckboxEvent,
|
|
1
|
+
<template> <label class="b-checkbox" :class="conditionalClass" v-bind="styleAttrs" :aria-hidden="getAriaHidden($attrs)"> <checkbox-input v-bind="$attrs" ref="input" :aria-label="computedAriaLabel" :aria-describedby="ariaDescribedBy" :aria-required="required" :disabled="disabled" :has-error="shouldShowError" :indeterminate="isIndeterminate" :value="value" :model-value="modelValue" :readonly="readonly" @update:model-value="onChange" /> <span v-if="hasSlot('default') || shouldShowErrorMessage" class="b-checkbox__text"> <bento-typography v-if="hasSlot('default')" class="b-checkbox__label" el="span" variant="body"> <span><slot /></span> <bento-typography v-if="optional" class="b-checkbox__label-requirement" el="span" >({{ t('optional') }})</bento-typography > <bento-typography v-else-if="required" class="b-checkbox__label-requirement" el="span" >*</bento-typography > <bento-tag v-if="tag" class="b-checkbox__label-tag" v-bind="tag" /> </bento-typography> <bento-typography v-if="hasSlot('default') && hasSlot('description')" :id="descriptionId" class="b-checkbox__description" el="span" variant="body" > <slot name="description"></slot> </bento-typography> <error-message v-if="shouldShowErrorMessage" :id="errorId" :error-message="errorMessage" /> <bento-typography v-if="contentSlotAvailable" class="b-checkbox__content" el="span" variant="body"> <slot name="content"></slot> </bento-typography> </span> </label> </template> <script lang="ts"> import { computed, defineComponent, type HTMLAttributes, onMounted, type PropType, ref, toRefs, useAttrs, } from 'vue'; import { BentoCheckboxEvent, type BentoCheckboxTag } from './checkbox.types'; import { BentoTypography } from '@/components/typography'; import { CheckboxInput } from '@/components/internal/checkbox-input'; import { ErrorMessage } from '@/components/internal/error-message'; import { useDefaultSlotValidator, useHasSlot } from '@/composables'; import { generateUid } from '@/utils/ts/generate-uid'; import { getSlotText } from '@/utils/ts/get-slot-text'; import { useI18n } from '@/utils/ts/i18n'; import { useAriaLabel } from '@/utils/ts/aria-label'; import { BentoCheckboxState, type BentoCheckboxType, type BentoMultiCheckboxType } from '@/types/checkbox'; import { BentoTag } from '@/components/tag'; import { type BentoCheckboxGroupItems } from './components/checkbox-group/checkbox-group.types'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; /** * Checkboxes are used to make a binary choice about an option. * The label tag area is also clickable. * * @usage * import { BentoCheckbox } from '@adyen/bento-vue2'; * * export default { * components: { BentoCheckbox }, * template: ` * <bento-checkbox> * Label text * <template #description>Sub label text</template> * </bento-checkbox> * `, * } */ export default defineComponent({ name: 'bento-checkbox', i18n: { messages }, components: { BentoTag, BentoTypography, CheckboxInput, ErrorMessage, }, inheritAttrs: false, model: { prop: 'modelValue' }, props: { /** * @deprecated Since v3.0.0. Use `aria-label` instead. * Accessible name for the radio button component. It is strongly recommended to pas this value in case this component is used without a label. */ ariaLabel: { type: String, default: null }, /** * Setting this property to true will disable the checkbox in your form. */ disabled: { type: Boolean, default: false }, /** * Renders the checkbox in an error state with an error message. */ errorMessage: { type: String, default: null }, /** * Setting this property to true will show the checkbox in error state. */ hasError: { type: Boolean, default: false }, /** * The :indeterminate CSS pseudo-class represents any form element * whose state is indeterminate, such as checkboxes which have their HTML indeterminate attribute * set to true, radio buttons which are members of a group in which all radio buttons are unchecked, * and indeterminate <progress> elements. https://developer.mozilla.org/en-US/docs/Web/CSS/:indeterminate * This property lets you control the input.indeterminate native property. */ indeterminate: { type: Boolean, default: false }, /** * When handling a single checkbox with a singular state, use a boolean. * * When handling multiple checkboxes, use an array of keys. * These keys exist as a set "value" prop for each checkbox. */ modelValue: { type: [Boolean, Array] as PropType<BentoCheckboxType | BentoCheckboxGroupItems>, default: false, }, /** * Highlights the checkbox is optional. */ optional: { type: Boolean, default: false }, /** * Setting this property to true will set the checkbox to read only state. */ readonly: { type: Boolean, default: false }, /** * Highlights the checkbox is required. */ required: { type: Boolean, default: false }, /** * Sets the properties of the BentoTag component that is placed next to the label. * {@see BentoTag} */ tag: { type: Object as PropType<BentoCheckboxTag>, default: undefined }, /** * The value of the component. The DOM API casts this to a string. * The browser uses "on" as the default value. * * In the case of multiple checkboxes this value is used as a unique key. */ value: { type: [String, Number], default: null }, }, emits: [BentoCheckboxEvent.UPDATE, BentoCheckboxEvent.INPUT], setup(props, { attrs, emit, slots }) { const { t } = useI18n<{ message: MessageSchema }>({ messages }); const descriptionId = generateUid('description'); const errorId = generateUid('error'); const hasSlot = useHasSlot(slots); const { disabled, indeterminate, modelValue, readonly, value } = toRefs(props); const defaultSlotValue = getSlotText(slots)('default'); const descriptionSlotValue = getSlotText(slots)('description'); useDefaultSlotValidator('bento-checkbox', slots.default, slots.description); const isCheckboxGroup = computed(() => Array.isArray(modelValue.value)); const isChecked = computed(() => { if (!isCheckboxGroup.value) { return modelValue.value as boolean; } return (modelValue.value as BentoMultiCheckboxType).some(item => item === value.value); }); const isIndeterminate = computed(() => indeterminate.value); const shouldShowError = computed( () => !props.disabled && !props.readonly && (props.hasError || !!props.errorMessage) ); const shouldShowErrorMessage = computed(() => !props.disabled && !props.readonly && !!props.errorMessage); // Content slot logic const hasContentSlot = computed(() => hasSlot('content')); const isCheckedOrIntermediate = computed(() => isIndeterminate?.value || isChecked?.value); const contentSlotAvailable = computed( () => hasContentSlot?.value && isCheckboxGroup?.value && isCheckedOrIntermediate?.value ); // ARIA fields const ariaDescribedBy = computed<HTMLAttributes['aria-describedby']>( () => `${shouldShowErrorMessage.value ? errorId : ''} ${ defaultSlotValue && descriptionSlotValue ? descriptionId : '' }`.trim() || null ); const ariaLabelAttribute = ref(attrs['aria-label']); const { ariaLabel } = toRefs(props); const checkboxTranslation = ref(); // Translations used in the script tag need to be inside onMounted otherwise they fail in Vue 3 onMounted(() => { checkboxTranslation.value = t('checkbox'); }); // Only add aria-label if no label slot is present const computedAriaLabel = computed( () => useAriaLabel({ ariaLabel: ariaLabelAttribute.value as string, // TODO: take this line away when the aria-label props is removed label: ariaLabel, defaultFallback: hasSlot('default') ? (getSlotText(slots)('default') as string) : checkboxTranslation.value, }).value ); const getAriaHidden = (attributes: HTMLAttributes) => attributes?.['aria-hidden']; const styleAttrs = computed(() => { const { style, class: cls } = useAttrs(); return { class: cls as HTMLAttributes['class'], style: style as HTMLAttributes['style'], }; }); const conditionalClass = computed(() => ({ [`b-checkbox--${BentoCheckboxState.DISABLED}`]: disabled.value, [`b-checkbox--${BentoCheckboxState.READONLY}`]: readonly.value, })); const onChange = (newValue: BentoCheckboxType | BentoCheckboxGroupItems) => { if (disabled.value) { return; } emit(BentoCheckboxEvent.UPDATE, newValue); emit(BentoCheckboxEvent.INPUT, newValue); }; return { // Values descriptionId, errorId, ariaDescribedBy, computedAriaLabel, conditionalClass, defaultSlotValue, descriptionSlotValue, isIndeterminate, shouldShowError, shouldShowErrorMessage, contentSlotAvailable, hasContentSlot, styleAttrs, // Methods hasSlot, onChange, getAriaHidden, t, }; }, }); </script> <style lang="scss" scoped src="./checkbox.scss" />
|