@xplortech/apollo-core 3.2.1 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +17 -0
- package/README.md +1 -1
- package/build/components/accordion.css +1 -1
- package/build/components/badge.css +1 -1
- package/build/components/banner.css +1 -1
- package/build/components/breadcrumbs.css +1 -1
- package/build/components/button.css +1 -1
- package/build/components/choicelist.css +1 -1
- package/build/components/data-card.css +1 -1
- package/build/components/divider.css +1 -1
- package/build/components/dropdown.css +1 -1
- package/build/components/dynamic-table-cell.css +1 -1
- package/build/components/header-accordion.css +1 -1
- package/build/components/icon.css +1 -1
- package/build/components/input-color.css +1 -1
- package/build/components/input-file.css +1 -1
- package/build/components/input-search.css +1 -1
- package/build/components/input.css +1 -1
- package/build/components/label.css +1 -1
- package/build/components/large-card.css +1 -1
- package/build/components/list-item.css +1 -1
- package/build/components/main-nav.css +1 -1
- package/build/components/modal.css +1 -1
- package/build/components/nav-item.css +1 -1
- package/build/components/pagination.css +1 -1
- package/build/components/secondary-nav.css +1 -1
- package/build/components/select.css +1 -1
- package/build/components/side-nav.css +1 -1
- package/build/components/slideout.css +1 -1
- package/build/components/spotlight.css +1 -1
- package/build/components/table-cell-base.css +1 -1
- package/build/components/table-header-cell.css +1 -1
- package/build/components/table.css +1 -1
- package/build/components/tag.css +1 -1
- package/build/components/toast.css +1 -1
- package/build/components/toggle.css +1 -1
- package/build/components/toolbar.css +1 -1
- package/build/components/tooltip.css +1 -1
- package/build/components/top-nav.css +1 -1
- package/build/core.css +1 -1
- package/build/style.css +1 -1
- package/build/typography.css +1 -1
- package/build/variables/apollo.css +31 -19
- package/build/variables/field-edge.css +33 -19
- package/build/vendor/flatpickr.css +1 -1
- package/dist/apollo-core/apollo-core.css +1 -1
- package/dist/apollo-core/apollo-core.esm.js +1 -1
- package/dist/apollo-core/{p-a0d3b7f8.entry.js → p-00e96d61.entry.js} +1 -1
- package/dist/apollo-core/{p-715baae0.entry.js → p-02a2d1a3.entry.js} +1 -1
- package/dist/apollo-core/p-035ed1ad.entry.js +1 -0
- package/dist/apollo-core/{p-aeb2bcb8.entry.js → p-066d3199.entry.js} +1 -1
- package/dist/apollo-core/{p-7eb02cf3.entry.js → p-066eccd6.entry.js} +1 -1
- package/dist/apollo-core/p-0e8514ff.entry.js +1 -0
- package/dist/apollo-core/{p-3417c1ce.entry.js → p-18115cd4.entry.js} +1 -1
- package/dist/apollo-core/{p-8f8f4759.entry.js → p-19d22455.entry.js} +1 -1
- package/dist/apollo-core/{p-24fa8a03.entry.js → p-1b00e924.entry.js} +1 -1
- package/dist/apollo-core/{p-49531864.entry.js → p-1ca46c11.entry.js} +1 -1
- package/dist/apollo-core/{p-bc821e69.entry.js → p-1e07745c.entry.js} +1 -1
- package/dist/apollo-core/{p-3713cd77.entry.js → p-31cbb36f.entry.js} +1 -1
- package/dist/apollo-core/p-321319c0.entry.js +1 -0
- package/dist/apollo-core/p-3222e5a7.entry.js +1 -0
- package/dist/apollo-core/{p-fcb17ff9.entry.js → p-325466bf.entry.js} +1 -1
- package/dist/apollo-core/p-32ac676a.entry.js +1 -0
- package/dist/apollo-core/{p-d469bf5d.entry.js → p-33063e8c.entry.js} +1 -1
- package/dist/apollo-core/{p-ff16f574.entry.js → p-34d84be8.entry.js} +1 -1
- package/dist/apollo-core/{p-b3b4678b.entry.js → p-36965939.entry.js} +1 -1
- package/dist/apollo-core/{p-7d70e089.entry.js → p-43fbf2aa.entry.js} +1 -1
- package/dist/apollo-core/p-44a1fd8b.entry.js +1 -0
- package/dist/apollo-core/p-462a804c.entry.js +1 -0
- package/dist/apollo-core/{p-808f3d9c.entry.js → p-47a4f0a8.entry.js} +1 -1
- package/dist/apollo-core/p-5cf30b9d.entry.js +1 -0
- package/dist/apollo-core/{p-f579e4b0.entry.js → p-606153e1.entry.js} +1 -1
- package/dist/apollo-core/{p-5c3be343.entry.js → p-60e3a798.entry.js} +1 -1
- package/dist/apollo-core/{p-14e86de8.entry.js → p-663e9521.entry.js} +1 -1
- package/dist/apollo-core/{p-11914cd4.entry.js → p-6e22ab86.entry.js} +1 -1
- package/dist/apollo-core/{p-907bc21e.entry.js → p-7781b569.entry.js} +1 -1
- package/dist/apollo-core/p-787a361c.entry.js +1 -0
- package/dist/apollo-core/{p-e09d8beb.entry.js → p-7b46b656.entry.js} +1 -1
- package/dist/apollo-core/p-7bfd9cfb.entry.js +1 -0
- package/dist/apollo-core/{p-f384a990.entry.js → p-8127dd6b.entry.js} +1 -1
- package/dist/apollo-core/{p-b64ed46d.entry.js → p-88367287.entry.js} +1 -1
- package/dist/apollo-core/p-8a59605f.entry.js +1 -0
- package/dist/apollo-core/p-8df2b9e8.entry.js +1 -0
- package/dist/apollo-core/p-9466f566.entry.js +1 -0
- package/dist/apollo-core/p-95b6e6e6.entry.js +1 -0
- package/dist/apollo-core/{p-8845106f.entry.js → p-966f3702.entry.js} +1 -1
- package/dist/apollo-core/{p-45c872d2.entry.js → p-9d7ead72.entry.js} +1 -1
- package/dist/apollo-core/p-CgJEmBQY.js +3 -0
- package/dist/apollo-core/{p-ca83003e.entry.js → p-a21c7976.entry.js} +1 -1
- package/dist/apollo-core/p-a30b51c8.entry.js +1 -0
- package/dist/apollo-core/p-a3537a74.entry.js +1 -0
- package/dist/apollo-core/{p-9d731673.entry.js → p-ac105b6c.entry.js} +1 -1
- package/dist/apollo-core/{p-2971e2ec.entry.js → p-adc14e6e.entry.js} +1 -1
- package/dist/apollo-core/p-b41b7950.entry.js +1 -0
- package/dist/apollo-core/{p-256ece8b.entry.js → p-b44a72e9.entry.js} +1 -1
- package/dist/apollo-core/{p-d3ada7d0.entry.js → p-b6f20359.entry.js} +1 -1
- package/dist/apollo-core/{p-df257cbf.entry.js → p-b7f75498.entry.js} +1 -1
- package/dist/apollo-core/p-b9136f21.entry.js +1 -0
- package/dist/apollo-core/{p-c5bc3b2c.entry.js → p-c526f16d.entry.js} +1 -1
- package/dist/apollo-core/p-c7b8a325.entry.js +1 -0
- package/dist/apollo-core/p-c9246567.entry.js +1 -0
- package/dist/apollo-core/p-cc04d4e7.entry.js +1 -0
- package/dist/apollo-core/p-cc27a41f.entry.js +1 -0
- package/dist/apollo-core/{p-050a8bf2.entry.js → p-d58523b6.entry.js} +1 -1
- package/dist/apollo-core/p-d7fba438.entry.js +1 -0
- package/dist/apollo-core/p-db998e2a.entry.js +1 -0
- package/dist/apollo-core/{p-ee68bed6.entry.js → p-e1f095dd.entry.js} +1 -1
- package/dist/apollo-core/{p-9feaa8be.entry.js → p-e30d204d.entry.js} +1 -1
- package/dist/apollo-core/{p-eba654a3.entry.js → p-e4649020.entry.js} +1 -1
- package/dist/apollo-core/p-ebe6a1d6.entry.js +1 -0
- package/dist/apollo-core/{p-9905c77c.entry.js → p-f0897ee2.entry.js} +1 -1
- package/dist/apollo-core/{p-64f5c129.entry.js → p-f13e14bd.entry.js} +1 -1
- package/dist/apollo-core/p-f88eefaf.entry.js +1 -0
- package/dist/apollo-core/p-fd2e7bb0.entry.js +1 -0
- package/dist/cjs/apollo-core.cjs.js +2 -2
- package/dist/cjs/{index-3cBvw409.js → index-CQbPtJas.js} +53 -165
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/xpl-accordion.cjs.entry.js +3 -3
- package/dist/cjs/xpl-application-shell.cjs.entry.js +2 -2
- package/dist/cjs/xpl-avatar_3.cjs.entry.js +5 -5
- package/dist/cjs/xpl-backdrop.cjs.entry.js +2 -2
- package/dist/cjs/xpl-badge.cjs.entry.js +2 -2
- package/dist/cjs/xpl-banner.cjs.entry.js +3 -3
- package/dist/cjs/xpl-breadcrumb-item.cjs.entry.js +2 -2
- package/dist/cjs/xpl-breadcrumbs.cjs.entry.js +2 -2
- package/dist/cjs/xpl-button-row.cjs.entry.js +2 -2
- package/dist/cjs/xpl-button.cjs.entry.js +3 -3
- package/dist/cjs/xpl-calendar.cjs.entry.js +2 -2
- package/dist/cjs/xpl-checkbox.cjs.entry.js +4 -4
- package/dist/cjs/xpl-choicelist.cjs.entry.js +2 -2
- package/dist/cjs/xpl-content-area.cjs.entry.js +2 -2
- package/dist/cjs/xpl-dashboard.cjs.entry.js +2 -2
- package/dist/cjs/xpl-data-card.cjs.entry.js +3 -3
- package/dist/cjs/xpl-dropdown_4.cjs.entry.js +9 -9
- package/dist/cjs/xpl-dynamic-table-cell.cjs.entry.js +3 -3
- package/dist/cjs/xpl-dynamic-table-row.cjs.entry.js +3 -3
- package/dist/cjs/xpl-dynamic-table.cjs.entry.js +3 -3
- package/dist/cjs/xpl-grid-item.cjs.entry.js +2 -2
- package/dist/cjs/xpl-grid.cjs.entry.js +1 -1
- package/dist/cjs/xpl-header-accordion.cjs.entry.js +2 -2
- package/dist/cjs/xpl-icon.cjs.entry.js +3 -6
- package/dist/cjs/xpl-input-color.cjs.entry.js +9 -9
- package/dist/cjs/xpl-input-phone.cjs.entry.js +1 -1
- package/dist/cjs/xpl-input-time.cjs.entry.js +1 -1
- package/dist/cjs/xpl-input_4.cjs.entry.js +6 -6
- package/dist/cjs/xpl-large-card.cjs.entry.js +2 -2
- package/dist/cjs/xpl-list-item.cjs.entry.js +1 -1
- package/dist/cjs/xpl-list.cjs.entry.js +3 -3
- package/dist/cjs/xpl-main-nav.cjs.entry.js +2 -2
- package/dist/cjs/xpl-modal.cjs.entry.js +1 -1
- package/dist/cjs/xpl-nav-header-menu.cjs.entry.js +3 -3
- package/dist/cjs/xpl-nav-item.cjs.entry.js +3 -3
- package/dist/cjs/xpl-pagination.cjs.entry.js +1 -1
- package/dist/cjs/xpl-panel.cjs.entry.js +1 -1
- package/dist/cjs/xpl-popover.cjs.entry.js +5 -5
- package/dist/cjs/xpl-progress-bar.cjs.entry.js +1 -1
- package/dist/cjs/xpl-progress-indicator.cjs.entry.js +1 -1
- package/dist/cjs/xpl-secondary-nav.cjs.entry.js +2 -2
- package/dist/cjs/xpl-select_2.cjs.entry.js +10 -10
- package/dist/cjs/xpl-side-nav-header-item.cjs.entry.js +1 -1
- package/dist/cjs/xpl-side-nav-item.cjs.entry.js +3 -3
- package/dist/cjs/xpl-side-nav-section.cjs.entry.js +6 -6
- package/dist/cjs/xpl-side-nav.cjs.entry.js +3 -3
- package/dist/cjs/xpl-skeleton.cjs.entry.js +1 -1
- package/dist/cjs/xpl-slideout.cjs.entry.js +2 -2
- package/dist/cjs/xpl-spotlight.cjs.entry.js +1 -1
- package/dist/cjs/xpl-tab-panel.cjs.entry.js +3 -3
- package/dist/cjs/xpl-tab.cjs.entry.js +1 -1
- package/dist/cjs/xpl-table-body.cjs.entry.js +2 -2
- package/dist/cjs/xpl-table-cell_3.cjs.entry.js +5 -5
- package/dist/cjs/xpl-table-footer.cjs.entry.js +2 -2
- package/dist/cjs/xpl-table-header.cjs.entry.js +2 -2
- package/dist/cjs/xpl-table-row.cjs.entry.js +3 -3
- package/dist/cjs/xpl-table.cjs.entry.js +1 -1
- package/dist/cjs/xpl-tabs.cjs.entry.js +1 -1
- package/dist/cjs/xpl-toast.cjs.entry.js +3 -3
- package/dist/cjs/xpl-toggle.cjs.entry.js +1 -1
- package/dist/cjs/xpl-toolbar.cjs.entry.js +3 -3
- package/dist/cjs/xpl-tooltip.cjs.entry.js +2 -2
- package/dist/cjs/xpl-top-nav-item.cjs.entry.js +3 -3
- package/dist/cjs/xpl-top-nav-menu.cjs.entry.js +3 -3
- package/dist/cjs/xpl-top-nav.cjs.entry.js +6 -6
- package/dist/cjs/xpl-utility-bar.cjs.entry.js +2 -2
- package/dist/collection/collection-manifest.json +1 -1
- package/dist/collection/components/xpl-accordion/xpl-accordion.js +2 -2
- package/dist/collection/components/xpl-application-shell/xpl-application-shell.js +1 -1
- package/dist/collection/components/xpl-avatar/xpl-avatar.js +8 -8
- package/dist/collection/components/xpl-backdrop/xpl-backdrop.js +1 -1
- package/dist/collection/components/xpl-badge/xpl-badge.js +3 -3
- package/dist/collection/components/xpl-banner/xpl-banner.js +2 -2
- package/dist/collection/components/xpl-breadcrumbs/xpl-breadcrumb-item/xpl-breadcrumb-item.js +1 -1
- package/dist/collection/components/xpl-breadcrumbs/xpl-breadcrumbs/xpl-breadcrumbs.js +1 -1
- package/dist/collection/components/xpl-button/xpl-button.js +2 -2
- package/dist/collection/components/xpl-button-row/xpl-button-row.js +1 -1
- package/dist/collection/components/xpl-calendar/xpl-calendar.js +1 -1
- package/dist/collection/components/xpl-checkbox/xpl-checkbox.js +3 -3
- package/dist/collection/components/xpl-choicelist/xpl-choicelist.js +2 -2
- package/dist/collection/components/xpl-content-area/xpl-content-area.js +1 -1
- package/dist/collection/components/xpl-dashboard/xpl-dashboard.js +1 -1
- package/dist/collection/components/xpl-data-card/xpl-data-card.js +2 -2
- package/dist/collection/components/xpl-divider/xpl-divider.js +1 -1
- package/dist/collection/components/xpl-dropdown/xpl-dropdown-group/xpl-dropdown-group.js +2 -2
- package/dist/collection/components/xpl-dropdown/xpl-dropdown-heading/xpl-dropdown-heading.js +1 -1
- package/dist/collection/components/xpl-dropdown/xpl-dropdown-option/xpl-dropdown-option.js +2 -2
- package/dist/collection/components/xpl-dropdown/xpl-dropdown.js +11 -10
- package/dist/collection/components/xpl-dynamic-table/xpl-dynamic-table.js +2 -2
- package/dist/collection/components/xpl-dynamic-table-cell/xpl-dynamic-table-cell.js +2 -2
- package/dist/collection/components/xpl-dynamic-table-row/xpl-dynamic-table-row.js +2 -2
- package/dist/collection/components/xpl-grid-item/xpl-grid-item.js +1 -1
- package/dist/collection/components/xpl-header-accordion/xpl-header-accordion.js +1 -1
- package/dist/collection/components/xpl-icon/xpl-icon.js +2 -12
- package/dist/collection/components/xpl-input/xpl-input-color/xpl-input-color.js +8 -8
- package/dist/collection/components/xpl-input/xpl-input-date/xpl-input-date.js +3 -3
- package/dist/collection/components/xpl-input/xpl-input.js +2 -2
- package/dist/collection/components/xpl-large-card/xpl-large-card.js +1 -1
- package/dist/collection/components/xpl-list/xpl-list-item/xpl-list-item.js +2 -2
- package/dist/collection/components/xpl-list/xpl-list.js +4 -4
- package/dist/collection/components/xpl-main-nav/xpl-main-nav.js +1 -1
- package/dist/collection/components/xpl-nav-item/xpl-nav-item.js +2 -2
- package/dist/collection/components/xpl-popover/xpl-popover.js +6 -6
- package/dist/collection/components/xpl-radio/xpl-radio.js +3 -3
- package/dist/collection/components/xpl-secondary-nav/xpl-secondary-nav.js +1 -1
- package/dist/collection/components/xpl-select/xpl-select.js +8 -8
- package/dist/collection/components/xpl-side-nav/xpl-side-nav-item/xpl-side-nav-item.js +2 -2
- package/dist/collection/components/xpl-side-nav/xpl-side-nav-section/xpl-side-nav-section.js +5 -5
- package/dist/collection/components/xpl-side-nav/xpl-side-nav.js +2 -2
- package/dist/collection/components/xpl-slideout/xpl-slideout.js +1 -1
- package/dist/collection/components/xpl-spotlight/xpl-spotlight.js +4 -4
- package/dist/collection/components/xpl-tab/xpl-tab.js +2 -2
- package/dist/collection/components/xpl-tab-panel/xpl-tab-panel.js +3 -3
- package/dist/collection/components/xpl-table/xpl-table-body/xpl-table-body.js +1 -1
- package/dist/collection/components/xpl-table/xpl-table-cell/xpl-table-cell.js +2 -2
- package/dist/collection/components/xpl-table/xpl-table-footer/xpl-table-footer.js +1 -1
- package/dist/collection/components/xpl-table/xpl-table-footer-cell/xpl-table-footer-cell.js +2 -2
- package/dist/collection/components/xpl-table/xpl-table-header-cell/xpl-table-header-cell.js +2 -2
- package/dist/collection/components/xpl-table/xpl-table-row/xpl-table-row.js +2 -2
- package/dist/collection/components/xpl-table/xpl-table.js +4 -4
- package/dist/collection/components/xpl-table-header/xpl-table-header.js +1 -1
- package/dist/collection/components/xpl-tag/xpl-tag.js +6 -6
- package/dist/collection/components/xpl-toast/xpl-toast.js +2 -2
- package/dist/collection/components/xpl-toolbar/xpl-toolbar.js +2 -2
- package/dist/collection/components/xpl-tooltip/xpl-tooltip.js +1 -1
- package/dist/collection/components/xpl-top-nav/xpl-nav-header-menu/xpl-nav-header-menu.js +2 -2
- package/dist/collection/components/xpl-top-nav/xpl-top-nav-item/xpl-top-nav-item.js +2 -2
- package/dist/collection/components/xpl-top-nav/xpl-top-nav-menu/xpl-top-nav-menu.js +2 -2
- package/dist/collection/components/xpl-top-nav/xpl-top-nav.js +5 -5
- package/dist/collection/components/xpl-utility-bar/xpl-utility-bar.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/{p-CQjJIHK6.js → p-6-DvgBzG.js} +1 -1
- package/dist/components/{p-C0AbGd4t.js → p-B54F4o_Z.js} +1 -1
- package/dist/components/{p-rLxtqgsy.js → p-BFUtaXqX.js} +1 -1
- package/dist/components/{p-D09sGbzs.js → p-BHRO2whA.js} +1 -1
- package/dist/components/{p-CdRmVtIN.js → p-BKajYWw6.js} +1 -1
- package/dist/components/{p-1D7CWIJ-.js → p-BU4pW_6c.js} +1 -1
- package/dist/components/p-B_6p2HCL.js +1 -0
- package/dist/components/{p-BOm_p_mz.js → p-Biie85R2.js} +1 -1
- package/dist/components/p-CIcKTXQj.js +1 -0
- package/dist/components/{p-Btb2UkLz.js → p-COq-vU2g.js} +1 -1
- package/dist/components/{p-DoVubWyd.js → p-CTy7V3XS.js} +1 -1
- package/dist/components/{p-8zrW9vEC.js → p-Cq8V05oj.js} +1 -1
- package/dist/components/{p-B7aaJikj.js → p-CthHapLu.js} +1 -1
- package/dist/components/{p-CmbpWpb0.js → p-DGxQJj8d.js} +1 -1
- package/dist/components/{p-ohy3NrgH.js → p-Dn1Qsv0Y.js} +1 -1
- package/dist/components/p-Dn6HsGUr.js +1 -0
- package/dist/components/p-DxjcChRd.js +1 -0
- package/dist/components/p-FS6KZMQV.js +1 -0
- package/dist/components/p-Fj_zi29t.js +1 -0
- package/dist/components/{p-2cJsJK3-.js → p-L9wSxXlk.js} +1 -1
- package/dist/components/{p-CuVYRPvz.js → p-ULcrhk_V.js} +1 -1
- package/dist/components/{p-DTh_zemx.js → p-WTdJQHaL.js} +1 -1
- package/dist/components/{p-CFXvQqUO.js → p-fstojyQr.js} +1 -1
- package/dist/components/{p-CV5nn1zR.js → p-gs07oY0j.js} +1 -1
- package/dist/components/p-nRygucMK.js +1 -0
- package/dist/components/{p-B56GeUtW.js → p-q4zX9LQ0.js} +1 -1
- package/dist/components/xpl-accordion.js +1 -1
- package/dist/components/xpl-application-shell.js +1 -1
- package/dist/components/xpl-avatar.js +1 -1
- package/dist/components/xpl-backdrop.js +1 -1
- package/dist/components/xpl-badge.js +1 -1
- package/dist/components/xpl-banner.js +1 -1
- package/dist/components/xpl-breadcrumb-item.js +1 -1
- package/dist/components/xpl-breadcrumbs.js +1 -1
- package/dist/components/xpl-button-row.js +1 -1
- package/dist/components/xpl-button.js +1 -1
- package/dist/components/xpl-calendar.js +1 -1
- package/dist/components/xpl-checkbox.js +1 -1
- package/dist/components/xpl-choicelist.js +1 -1
- package/dist/components/xpl-content-area.js +1 -1
- package/dist/components/xpl-dashboard.js +1 -1
- package/dist/components/xpl-data-card.js +1 -1
- package/dist/components/xpl-divider.js +1 -1
- package/dist/components/xpl-dropdown-group.js +1 -1
- package/dist/components/xpl-dropdown-heading.js +1 -1
- package/dist/components/xpl-dropdown-option.js +1 -1
- package/dist/components/xpl-dropdown.js +1 -1
- package/dist/components/xpl-dynamic-table-cell.js +1 -1
- package/dist/components/xpl-dynamic-table-row.js +1 -1
- package/dist/components/xpl-dynamic-table.js +1 -1
- package/dist/components/xpl-grid-item.js +1 -1
- package/dist/components/xpl-grid.js +1 -1
- package/dist/components/xpl-header-accordion.js +1 -1
- package/dist/components/xpl-icon.js +1 -1
- package/dist/components/xpl-input-color.js +1 -1
- package/dist/components/xpl-input-date.js +1 -1
- package/dist/components/xpl-input-file.js +1 -1
- package/dist/components/xpl-input-phone.js +1 -1
- package/dist/components/xpl-input-search.js +1 -1
- package/dist/components/xpl-input-time.js +1 -1
- package/dist/components/xpl-input.js +1 -1
- package/dist/components/xpl-large-card.js +1 -1
- package/dist/components/xpl-list-item.js +1 -1
- package/dist/components/xpl-list.js +1 -1
- package/dist/components/xpl-main-nav.js +1 -1
- package/dist/components/xpl-modal.js +1 -1
- package/dist/components/xpl-nav-header-menu.js +1 -1
- package/dist/components/xpl-nav-item.js +1 -1
- package/dist/components/xpl-pagination.js +1 -1
- package/dist/components/xpl-panel.js +1 -1
- package/dist/components/xpl-popover.js +1 -1
- package/dist/components/xpl-progress-bar.js +1 -1
- package/dist/components/xpl-progress-indicator.js +1 -1
- package/dist/components/xpl-radio.js +1 -1
- package/dist/components/xpl-secondary-nav.js +1 -1
- package/dist/components/xpl-select.js +1 -1
- package/dist/components/xpl-side-nav-header-item.js +1 -1
- package/dist/components/xpl-side-nav-item.js +1 -1
- package/dist/components/xpl-side-nav-section.js +1 -1
- package/dist/components/xpl-side-nav.js +1 -1
- package/dist/components/xpl-skeleton.js +1 -1
- package/dist/components/xpl-slideout.js +1 -1
- package/dist/components/xpl-spotlight.js +1 -1
- package/dist/components/xpl-tab-panel.js +1 -1
- package/dist/components/xpl-tab.js +1 -1
- package/dist/components/xpl-table-body.js +1 -1
- package/dist/components/xpl-table-cell.js +1 -1
- package/dist/components/xpl-table-footer-cell.js +1 -1
- package/dist/components/xpl-table-footer.js +1 -1
- package/dist/components/xpl-table-header-cell.js +1 -1
- package/dist/components/xpl-table-header.js +1 -1
- package/dist/components/xpl-table-row.js +1 -1
- package/dist/components/xpl-table.js +1 -1
- package/dist/components/xpl-tabs.js +1 -1
- package/dist/components/xpl-tag.js +1 -1
- package/dist/components/xpl-toast.js +1 -1
- package/dist/components/xpl-toggle.js +1 -1
- package/dist/components/xpl-toolbar.js +1 -1
- package/dist/components/xpl-tooltip.js +1 -1
- package/dist/components/xpl-top-nav-item.js +1 -1
- package/dist/components/xpl-top-nav-menu.js +1 -1
- package/dist/components/xpl-top-nav.js +1 -1
- package/dist/components/xpl-utility-bar.js +1 -1
- package/dist/docs/xpl-accordion/readme.md +5 -4
- package/dist/docs/xpl-application-shell/readme.md +10 -0
- package/dist/docs/xpl-avatar/readme.md +8 -1
- package/dist/docs/xpl-badge/readme.md +7 -0
- package/dist/docs/xpl-breadcrumbs/xpl-breadcrumb-item/readme.md +1 -0
- package/dist/docs/xpl-breadcrumbs/xpl-breadcrumbs/readme.md +1 -0
- package/dist/docs/xpl-button/readme.md +7 -0
- package/dist/docs/xpl-checkbox/readme.md +7 -0
- package/dist/docs/xpl-content-area/readme.md +7 -0
- package/dist/docs/xpl-dashboard/readme.md +7 -0
- package/dist/docs/xpl-data-card/readme.md +1 -0
- package/dist/docs/xpl-divider/readme.md +7 -0
- package/dist/docs/xpl-dropdown/readme.md +18 -1
- package/dist/docs/xpl-dropdown/xpl-dropdown-group/readme.md +7 -0
- package/dist/docs/xpl-dropdown/xpl-dropdown-heading/readme.md +7 -0
- package/dist/docs/xpl-dropdown/xpl-dropdown-option/readme.md +7 -0
- package/dist/docs/xpl-dynamic-table/readme.md +8 -0
- package/dist/docs/xpl-dynamic-table-cell/readme.md +7 -0
- package/dist/docs/xpl-dynamic-table-row/readme.md +7 -0
- package/dist/docs/xpl-grid-item/readme.md +7 -0
- package/dist/docs/xpl-header-accordion/readme.md +8 -0
- package/dist/docs/xpl-icon/readme.md +1 -1
- package/dist/docs/xpl-input/readme.md +8 -0
- package/dist/docs/xpl-list/readme.md +8 -1
- package/dist/docs/xpl-list/xpl-list-item/readme.md +16 -0
- package/dist/docs/xpl-main-nav/readme.md +12 -0
- package/dist/docs/xpl-nav-item/readme.md +10 -1
- package/dist/docs/xpl-pagination/readme.md +1 -1
- package/dist/docs/xpl-popover/readme.md +1 -0
- package/dist/docs/xpl-radio/readme.md +7 -0
- package/dist/docs/xpl-secondary-nav/readme.md +11 -2
- package/dist/docs/xpl-select/readme.md +7 -0
- package/dist/docs/xpl-side-nav/xpl-side-nav-item/readme.md +9 -0
- package/dist/docs/xpl-side-nav/xpl-side-nav-section/readme.md +8 -0
- package/dist/docs/xpl-slideout/readme.md +13 -0
- package/dist/docs/xpl-spotlight/readme.md +1 -0
- package/dist/docs/xpl-table/readme.md +12 -0
- package/dist/docs/xpl-table/xpl-table-body/readme.md +7 -0
- package/dist/docs/xpl-table/xpl-table-cell/readme.md +7 -0
- package/dist/docs/xpl-table/xpl-table-footer/readme.md +7 -0
- package/dist/docs/xpl-table/xpl-table-footer-cell/readme.md +7 -0
- package/dist/docs/xpl-table/xpl-table-header-cell/readme.md +59 -52
- package/dist/docs/xpl-table/xpl-table-row/readme.md +7 -0
- package/dist/docs/xpl-table-header/readme.md +7 -0
- package/dist/docs/xpl-tag/readme.md +9 -2
- package/dist/docs/xpl-toast/readme.md +8 -0
- package/dist/docs/xpl-toolbar/readme.md +9 -1
- package/dist/docs/xpl-tooltip/readme.md +7 -0
- package/dist/docs/xpl-top-nav/xpl-nav-header-menu/readme.md +2 -1
- package/dist/docs/xpl-top-nav/xpl-top-nav-item/readme.md +1 -0
- package/dist/docs/xpl-top-nav/xpl-top-nav-menu/readme.md +1 -0
- package/dist/docs/xpl-utility-bar/readme.md +8 -0
- package/dist/docs.json +933 -251
- package/dist/esm/apollo-core.js +3 -3
- package/dist/esm/{index-ukZKsqqq.js → index-CgJEmBQY.js} +53 -165
- package/dist/esm/loader.js +2 -2
- package/dist/esm/xpl-accordion.entry.js +3 -3
- package/dist/esm/xpl-application-shell.entry.js +2 -2
- package/dist/esm/xpl-avatar_3.entry.js +5 -5
- package/dist/esm/xpl-backdrop.entry.js +2 -2
- package/dist/esm/xpl-badge.entry.js +2 -2
- package/dist/esm/xpl-banner.entry.js +3 -3
- package/dist/esm/xpl-breadcrumb-item.entry.js +2 -2
- package/dist/esm/xpl-breadcrumbs.entry.js +2 -2
- package/dist/esm/xpl-button-row.entry.js +2 -2
- package/dist/esm/xpl-button.entry.js +3 -3
- package/dist/esm/xpl-calendar.entry.js +2 -2
- package/dist/esm/xpl-checkbox.entry.js +4 -4
- package/dist/esm/xpl-choicelist.entry.js +2 -2
- package/dist/esm/xpl-content-area.entry.js +2 -2
- package/dist/esm/xpl-dashboard.entry.js +2 -2
- package/dist/esm/xpl-data-card.entry.js +3 -3
- package/dist/esm/xpl-dropdown_4.entry.js +9 -9
- package/dist/esm/xpl-dynamic-table-cell.entry.js +3 -3
- package/dist/esm/xpl-dynamic-table-row.entry.js +3 -3
- package/dist/esm/xpl-dynamic-table.entry.js +3 -3
- package/dist/esm/xpl-grid-item.entry.js +2 -2
- package/dist/esm/xpl-grid.entry.js +1 -1
- package/dist/esm/xpl-header-accordion.entry.js +2 -2
- package/dist/esm/xpl-icon.entry.js +3 -6
- package/dist/esm/xpl-input-color.entry.js +9 -9
- package/dist/esm/xpl-input-phone.entry.js +1 -1
- package/dist/esm/xpl-input-time.entry.js +1 -1
- package/dist/esm/xpl-input_4.entry.js +6 -6
- package/dist/esm/xpl-large-card.entry.js +2 -2
- package/dist/esm/xpl-list-item.entry.js +1 -1
- package/dist/esm/xpl-list.entry.js +3 -3
- package/dist/esm/xpl-main-nav.entry.js +2 -2
- package/dist/esm/xpl-modal.entry.js +1 -1
- package/dist/esm/xpl-nav-header-menu.entry.js +3 -3
- package/dist/esm/xpl-nav-item.entry.js +3 -3
- package/dist/esm/xpl-pagination.entry.js +1 -1
- package/dist/esm/xpl-panel.entry.js +1 -1
- package/dist/esm/xpl-popover.entry.js +5 -5
- package/dist/esm/xpl-progress-bar.entry.js +1 -1
- package/dist/esm/xpl-progress-indicator.entry.js +1 -1
- package/dist/esm/xpl-secondary-nav.entry.js +2 -2
- package/dist/esm/xpl-select_2.entry.js +10 -10
- package/dist/esm/xpl-side-nav-header-item.entry.js +1 -1
- package/dist/esm/xpl-side-nav-item.entry.js +3 -3
- package/dist/esm/xpl-side-nav-section.entry.js +6 -6
- package/dist/esm/xpl-side-nav.entry.js +3 -3
- package/dist/esm/xpl-skeleton.entry.js +1 -1
- package/dist/esm/xpl-slideout.entry.js +2 -2
- package/dist/esm/xpl-spotlight.entry.js +1 -1
- package/dist/esm/xpl-tab-panel.entry.js +3 -3
- package/dist/esm/xpl-tab.entry.js +1 -1
- package/dist/esm/xpl-table-body.entry.js +2 -2
- package/dist/esm/xpl-table-cell_3.entry.js +5 -5
- package/dist/esm/xpl-table-footer.entry.js +2 -2
- package/dist/esm/xpl-table-header.entry.js +2 -2
- package/dist/esm/xpl-table-row.entry.js +3 -3
- package/dist/esm/xpl-table.entry.js +1 -1
- package/dist/esm/xpl-tabs.entry.js +1 -1
- package/dist/esm/xpl-toast.entry.js +3 -3
- package/dist/esm/xpl-toggle.entry.js +1 -1
- package/dist/esm/xpl-toolbar.entry.js +3 -3
- package/dist/esm/xpl-tooltip.entry.js +2 -2
- package/dist/esm/xpl-top-nav-item.entry.js +3 -3
- package/dist/esm/xpl-top-nav-menu.entry.js +3 -3
- package/dist/esm/xpl-top-nav.entry.js +6 -6
- package/dist/esm/xpl-utility-bar.entry.js +2 -2
- package/dist/types/components.d.ts +3 -1
- package/dist/types/stencil-public-runtime.d.ts +12 -0
- package/hydrate/index.js +143 -234
- package/hydrate/index.mjs +143 -234
- package/loader/index.d.ts +1 -1
- package/package.json +17 -17
- package/dist/apollo-core/p-045a4538.entry.js +0 -1
- package/dist/apollo-core/p-08767607.entry.js +0 -1
- package/dist/apollo-core/p-194c0ccd.entry.js +0 -1
- package/dist/apollo-core/p-1c031055.entry.js +0 -1
- package/dist/apollo-core/p-24f7280a.entry.js +0 -1
- package/dist/apollo-core/p-386851a2.entry.js +0 -1
- package/dist/apollo-core/p-3cd1238b.entry.js +0 -1
- package/dist/apollo-core/p-4e3c6616.entry.js +0 -1
- package/dist/apollo-core/p-5b9fd96e.entry.js +0 -1
- package/dist/apollo-core/p-5cbf5d42.entry.js +0 -1
- package/dist/apollo-core/p-5ec2b180.entry.js +0 -1
- package/dist/apollo-core/p-65f6b66c.entry.js +0 -1
- package/dist/apollo-core/p-72e0455f.entry.js +0 -1
- package/dist/apollo-core/p-7ac7fbc0.entry.js +0 -1
- package/dist/apollo-core/p-7f4463ff.entry.js +0 -1
- package/dist/apollo-core/p-87582346.entry.js +0 -1
- package/dist/apollo-core/p-a6ecca68.entry.js +0 -1
- package/dist/apollo-core/p-a789c272.entry.js +0 -1
- package/dist/apollo-core/p-bd493c4a.entry.js +0 -1
- package/dist/apollo-core/p-bdcece21.entry.js +0 -1
- package/dist/apollo-core/p-bfb7a83a.entry.js +0 -1
- package/dist/apollo-core/p-c22f70f4.entry.js +0 -1
- package/dist/apollo-core/p-d3230277.entry.js +0 -1
- package/dist/apollo-core/p-d7f8ee34.entry.js +0 -1
- package/dist/apollo-core/p-d879c349.entry.js +0 -1
- package/dist/apollo-core/p-e4d50301.entry.js +0 -1
- package/dist/apollo-core/p-ea9cdd65.entry.js +0 -1
- package/dist/apollo-core/p-ukZKsqqq.js +0 -2
- package/dist/collection/components/xpl-icon/xpl-icon.css +0 -5
- package/dist/components/p-B6YLKDUX.js +0 -1
- package/dist/components/p-BSHdGbmH.js +0 -1
- package/dist/components/p-BZIZSovL.js +0 -1
- package/dist/components/p-CgemLtmL.js +0 -1
- package/dist/components/p-Dp62sBqX.js +0 -1
- package/dist/components/p-DqgnC_vS.js +0 -1
- package/dist/components/p-DtV4i45B.js +0 -1
- /package/dist/{utils → collection/utils}/form-bindings.js +0 -0
- /package/dist/{utils → collection/utils}/story-vrt.js +0 -0
- /package/dist/types/{third-party.d.ts → types/third-party.d.ts} +0 -0
- /package/dist/types/{home/runner/work/apollo/apollo/packages/apollo-core/.stencil/utils → utils}/form-bindings.d.ts +0 -0
- /package/dist/types/{home/runner/work/apollo/apollo/packages/apollo-core/.stencil/utils → utils}/story-vrt.d.ts +0 -0
package/dist/docs.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"timestamp": "2026-
|
|
2
|
+
"timestamp": "2026-09-22T15:57:00",
|
|
3
3
|
"compiler": {
|
|
4
4
|
"name": "@stencil/core",
|
|
5
|
-
"version": "4.
|
|
5
|
+
"version": "4.44.2",
|
|
6
6
|
"typescriptVersion": "5.8.3"
|
|
7
7
|
},
|
|
8
8
|
"components": [
|
|
9
9
|
{
|
|
10
|
-
"filePath": "src/components/
|
|
10
|
+
"filePath": "src/components/xpl-accordion/xpl-accordion.tsx",
|
|
11
11
|
"encapsulation": "none",
|
|
12
12
|
"tag": "xpl-accordion",
|
|
13
13
|
"readme": "# xpl-accordion\n\nAccordions are collapsable containers and allow users to collapse or expand the container. Useful when many items are present in a section and users may benefit from closing content to gain more space or focus on content that is most important to them. \n\nUse the content slot in the opened state to swap in Apollo components or make your own local component with groups of Apollo components or custom content.\n\nNote: Users will often miss any content that is hidden behind an interaction. If it is important that users see the content, use an accordion's open state on load `initialExpanded`, or use another pattern.\n",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"name": "slot",
|
|
18
18
|
"text": "heading - The header for the accordion component"
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
"name": "slot",
|
|
22
|
+
"text": "description - Additional text displayed under the header. Falls back to the `description` prop."
|
|
23
|
+
},
|
|
20
24
|
{
|
|
21
25
|
"name": "slot",
|
|
22
26
|
"text": "content - Content rendered inside of the collapsible body of the accordion."
|
|
@@ -265,6 +269,10 @@
|
|
|
265
269
|
"name": "content",
|
|
266
270
|
"docs": "Content rendered inside of the collapsible body of the accordion."
|
|
267
271
|
},
|
|
272
|
+
{
|
|
273
|
+
"name": "description",
|
|
274
|
+
"docs": "Additional text displayed under the header. Falls back to the `description` prop."
|
|
275
|
+
},
|
|
268
276
|
{
|
|
269
277
|
"name": "heading",
|
|
270
278
|
"docs": "The header for the accordion component"
|
|
@@ -283,12 +291,28 @@
|
|
|
283
291
|
}
|
|
284
292
|
},
|
|
285
293
|
{
|
|
286
|
-
"filePath": "src/components/
|
|
294
|
+
"filePath": "src/components/xpl-application-shell/xpl-application-shell.tsx",
|
|
287
295
|
"encapsulation": "none",
|
|
288
296
|
"tag": "xpl-application-shell",
|
|
289
297
|
"readme": "# xpl-application-shell\n\n`xpl-application-shell` is the top-level layout container for an Apollo application. It arranges the main navigation rail, an optional utility bar, an optional secondary navigation column, and the page content into a responsive CSS grid, and drives the CSS-only open/close animation of the navigation rail.\n\n## Usage\n\n```html\n<xpl-application-shell with-subnav is-nav-open-at-startup=\"true\">\n <xpl-main-nav slot=\"nav\" width=\"default\"><!-- ... --></xpl-main-nav>\n <xpl-utility-bar slot=\"utility\"><!-- ... --></xpl-utility-bar>\n <xpl-secondary-nav slot=\"subnav\"><!-- ... --></xpl-secondary-nav>\n <xpl-content-area slot=\"content\"><!-- ... --></xpl-content-area>\n</xpl-application-shell>\n```\n\n## Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`. All purpose-specific tokens theme automatically in dark mode (no `.dark` overrides in the CSS).\n\n**Color**\n\n| Element | Property | Token | Resolves (light / dark) |\n| --- | --- | --- | --- |\n| Host nav rail | `background-color` | `--xpl-background-surface-inverse-on-light` | neutral-1000 / neutral-1000 (always dark) |\n| `&__subnav` | `background-color` | `--xpl-background-surface-default` | neutral-0 / neutral-1000 |\n| `&__content` | `background-color` | `--xpl-background-surface-subtlest` | neutral-50 / neutral-900 |\n| `&__subnav`, `&__content` | `color` (on-surface text) | `--xpl-text-default` | neutral-900 / neutral-50 |\n| `&__subnav` (top), `&__content` (left/top), `&__utility` (left) | `border-color` | `--xpl-border-default` | neutral-400 / neutral-600 |\n\n**Border width**\n\n- `--xpl-border-small` (0.0625rem / 1px) — all shell dividers.\n\n**Layout literals (not themeable)**\n\nThe nav rail widths / transforms (`74px`, `112px`, `240px`) drive the CSS-only open/close animation and are kept as literals; no Foundation size token set covers animated grid-track widths. `grid-template`, `100vh`, and `-webkit-fill-available` are also kept as literals. See `TECH_DEBT.md`.\n",
|
|
290
298
|
"docs": "`xpl-application-shell` is the top-level layout container for an Apollo application. It arranges the main navigation rail, an optional utility bar, an optional secondary navigation column, and the page content into a responsive CSS grid, and drives the CSS-only open/close animation of the navigation rail.",
|
|
291
299
|
"docsTags": [
|
|
300
|
+
{
|
|
301
|
+
"name": "slot",
|
|
302
|
+
"text": "nav - The primary navigation area (e.g. `xpl-main-nav` or `xpl-side-nav`)."
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"name": "slot",
|
|
306
|
+
"text": "subnav - The secondary navigation area (e.g. `xpl-secondary-nav`)."
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"name": "slot",
|
|
310
|
+
"text": "utility - The utility bar area (e.g. `xpl-utility-bar`)."
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"name": "slot",
|
|
314
|
+
"text": "content - The main page content area."
|
|
315
|
+
},
|
|
292
316
|
{
|
|
293
317
|
"name": "since",
|
|
294
318
|
"text": "0.5.0"
|
|
@@ -449,7 +473,24 @@
|
|
|
449
473
|
}
|
|
450
474
|
],
|
|
451
475
|
"styles": [],
|
|
452
|
-
"slots": [
|
|
476
|
+
"slots": [
|
|
477
|
+
{
|
|
478
|
+
"name": "content",
|
|
479
|
+
"docs": "The main page content area."
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"name": "nav",
|
|
483
|
+
"docs": "The primary navigation area (e.g. `xpl-main-nav` or `xpl-side-nav`)."
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"name": "subnav",
|
|
487
|
+
"docs": "The secondary navigation area (e.g. `xpl-secondary-nav`)."
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"name": "utility",
|
|
491
|
+
"docs": "The utility bar area (e.g. `xpl-utility-bar`)."
|
|
492
|
+
}
|
|
493
|
+
],
|
|
453
494
|
"parts": [],
|
|
454
495
|
"states": [],
|
|
455
496
|
"dependents": [],
|
|
@@ -463,12 +504,16 @@
|
|
|
463
504
|
}
|
|
464
505
|
},
|
|
465
506
|
{
|
|
466
|
-
"filePath": "src/components/
|
|
507
|
+
"filePath": "src/components/xpl-avatar/xpl-avatar.tsx",
|
|
467
508
|
"encapsulation": "none",
|
|
468
509
|
"tag": "xpl-avatar",
|
|
469
|
-
"readme": "# xpl-avatar\n\nThe **Avatar** component shows a person or entity: a photo, initials on a colored surface, or custom slot content. It aligns with Apollo’s Figma patterns for default avatars, profile layouts, stacked groups, and rows with supporting text.\n\n## When to use\n\n- **Default (no `variant`)** — Inline UI: tables, nav, comments, lists. Supports image (`src`), initials from `name`, and an optional status dot (`status`).\n- **Profile (`variant=\"profile\"`)** — Large avatars for profile pages and settings surfaces; optional `status` dot uses the same badge palette as the default avatar.\n- **Group (`variant=\"group\"`)** — Stacked avatar groups with overflow count (`+N`). The `status` prop is not used (status dots are not shown for groups).\n- **With Text (`variant=\"with-text\"`)** — Horizontal layout with avatar paired with name and optional sub-text; optional `status` on the avatar image.\n\n\n| Variant | Purpose | `status` dot |\n| ----------- | ------------------------------------------------------ | ------------ |\n| *(none)* | Standard single avatar | Supported |\n| `profile` | Larger profile-sized avatar for settings/profile pages | Supported |\n| `group` | Stacked avatar group with overflow count (`+N`) | Not shown |\n| `with-text` | Avatar paired with name and optional sub-text | Supported |\n\n\n---\n\n## Quick Start\n\n### Basic Avatar (Image)\n\n```html\n<xpl-avatar name=\"Katie Wilson\" src=\"https://example.com/photo.jpg\"></xpl-avatar>\n```\n\n### Initials Placeholder (No Image)\n\n```html\n<!-- Automatic initials from name -->\n<xpl-avatar name=\"Katie Wilson\" color=\"green\"></xpl-avatar>\n\n<!-- Custom initials via slot -->\n<xpl-avatar color=\"primary\">KW</xpl-avatar>\n```\n\n### With Status Dot\n\nStatus dots are rendered with [`xpl-badge`] using `dot-only` and `bordered`. The `status` prop sets the badge **variant** , so avatar status colors stay aligned with badge semantics across the system.\n\n**Where `status` applies:** default (no `variant`), `profile`, and `with-text`. It does **not** apply to `group` — stacked groups ignore `status`.\n\n**`status` values** (same names as `xpl-badge` `variant` palette values):\n\n\n| `status` | Badge palette | Typical meaning (choose per product copy) |\n| -------- | ---------------- | ----------------------------------------- |\n| `purple` | Purple (default) | Default / general presence |\n| `green` | Green | Positive, available, success-aligned |\n| `yellow` | Yellow | Caution, pending, away, warning-aligned |\n| `orange` | Orange | Attention, busy, secondary emphasis |\n| `gray` | Gray | Neutral, offline, inactive |\n| `red` | Red | Error, do not disturb, critical |\n| `blue` | Blue | Informational, notifications |\n\n\n```html\n<xpl-avatar name=\"Alex Chen\" src=\"photo.jpg\" status=\"green\"></xpl-avatar>\n<xpl-avatar name=\"Jordan Lee\" status=\"red\"></xpl-avatar>\n<xpl-avatar name=\"Sam Smith\" status=\"gray\"></xpl-avatar>\n<xpl-avatar variant=\"with-text\" name=\"Riley Park\" sub-text=\"Designer\" src=\"photo.jpg\" status=\"blue\"></xpl-avatar>\n```\n\n### Clickable Avatar (Link)\n\n```html\n<xpl-avatar name=\"Profile\" src=\"photo.jpg\" href=\"/profile\" target=\"_blank\"></xpl-avatar>\n```\n\n---\n\n## Variant Examples\n\n### Profile Avatar (Larger Size)\n\nFor profile pages and settings surfaces. Optional `status` uses the same badge palette as other non-group variants.\n\n```html\n<!-- Large profile avatar (144px) -->\n<xpl-avatar variant=\"profile\" name=\"Katie Wilson\" src=\"photo.jpg\"></xpl-avatar>\n\n<!-- With status dot -->\n<xpl-avatar variant=\"profile\" name=\"Katie Wilson\" src=\"photo.jpg\" status=\"green\"></xpl-avatar>\n\n<!-- Small profile avatar (80px) -->\n<xpl-avatar variant=\"profile\" name=\"Jordan Lee\" size=\"sm\"></xpl-avatar>\n```\n\n### Avatar Group (Stacked)\n\nDisplays up to 4 visible avatars with a `+N` overflow pill for additional members. The `status` prop is not used in this layout (no per-avatar or group-level status dot).\n\n```html\n<!-- Basic group with JSON data -->\n<xpl-avatar\n variant=\"group\"\n group-data='[\n {\"name\": \"Alex\", \"color\": \"green\"},\n {\"name\": \"Jordan\", \"color\": \"yellow\"},\n {\"name\": \"Sam\", \"color\": \"pink\"},\n {\"src\": \"https://example.com/photo.jpg\", \"name\": \"Dana\"},\n {\"name\": \"Extra User\"}\n ]'\n></xpl-avatar>\n\n<!-- Medium group -->\n<xpl-avatar variant=\"group\" size=\"md\" group-data='[...]'></xpl-avatar>\n\n<!-- Small group -->\n<xpl-avatar variant=\"group\" size=\"sm\" group-data='[...]'></xpl-avatar>\n```\n\n**Group data format:**\n\n```typescript\ninterface AvatarGroupItem {\n src?: string; // Image URL (optional)\n name?: string; // Used for initials and alt text\n color?: 'green' | 'yellow' | 'pink' | 'primary' | 'secondary';\n}\n```\n\n### Avatar with Text\n\nHorizontal layout with avatar + name + optional sub-text (e.g., email).\n\n```html\n<!-- Basic with-text -->\n<xpl-avatar\n variant=\"with-text\"\n name=\"Katie Wilson\"\n sub-text=\"katie@example.com\"\n src=\"photo.jpg\"\n></xpl-avatar>\n\n<!-- Clickable version -->\n<xpl-avatar\n variant=\"with-text\"\n name=\"View Profile\"\n sub-text=\"Product Designer\"\n src=\"photo.jpg\"\n href=\"/profile\"\n></xpl-avatar>\n\n<!-- With status dot on the avatar -->\n<xpl-avatar\n variant=\"with-text\"\n name=\"Katie Wilson\"\n sub-text=\"katie@example.com\"\n src=\"photo.jpg\"\n status=\"green\"\n></xpl-avatar>\n```\n\n---\n\n## Size Options\n\n\n| Size | Default Avatar | Profile Avatar | Group |\n| -------- | -------------- | -------------- | ------------------ |\n| *(none)* | 40×40px | 144×144px | 40×40px per avatar |\n| `md` | 32×32px | — | 32×32px per avatar |\n| `sm` | 24×24px | 80×80px | 24×24px per avatar |\n\n\n---\n\n## Status vs placeholder `color`\n\n- **`status`** — Badge palette for the **status dot** (`purple` | `green` | `yellow` | `orange` | `gray` | `red` | `blue`). Passed through to `xpl-badge` as `variant`. Not used when `variant=\"group\"`.\n- **`color`** — Placeholder **surface** behind initials when there is no `src` (`green` | `yellow` | `pink` | `primary` | `secondary`). Unrelated to the status dot.\n\n## Color Options (Placeholder Backgrounds)\n\nUse `color` when no `src` is provided to set the placeholder background:\n\n- `green` — Positive accent\n- `yellow` — Highlight accent\n- `pink` — Pink accent\n- `primary` — Brand primary\n- `secondary` — Action primary (purple)\n\n---\n\n## Design tokens\n\nThese are the main Apollo Foundation tokens used in `packages/apollo-core/src/css/avatar.css`. Use them when overriding or migrating styles.\n\n| Role | Token(s) |\n| ---- | -------- |\n| Circular shape | `var(--xpl-border-radius-full)` |\n| Placeholder surface (default) | `var(--xpl-background-brand-secondary)`, `var(--xpl-text-inverse)` |\n| Placeholder `green` / `yellow` / `pink` | `var(--xpl-background-accent-positive)` / `var(--xpl-background-accent-highlight)` / `var(--xpl-background-accent-pink)` with `var(--xpl-text-inverse-on-light)` where applicable |\n| Placeholder `primary` / `secondary` | `var(--xpl-background-accent-brand)` / `var(--xpl-background-brand-secondary)` |\n| Link hover overlay | `var(--xpl-background-surface-transparent-25)` |\n| Focus outline | `var(--xpl-border-accent-default)` base; `color` modifiers use `var(--xpl-border-positive)`, `var(--xpl-border-accent-highlight)`, `var(--xpl-border-accent-brand)`, etc. (`outline` / `outline-offset` per `avatar.css`) |\n| With-text primary line | `var(--xpl-text-strong)`, `var(--xpl-font-size-title-5)`, `var(--xpl-font-weight-medium)` |\n| With-text secondary line | `var(--xpl-text-subdued)`, `var(--xpl-font-size-body)` |\n| Group overflow pill | `var(--xpl-background-surface-subtle)`, `var(--xpl-text-subdued)` |\n| Group avatar ring | `box-shadow` using `var(--xpl-border-large)` and `var(--xpl-background-surface-default)` |\n| Width / height | `var(--xpl-size-*)` for standard sizes; profile default uses `var(--xpl-size-900)` (144px) |\n| Spacing & overlap | `var(--xpl-space-*)`, `var(--xpl-z-index-*)` |\n\n**Status dots** are styled by `xpl-badge`; see [`xpl-badge` readme](../xpl-badge/readme.md) for badge token usage.\n\n---\n\n## Accessibility\n\n- `name` is required for proper `alt` text on images and screen reader announcements\n- **Status dots** are implemented via `xpl-badge` and marked `aria-hidden` (purely visual); convey meaning in surrounding UI copy or labels if required\n- **Group overflow** includes `aria-label=\"{count} more\"` for screen readers\n- **Links** use native `<a>` elements with full keyboard support\n- **Disabled state**: Use `disabled` prop to disable link behavior while keeping visual styles\n- **Focus management**: All interactive avatars (links) use `:focus-visible` for keyboard focus indicators\n\n---\n\n## Best Practices\n\n1. **Always provide `name`** — Essential for accessibility (alt text and screen readers; for placeholder initials, slot input has higher priority than the value passed in `name`)\n2. **Use `color` for placeholder consistency** — Assign consistent colors to users based on ID or name hash\n3. **Limit group data** — While the component handles any number, consider capping at reasonable numbers for UX\n4. **Slot content** — Use the default slot sparingly; prefer `name` prop for consistent initials generation\n\n---\n\n## Migration Notes\n\n### Status Dot Implementation:\n\n**What changed:** Status dots are implemented with `xpl-badge` (`dot-only` + `bordered`). The `status` prop uses the **badge color palette** (`purple`, `green`, `yellow`, `orange`, `gray`, `red`, `blue`) — the same names as `xpl-badge` `variant` — so avatar status stays consistent with badge semantics.\n\n**Impact:**\n\n- **Internal markup:** The status dot renders as `<xpl-badge dot-only bordered variant=\"...\">` (with `variant` from `status`), not legacy `.xpl-avatar__dot--` classes.\n- **CSS targeting:** Custom selectors like `.xpl-avatar__dot--active` / `--warning` / `--inactive` are not used. Target `.xpl-avatar .xpl-badge--dot-only` if you must override styles.\n- **Prop values:** Use palette names above. Older examples sometimes used labels like `active` / `warning` / `inactive`; map those concepts to the palette (e.g. available → `green`, caution → `yellow`, offline → `gray`) per your design guidelines.\n\n**Recommended migration:**\n\n1. Replace custom CSS on `.xpl-avatar__dot--` with `.xpl-avatar .xpl-badge--dot-only` if needed\n2. Set `status` to the badge palette value that matches the intended color (see the status table in this readme)\n3. Remember `status` applies to default, `profile`, and `with-text` only — not `group`\n\n### Legacy `status` values — scheduled for removal (next major release)\n\n**These legacy string values are deprecated.** They exist only for backward compatibility with older integrations. They **will be removed** in the **next major** version of `@xplortech/apollo-core`. Plan your migration now; do not introduce new usage of the legacy names.\n\n| Deprecated `status` | Current mapping (temporary) | Replace with (badge palette) |\n| ------------------- | --------------------------- | ---------------------------- |\n| `active` | `green` | `green` |\n| `inactive` | `gray` | `gray` |\n| `warning` | `red` | `red` |\n\n**Why:** Status dots use the same vocabulary as `xpl-badge` variants (`purple`, `green`, `yellow`, `orange`, `gray`, `red`, `blue`). The old semantic aliases (`active` / `warning` / `inactive`) duplicate that meaning with different names and increase maintenance cost, so they are being dropped from the public API.\n\n**Action items before the major release:**\n\n1. Search your codebase for `status=\"active\"`, `status=\"inactive\"`, and `status=\"warning\"` on `<xpl-avatar>` (and framework wrappers).\n2. Replace each with the **`green`**, **`gray`**, or **`red`** value from the table above, matching your product intent.\n3. Re-test visuals: the mapped colors are unchanged today; after removal, only palette names will be accepted.\n\n### Component Dependency\n\nThis component now depends on `xpl-badge`. Ensure `xpl-badge` is loaded in your application when using avatars with status dots.\n\n",
|
|
510
|
+
"readme": "# xpl-avatar\n\nThe **Avatar** component shows a person or entity: a photo, initials on a colored surface, or custom slot content. It aligns with Apollo’s Figma patterns for default avatars, profile layouts, stacked groups, and rows with supporting text.\n\n## When to use\n\n- **Default (no `variant`)** — Inline UI: tables, nav, comments, lists. Supports image (`src`), initials from `name`, and an optional status dot (`status`).\n- **Profile (`variant=\"profile\"`)** — Large avatars for profile pages and settings surfaces; optional `status` dot uses the same badge palette as the default avatar.\n- **Group (`variant=\"group\"`)** — Stacked avatar groups with overflow count (`+N`). The `status` prop is not used (status dots are not shown for groups).\n- **With Text (`variant=\"with-text\"`)** — Horizontal layout with avatar paired with name and optional sub-text; optional `status` on the avatar image.\n\n\n| Variant | Purpose | `status` dot |\n| ----------- | ------------------------------------------------------ | ------------ |\n| *(none)* | Standard single avatar | Supported |\n| `profile` | Larger profile-sized avatar for settings/profile pages | Supported |\n| `group` | Stacked avatar group with overflow count (`+N`) | Not shown |\n| `with-text` | Avatar paired with name and optional sub-text | Supported |\n\n\n---\n\n## Quick Start\n\n### Basic Avatar (Image)\n\n```html\n<xpl-avatar name=\"Katie Wilson\" src=\"https://example.com/photo.jpg\"></xpl-avatar>\n```\n\n### Initials Placeholder (No Image)\n\n```html\n<!-- Automatic initials from name -->\n<xpl-avatar name=\"Katie Wilson\" color=\"green\"></xpl-avatar>\n\n<!-- Custom initials via slot -->\n<xpl-avatar color=\"primary\">KW</xpl-avatar>\n```\n\n### With Status Dot\n\nStatus dots are rendered with [`xpl-badge`] using `dot-only` and `bordered`. The `status` prop sets the badge **variant** , so avatar status colors stay aligned with badge semantics across the system.\n\n**Where `status` applies:** default (no `variant`), `profile`, and `with-text`. It does **not** apply to `group` — stacked groups ignore `status`.\n\n**`status` values** (same names as `xpl-badge` `variant` palette values):\n\n\n| `status` | Badge palette | Typical meaning (choose per product copy) |\n| -------- | ---------------- | ----------------------------------------- |\n| `purple` | Purple (default) | Default / general presence |\n| `green` | Green | Positive, available, success-aligned |\n| `yellow` | Yellow | Caution, pending, away, warning-aligned |\n| `orange` | Orange | Attention, busy, secondary emphasis |\n| `gray` | Gray | Neutral, offline, inactive |\n| `red` | Red | Error, do not disturb, critical |\n| `blue` | Blue | Informational, notifications |\n\n\n```html\n<xpl-avatar name=\"Alex Chen\" src=\"photo.jpg\" status=\"green\"></xpl-avatar>\n<xpl-avatar name=\"Jordan Lee\" status=\"red\"></xpl-avatar>\n<xpl-avatar name=\"Sam Smith\" status=\"gray\"></xpl-avatar>\n<xpl-avatar variant=\"with-text\" name=\"Riley Park\" sub-text=\"Designer\" src=\"photo.jpg\" status=\"blue\"></xpl-avatar>\n```\n\n### Clickable Avatar (Link)\n\n```html\n<xpl-avatar name=\"Profile\" src=\"photo.jpg\" href=\"/profile\" target=\"_blank\"></xpl-avatar>\n```\n\n---\n\n## Variant Examples\n\n### Profile Avatar (Larger Size)\n\nFor profile pages and settings surfaces. Optional `status` uses the same badge palette as other non-group variants.\n\n```html\n<!-- Large profile avatar (144px) -->\n<xpl-avatar variant=\"profile\" name=\"Katie Wilson\" src=\"photo.jpg\"></xpl-avatar>\n\n<!-- With status dot -->\n<xpl-avatar variant=\"profile\" name=\"Katie Wilson\" src=\"photo.jpg\" status=\"green\"></xpl-avatar>\n\n<!-- Small profile avatar (80px) -->\n<xpl-avatar variant=\"profile\" name=\"Jordan Lee\" size=\"sm\"></xpl-avatar>\n```\n\n### Avatar Group (Stacked)\n\nDisplays up to 4 visible avatars with a `+N` overflow pill for additional members. The `status` prop is not used in this layout (no per-avatar or group-level status dot).\n\n```html\n<!-- Basic group with JSON data -->\n<xpl-avatar\n variant=\"group\"\n group-data='[\n {\"name\": \"Alex\", \"color\": \"green\"},\n {\"name\": \"Jordan\", \"color\": \"yellow\"},\n {\"name\": \"Sam\", \"color\": \"pink\"},\n {\"src\": \"https://example.com/photo.jpg\", \"name\": \"Dana\"},\n {\"name\": \"Extra User\"}\n ]'\n></xpl-avatar>\n\n<!-- Medium group -->\n<xpl-avatar variant=\"group\" size=\"md\" group-data='[...]'></xpl-avatar>\n\n<!-- Small group -->\n<xpl-avatar variant=\"group\" size=\"sm\" group-data='[...]'></xpl-avatar>\n```\n\n**Group data format:**\n\n```typescript\ninterface AvatarGroupItem {\n src?: string; // Image URL (optional)\n name?: string; // Used for initials and alt text\n color?: 'green' | 'yellow' | 'pink' | 'primary' | 'secondary';\n}\n```\n\n### Avatar with Text\n\nHorizontal layout with avatar + name + optional sub-text (e.g., email).\n\n```html\n<!-- Basic with-text -->\n<xpl-avatar\n variant=\"with-text\"\n name=\"Katie Wilson\"\n sub-text=\"katie@example.com\"\n src=\"photo.jpg\"\n></xpl-avatar>\n\n<!-- Clickable version -->\n<xpl-avatar\n variant=\"with-text\"\n name=\"View Profile\"\n sub-text=\"Product Designer\"\n src=\"photo.jpg\"\n href=\"/profile\"\n></xpl-avatar>\n\n<!-- With status dot on the avatar -->\n<xpl-avatar\n variant=\"with-text\"\n name=\"Katie Wilson\"\n sub-text=\"katie@example.com\"\n src=\"photo.jpg\"\n status=\"green\"\n></xpl-avatar>\n```\n\n---\n\n## Size Options\n\n\n| Size | Default Avatar | Profile Avatar | Group |\n| -------- | -------------- | -------------- | ------------------ |\n| *(none)* | 40×40px | 144×144px | 40×40px per avatar |\n| `md` | 32×32px | — | 32×32px per avatar |\n| `sm` | 24×24px | 80×80px | 24×24px per avatar |\n\n\n---\n\n## Status vs placeholder `color`\n\n- **`status`** — Badge palette for the **status dot** (`purple` | `green` | `yellow` | `orange` | `gray` | `red` | `blue`). Passed through to `xpl-badge` as `variant`. Not used when `variant=\"group\"`.\n- **`color`** — Placeholder **surface** behind initials when there is no `src` (`green` | `yellow` | `pink` | `primary` | `secondary`). Unrelated to the status dot.\n\n## Color Options (Placeholder Backgrounds)\n\nUse `color` when no `src` is provided to set the placeholder background:\n\n- `green` — Positive accent\n- `yellow` — Highlight accent\n- `pink` — Pink accent\n- `primary` — Brand primary\n- `secondary` — Action primary (purple)\n\n---\n\n## Design tokens\n\nThese are the main Apollo Foundation tokens used in `packages/apollo-core/src/components/xpl-avatar/avatar.css`. Use them when overriding or migrating styles.\n\n| Role | Token(s) |\n| ---- | -------- |\n| Circular shape | `var(--xpl-border-radius-full)` |\n| Placeholder surface (default) | `var(--xpl-background-brand-secondary)`, `var(--xpl-text-inverse)` |\n| Placeholder `green` / `yellow` / `pink` | `var(--xpl-background-accent-positive)` / `var(--xpl-background-accent-highlight)` / `var(--xpl-background-accent-pink)` with `var(--xpl-text-inverse-on-light)` where applicable |\n| Placeholder `primary` / `secondary` | `var(--xpl-background-accent-brand)` / `var(--xpl-background-brand-secondary)` |\n| Link hover overlay | `var(--xpl-background-surface-transparent-25)` |\n| Focus outline | `var(--xpl-border-accent-default)` base; `color` modifiers use `var(--xpl-border-positive)`, `var(--xpl-border-accent-highlight)`, `var(--xpl-border-accent-brand)`, etc. (`outline` / `outline-offset` per `avatar.css`) |\n| With-text primary line | `var(--xpl-text-strong)`, `var(--xpl-font-size-title-5)`, `var(--xpl-font-weight-medium)` |\n| With-text secondary line | `var(--xpl-text-subdued)`, `var(--xpl-font-size-body)` |\n| Group overflow pill | `var(--xpl-background-surface-subtle)`, `var(--xpl-text-subdued)` |\n| Group avatar ring | `box-shadow` using `var(--xpl-border-large)` and `var(--xpl-background-surface-default)` |\n| Width / height | `var(--xpl-size-*)` for standard sizes; profile default uses `var(--xpl-size-900)` (144px) |\n| Spacing & overlap | `var(--xpl-space-*)`, `var(--xpl-z-index-*)` |\n\n**Status dots** are styled by `xpl-badge`; see [`xpl-badge` readme](../xpl-badge/readme.md) for badge token usage.\n\n---\n\n## Accessibility\n\n- `name` is required for proper `alt` text on images and screen reader announcements\n- **Status dots** are implemented via `xpl-badge` and marked `aria-hidden` (purely visual); convey meaning in surrounding UI copy or labels if required\n- **Group overflow** includes `aria-label=\"{count} more\"` for screen readers\n- **Links** use native `<a>` elements with full keyboard support\n- **Disabled state**: Use `disabled` prop to disable link behavior while keeping visual styles\n- **Focus management**: All interactive avatars (links) use `:focus-visible` for keyboard focus indicators\n\n---\n\n## Best Practices\n\n1. **Always provide `name`** — Essential for accessibility (alt text and screen readers; for placeholder initials, slot input has higher priority than the value passed in `name`)\n2. **Use `color` for placeholder consistency** — Assign consistent colors to users based on ID or name hash\n3. **Limit group data** — While the component handles any number, consider capping at reasonable numbers for UX\n4. **Slot content** — Use the default slot sparingly; prefer `name` prop for consistent initials generation\n\n---\n\n## Migration Notes\n\n### Status Dot Implementation:\n\n**What changed:** Status dots are implemented with `xpl-badge` (`dot-only` + `bordered`). The `status` prop uses the **badge color palette** (`purple`, `green`, `yellow`, `orange`, `gray`, `red`, `blue`) — the same names as `xpl-badge` `variant` — so avatar status stays consistent with badge semantics.\n\n**Impact:**\n\n- **Internal markup:** The status dot renders as `<xpl-badge dot-only bordered variant=\"...\">` (with `variant` from `status`), not legacy `.xpl-avatar__dot--` classes.\n- **CSS targeting:** Custom selectors like `.xpl-avatar__dot--active` / `--warning` / `--inactive` are not used. Target `.xpl-avatar .xpl-badge--dot-only` if you must override styles.\n- **Prop values:** Use palette names above. Older examples sometimes used labels like `active` / `warning` / `inactive`; map those concepts to the palette (e.g. available → `green`, caution → `yellow`, offline → `gray`) per your design guidelines.\n\n**Recommended migration:**\n\n1. Replace custom CSS on `.xpl-avatar__dot--` with `.xpl-avatar .xpl-badge--dot-only` if needed\n2. Set `status` to the badge palette value that matches the intended color (see the status table in this readme)\n3. Remember `status` applies to default, `profile`, and `with-text` only — not `group`\n\n### Legacy `status` values — scheduled for removal (next major release)\n\n**These legacy string values are deprecated.** They exist only for backward compatibility with older integrations. They **will be removed** in the **next major** version of `@xplortech/apollo-core`. Plan your migration now; do not introduce new usage of the legacy names.\n\n| Deprecated `status` | Current mapping (temporary) | Replace with (badge palette) |\n| ------------------- | --------------------------- | ---------------------------- |\n| `active` | `green` | `green` |\n| `inactive` | `gray` | `gray` |\n| `warning` | `red` | `red` |\n\n**Why:** Status dots use the same vocabulary as `xpl-badge` variants (`purple`, `green`, `yellow`, `orange`, `gray`, `red`, `blue`). The old semantic aliases (`active` / `warning` / `inactive`) duplicate that meaning with different names and increase maintenance cost, so they are being dropped from the public API.\n\n**Action items before the major release:**\n\n1. Search your codebase for `status=\"active\"`, `status=\"inactive\"`, and `status=\"warning\"` on `<xpl-avatar>` (and framework wrappers).\n2. Replace each with the **`green`**, **`gray`**, or **`red`** value from the table above, matching your product intent.\n3. Re-test visuals: the mapped colors are unchanged today; after removal, only palette names will be accepted.\n\n### Component Dependency\n\nThis component now depends on `xpl-badge`. Ensure `xpl-badge` is loaded in your application when using avatars with status dots.\n\n",
|
|
470
511
|
"docs": "The **Avatar** component shows a person or entity: a photo, initials on a colored surface, or custom slot content. It aligns with Apollo’s Figma patterns for default avatars, profile layouts, stacked groups, and rows with supporting text.",
|
|
471
512
|
"docsTags": [
|
|
513
|
+
{
|
|
514
|
+
"name": "slot",
|
|
515
|
+
"text": "- Custom placeholder content (e.g. initials) shown when no `src` image is available."
|
|
516
|
+
},
|
|
472
517
|
{
|
|
473
518
|
"name": "since",
|
|
474
519
|
"text": "0.1.1"
|
|
@@ -485,8 +530,8 @@
|
|
|
485
530
|
"references": {
|
|
486
531
|
"AvatarColor": {
|
|
487
532
|
"location": "local",
|
|
488
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
489
|
-
"id": "src/components/
|
|
533
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-avatar/xpl-avatar.tsx",
|
|
534
|
+
"id": "src/components/xpl-avatar/xpl-avatar.tsx::AvatarColor"
|
|
490
535
|
}
|
|
491
536
|
}
|
|
492
537
|
},
|
|
@@ -560,8 +605,8 @@
|
|
|
560
605
|
"references": {
|
|
561
606
|
"AvatarGroupItem": {
|
|
562
607
|
"location": "local",
|
|
563
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
564
|
-
"id": "src/components/
|
|
608
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-avatar/xpl-avatar.tsx",
|
|
609
|
+
"id": "src/components/xpl-avatar/xpl-avatar.tsx::AvatarGroupItem"
|
|
565
610
|
}
|
|
566
611
|
}
|
|
567
612
|
},
|
|
@@ -689,8 +734,8 @@
|
|
|
689
734
|
"references": {
|
|
690
735
|
"AvatarStatus": {
|
|
691
736
|
"location": "local",
|
|
692
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
693
|
-
"id": "src/components/
|
|
737
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-avatar/xpl-avatar.tsx",
|
|
738
|
+
"id": "src/components/xpl-avatar/xpl-avatar.tsx::AvatarStatus"
|
|
694
739
|
}
|
|
695
740
|
}
|
|
696
741
|
},
|
|
@@ -807,8 +852,8 @@
|
|
|
807
852
|
"references": {
|
|
808
853
|
"AvatarVariant": {
|
|
809
854
|
"location": "local",
|
|
810
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
811
|
-
"id": "src/components/
|
|
855
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-avatar/xpl-avatar.tsx",
|
|
856
|
+
"id": "src/components/xpl-avatar/xpl-avatar.tsx::AvatarVariant"
|
|
812
857
|
}
|
|
813
858
|
}
|
|
814
859
|
},
|
|
@@ -841,7 +886,12 @@
|
|
|
841
886
|
"events": [],
|
|
842
887
|
"listeners": [],
|
|
843
888
|
"styles": [],
|
|
844
|
-
"slots": [
|
|
889
|
+
"slots": [
|
|
890
|
+
{
|
|
891
|
+
"name": "",
|
|
892
|
+
"docs": "Custom placeholder content (e.g. initials) shown when no `src` image is available."
|
|
893
|
+
}
|
|
894
|
+
],
|
|
845
895
|
"parts": [],
|
|
846
896
|
"states": [],
|
|
847
897
|
"dependents": [
|
|
@@ -860,7 +910,7 @@
|
|
|
860
910
|
}
|
|
861
911
|
},
|
|
862
912
|
{
|
|
863
|
-
"filePath": "src/components/
|
|
913
|
+
"filePath": "src/components/xpl-backdrop/xpl-backdrop.tsx",
|
|
864
914
|
"encapsulation": "none",
|
|
865
915
|
"tag": "xpl-backdrop",
|
|
866
916
|
"readme": "# xpl-backdrop\n\nThis backdrop is used to add a transparent darker layer on top of the content area to focus the user’s attention. Typically used when a dialog such as a modal or slide out panel is active. \n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-background-surface-backdrop` — backdrop scrim fill. The token bakes the neutral alpha into the color (`rgba(48 45 59 / 0.5)` light / `rgba(48 45 59 / 0.75)` dark), so the standalone `opacity` property was removed to avoid double-dimming. It themes automatically — no `.dark` override.\n",
|
|
@@ -937,12 +987,16 @@
|
|
|
937
987
|
}
|
|
938
988
|
},
|
|
939
989
|
{
|
|
940
|
-
"filePath": "src/components/
|
|
990
|
+
"filePath": "src/components/xpl-badge/xpl-badge.tsx",
|
|
941
991
|
"encapsulation": "none",
|
|
942
992
|
"tag": "xpl-badge",
|
|
943
993
|
"readme": "# xpl-badge\n\n`xpl-badge` is a small, non-interactive status indicator used to communicate counts, states, or supplementary information next to another element. Badges are **never clickable** – use a button or link if you need interaction.\n\nBadges support multiple **variants** (colors), **sizes**, **shapes**, and **dot styles**, so they can be used both as pill labels and as compact status / notification indicators.\n\n## Usage\n\n```html\n<xpl-badge variant=\"green\">Active</xpl-badge>\n<xpl-badge variant=\"yellow\">Pending</xpl-badge>\n<xpl-badge variant=\"red\">Error</xpl-badge>\n<xpl-badge variant=\"gray\" size=\"small\">Draft</xpl-badge>\n```\n\nAttach badges close to the item they describe (a label, row, chip, or control). Prefer **short labels** (often one or two words) for readability.\n\n### Label text and overflow\n\nSlot content is rendered inside an internal `.xpl-badge__label` wrapper (you do not add this in your markup). Labels are **single-line**: text does not wrap to multiple lines. When horizontal space is tight (for example a narrow column or flex layout), overflowing text **truncates with an ellipsis** (`…`). The host respects the parent width (`max-width: 100%`). If truncation makes a label hard to read, shorten the copy or widen the layout; use a tooltip or similar only if your product needs the full string on hover.\n\n## Sizes & shapes\n\n- **size**\n - `default` (default): `24px` tall pill, used for most cases.\n - `small`: `20px` tall, more compact for dense UIs or table rows.\n- **shape**\n - `rounded` (default): full pill with fully rounded ends.\n - `boxy`: rounded corners but not a full pill; better for more neutral / data-heavy contexts.\n\n```html\n<xpl-badge size=\"default\" shape=\"rounded\">Default pill</xpl-badge>\n<xpl-badge size=\"small\" shape=\"boxy\">Small boxy</xpl-badge>\n```\n\n## Dots and dot-only badges\n\n### Dot badge (pill with leading dot)\n\nSet `dot` to add a colored dot before the text, inside the pill:\n\n```html\n<xpl-badge variant=\"green\" dot>Online</xpl-badge>\n<xpl-badge variant=\"yellow\" dot>Syncing</xpl-badge>\n<xpl-badge variant=\"red\" dot>Error</xpl-badge>\n```\n\n### Dot-only badge (compact status / count)\n\n> [!IMPORTANT]\n> Dot-only badges are meant to be used with **numeric values** (or very short strings). For longer text labels, use the standard badge (without `dot-only`).\n\n- When overlaying another element with a background color, use the `bordered` property so the badge separates clearly from what is behind it.\n\nSet `dot-only` when you want a badge built around the dot:\n\n- With **no children**: renders a small circular status dot.\n- With **children**: renders a compact pill with text or a number inside (for example an unread count).\n- **Notification-style counts** are often appended to a label or another component. Dot-only label text follows the same **single-line truncation** rules as standard badges when space is limited.\n- Use **`bordered`** to toggle a ring around the dot badge for separation from an avatar or similar surface.\n\n```html\n<!-- Status dot only -->\n<xpl-badge variant=\"green\" dot-only></xpl-badge>\n\n<!-- Dot with count / text -->\n<xpl-badge variant=\"red\" dot-only>3</xpl-badge>\n<xpl-badge variant=\"blue\" dot-only>99+</xpl-badge>\n```\n\n## Variants\n\nUse variants to communicate state or category. Preferred values for `variant`:\n\n- `purple` (default)\n- `green`\n- `yellow`\n- `orange`\n- `gray`\n- `red`\n- `blue`\n\nThe legacy semantic names `success`, `warning`, `inactive`, and `error` are still accepted and map to `green`, `yellow`, `gray`, and `red` respectively. Prefer the color names for new code.\n\n```html\n<xpl-badge variant=\"purple\">Default</xpl-badge>\n<xpl-badge variant=\"orange\" dot>In progress</xpl-badge>\n<xpl-badge variant=\"blue\" dot-only>12</xpl-badge>\n```\n\n- Each dot has **stronger solid color** for dot-only badges, with dark-mode adjustments handled by CSS.\n\n- Each variant uses Apollo Foundation badge tokens (`--xpl-background-badge-`*, `--xpl-border-badge-*`, `--xpl-icon-badge-*`, `--xpl-text-badge-*`) that auto-switch between light and dark modes. Dot-only badges use the corresponding `--xpl-icon-badge-*` accent color for their solid fill.\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-background-badge-{default,green,yellow,grey,blue,red}` — variant backgrounds\n- `--xpl-border-badge-{purple,green,yellow,grey,blue,red}` — variant borders\n- `--xpl-text-badge-{default,green,yellow,gray,blue,red}` — variant text colors\n- `--xpl-icon-badge-{default,green,yellow,grey,blue,red}` — dot / dot-only fill\n- `--xpl-text-inverse` — dot-only text (green, blue, red)\n- `--xpl-text-strong` — orange variant text\n- `--xpl-border-inverse` — dot-only bordered ring\n- `--xpl-color-transparent-0` — dot-only / orange transparent border\n- `--xpl-color-neutral-1100` — dot-only text on yellow, gray, orange\n- `--xpl-background-surface-transparent-0` — orange background (dark mode)\n- `--xpl-background-accent-brand` — orange dot/dot-only fill (tech debt)\n- `--xpl-color-orange-{100,300}` — orange variant primitives (tech debt)\n\n**Spacing**\n- `--xpl-space-{2,4,8,12}` — padding variants\n\n**Sizing**\n- `--xpl-size-{150,125,050}` — height / dot sizes\n- `0.875rem` literal — dot-only badge height/min-width (no 14px Foundation token; tech debt)\n\n**Typography**\n- `--xpl-font-family-default` — font family\n- Default badge extends `.xpl-text-title-5` (Figma `Title/5`); small badge extends `.xpl-text-callout-bold` (Figma `Callout/Bold`)\n- `0.5rem` literal — dot-only (number) badge font-size/line-height (no 8px Foundation token or typography level; tech debt)\n\n**Border**\n- `--xpl-border-small` — border width (1px)\n- `--xpl-border-radius-{full,small}` — shape variants\n",
|
|
944
994
|
"docs": "`xpl-badge` is a small, non-interactive status indicator used to communicate counts, states, or supplementary information next to another element. Badges are **never clickable** – use a button or link if you need interaction.\n\nBadges support multiple **variants** (colors), **sizes**, **shapes**, and **dot styles**, so they can be used both as pill labels and as compact status / notification indicators.",
|
|
945
995
|
"docsTags": [
|
|
996
|
+
{
|
|
997
|
+
"name": "slot",
|
|
998
|
+
"text": "- The badge label content."
|
|
999
|
+
},
|
|
946
1000
|
{
|
|
947
1001
|
"name": "since",
|
|
948
1002
|
"text": "0.1.1"
|
|
@@ -1108,8 +1162,8 @@
|
|
|
1108
1162
|
"references": {
|
|
1109
1163
|
"BadgeVariantProp": {
|
|
1110
1164
|
"location": "local",
|
|
1111
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
1112
|
-
"id": "src/components/
|
|
1165
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-badge/xpl-badge.tsx",
|
|
1166
|
+
"id": "src/components/xpl-badge/xpl-badge.tsx::BadgeVariantProp"
|
|
1113
1167
|
}
|
|
1114
1168
|
}
|
|
1115
1169
|
},
|
|
@@ -1180,7 +1234,12 @@
|
|
|
1180
1234
|
"events": [],
|
|
1181
1235
|
"listeners": [],
|
|
1182
1236
|
"styles": [],
|
|
1183
|
-
"slots": [
|
|
1237
|
+
"slots": [
|
|
1238
|
+
{
|
|
1239
|
+
"name": "",
|
|
1240
|
+
"docs": "The badge label content."
|
|
1241
|
+
}
|
|
1242
|
+
],
|
|
1184
1243
|
"parts": [],
|
|
1185
1244
|
"states": [],
|
|
1186
1245
|
"dependents": [
|
|
@@ -1202,7 +1261,7 @@
|
|
|
1202
1261
|
}
|
|
1203
1262
|
},
|
|
1204
1263
|
{
|
|
1205
|
-
"filePath": "src/components/
|
|
1264
|
+
"filePath": "src/components/xpl-banner/xpl-banner.tsx",
|
|
1206
1265
|
"encapsulation": "none",
|
|
1207
1266
|
"tag": "xpl-banner",
|
|
1208
1267
|
"readme": "# xpl-banner\n\nBanners display a system level or page level message at the top of the screen. The section-banner variant displays important messages inline within a section.\n\n## Usage\n\n### Web component (`<xpl-banner>`)\n\nBar layout (default) with heading, description, primary action, and dismiss:\n\n```html\n<xpl-banner\n appearance=\"information\"\n heading=\"Your session will expire soon.\"\n description=\"Save your work to avoid losing changes.\"\n action-text=\"Extend session\"\n is-dismissible=\"true\"\n></xpl-banner>\n```\n\nSection layout with optional secondary action and no leading icon:\n\n```html\n<xpl-banner\n appearance=\"positive\"\n is-section=\"true\"\n has-icon=\"false\"\n heading=\"Changes saved\"\n description=\"Your updates are stored.\"\n action-text=\"View details\"\n secondary-action-text=\"Undo\"\n></xpl-banner>\n```\n\n### Plain HTML (BEM classes)\n\nUse the same structure when styling with `banner.css` without the Stencil component. Switch bar vs section with host modifiers (`xpl-banner--section`, `xpl-banner--no-icon`, `xpl-banner--{appearance}`).\n\n## Accessibility\n\n`xpl-banner` uses `role=\"region\"` so the banner is a navigable landmark.\n\n**`aria-label` on the host (never empty):**\n\n| Layout | `aria-label` source |\n| ------ | ------------------- |\n| Bar (default) | Fixed label from `appearance`: `\"Information banner\"`, `\"Positive banner\"`, `\"Warning banner\"`, or `\"Error banner\"`. |\n| Section | Trimmed `heading` when present; otherwise `\"Section banner\"`. |\n\nKeyboard: **Tab** moves focus to action buttons and the dismiss control; **Enter** and **Space** activate `xpl-button` actions and the dismiss button. Focus rings use `:focus-visible` (dismiss uses appearance-specific outline tokens in CSS; actions use `xpl-button` focus styles).\n\n- The leading icon wrapper carries `aria-hidden=\"true\"` — the icon is decorative; the message text is the accessible content.\n- The dismiss `<xpl-icon>` inside the dismiss button also carries `aria-hidden=\"true\"` so the decorative icon is not announced in addition to the button label.\n- The dismiss button `aria-label` is `\"Dismiss banner\"` in bar layout and `\"Dismiss section banner\"` when `is-section` is true.\n\n## Token Use\n\n- `information`\n - Background: `--xpl-background-messaging-information`\n - Border: `--xpl-border-accent-information`\n - Icon: `--xpl-icon-default`\n - Main text: `--xpl-text-strong` (with `--xpl-text-default` fallback)\n - Detail text: `--xpl-text-default`\n- `warning`\n - Background: `--xpl-background-messaging-warning`\n - Border: `--xpl-border-accent-warning`\n - Icon: `--xpl-icon-default`\n - Main text: `--xpl-text-strong` (with `--xpl-text-default` fallback)\n - Detail text: `--xpl-text-default`\n - Dismiss focus ring: `--xpl-border-accent-warning`\n- `positive`\n - Background: `--xpl-background-messaging-positive`\n - Border: `--xpl-border-positive`\n - Icon: `--xpl-icon-default`\n - Main text: `--xpl-text-strong` (with `--xpl-text-default` fallback)\n - Detail text: `--xpl-text-default`\n- `error`\n - Background: `--xpl-background-messaging-negative-bold`\n - Border: `--xpl-border-negative`\n - Icon and text: `--xpl-text-inverse-on-dark`\n - Dismiss focus ring: `--xpl-text-inverse-on-dark`\n- Dismiss button follows the same icon token as the current appearance.\n- `information` dismiss focus ring uses `--xpl-border-accent-information`.\n\nLight and dark mode are handled by Apollo Foundation token definitions. `xpl-banner` does not use component-level `.dark` token overrides.\n\n## Icon Mapping\n\nEach `appearance` value maps to a fixed `xpl-icon` name. When building the component in plain HTML, use the icon from this table:\n\n| `appearance` | `xpl-icon` name |\n| ------------- | ------------------ |\n| `information` | `circle-info` |\n| `warning` | `triangle-warning` |\n| `positive` | `circle-check` |\n| `error` | `octagon-warning` |\n\n## Actions\n\nUse `actionText` and `secondaryActionText` to render up to two `xpl-button` actions in the banner.\nBoth action buttons always render at `size=\"xs\"` to match compact banner spacing.\n\nThe `variant` and `state` attributes on the action buttons depend on both `appearance` and layout:\n\n| Layout | `appearance` | `variant` | `state` |\n| --------- | ------------- | ----------- | ----------- |\n| bar | `information` | `subtle` | — |\n| bar | `warning` | `subtle` | — |\n| bar | `positive` | `subtle` | — |\n| bar | `error` | `primary` | `warning` |\n| section | `information` | `subtle` | — |\n| section | `warning` | `subtle` | — |\n| section | `positive` | `subtle` | `success` |\n| section | `error` | `subtle` | `warning` |\n\n## Section Layout\n\nSet `is-section` to render the section-banner layout:\n- Header row with icon, heading, and optional dismiss\n- Description below the header (2-line clamp by default)\n- Actions below description\n\nSet `has-icon=\"false\"` to hide the leading icon in the section layout. This applies `xpl-banner--no-icon` on the host, which shifts heading, description, and actions to start in the first grid column instead of the second. In bar layout the icon always renders regardless of `hasIcon`.\n\nBar and section variants share the same DOM shape. Plain-HTML example (classes only):\n\n```html\n<!-- Bar variant -->\n<div class=\"xpl-banner xpl-banner--information\">\n <div class=\"xpl-banner__icon\" aria-hidden=\"true\">\n <xpl-icon icon=\"circle-info\" size=\"24\"></xpl-icon>\n </div>\n <div class=\"xpl-banner__body\">\n <p class=\"xpl-banner__heading\">Heading</p>\n <p class=\"xpl-banner__description\">Description text</p>\n </div>\n <div class=\"xpl-banner__actions\">\n <xpl-button size=\"xs\" variant=\"subtle\">Action</xpl-button>\n </div>\n <button class=\"xpl-banner__dismiss\" type=\"button\" aria-label=\"Dismiss banner\">\n <xpl-icon icon=\"xmark\" size=\"24\" aria-hidden=\"true\"></xpl-icon>\n </button>\n</div>\n\n<!-- Section variant — add xpl-banner--section; same markup otherwise -->\n<div class=\"xpl-banner xpl-banner--section xpl-banner--information\">\n ...\n</div>\n\n<!-- Section variant without icon -->\n<div class=\"xpl-banner xpl-banner--section xpl-banner--no-icon xpl-banner--information\">\n <!-- omit .xpl-banner__icon -->\n <div class=\"xpl-banner__body\">...</div>\n ...\n</div>\n```\n",
|
|
@@ -1532,7 +1591,7 @@
|
|
|
1532
1591
|
}
|
|
1533
1592
|
},
|
|
1534
1593
|
{
|
|
1535
|
-
"filePath": "src/components/
|
|
1594
|
+
"filePath": "src/components/xpl-breadcrumbs/xpl-breadcrumb-item/xpl-breadcrumb-item.tsx",
|
|
1536
1595
|
"encapsulation": "none",
|
|
1537
1596
|
"tag": "xpl-breadcrumb-item",
|
|
1538
1597
|
"readme": "# xpl-breadcrumb-item\n\nThe `<xpl-breadcrumb-item>` component has a role of `listitem`. This component should only be used in combination with `<xpl-breadcrumbs>`.\nThis component yields an unnamed slot. Only links and buttons (styled as links) should be used within this component.\n\n",
|
|
@@ -1550,6 +1609,10 @@
|
|
|
1550
1609
|
"listeners": [],
|
|
1551
1610
|
"styles": [],
|
|
1552
1611
|
"slots": [
|
|
1612
|
+
{
|
|
1613
|
+
"name": "",
|
|
1614
|
+
"docs": "The default slot"
|
|
1615
|
+
},
|
|
1553
1616
|
{
|
|
1554
1617
|
"name": "unnamed",
|
|
1555
1618
|
"docs": "content rendered inside <li>, should be link or button (styled as link)"
|
|
@@ -1562,7 +1625,7 @@
|
|
|
1562
1625
|
"dependencyGraph": {}
|
|
1563
1626
|
},
|
|
1564
1627
|
{
|
|
1565
|
-
"filePath": "src/components/
|
|
1628
|
+
"filePath": "src/components/xpl-breadcrumbs/xpl-breadcrumbs/xpl-breadcrumbs.tsx",
|
|
1566
1629
|
"encapsulation": "none",
|
|
1567
1630
|
"tag": "xpl-breadcrumbs",
|
|
1568
1631
|
"readme": "# xpl-breadcrumbs\n\nThe `xpl-breadcrumbs` component is a navigation group. It yields an unnamed slot that is rendered inside a `<ol></ol>` element.\n\nThis component can be used as a wrapper to `<xpl-breadcrumb-item>` components.\n\nThe number of items is not restricted, although per Apollo's design guidelines, a maximum of three items should be used.\nIn small screens (xs), only the 2 deepest items will be visible, even if 3 items are provided.\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation` (light/dark handled automatically — no `.dark` overrides).\n\n**Color**\n- `--xpl-text-subdued` — breadcrumb list text and the separator glyph\n- `--xpl-text-link-hovered` — hovered breadcrumb item (per Figma node 1536:178167 UX note)\n- `--xpl-text-default` — current page (last item)\n",
|
|
@@ -1580,6 +1643,10 @@
|
|
|
1580
1643
|
"listeners": [],
|
|
1581
1644
|
"styles": [],
|
|
1582
1645
|
"slots": [
|
|
1646
|
+
{
|
|
1647
|
+
"name": "",
|
|
1648
|
+
"docs": "The default slot"
|
|
1649
|
+
},
|
|
1583
1650
|
{
|
|
1584
1651
|
"name": "unnamed",
|
|
1585
1652
|
"docs": "content rendered <ol>, should be a group of <li> or <xpl-breadcrumb-item>"
|
|
@@ -1592,12 +1659,16 @@
|
|
|
1592
1659
|
"dependencyGraph": {}
|
|
1593
1660
|
},
|
|
1594
1661
|
{
|
|
1595
|
-
"filePath": "src/components/
|
|
1662
|
+
"filePath": "src/components/xpl-button/xpl-button.tsx",
|
|
1596
1663
|
"encapsulation": "none",
|
|
1597
1664
|
"tag": "xpl-button",
|
|
1598
1665
|
"readme": "# xpl-button\n\nButtons allow users to take an action with clear visual hierarchy (variant), semantic meaning (sentiment), and size.\n\n## Usage\n\n> [!IMPORTANT]\n> Older props such as `state` still work, but we recommend using the sentiment described below.\n\n\n### Basic button\n\nPass button text via the default slot (same as native `<button>`):\n\n```html\n<xpl-button>Primary action</xpl-button>\n```\n\n### Variant and sentiment\n\nUse `variant` for style (primary, secondary, tertiary) and `sentiment` for intent (default, positive, negative):\n\n```html\n<xpl-button variant=\"secondary\">Secondary</xpl-button>\n<xpl-button variant=\"tertiary\" sentiment=\"positive\">Positive action</xpl-button>\n<xpl-button sentiment=\"negative\">Destructive</xpl-button>\n```\n\n### Size\n\nUse **`size`** for button size: `default`, `sm` (small), or `xs` (extra small):\n\n```html\n<xpl-button size=\"sm\">Small</xpl-button>\n<xpl-button size=\"xs\">Extra small</xpl-button>\n```\n\n### Icon from Apollo icon library\n\nUse `icon` with a name from the xpl-icon library; use `icon-position` to place the icon at start or end:\n\n```html\n<xpl-button icon=\"download\" icon-position=\"end\">\n Download\n</xpl-button>\n```\n\n### Icon-only button\n\nUse `icon-only` when the button shows only an icon (no label). Always set `icon` and use a descriptive `aria-label` on the host or inner button for accessibility:\n\n```html\n<xpl-button icon-only icon=\"xmark\" aria-label=\"Close\"></xpl-button>\n```\n\n### Loading state\n\nWhen `is-loading` is true, the button shows a spinner, hides the label and icon, stays the same size, and is non-interactive:\n\n```html\n<xpl-button is-loading>Submitting</xpl-button>\n```\n\n### Form submission\n\nThe component renders a native `<button>`. Use `type` (`submit`, `reset`, or `button`), `name`, `value`, and `form` for form behaviour:\n\n```html\n<form id=\"my-form\">\n <xpl-button type=\"submit\" name=\"action\" value=\"save\">Save</xpl-button>\n</form>\n```\n\n### Disabled\n\nUse the `disabled` prop to disable the button (same as native `disabled`):\n\n```html\n<xpl-button disabled>Disabled</xpl-button>\n```\n\n## DOM classes\n\nThe host element includes BEM-style classes, including:\n\n- **Size:** `xpl-button--default` | `xpl-button--sm` | `xpl-button--xs`\n- **Variant:** `xpl-button--primary` | `xpl-button--secondary` | `xpl-button--tertiary` (and `xpl-button--subtle` while that value is still supported)\n- **Sentiment:** `xpl-button--neutral` | `xpl-button--positive` | `xpl-button--negative` when using `sentiment`\n- **Deprecated `state`:** if set, legacy classes `xpl-button--neutral` | `xpl-button--warning` | `xpl-button--success` are applied instead of the sentiment-based classes above (see migration)\n\nPrefer targeting **`sentiment`** + **`variant`** + **`size`** in new code; avoid relying on deprecated `state` class names for new selectors.\n\n## Migration Notes:\n\nThe class **`xpl-button--default`** on the host continues to mean **size** (`size=\"default\"`), not sentiment.\n\n### Deprecated `state` prop\n\nThe **`state`** prop (`neutral` | `warning` | `success`) is deprecated. Use **`sentiment`** instead:\n\n| Old `state` | New `sentiment` |\n| ------------- | ----------------- |\n| `neutral` | `neutral` (default) |\n| `warning` | `negative` |\n| `success` | `positive` |\n\n**Backward compatibility:** if **`state`** is set, it controls the sentiment segment of the host class list (`xpl-button--neutral`, `xpl-button--warning`, `xpl-button--success`) so existing styles or tests that key off those class names can keep working. New work should use **`sentiment`** only (`neutral` | `negative` | `positive`).\n\n### Deprecated `variant=\"subtle\"` → `tertiary`\n\n**`variant=\"subtle\"`** is deprecated and retained only for backward compatibility, applying the **`xpl-button--subtle`** class. Use **`variant=\"tertiary\"`** instead, which applies **`xpl-button--tertiary`**.\n\n### Other API notes\n\n- **`isLoading` / `is-loading`:** loading UI without forcing the disabled (gray) visual treatment.\n- **`icon`**, **`icon-position`**, **`icon-only`:** use Apollo icon names; no inline SVGs required.\n- **`data-*`, `aria-*`, and `role` on the host:** mirrored onto the inner `<button>` after render for accessibility and testing tools. After forwarding, these attributes are removed from the host element. Avoid relying on `role` on the host for external selectors.\n\n## Guidelines\n\n- **Pass button content via the default slot:** `<xpl-button>Save</xpl-button>`. Slots support rich content (formatted text, inline icons, etc.).\n- Use **`iconOnly`** for icon-only buttons and provide an **`aria-label`** (or ensure the inner button has an accessible name).\n- Use **`icon`** for icon names from the xpl-icon library; use **`icon-position`** to place the icon at start or end of the slot content.\n\n## Accessibility\n\n- The component renders a native `<button>`, so it is focusable and keyboard-activable by default.\n- When **`is-loading`** is true, the inner button has `aria-busy=\"true\"` and the loading spinner is marked **`aria-hidden=\"true\"`** so the label remains the accessible name.\n- For **icon-only** buttons, provide an accessible name via **`aria-label`** on the host (e.g. `<xpl-button icon-only icon=\"xmark\" aria-label=\"Close\">`) so screen readers announce the action.\n- For **WAI-ARIA composite widgets** (like tabs), use the **`controlAttrs`** prop to apply `id`, `role`, `aria-controls`, `aria-selected`, and `aria-current` directly to the inner `<button>`. This is preferred over setting these attributes on the host, which would be forwarded and removed from the host.\n",
|
|
1599
1666
|
"docs": "Buttons allow users to take an action with clear visual hierarchy (variant), semantic meaning (sentiment), and size.",
|
|
1600
1667
|
"docsTags": [
|
|
1668
|
+
{
|
|
1669
|
+
"name": "slot",
|
|
1670
|
+
"text": "- The button label content."
|
|
1671
|
+
},
|
|
1601
1672
|
{
|
|
1602
1673
|
"name": "since",
|
|
1603
1674
|
"text": "0.1.1"
|
|
@@ -2100,7 +2171,12 @@
|
|
|
2100
2171
|
}
|
|
2101
2172
|
],
|
|
2102
2173
|
"styles": [],
|
|
2103
|
-
"slots": [
|
|
2174
|
+
"slots": [
|
|
2175
|
+
{
|
|
2176
|
+
"name": "",
|
|
2177
|
+
"docs": "The button label content."
|
|
2178
|
+
}
|
|
2179
|
+
],
|
|
2104
2180
|
"parts": [],
|
|
2105
2181
|
"states": [],
|
|
2106
2182
|
"dependents": [
|
|
@@ -2155,7 +2231,7 @@
|
|
|
2155
2231
|
}
|
|
2156
2232
|
},
|
|
2157
2233
|
{
|
|
2158
|
-
"filePath": "src/components/
|
|
2234
|
+
"filePath": "src/components/xpl-button-row/xpl-button-row.tsx",
|
|
2159
2235
|
"encapsulation": "none",
|
|
2160
2236
|
"tag": "xpl-button-row",
|
|
2161
2237
|
"readme": "# xpl-button-row\n\n\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-border-default` — top border color\n\n**Spacing**\n- `--xpl-space-{0,16,24}` — padding / margins\n\n**Border**\n- `--xpl-border-small` — top border width (1px)\n",
|
|
@@ -2305,7 +2381,7 @@
|
|
|
2305
2381
|
}
|
|
2306
2382
|
},
|
|
2307
2383
|
{
|
|
2308
|
-
"filePath": "src/components/
|
|
2384
|
+
"filePath": "src/components/xpl-calendar/xpl-calendar.tsx",
|
|
2309
2385
|
"encapsulation": "none",
|
|
2310
2386
|
"tag": "xpl-calendar",
|
|
2311
2387
|
"readme": "# xpl-calendar\n\nCalendars allow users to view and select dates. Use XPL-Calendar when date picking is needed on a page or in a in a container.\nIf a calendar is needed within a form, use [XPL-Datepicker](https://apollo.xplordocs.com/?path=/story/components-input--datepicker).\n",
|
|
@@ -2548,12 +2624,16 @@
|
|
|
2548
2624
|
"dependencyGraph": {}
|
|
2549
2625
|
},
|
|
2550
2626
|
{
|
|
2551
|
-
"filePath": "src/components/
|
|
2627
|
+
"filePath": "src/components/xpl-checkbox/xpl-checkbox.tsx",
|
|
2552
2628
|
"encapsulation": "none",
|
|
2553
2629
|
"tag": "xpl-checkbox",
|
|
2554
2630
|
"readme": "# xpl-checkbox\n\nCheckboxes allow users to make selections or choices. Checkboxes can be multi-select, and also act as controls.\n\nProvide visible label text in the default slot, or set `aria-label` when the checkbox has no adjacent label (for example, icon-only toolbars or table selection cells).\n\n## Design Tokens\n\nThe checkbox component uses the following Apollo Foundation tokens:\n\n| Token | Usage |\n|-------|-------|\n| `--xpl-background-surface-default` | Default checkbox background; styled label background (resting/hover/focused) |\n| `--xpl-background-action-primary-default` | Checked/indeterminate state background and border |\n| `--xpl-background-action-disabled` | Disabled state background; disabled label background (styled variant) |\n| `--xpl-background-surface-information` | Checked/indeterminate label background (styled variant) |\n| `--xpl-text-inverse` | Checkmark and indeterminate icon color (checked / indeterminate states; inverse foreground on primary fill) |\n| `--xpl-icon-disabled` | Checkmark and indeterminate icon color (disabled state) |\n| `--xpl-border-strong` | Resting (unchecked) border color |\n| `--xpl-border-hover` | Hover, checked, and indeterminate border color; styled container hover/focus border |\n| `--xpl-border-default` | Styled container border; disabled state border |\n| `--xpl-border-focus` | Focus visible outline |\n| `--xpl-border-radius-small` | Checkbox corner radius and styled container corner radius (4px) |\n| `--xpl-border-small` | Border width (1px) |\n| `--xpl-size-100` | Checkbox dimensions (16px) |\n\n### Label tokens (shared `label.css`)\n\nThe checkbox label and description are styled by the shared `.xpl-label` / `.xpl-description` classes.\n\n| Token | Usage |\n|-------|-------|\n| `--xpl-text-strong` | Label text color (matches `.xpl-input-label`; resolves to white in dark mode) |\n| `--xpl-text-disabled` | Disabled label text color |\n| `--xpl-text-subdued` | Description text color (enabled and disabled) |\n| `.xpl-text-body` | Label typography: `--xpl-font-size-body` (14px) / normal / 1.4286 line-height |\n| `.xpl-text-callout` | Description typography: `--xpl-font-size-callout` (12px) / normal / 1.3333 line-height |\n",
|
|
2555
2631
|
"docs": "Checkboxes allow users to make selections or choices. Checkboxes can be multi-select, and also act as controls.\n\nProvide visible label text in the default slot, or set `aria-label` when the checkbox has no adjacent label (for example, icon-only toolbars or table selection cells).",
|
|
2556
2632
|
"docsTags": [
|
|
2633
|
+
{
|
|
2634
|
+
"name": "slot",
|
|
2635
|
+
"text": "- The checkbox label content."
|
|
2636
|
+
},
|
|
2557
2637
|
{
|
|
2558
2638
|
"name": "since",
|
|
2559
2639
|
"text": "0.1.1"
|
|
@@ -2817,7 +2897,12 @@
|
|
|
2817
2897
|
],
|
|
2818
2898
|
"listeners": [],
|
|
2819
2899
|
"styles": [],
|
|
2820
|
-
"slots": [
|
|
2900
|
+
"slots": [
|
|
2901
|
+
{
|
|
2902
|
+
"name": "",
|
|
2903
|
+
"docs": "The checkbox label content."
|
|
2904
|
+
}
|
|
2905
|
+
],
|
|
2821
2906
|
"parts": [],
|
|
2822
2907
|
"states": [],
|
|
2823
2908
|
"dependents": [
|
|
@@ -2839,7 +2924,7 @@
|
|
|
2839
2924
|
}
|
|
2840
2925
|
},
|
|
2841
2926
|
{
|
|
2842
|
-
"filePath": "src/components/
|
|
2927
|
+
"filePath": "src/components/xpl-choicelist/xpl-choicelist.tsx",
|
|
2843
2928
|
"encapsulation": "none",
|
|
2844
2929
|
"tag": "xpl-choicelist",
|
|
2845
2930
|
"readme": "# xpl-choicelist\n\nA Choice List allows users to make single or multiple selections from a list of choices. This component is meant to consume the radio and checkbox components, either styled or unstyled, then allow for customizing an option list very quickly.\n\n## Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n| Token | Usage |\n|-------|-------|\n| `--xpl-text-strong` | Heading (`h3`) text color |\n| `--xpl-text-subdued` | Description (`p`) text color |\n| `--xpl-background-surface-information` | Selected row background (styled variant) — matches the `xpl-checkbox` / `xpl-radio` styled selected state |\n| `--xpl-border-default` | Styled container border and per-row dividers — matches the `xpl-checkbox` / `xpl-radio` styled card border |\n| `--xpl-border-radius-small` | Styled container corner radius (4px) — matches the `xpl-checkbox` / `xpl-radio` styled card |\n| `--xpl-border-small` | Border width (1px) |\n| `--xpl-border-none` | Removes the divider on the last styled row (0) |\n| `.xpl-text-title-5` | Heading typography: `--xpl-font-size-title-5` (14px) / medium (500) / 1.4286 line-height |\n| `.xpl-text-callout` | Description typography: `--xpl-font-size-callout` (12px) / normal / 1.3333 line-height |\n| `--xpl-space-{8,12,16}` | Heading, row, and styled input/label spacing |\n| `--xpl-size-100` | Control width used to offset the styled label padding (16px) |\n\nChoice item labels and descriptions inherit their text tokens from the shared `label.css` (see `xpl-checkbox` / `xpl-radio`).\n",
|
|
@@ -2862,7 +2947,7 @@
|
|
|
2862
2947
|
"Choice": {
|
|
2863
2948
|
"location": "import",
|
|
2864
2949
|
"path": "./choice",
|
|
2865
|
-
"id": "src/components/
|
|
2950
|
+
"id": "src/components/xpl-choicelist/choice.ts::Choice",
|
|
2866
2951
|
"referenceLocation": "Choice"
|
|
2867
2952
|
}
|
|
2868
2953
|
}
|
|
@@ -3052,12 +3137,16 @@
|
|
|
3052
3137
|
}
|
|
3053
3138
|
},
|
|
3054
3139
|
{
|
|
3055
|
-
"filePath": "src/components/
|
|
3140
|
+
"filePath": "src/components/xpl-content-area/xpl-content-area.tsx",
|
|
3056
3141
|
"encapsulation": "none",
|
|
3057
3142
|
"tag": "xpl-content-area",
|
|
3058
3143
|
"readme": "# xpl-content-area\n\nThe `<xpl-content-area>` sets up the area for the main content of the page. This component renders a `<main>` element with an unnamed `<slot>`, and should not be combined with another `<main>` in the same page.\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-background-surface-subtlest` — page surface behind the content (neutral-50 light / neutral-900 dark). Themes automatically — no `.dark` override. Matches the intended application-shell content surface.\n- `--xpl-text-default` — default text color (neutral-900 light / neutral-50 dark).\n",
|
|
3059
3144
|
"docs": "The `<xpl-content-area>` sets up the area for the main content of the page. This component renders a `<main>` element with an unnamed `<slot>`, and should not be combined with another `<main>` in the same page.",
|
|
3060
3145
|
"docsTags": [
|
|
3146
|
+
{
|
|
3147
|
+
"name": "slot",
|
|
3148
|
+
"text": "- The page content."
|
|
3149
|
+
},
|
|
3061
3150
|
{
|
|
3062
3151
|
"name": "since",
|
|
3063
3152
|
"text": "0.1.2"
|
|
@@ -3112,7 +3201,12 @@
|
|
|
3112
3201
|
"events": [],
|
|
3113
3202
|
"listeners": [],
|
|
3114
3203
|
"styles": [],
|
|
3115
|
-
"slots": [
|
|
3204
|
+
"slots": [
|
|
3205
|
+
{
|
|
3206
|
+
"name": "",
|
|
3207
|
+
"docs": "The page content."
|
|
3208
|
+
}
|
|
3209
|
+
],
|
|
3116
3210
|
"parts": [],
|
|
3117
3211
|
"states": [],
|
|
3118
3212
|
"dependents": [],
|
|
@@ -3120,12 +3214,16 @@
|
|
|
3120
3214
|
"dependencyGraph": {}
|
|
3121
3215
|
},
|
|
3122
3216
|
{
|
|
3123
|
-
"filePath": "src/components/
|
|
3217
|
+
"filePath": "src/components/xpl-dashboard/xpl-dashboard.tsx",
|
|
3124
3218
|
"encapsulation": "none",
|
|
3125
3219
|
"tag": "xpl-dashboard",
|
|
3126
3220
|
"readme": "# xpl-dashboard\n\nThe XPL-Dashboard component is a code-only utility component for responsive layouts using the XPL-Data Card component. \n",
|
|
3127
3221
|
"docs": "The XPL-Dashboard component is a code-only utility component for responsive layouts using the XPL-Data Card component.",
|
|
3128
3222
|
"docsTags": [
|
|
3223
|
+
{
|
|
3224
|
+
"name": "slot",
|
|
3225
|
+
"text": "- The dashboard content."
|
|
3226
|
+
},
|
|
3129
3227
|
{
|
|
3130
3228
|
"name": "since",
|
|
3131
3229
|
"text": "1.0.0"
|
|
@@ -3137,7 +3235,12 @@
|
|
|
3137
3235
|
"events": [],
|
|
3138
3236
|
"listeners": [],
|
|
3139
3237
|
"styles": [],
|
|
3140
|
-
"slots": [
|
|
3238
|
+
"slots": [
|
|
3239
|
+
{
|
|
3240
|
+
"name": "",
|
|
3241
|
+
"docs": "The dashboard content."
|
|
3242
|
+
}
|
|
3243
|
+
],
|
|
3141
3244
|
"parts": [],
|
|
3142
3245
|
"states": [],
|
|
3143
3246
|
"dependents": [],
|
|
@@ -3145,10 +3248,10 @@
|
|
|
3145
3248
|
"dependencyGraph": {}
|
|
3146
3249
|
},
|
|
3147
3250
|
{
|
|
3148
|
-
"filePath": "src/components/
|
|
3251
|
+
"filePath": "src/components/xpl-data-card/xpl-data-card.tsx",
|
|
3149
3252
|
"encapsulation": "none",
|
|
3150
3253
|
"tag": "xpl-data-card",
|
|
3151
|
-
"readme": "# xpl-data-card\n\nData Cards display snippets of information and can be linked to larger data sets. Data Cards give users \"at a glance\" information about their data.\n\nThe `icon` and `smallStatIcon` properties accept icon names as strings. See [xpl-icon available icons](../xpl-icon/ICONS.md) for the complete list.\n\n## Design Tokens\n\nThe card is styled entirely with Apollo Foundation purpose-specific tokens (dark mode is automatic — no `.dark` overrides).\n\n| Element / state | Property | Token |\n| --- | --- | --- |\n| Host surface | `background-color` | `--xpl-background-surface-default` |\n| Host / anchor border | `border-color` | `--xpl-border-default` |\n| Host, header, stats text | `color` | `--xpl-text-default` |\n| Header arrow (chevron) icon | `color` | `--xpl-icon-default` |\n| Detail text | `color` | `--xpl-text-subdued` |\n| `.positive` stat | `color` | `--xpl-text-positive` |\n| `.negative` stat | `color` | `--xpl-text-negative` |\n| `.neutral` stat | `color` | `--xpl-text-subdued` |\n| Primary leading icon | `color` | `--xpl-icon-brand` (orange) |\n| Secondary leading icon | `color` | `--xpl-background-action-primary-default` (purple) |\n| Anchor hover / active border | `border` | `--xpl-border-small` + `--xpl-background-action-primary-default` |\n| Anchor focus-visible border | `border` | `--xpl-border-small` + `--xpl-border-focus` (purple) |\n| Anchor focus-visible outline | `outline` | `--xpl-border-focus`, 2px width / 2px offset |\n| Anchor hover / focus-visible radius | `border-radius` | `--xpl-border-radius-default` |\n| Anchor hover shadow | `box-shadow` | `--xpl-elevation-2` (theme-aware) |\n| Header / stat spacing | `margin` | `--xpl-space-4`, `--xpl-space-6` |\n| Container-query stat | `font-size` | `--xpl-font-size-title-2` |\n\nThe resting anchor overlay keeps a `0.375rem` (6px) radius to match the card's `rounded-md`; Foundation has no 6px radius token (see `TECH_DEBT.md`).\n",
|
|
3254
|
+
"readme": "# xpl-data-card\n\nData Cards display snippets of information and can be linked to larger data sets. Data Cards give users \"at a glance\" information about their data.\n\nThe `icon` and `smallStatIcon` properties accept icon names as strings. See [xpl-icon available icons](../xpl-icon/ICONS.md) for the complete list.\n\n## Design Tokens\n\nThe card is styled entirely with Apollo Foundation purpose-specific tokens (dark mode is automatic — no `.dark` overrides).\n\n| Element / state | Property | Token |\n| --- | --- | --- |\n| Host surface | `background-color` | `--xpl-background-surface-default` |\n| Host / anchor border | `border-color` | `--xpl-border-default` |\n| Host, header, stats text | `color` | `--xpl-text-default` |\n| Header arrow (chevron) icon | `color` | `--xpl-icon-default` |\n| Detail text | `color` | `--xpl-text-subdued` |\n| `.positive` stat | `color` | `--xpl-text-positive` |\n| `.negative` stat | `color` | `--xpl-text-negative` |\n| `.neutral` stat | `color` | `--xpl-text-subdued` |\n| Primary leading icon | `color` | `--xpl-icon-brand` (orange) |\n| Secondary leading icon | `color` | `--xpl-background-action-primary-default` (purple) |\n| Anchor hover / active border | `border` | `--xpl-border-small` + `--xpl-background-action-primary-default` |\n| Anchor focus-visible border | `border` | `--xpl-border-small` + `--xpl-border-focus` (purple) |\n| Anchor focus-visible outline | `outline` | `--xpl-border-focus`, 2px width / 2px offset |\n| Anchor hover / focus-visible radius | `border-radius` | `--xpl-border-radius-default` |\n| Anchor hover shadow | `box-shadow` | `--xpl-elevation-2` (theme-aware) |\n| Header / stat spacing | `margin` | `--xpl-space-4`, `--xpl-space-6` |\n| Container-query stat | `font-size` | `--xpl-font-size-title-2` |\n| Container-query stat | `line-height` | `--xpl-line-height-title-2` |\n\nThe resting anchor overlay keeps a `0.375rem` (6px) radius to match the card's `rounded-md`; Foundation has no 6px radius token (see `TECH_DEBT.md`).\n",
|
|
3152
3255
|
"docs": "Data Cards display snippets of information and can be linked to larger data sets. Data Cards give users \"at a glance\" information about their data.\n\nThe `icon` and `smallStatIcon` properties accept icon names as strings. See [xpl-icon available icons](../xpl-icon/ICONS.md) for the complete list.",
|
|
3153
3256
|
"docsTags": [
|
|
3154
3257
|
{
|
|
@@ -3527,12 +3630,16 @@
|
|
|
3527
3630
|
}
|
|
3528
3631
|
},
|
|
3529
3632
|
{
|
|
3530
|
-
"filePath": "src/components/
|
|
3633
|
+
"filePath": "src/components/xpl-divider/xpl-divider.tsx",
|
|
3531
3634
|
"encapsulation": "none",
|
|
3532
3635
|
"tag": "xpl-divider",
|
|
3533
3636
|
"readme": "# xpl-divider\n\nAllows for easy separation and titling of sections within forms or other content.\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-border-default` — divider line color\n- `--xpl-text-default` — label text color\n\n**Spacing**\n- `--xpl-space-{0,4,16}` — padding / margin\n\n**Typography**\n- `--xpl-font-size-body` — base label font size\n- Tier typography extends the shared type scale from `typography.css`: tier 3 → `.xpl-text-title-3`, tier 2 → `.xpl-text-title-4`, tier 1 → `.xpl-text-title-5`\n\n**Border**\n- `--xpl-border-small` — line width (1px)\n",
|
|
3534
3637
|
"docs": "Allows for easy separation and titling of sections within forms or other content.",
|
|
3535
3638
|
"docsTags": [
|
|
3639
|
+
{
|
|
3640
|
+
"name": "slot",
|
|
3641
|
+
"text": "- Optional text content rendered inside the divider (not displayed for tier 0)."
|
|
3642
|
+
},
|
|
3536
3643
|
{
|
|
3537
3644
|
"name": "since",
|
|
3538
3645
|
"text": "0.3.0"
|
|
@@ -3568,7 +3675,12 @@
|
|
|
3568
3675
|
"events": [],
|
|
3569
3676
|
"listeners": [],
|
|
3570
3677
|
"styles": [],
|
|
3571
|
-
"slots": [
|
|
3678
|
+
"slots": [
|
|
3679
|
+
{
|
|
3680
|
+
"name": "",
|
|
3681
|
+
"docs": "Optional text content rendered inside the divider (not displayed for tier 0)."
|
|
3682
|
+
}
|
|
3683
|
+
],
|
|
3572
3684
|
"parts": [],
|
|
3573
3685
|
"states": [],
|
|
3574
3686
|
"dependents": [
|
|
@@ -3586,12 +3698,20 @@
|
|
|
3586
3698
|
}
|
|
3587
3699
|
},
|
|
3588
3700
|
{
|
|
3589
|
-
"filePath": "src/components/
|
|
3701
|
+
"filePath": "src/components/xpl-dropdown/xpl-dropdown.tsx",
|
|
3590
3702
|
"encapsulation": "none",
|
|
3591
3703
|
"tag": "xpl-dropdown",
|
|
3592
|
-
"readme": "# xpl-dropdown\n\nA Dropdown is a menu with a list of actions a user can take. Use a dropdown when you want to present a list of actions in a limited space. Dropdowns are single-select ***actions***, can be presented in groups, and can be triggered by other elements such as a button, icon, text etc. \nA selection within a dropdown does not change the parent trigger.\n\n***If you want to present a list of **options** a user can select, or multi-select options, please use [XPL-Select](https://apollo.xplordocs.com/?path=/story/components-select--select).***\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`. The panel surface and border are aligned with the migrated [xpl-popover](../xpl-popover).\n\n**Color**\n- `--xpl-background-surface-default` — panel background\n- `--xpl-text-default` — panel text color (inherited default), option label color, and heading color\n- `--xpl-icon-default` — leading option icon color (`--xpl-icon` via the `icon` prop)\n- `--xpl-border-default` — panel border and heading bottom border\n- `--xpl-text-subdued` — list-item subtitle color\n- `--xpl-background-action-tertiary-hover` — option `:focus` background\n- `--xpl-background-surface-subtlest` — option `:hover` background (neutral subtle surface)\n- `--xpl-background-surface-information` — `--selected` background (purple-50 light / neutral-700 dark)\n- `--xpl-background-action-primary-default` — `--selected` right accent border color\n\n**Border**\n- `--xpl-border-small` — panel and heading border width (1px)\n- `--xpl-border-
|
|
3704
|
+
"readme": "# xpl-dropdown\n\nA Dropdown is a menu with a list of actions a user can take. Use a dropdown when you want to present a list of actions in a limited space. Dropdowns are single-select ***actions***, can be presented in groups, and can be triggered by other elements such as a button, icon, text etc. \nA selection within a dropdown does not change the parent trigger.\n\n***If you want to present a list of **options** a user can select, or multi-select options, please use [XPL-Select](https://apollo.xplordocs.com/?path=/story/components-select--select).***\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`. The panel surface and border are aligned with the migrated [xpl-popover](../xpl-popover).\n\n**Color**\n- `--xpl-background-surface-default` — panel background\n- `--xpl-text-default` — panel text color (inherited default), option label color, and heading color\n- `--xpl-icon-default` — leading option icon color (`--xpl-icon` via the `icon` prop)\n- `--xpl-border-default` — panel border and heading bottom border\n- `--xpl-text-subdued` — list-item subtitle color\n- `--xpl-background-action-tertiary-hover` — option `:focus` background\n- `--xpl-background-surface-subtlest` — option `:hover` background (neutral subtle surface)\n- `--xpl-background-surface-information` — `--selected` background (purple-50 light / neutral-700 dark)\n- `--xpl-background-action-primary-default` — `--selected` right accent border color\n- `--xpl-icon-information` — multi-select checkmark color (purple in both light and dark mode)\n\n**Border**\n- `--xpl-border-small` — panel and heading border width (1px)\n- `--xpl-border-xlarge` — 4px `--selected` accent border\n- `--xpl-border-radius-small` — panel corner radius (4px), matching the anchored `xpl-select` trigger\n\n**Spacing / Sizing**\n- `--xpl-space-16` — multi-select checkmark right offset\n- `--xpl-size-075` — multi-select checkmark size (12px)\n- `--xpl-dropdown-list-max-height` — component custom property for the options list max-height (default 300px)\n\n**Elevation**\n- `--xpl-elevation-2` — panel drop shadow\n\n**Typography**\n- `@extend .xpl-text-callout-bold` — heading: 12px / semibold weight / line-height 1.3333\n- `@extend .xpl-text-callout` — list-item subtitle: 12px / normal weight / line-height 1.3333\n\n**Note:** The multi-select checkmark is a data-URI SVG whose `fill` cannot be themed by a CSS variable, so a `.dark` override supplies the dark-mode glyph; and the disabled option keeps `opacity-60`. Both are tracked in `TECH_DEBT.md`.\n",
|
|
3593
3705
|
"docs": "A Dropdown is a menu with a list of actions a user can take. Use a dropdown when you want to present a list of actions in a limited space. Dropdowns are single-select ***actions***, can be presented in groups, and can be triggered by other elements such as a button, icon, text etc. \nA selection within a dropdown does not change the parent trigger.\n\n***If you want to present a list of **options** a user can select, or multi-select options, please use [XPL-Select](https://apollo.xplordocs.com/?path=/story/components-select--select).***",
|
|
3594
3706
|
"docsTags": [
|
|
3707
|
+
{
|
|
3708
|
+
"name": "slot",
|
|
3709
|
+
"text": "header - Optional header content rendered above the options list."
|
|
3710
|
+
},
|
|
3711
|
+
{
|
|
3712
|
+
"name": "slot",
|
|
3713
|
+
"text": "options - The `xpl-dropdown-option` / `xpl-dropdown-group` items. Used when the `options` prop is not set."
|
|
3714
|
+
},
|
|
3595
3715
|
{
|
|
3596
3716
|
"name": "since",
|
|
3597
3717
|
"text": "0.4.0"
|
|
@@ -3667,7 +3787,7 @@
|
|
|
3667
3787
|
"Placement": {
|
|
3668
3788
|
"location": "import",
|
|
3669
3789
|
"path": "../../utils/floating",
|
|
3670
|
-
"id": "src/
|
|
3790
|
+
"id": "src/utils/floating.ts::Placement",
|
|
3671
3791
|
"referenceLocation": "Placement"
|
|
3672
3792
|
}
|
|
3673
3793
|
}
|
|
@@ -3759,7 +3879,7 @@
|
|
|
3759
3879
|
"DropdownItem": {
|
|
3760
3880
|
"location": "import",
|
|
3761
3881
|
"path": "./dropdown-option",
|
|
3762
|
-
"id": "src/components/
|
|
3882
|
+
"id": "src/components/xpl-dropdown/dropdown-option.ts::DropdownItem",
|
|
3763
3883
|
"referenceLocation": "DropdownItem"
|
|
3764
3884
|
}
|
|
3765
3885
|
}
|
|
@@ -3788,7 +3908,7 @@
|
|
|
3788
3908
|
"Placement": {
|
|
3789
3909
|
"location": "import",
|
|
3790
3910
|
"path": "../../utils/floating",
|
|
3791
|
-
"id": "src/
|
|
3911
|
+
"id": "src/utils/floating.ts::Placement",
|
|
3792
3912
|
"referenceLocation": "Placement"
|
|
3793
3913
|
}
|
|
3794
3914
|
}
|
|
@@ -3951,8 +4071,9 @@
|
|
|
3951
4071
|
"referenceLocation": "Event"
|
|
3952
4072
|
},
|
|
3953
4073
|
"Dropdown": {
|
|
3954
|
-
"location": "
|
|
3955
|
-
"
|
|
4074
|
+
"location": "local",
|
|
4075
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-dropdown/xpl-dropdown.tsx",
|
|
4076
|
+
"id": "src/components/xpl-dropdown/xpl-dropdown.tsx::Dropdown"
|
|
3956
4077
|
}
|
|
3957
4078
|
}
|
|
3958
4079
|
},
|
|
@@ -4010,7 +4131,7 @@
|
|
|
4010
4131
|
"DropdownItem": {
|
|
4011
4132
|
"location": "import",
|
|
4012
4133
|
"path": "./dropdown-option",
|
|
4013
|
-
"id": "src/components/
|
|
4134
|
+
"id": "src/components/xpl-dropdown/dropdown-option.ts::DropdownItem",
|
|
4014
4135
|
"referenceLocation": "DropdownItem"
|
|
4015
4136
|
},
|
|
4016
4137
|
"HTMLXplDropdownOptionElement": {
|
|
@@ -4055,7 +4176,16 @@
|
|
|
4055
4176
|
],
|
|
4056
4177
|
"listeners": [],
|
|
4057
4178
|
"styles": [],
|
|
4058
|
-
"slots": [
|
|
4179
|
+
"slots": [
|
|
4180
|
+
{
|
|
4181
|
+
"name": "header",
|
|
4182
|
+
"docs": "Optional header content rendered above the options list."
|
|
4183
|
+
},
|
|
4184
|
+
{
|
|
4185
|
+
"name": "options",
|
|
4186
|
+
"docs": "The `xpl-dropdown-option` / `xpl-dropdown-group` items. Used when the `options` prop is not set."
|
|
4187
|
+
}
|
|
4188
|
+
],
|
|
4059
4189
|
"parts": [],
|
|
4060
4190
|
"states": [],
|
|
4061
4191
|
"dependents": [
|
|
@@ -4092,12 +4222,17 @@
|
|
|
4092
4222
|
}
|
|
4093
4223
|
},
|
|
4094
4224
|
{
|
|
4095
|
-
"filePath": "src/components/
|
|
4225
|
+
"filePath": "src/components/xpl-dropdown/xpl-dropdown-group/xpl-dropdown-group.tsx",
|
|
4096
4226
|
"encapsulation": "none",
|
|
4097
4227
|
"tag": "xpl-dropdown-group",
|
|
4098
4228
|
"readme": "# xpl-dropdown-group\n\n\n",
|
|
4099
4229
|
"docs": "",
|
|
4100
|
-
"docsTags": [
|
|
4230
|
+
"docsTags": [
|
|
4231
|
+
{
|
|
4232
|
+
"name": "slot",
|
|
4233
|
+
"text": "options - The `xpl-dropdown-option` items in this group. Used when the `options` prop is not set."
|
|
4234
|
+
}
|
|
4235
|
+
],
|
|
4101
4236
|
"usage": {},
|
|
4102
4237
|
"props": [
|
|
4103
4238
|
{
|
|
@@ -4133,7 +4268,7 @@
|
|
|
4133
4268
|
"DropdownOptionGroup": {
|
|
4134
4269
|
"location": "import",
|
|
4135
4270
|
"path": "../dropdown-option",
|
|
4136
|
-
"id": "src/components/
|
|
4271
|
+
"id": "src/components/xpl-dropdown/dropdown-option.ts::DropdownOptionGroup",
|
|
4137
4272
|
"referenceLocation": "DropdownOptionGroup"
|
|
4138
4273
|
}
|
|
4139
4274
|
}
|
|
@@ -4157,7 +4292,12 @@
|
|
|
4157
4292
|
"events": [],
|
|
4158
4293
|
"listeners": [],
|
|
4159
4294
|
"styles": [],
|
|
4160
|
-
"slots": [
|
|
4295
|
+
"slots": [
|
|
4296
|
+
{
|
|
4297
|
+
"name": "options",
|
|
4298
|
+
"docs": "The `xpl-dropdown-option` items in this group. Used when the `options` prop is not set."
|
|
4299
|
+
}
|
|
4300
|
+
],
|
|
4161
4301
|
"parts": [],
|
|
4162
4302
|
"states": [],
|
|
4163
4303
|
"dependents": [
|
|
@@ -4182,12 +4322,17 @@
|
|
|
4182
4322
|
}
|
|
4183
4323
|
},
|
|
4184
4324
|
{
|
|
4185
|
-
"filePath": "src/components/
|
|
4325
|
+
"filePath": "src/components/xpl-dropdown/xpl-dropdown-heading/xpl-dropdown-heading.tsx",
|
|
4186
4326
|
"encapsulation": "none",
|
|
4187
4327
|
"tag": "xpl-dropdown-heading",
|
|
4188
4328
|
"readme": "# xpl-dropdown-heading\n\n\n",
|
|
4189
4329
|
"docs": "",
|
|
4190
|
-
"docsTags": [
|
|
4330
|
+
"docsTags": [
|
|
4331
|
+
{
|
|
4332
|
+
"name": "slot",
|
|
4333
|
+
"text": "heading - Custom heading content. Used when the `label` prop is not set."
|
|
4334
|
+
}
|
|
4335
|
+
],
|
|
4191
4336
|
"usage": {},
|
|
4192
4337
|
"props": [
|
|
4193
4338
|
{
|
|
@@ -4218,7 +4363,12 @@
|
|
|
4218
4363
|
"events": [],
|
|
4219
4364
|
"listeners": [],
|
|
4220
4365
|
"styles": [],
|
|
4221
|
-
"slots": [
|
|
4366
|
+
"slots": [
|
|
4367
|
+
{
|
|
4368
|
+
"name": "heading",
|
|
4369
|
+
"docs": "Custom heading content. Used when the `label` prop is not set."
|
|
4370
|
+
}
|
|
4371
|
+
],
|
|
4222
4372
|
"parts": [],
|
|
4223
4373
|
"states": [],
|
|
4224
4374
|
"dependents": [
|
|
@@ -4232,12 +4382,17 @@
|
|
|
4232
4382
|
}
|
|
4233
4383
|
},
|
|
4234
4384
|
{
|
|
4235
|
-
"filePath": "src/components/
|
|
4385
|
+
"filePath": "src/components/xpl-dropdown/xpl-dropdown-option/xpl-dropdown-option.tsx",
|
|
4236
4386
|
"encapsulation": "none",
|
|
4237
4387
|
"tag": "xpl-dropdown-option",
|
|
4238
4388
|
"readme": "# xpl-dropdown-option\n\n\n",
|
|
4239
4389
|
"docs": "",
|
|
4240
|
-
"docsTags": [
|
|
4390
|
+
"docsTags": [
|
|
4391
|
+
{
|
|
4392
|
+
"name": "slot",
|
|
4393
|
+
"text": "option - Custom option content. Used when the `label` prop is not set."
|
|
4394
|
+
}
|
|
4395
|
+
],
|
|
4241
4396
|
"usage": {},
|
|
4242
4397
|
"props": [
|
|
4243
4398
|
{
|
|
@@ -4383,7 +4538,12 @@
|
|
|
4383
4538
|
"events": [],
|
|
4384
4539
|
"listeners": [],
|
|
4385
4540
|
"styles": [],
|
|
4386
|
-
"slots": [
|
|
4541
|
+
"slots": [
|
|
4542
|
+
{
|
|
4543
|
+
"name": "option",
|
|
4544
|
+
"docs": "Custom option content. Used when the `label` prop is not set."
|
|
4545
|
+
}
|
|
4546
|
+
],
|
|
4387
4547
|
"parts": [],
|
|
4388
4548
|
"states": [],
|
|
4389
4549
|
"dependents": [
|
|
@@ -4406,12 +4566,20 @@
|
|
|
4406
4566
|
}
|
|
4407
4567
|
},
|
|
4408
4568
|
{
|
|
4409
|
-
"filePath": "src/components/
|
|
4569
|
+
"filePath": "src/components/xpl-dynamic-table/xpl-dynamic-table.tsx",
|
|
4410
4570
|
"encapsulation": "none",
|
|
4411
4571
|
"tag": "xpl-dynamic-table",
|
|
4412
4572
|
"readme": "# xpl-dynamic-table\n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\nThe Dynamic Table is a rich content table that can accommodate multiple types of data.\n\n> **[DEPRECATED]** Use the compositional `<xpl-table>` API instead.\n> This component will be removed in a future major release.\n\n## Design Tokens\n\nThe table, cells, and rows use Apollo Foundation purpose-specific tokens (light / dark resolve automatically — no `.dark` overrides):\n\n**Table** (`.xpl-dynamic-table`)\n\n| Element | Property | Token |\n| --- | --- | --- |\n| Grid columns | `grid-template-columns` | `--xpl-column-widths` (set at runtime from header cell widths) |\n| Row gap (with accordions) | `row-gap` (8px) | `--xpl-space-8` |\n\n**Cell** (`.xpl-dynamic-table-cell`)\n\n| Element | Property | Token |\n| --- | --- | --- |\n| Cell | Background | `--xpl-background-surface-default` |\n| Cell | Border | `--xpl-border-default` |\n| Cell | Text | `--xpl-text-default` |\n| Cell | Typography (title-5 / medium / 1.4286) | `@extend .xpl-text-title-5` |\n| Cell | Height (56px) | `--xpl-size-350` |\n| Cell | Min width (48px) | `--xpl-size-300` |\n| Cell rounded corners | Border radius (8px) | `--xpl-border-radius-default` |\n| Cell icons (chevron, kebab) | Color | `--xpl-icon-default` |\n| Dropdown button (`:focus-visible`) | Inset ring | `--xpl-border-focus` |\n\n**Row** (`.xpl-dynamic-table-row`)\n\n| State | Property | Token |\n| --- | --- | --- |\n| First cell | Left border | `--xpl-border-default` |\n| Selected | Cell background | `--xpl-background-surface-information` |\n| Disabled | Cell background | `--xpl-background-surface-subtlest` |\n| Disabled | Cell / badge text | `--xpl-text-disabled` |\n| Disabled | Cell icons | `--xpl-icon-disabled` |\n",
|
|
4413
4573
|
"docs": "> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\nThe Dynamic Table is a rich content table that can accommodate multiple types of data.\n\n> **[DEPRECATED]** Use the compositional `<xpl-table>` API instead.\n> This component will be removed in a future major release.",
|
|
4414
4574
|
"docsTags": [
|
|
4575
|
+
{
|
|
4576
|
+
"name": "slot",
|
|
4577
|
+
"text": "header - The header region of the table."
|
|
4578
|
+
},
|
|
4579
|
+
{
|
|
4580
|
+
"name": "slot",
|
|
4581
|
+
"text": "body - The body region of the table."
|
|
4582
|
+
},
|
|
4415
4583
|
{
|
|
4416
4584
|
"name": "since",
|
|
4417
4585
|
"text": "1.4.0"
|
|
@@ -4451,7 +4619,16 @@
|
|
|
4451
4619
|
}
|
|
4452
4620
|
],
|
|
4453
4621
|
"styles": [],
|
|
4454
|
-
"slots": [
|
|
4622
|
+
"slots": [
|
|
4623
|
+
{
|
|
4624
|
+
"name": "body",
|
|
4625
|
+
"docs": "The body region of the table."
|
|
4626
|
+
},
|
|
4627
|
+
{
|
|
4628
|
+
"name": "header",
|
|
4629
|
+
"docs": "The header region of the table."
|
|
4630
|
+
}
|
|
4631
|
+
],
|
|
4455
4632
|
"parts": [],
|
|
4456
4633
|
"states": [],
|
|
4457
4634
|
"dependents": [],
|
|
@@ -4459,12 +4636,16 @@
|
|
|
4459
4636
|
"dependencyGraph": {}
|
|
4460
4637
|
},
|
|
4461
4638
|
{
|
|
4462
|
-
"filePath": "src/components/
|
|
4639
|
+
"filePath": "src/components/xpl-dynamic-table-cell/xpl-dynamic-table-cell.tsx",
|
|
4463
4640
|
"encapsulation": "none",
|
|
4464
4641
|
"tag": "xpl-dynamic-table-cell",
|
|
4465
4642
|
"readme": "# xpl-dynamic-table-cell\n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\n> **[DEPRECATED]** Use `<xpl-table-cell>` instead.\n> This component will be removed in a future major release.\n",
|
|
4466
4643
|
"docs": "> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\n> **[DEPRECATED]** Use `<xpl-table-cell>` instead.\n> This component will be removed in a future major release.",
|
|
4467
4644
|
"docsTags": [
|
|
4645
|
+
{
|
|
4646
|
+
"name": "slot",
|
|
4647
|
+
"text": "- The cell content."
|
|
4648
|
+
},
|
|
4468
4649
|
{
|
|
4469
4650
|
"name": "since",
|
|
4470
4651
|
"text": "1.3.0"
|
|
@@ -4506,7 +4687,12 @@
|
|
|
4506
4687
|
"events": [],
|
|
4507
4688
|
"listeners": [],
|
|
4508
4689
|
"styles": [],
|
|
4509
|
-
"slots": [
|
|
4690
|
+
"slots": [
|
|
4691
|
+
{
|
|
4692
|
+
"name": "",
|
|
4693
|
+
"docs": "The cell content."
|
|
4694
|
+
}
|
|
4695
|
+
],
|
|
4510
4696
|
"parts": [],
|
|
4511
4697
|
"states": [],
|
|
4512
4698
|
"dependents": [],
|
|
@@ -4514,12 +4700,16 @@
|
|
|
4514
4700
|
"dependencyGraph": {}
|
|
4515
4701
|
},
|
|
4516
4702
|
{
|
|
4517
|
-
"filePath": "src/components/
|
|
4703
|
+
"filePath": "src/components/xpl-dynamic-table-row/xpl-dynamic-table-row.tsx",
|
|
4518
4704
|
"encapsulation": "none",
|
|
4519
4705
|
"tag": "xpl-dynamic-table-row",
|
|
4520
4706
|
"readme": "# xpl-dynamic-table-row\n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\n> **[DEPRECATED]** Use `<xpl-table-row>` instead.\n> This component will be removed in a future major release.\n",
|
|
4521
4707
|
"docs": "> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\n> **[DEPRECATED]** Use `<xpl-table-row>` instead.\n> This component will be removed in a future major release.",
|
|
4522
4708
|
"docsTags": [
|
|
4709
|
+
{
|
|
4710
|
+
"name": "slot",
|
|
4711
|
+
"text": "- The row cells (`xpl-dynamic-table-cell` elements)."
|
|
4712
|
+
},
|
|
4523
4713
|
{
|
|
4524
4714
|
"name": "since",
|
|
4525
4715
|
"text": "1.3.0"
|
|
@@ -4590,7 +4780,12 @@
|
|
|
4590
4780
|
"events": [],
|
|
4591
4781
|
"listeners": [],
|
|
4592
4782
|
"styles": [],
|
|
4593
|
-
"slots": [
|
|
4783
|
+
"slots": [
|
|
4784
|
+
{
|
|
4785
|
+
"name": "",
|
|
4786
|
+
"docs": "The row cells (`xpl-dynamic-table-cell` elements)."
|
|
4787
|
+
}
|
|
4788
|
+
],
|
|
4594
4789
|
"parts": [],
|
|
4595
4790
|
"states": [],
|
|
4596
4791
|
"dependents": [],
|
|
@@ -4598,7 +4793,7 @@
|
|
|
4598
4793
|
"dependencyGraph": {}
|
|
4599
4794
|
},
|
|
4600
4795
|
{
|
|
4601
|
-
"filePath": "src/components/
|
|
4796
|
+
"filePath": "src/components/xpl-grid/xpl-grid.tsx",
|
|
4602
4797
|
"encapsulation": "none",
|
|
4603
4798
|
"tag": "xpl-grid",
|
|
4604
4799
|
"readme": "# xpl-grid\n\nXPL-Grid is a code only utility component to help with responsive layouts. \n",
|
|
@@ -4623,12 +4818,16 @@
|
|
|
4623
4818
|
"dependencyGraph": {}
|
|
4624
4819
|
},
|
|
4625
4820
|
{
|
|
4626
|
-
"filePath": "src/components/
|
|
4821
|
+
"filePath": "src/components/xpl-grid-item/xpl-grid-item.tsx",
|
|
4627
4822
|
"encapsulation": "none",
|
|
4628
4823
|
"tag": "xpl-grid-item",
|
|
4629
4824
|
"readme": "# xpl-grid-item\n\n\n",
|
|
4630
4825
|
"docs": "",
|
|
4631
4826
|
"docsTags": [
|
|
4827
|
+
{
|
|
4828
|
+
"name": "slot",
|
|
4829
|
+
"text": "- Content rendered inside the grid item."
|
|
4830
|
+
},
|
|
4632
4831
|
{
|
|
4633
4832
|
"name": "since",
|
|
4634
4833
|
"text": "0.4.0"
|
|
@@ -4757,7 +4956,12 @@
|
|
|
4757
4956
|
"events": [],
|
|
4758
4957
|
"listeners": [],
|
|
4759
4958
|
"styles": [],
|
|
4760
|
-
"slots": [
|
|
4959
|
+
"slots": [
|
|
4960
|
+
{
|
|
4961
|
+
"name": "",
|
|
4962
|
+
"docs": "Content rendered inside the grid item."
|
|
4963
|
+
}
|
|
4964
|
+
],
|
|
4761
4965
|
"parts": [],
|
|
4762
4966
|
"states": [],
|
|
4763
4967
|
"dependents": [],
|
|
@@ -4765,12 +4969,20 @@
|
|
|
4765
4969
|
"dependencyGraph": {}
|
|
4766
4970
|
},
|
|
4767
4971
|
{
|
|
4768
|
-
"filePath": "src/components/
|
|
4972
|
+
"filePath": "src/components/xpl-header-accordion/xpl-header-accordion.tsx",
|
|
4769
4973
|
"encapsulation": "none",
|
|
4770
4974
|
"tag": "xpl-header-accordion",
|
|
4771
4975
|
"readme": "# xpl-header-accordion\n\nThe toolbar component allows users to manipulate selections within the Dynamic Table. It is only visible when a row or cell is in the selected state and bulk actions can be taken on that row or cell. \n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\n## Design Tokens\n\nThe header uses Apollo Foundation purpose-specific tokens (light / dark resolve automatically — no `.dark` overrides):\n\n| Element | Property | Token |\n| --- | --- | --- |\n| Header bar | Background | `--xpl-background-surface-subtlest` |\n| Header bar | Border | `--xpl-border-default` |\n| Header bar | Text | `--xpl-text-subdued` |\n| Header bar | Typography (title-5 / medium / 1.4286) | `@extend .xpl-text-title-5` |\n| Header bar | Min height (56px) | `--xpl-size-350` |\n| Header bar corners | Border radius (8px) | `--xpl-border-radius-default` |\n| Toggle area (`:focus-visible`) | Outline color | `--xpl-border-focus` |\n| Chevron icon | Color | `--xpl-icon-default` |\n| Content panel | Background | `--xpl-background-surface-default` |\n| Content panel | Border | `--xpl-border-default` |\n| Content panel | Text | `--xpl-text-link-default` |\n| Content grid | `grid-template-columns` | `--xpl-column-widths` (set at runtime by `xpl-dynamic-table`) |\n",
|
|
4772
4976
|
"docs": "The toolbar component allows users to manipulate selections within the Dynamic Table. It is only visible when a row or cell is in the selected state and bulk actions can be taken on that row or cell. \n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.",
|
|
4773
4977
|
"docsTags": [
|
|
4978
|
+
{
|
|
4979
|
+
"name": "slot",
|
|
4980
|
+
"text": "title - The header content of the accordion toggle."
|
|
4981
|
+
},
|
|
4982
|
+
{
|
|
4983
|
+
"name": "slot",
|
|
4984
|
+
"text": "content - Content rendered inside the collapsible body of the accordion."
|
|
4985
|
+
},
|
|
4774
4986
|
{
|
|
4775
4987
|
"name": "since",
|
|
4776
4988
|
"text": "1.2.0"
|
|
@@ -4928,7 +5140,16 @@
|
|
|
4928
5140
|
}
|
|
4929
5141
|
],
|
|
4930
5142
|
"styles": [],
|
|
4931
|
-
"slots": [
|
|
5143
|
+
"slots": [
|
|
5144
|
+
{
|
|
5145
|
+
"name": "content",
|
|
5146
|
+
"docs": "Content rendered inside the collapsible body of the accordion."
|
|
5147
|
+
},
|
|
5148
|
+
{
|
|
5149
|
+
"name": "title",
|
|
5150
|
+
"docs": "The header content of the accordion toggle."
|
|
5151
|
+
}
|
|
5152
|
+
],
|
|
4932
5153
|
"parts": [],
|
|
4933
5154
|
"states": [],
|
|
4934
5155
|
"dependents": [],
|
|
@@ -4944,10 +5165,10 @@
|
|
|
4944
5165
|
}
|
|
4945
5166
|
},
|
|
4946
5167
|
{
|
|
4947
|
-
"filePath": "src/components/
|
|
5168
|
+
"filePath": "src/components/xpl-icon/xpl-icon.tsx",
|
|
4948
5169
|
"encapsulation": "none",
|
|
4949
5170
|
"tag": "xpl-icon",
|
|
4950
|
-
"readme": "# xpl-icon\n\n## Available Icons\n\nFor a complete list of available icon names, see [ICONS.md](./ICONS.md) (
|
|
5171
|
+
"readme": "# xpl-icon\n\n## Available Icons\n\nFor a complete list of available icon names, see [ICONS.md](./ICONS.md) (554 icons).\n\nYou can also browse icons visually in [Storybook](?path=/story/components-icons--icons) with search functionality.\n\n## Usage\n\n```html\n<xpl-icon icon=\"rocket\" size=\"24\"></xpl-icon>\n```\n\nThe `icon` property accepts any icon name as a string. See the links above for the full list of available icons.\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color — icon accent backgrounds (`&--with-background`)**\n\nSubtle per-hue accent tints use primitive color tokens (`-50` light / `-900` dark). Foundation has no purpose-specific token for these subtle tints (`--xpl-background-accent-*` are far bolder), so primitives are used and the `.dark` overrides are **deliberately retained** to swap the dark value. This is a documented exception to the \"no `.dark`\" migration DoD (tracked in `TECH_DEBT.md`).\n\n- `--xpl-icon-default` — fallback glyph color for accent-background icons (neutral-900 light / neutral-50 dark). Set explicitly so the glyph themes with the background instead of relying on inherited `currentColor` (which left a dark glyph on the dark `-900` tint in dark mode). Note: `xpl-data-card` also uses the accent-background prop and overrides the glyph color with a hue-matched value directly on `.xpl-icon`, so it is unaffected by this fallback.\n- `--xpl-color-neutral-50` / `--xpl-color-neutral-900` — `--gray` background\n- `--xpl-color-orange-50` / `--xpl-color-orange-900` — `--orange` background\n- `--xpl-color-purple-50` / `--xpl-color-purple-900` — `--purple` background\n- `--xpl-color-red-50` / `--xpl-color-red-900` — `--red` background\n- `--xpl-color-yellow-50` / `--xpl-color-yellow-900` — `--yellow` background\n\n---\n",
|
|
4951
5172
|
"docs": "",
|
|
4952
5173
|
"docsTags": [
|
|
4953
5174
|
{
|
|
@@ -5182,12 +5403,20 @@
|
|
|
5182
5403
|
}
|
|
5183
5404
|
},
|
|
5184
5405
|
{
|
|
5185
|
-
"filePath": "src/components/
|
|
5406
|
+
"filePath": "src/components/xpl-input/xpl-input.tsx",
|
|
5186
5407
|
"encapsulation": "none",
|
|
5187
5408
|
"tag": "xpl-input",
|
|
5188
5409
|
"readme": "# xpl-input\n\nA flexible form input that supports multiple `type` values: `text`, `number`, `password`, `date`, `time`, `file`, `color`, `phone`, and `search`. Each type delegates to a dedicated sub-component (`xpl-input-date`, `xpl-input-time`, `xpl-input-phone`, `xpl-input-search`, etc.) while sharing a common label, description, and error-message wrapper.\n\nFor `type=\"phone\"`, the value is always emitted in **E.164** format (e.g. `+14155551234`). See [`xpl-input-phone`](xpl-input-phone) for full phone-input documentation.\n\n## Design Tokens\n\nThe `xpl-input` component uses Apollo Foundation tokens for consistent theming across light and dark modes:\n\n| Element | Property | Token |\n|---------|----------|-------|\n| Input wrapper border (default) | `border-color` | `var(--xpl-border-default)` |\n| Input wrapper border (focus) | `border-color` | `var(--xpl-border-focus)` |\n| Input wrapper border (error) | `border-color` | `var(--xpl-border-negative)` |\n| Input wrapper background (default) | `background-color` | `var(--xpl-background-surface-default)` |\n| Input/textarea background | `background-color` | `var(--xpl-background-surface-transparent-0)` |\n| Disabled/readonly wrapper background | `background-color` | `var(--xpl-background-action-disabled)` |\n| Post element background | `background-color` | `var(--xpl-background-surface-subtle)` |\n| Input text | `color` | `var(--xpl-text-default)` |\n| Disabled/readonly text | `color` | `var(--xpl-text-disabled)` |\n| Label text | `color` | `var(--xpl-text-strong)` |\n| Description text | `color` | `var(--xpl-text-subdued)` |\n| Error text | `color` | `var(--xpl-text-negative)` |\n| Character counter background (default) | `background-color` | `var(--xpl-background-surface-default)` |\n| Character counter background (disabled/readonly) | `background-color` | `var(--xpl-background-action-disabled)` |\n| Character counter text | `color` | `var(--xpl-text-subdued)` |\n| Calendar/password icon | `color` | `var(--xpl-icon-default)` |\n\n### Spacing Tokens\n\n| Element | Property | Token |\n|---------|----------|-------|\n| Input | `padding-right` | `var(--xpl-space-8)` |\n| Textarea | `padding-top` | `var(--xpl-space-12)` |\n| Textarea | `padding-bottom` | `var(--xpl-space-8)` |\n| Wrapper | `padding-left` | `var(--xpl-space-12)` |\n| Pre element (leading icon/text) | `padding-right` | `var(--xpl-space-8)` |\n| Post element (trailing unit / AM-PM) | `padding-left`, `padding-right` | `var(--xpl-space-12)` |\n| Label | `padding-bottom` | `var(--xpl-space-4)` |\n| Character counter | `padding` | `var(--xpl-space-8) var(--xpl-space-12)` |\n| Error message | `padding`, `gap` | `var(--xpl-space-4)` |\n| Calendar icon | `right` | `var(--xpl-space-12)` |\n| Password button | `padding-left`, `padding-right` | `var(--xpl-space-12)` |\n\n### Dimension Tokens\n\n| Element | Property | Token |\n|---------|----------|-------|\n| Input | `height` | `var(--xpl-size-250)` (40px; matches Figma `form/height`) |\n| Textarea | `min-height` | `var(--xpl-size-250)` (40px) |\n| Textarea | `height` | `var(--xpl-size-700)` (112px; rounded up from 98px) |\n| Wrapper | `border-width` | `var(--xpl-border-small)` |\n| Wrapper | `border-radius` | `var(--xpl-border-radius-small)` (4px; matches Figma `border/radius/small`) |\n| Post element | `height` | `var(--xpl-size-250)` (40px; vertically centered via flex) |\n| Post element | `border-left-width` | `var(--xpl-border-small)` |\n\n### Delegated types (`search`, `phone`, `date`, `time`, …)\n\n`valueChange`, `inputEvent`, `focusEvent`, and `blurEvent` are emitted by the inner component and **bubble** to `<xpl-input>`. For **`type=\"search\"`**, **`focusEvent`** and **`blurEvent`** are **re-emitted from `<xpl-input>`** (parent uses **`onFocusEvent`** / **`onBlurEvent`** on **`<xpl-input-search>`** with **`stopPropagation`**) so **`event.target`** matches **`type=\"text\"`**. For **`valueChange`** and **`inputEvent`** on search, events still **bubble** from **`xpl-input-search`** without parent re-emission; **`event.target`** may be the inner host—prefer **`event.detail`** (the string) or **`event.currentTarget`** when you attach the listener on **`<xpl-input>`**. Other delegated types follow the same **`event.detail`** / **`event.currentTarget`** guidance.\n\nFor **`type=\"search\"`** commit: **`<xpl-input-search>`** defines a Stencil **`@Event() search`** (trimmed query in **`detail`**). **`<xpl-input>`** listens with **`onSearch`** on the inner tag, **`stopPropagation`s**, then **`this.search.emit(detail)`** so the canonical **`search`** **`@Event`** stays on **`<xpl-input>`** and listeners are not doubled. **`setFocus()`** on **`<xpl-input>`** uses a **`ref`** to the inner component to delegate focus.\n",
|
|
5189
5410
|
"docs": "A flexible form input that supports multiple `type` values: `text`, `number`, `password`, `date`, `time`, `file`, `color`, `phone`, and `search`. Each type delegates to a dedicated sub-component (`xpl-input-date`, `xpl-input-time`, `xpl-input-phone`, `xpl-input-search`, etc.) while sharing a common label, description, and error-message wrapper.\n\nFor `type=\"phone\"`, the value is always emitted in **E.164** format (e.g. `+14155551234`). See [`xpl-input-phone`](xpl-input-phone) for full phone-input documentation.",
|
|
5190
5411
|
"docsTags": [
|
|
5412
|
+
{
|
|
5413
|
+
"name": "slot",
|
|
5414
|
+
"text": "trigger - Custom trigger element for the file picker. Only used with `type=\"file\"`."
|
|
5415
|
+
},
|
|
5416
|
+
{
|
|
5417
|
+
"name": "slot",
|
|
5418
|
+
"text": "pre - Leading add-on content rendered before the input. Falls back to the `pre` prop text."
|
|
5419
|
+
},
|
|
5191
5420
|
{
|
|
5192
5421
|
"name": "since",
|
|
5193
5422
|
"text": "0.3.0"
|
|
@@ -6223,7 +6452,16 @@
|
|
|
6223
6452
|
],
|
|
6224
6453
|
"listeners": [],
|
|
6225
6454
|
"styles": [],
|
|
6226
|
-
"slots": [
|
|
6455
|
+
"slots": [
|
|
6456
|
+
{
|
|
6457
|
+
"name": "pre",
|
|
6458
|
+
"docs": "Leading add-on content rendered before the input. Falls back to the `pre` prop text."
|
|
6459
|
+
},
|
|
6460
|
+
{
|
|
6461
|
+
"name": "trigger",
|
|
6462
|
+
"docs": "Custom trigger element for the file picker. Only used with `type=\"file\"`."
|
|
6463
|
+
}
|
|
6464
|
+
],
|
|
6227
6465
|
"parts": [],
|
|
6228
6466
|
"states": [],
|
|
6229
6467
|
"dependents": [
|
|
@@ -6283,7 +6521,7 @@
|
|
|
6283
6521
|
}
|
|
6284
6522
|
},
|
|
6285
6523
|
{
|
|
6286
|
-
"filePath": "src/components/
|
|
6524
|
+
"filePath": "src/components/xpl-input/xpl-input-color/xpl-input-color.tsx",
|
|
6287
6525
|
"encapsulation": "none",
|
|
6288
6526
|
"tag": "xpl-input-color",
|
|
6289
6527
|
"readme": "# xpl-input-color\n\n\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-border-default` — display and swatch border\n- `--xpl-text-default` — display text color\n- `--xpl-text-subdued` — placeholder text color\n- `--xpl-background-action-disabled` — disabled display background\n- `--xpl-border-negative` — error state border color (unified with input-date / input-time)\n- `--xpl-icon-default` — toggle icon color\n- `--xpl-background-action-primary-default` — toggle icon hover color (purple; intentionally not `--xpl-icon-brand`, which is orange)\n- `--xpl-border-subtle` — picker saturation/lightness grid, preview, and range-track borders\n- `--xpl-color-neutral-0`, `--xpl-color-neutral-600` — fixed-color picker thumb ring/shadow (functional, non-themeable)\n\n**Typography**\n- `__placeholder`, `__value` — `@extend .xpl-text-body` (14 px normal)\n",
|
|
@@ -6500,7 +6738,7 @@
|
|
|
6500
6738
|
}
|
|
6501
6739
|
},
|
|
6502
6740
|
{
|
|
6503
|
-
"filePath": "src/components/
|
|
6741
|
+
"filePath": "src/components/xpl-input/xpl-input-date/xpl-input-date.tsx",
|
|
6504
6742
|
"encapsulation": "none",
|
|
6505
6743
|
"tag": "xpl-input-date",
|
|
6506
6744
|
"readme": "# xpl-input-date\n\n\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-border-negative` — error state border color\n",
|
|
@@ -6902,7 +7140,7 @@
|
|
|
6902
7140
|
}
|
|
6903
7141
|
},
|
|
6904
7142
|
{
|
|
6905
|
-
"filePath": "src/components/
|
|
7143
|
+
"filePath": "src/components/xpl-input/xpl-input-file/xpl-input-file.tsx",
|
|
6906
7144
|
"encapsulation": "none",
|
|
6907
7145
|
"tag": "xpl-input-file",
|
|
6908
7146
|
"readme": "# xpl-file-upload\n\n\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-text-default` — selected file list text color\n- `--xpl-text-subdued` — accepted-types (help) text color\n- `--xpl-icon-default` — remove (x-circle) icon color\n\n**Typography**\n- `__file-name` — `@extend .xpl-text-callout` (12 px normal) — uploaded file names\n- `__accept` — `@extend .xpl-text-caption` (10 px normal) — accepted file types help text\n",
|
|
@@ -7218,7 +7456,7 @@
|
|
|
7218
7456
|
}
|
|
7219
7457
|
},
|
|
7220
7458
|
{
|
|
7221
|
-
"filePath": "src/components/
|
|
7459
|
+
"filePath": "src/components/xpl-input/xpl-input-phone/xpl-input-phone.tsx",
|
|
7222
7460
|
"encapsulation": "none",
|
|
7223
7461
|
"tag": "xpl-input-phone",
|
|
7224
7462
|
"readme": "# xpl-input-phone\n\nThe Phone Input Field allows users to input properly formatted phone numbers. It supports two modes: **international** (country selector + dial code prefix) and **domestic** (single country, no selector). Used as a subcomponent of `xpl-input` when `type=\"phone\"`. The value is always emitted in **E.164** format (e.g. `+14155551234`).\n\n## Usage\n\n### International mode (default)\n\nUse via the parent component for full international support with a country selector:\n\n```html\n<xpl-input type=\"phone\" label=\"Phone number\" name=\"phone\"></xpl-input>\n```\n\nWith preferred countries pinned to the top of the list:\n\n```html\n<xpl-input\n type=\"phone\"\n label=\"Phone number\"\n name=\"phone\"\n preferred-countries='[\"US\",\"CA\",\"GB\"]'\n></xpl-input>\n```\n\n### Domestic mode\n\nSet `is-international=\"false\"` to lock the input to a single country. The country selector trigger and dropdown are hidden, and no dial code is shown in the input. The emitted value is still E.164.\n\n```html\n<xpl-input\n type=\"phone\"\n label=\"Phone number\"\n name=\"phone\"\n default-country=\"US\"\n is-international=\"false\"\n></xpl-input>\n```\n\n### Pre-populating a value\n\nPass an E.164 string to `value`. The component parses it into the correct country and national number:\n\n```html\n<xpl-input type=\"phone\" label=\"Phone\" value=\"+14155551234\"></xpl-input>\n```\n\n## Value format\n\n- **value** / **valueChange**: E.164 string (e.g. `+14155551234`). You can set `value` to pre-fill; the component parses it into country and national number.\n- **defaultCountry**: ISO 3166-1 alpha-2 code (e.g. `\"US\"`) used when value is empty. In domestic mode, this locks the country permanently.\n- **preferredCountries**: Optional array of country codes to show at the top of the country list (international mode only).\n- **isInternational**: When `true` (default), the full international UI is shown. When `false`, the component is a simple domestic phone input locked to `defaultCountry`.\n\n## Design and behaviour\n\n### Country selector (international mode)\n\n- The **trigger** displays a country flag icon (`xpl-icon`) and a chevron-down icon.\n- Clicking the trigger opens an `xpl-dropdown` panel containing a **type-ahead search** field and a scrollable list of countries. Each option shows its flag icon, name, and dial code.\n- Search filters by country name, dial code, or ISO country code.\n- When a country is selected, focus returns to the phone input and the cursor is positioned after the dial code.\n- Countries sharing a dial code (e.g. US and Canada both use `+1`) are handled correctly: changing the country in the dropdown preserves the selection even when the dial code is the same.\n\n### Domestic mode\n\nNo country selector is rendered. The input behaves as a standard phone field with country-specific formatting and validation based on `defaultCountry`. The dial code is not displayed in the input, but the emitted value is still E.164.\n\n### Input handling\n\n- **Sanitization**: Non-numeric characters are automatically stripped on every keystroke, paste, or autofill. The input only accepts digits.\n- **Max length**: Enforced per country based on the national number format (e.g. 10 digits for US/CA, 9 for AU/FR).\n- **Cursor protection** (international mode): The dial code prefix (e.g. `+1 `) is read-only within the input. Users cannot backspace into it, click before it, or use Home/ArrowLeft to move the cursor before it.\n- **Clear button**: A clear (`x-circle`) button appears when there is input and the field is not disabled or readonly.\n\n### Phone formatting\n\nThe national number is formatted as the user types (e.g. US: `415 555 1234`, FR: `6 12 34 56 78`). The stored and emitted value remains E.164. Cursor position is intelligently preserved during formatting so it does not jump.\n\nCountries with custom formatters: US/CA, GB, AU, DE/AT/CH, FR, BR, MX, JP, CN, IN, KR. All other countries use a generic grouping format.\n\n### Validation and errors\n\n- When `required` is set, the component emits a `hasErrorStateChanged` event with `\"required\"` if the national number is empty on change.\n- The parent `xpl-input` can pass an `error` prop for external error messages (e.g. server-side validation).\n- The component applies `xpl-input-phone--error` to the host when an internal error state is active.\n\n### Accessibility\n\n- The country selector trigger has `aria-haspopup=\"listbox\"` and `aria-expanded`.\n- The country selector trigger has `aria-label=\"Select country\"` for screen-reader clarity.\n- The dropdown panel has `aria-label=\"Country\"`.\n- The clear button has `aria-label=\"Clear phone number\"`.\n- The input uses `inputmode=\"numeric\"` to hint a numeric keyboard on mobile and `autocomplete=\"tel-national\"` (international) or `autocomplete=\"tel\"` (domestic).\n- The input sets `aria-invalid=\"true\"` when in an error state (e.g. required field left empty).\n- Decorative icons (flag, chevron) use `aria-hidden=\"true\"` to avoid screen reader noise.\n\n## Supported countries\n\n28 countries are currently supported. See `phone-country-data.ts` for the full list. Countries with custom number formatting are noted above. To add a new country, add an entry to the `PHONE_COUNTRIES` array and optionally add a formatter in `phone-format.ts`.\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-background-surface-subtlest` — trigger background\n- `--xpl-background-surface-information` — trigger hover / open background\n- `--xpl-border-negative` — error state border\n- `--xpl-border-focus` — wrapper and trigger focus outline\n- `--xpl-border-default` — trigger divider, search border\n- `--xpl-text-default` — trigger text, dial code\n- `--xpl-text-subdued` — clear button color\n- `--xpl-icon-default` — search icon\n\n**Border**\n- `--xpl-border-small` — trigger divider width (1px)\n\n**Focus**\n- `--xpl-border-focus` — `:focus-visible` outline (inset, 2px)\n",
|
|
@@ -7578,7 +7816,7 @@
|
|
|
7578
7816
|
}
|
|
7579
7817
|
},
|
|
7580
7818
|
{
|
|
7581
|
-
"filePath": "src/components/
|
|
7819
|
+
"filePath": "src/components/xpl-input/xpl-input-search/xpl-input-search.tsx",
|
|
7582
7820
|
"encapsulation": "none",
|
|
7583
7821
|
"tag": "xpl-input-search",
|
|
7584
7822
|
"readme": "# xpl-input-search\n\nInner search field used by [`xpl-input`](../readme.md) when `type=\"search\"`. It provides a leading magnifier, a native text field with `role=\"searchbox\"`, an optional clear control, and a `shape` shell (`rounded` pill vs `box`). You normally consume search through **`xpl-input`**; use `xpl-input-search` only when composing a custom shell that still matches Apollo search visuals.\n\n## Usage\n\n### Recommended: `xpl-input` with `type=\"search\"`\n\nDefault pill shell (`shape` defaults to `rounded`), placeholder, and optional `name` for forms:\n\n```html\n<xpl-input type=\"search\" name=\"q\" placeholder=\"Search products\"></xpl-input>\n```\n\nVisible label, description, `box` shape, and `autocomplete`:\n\n```html\n<xpl-input\n type=\"search\"\n label=\"Search catalog\"\n description=\"SKU or product name\"\n name=\"q\"\n placeholder=\"SKU or name\"\n shape=\"box\"\n autocomplete=\"search\"\n></xpl-input>\n```\n\nWhen there is no visible label, set `aria-label` on `xpl-input` (forwarded to the inner field for assistive naming):\n\n```html\n<xpl-input type=\"search\" aria-label=\"Search help topics\" placeholder=\"Search…\"></xpl-input>\n```\n\nError state (border, `aria-invalid`, and error text on the parent) and an initial value (clear control appears when there is text):\n\n```html\n<xpl-input type=\"search\" shape=\"box\" error=\"Invalid query\" value=\"abc\"></xpl-input>\n```\n\nListening for submit and live updates (vanilla JS):\n\n```html\n<xpl-input id=\"search\" type=\"search\" placeholder=\"Search\"></xpl-input>\n<script type=\"module\">\n const el = document.getElementById('search');\n el.addEventListener('search', (e) => {\n console.log('submit', e.detail); // trimmed string\n });\n el.addEventListener('valueChange', (e) => {\n console.log('value', e.detail); // raw string\n });\n</script>\n```\n\n### Events on `<xpl-input type=\"search\">`\n\n`valueChange`, `inputEvent`, `focusEvent`, and `blurEvent` are Stencil **`@Event`s** on **`xpl-input-search`** and **bubble** to the **`<xpl-input>`** host. **`focusEvent`** / **`blurEvent`** are also **re-emitted from `<xpl-input>`** so **`event.target`** matches **`type=\"text\"`** (see **`xpl-input`** readme). **`valueChange`** / **`inputEvent`** are **not** re-emitted by the parent; use **`event.detail`** for the string if you do not want to depend on **`event.target`**.\n\nThe **commit** signal is a Stencil **`search`** **`@Event`** on **`xpl-input-search`** (trimmed query in **`detail`**). **`xpl-input`** wires **`onSearch`** on the inner tag, **`stopPropagation`s**, and **`this.search.emit(detail)`** so the public **`search`** **`@Event`** remains on **`<xpl-input>`**. **`setFocus()`** on **`<xpl-input>`** uses a **`ref`** to call the inner **`setFocus()`** only.\n\nFor advanced composition you can render `<xpl-input-search>` directly. You must pass **`input-id`** (matches a `<label for=\"…\">` when used with a visible label). Set **`disabled`** and **`has-error`** (plus **`error-message-id`** when invalid) for both accessibility and visuals: the host adds `xpl-input-search--disabled` / `xpl-input-search--error` so disabled and error chrome match the wrapped `xpl-input` case. When nested under `xpl-input type=\"search\"`, those props are set for you from the parent.\n\n```html\n<label class=\"xpl-input-label\" for=\"sid\">Search</label>\n<xpl-input-search input-id=\"sid\" name=\"q\" placeholder=\"Search…\"></xpl-input-search>\n```\n\n## Design tokens\n\n| Part | Token |\n| ---- | ----- |\n| Host text (input inherits) | `--xpl-text-default` |\n| Shell layout | `gap`: `--xpl-space-12`; horizontal padding: `--xpl-space-12`; `min-height` / `max-height`: `--xpl-size-250` |\n| Shell fill (resting) | `--xpl-background-surface-default` |\n| Shell `border-radius` (pill, default `shape=\"rounded\"`) | `--xpl-border-radius-button` |\n| Shell `border-radius` (`shape=\"box\"`) | `--xpl-border-radius-small` |\n| Shell border (resting) | `--xpl-border-default` |\n| Shell border (input focus, empty) | `--xpl-border-active` |\n| Shell border (input focus, with value) | `--xpl-border-focus` |\n| Shell border (error, from parent `xpl-input`) | `--xpl-border-negative` |\n| Disabled shell (parent) | `--xpl-background-action-disabled` |\n| Input typography | `--xpl-font-family-default`, `--xpl-font-size-body`, `--xpl-font-weight-normal` |\n| Placeholder | `--xpl-text-subdued` |\n| Disabled text / placeholder (parent) | `--xpl-text-disabled` |\n| Leading icon | `--xpl-icon-default` / `--xpl-icon-disabled` |\n| Clear icon | `--xpl-icon-subtle` |\n| Caret (focus, with value) | `--xpl-border-focus` |\n| Caret (focus, error, parent) | `--xpl-border-negative` |\n\nLight and dark mode use Foundation purpose-specific tokens only (no component `.dark` overrides).\n\n## Icon mapping\n\n| Role | When | `xpl-icon` name | `size` |\n| ---- | ---- | ----------------- | ------ |\n| Leading search | Always (when the control renders) | `magnifier` | 20 |\n| Clear | Value non-empty and not `disabled` | `circle-xmark` | 16 |\n\n## Accessibility\n\n- **Role and naming:** The field uses a native `<input type=\"text\">` with `role=\"searchbox\"`. `type=\"text\"` avoids browser search-field chrome that would clash with the design-system clear control. When the parent does not render a visible label, `aria-label` on the inner input defaults to `\"Search\"` unless `ariaLabel` / parent `aria-label` overrides it. With a visible label, the input is named via `<label for=\"…\">` and redundant `aria-label` on the input is omitted.\n- **`autocomplete`:** Default `off` is typical for inline search; set `autocomplete` on `xpl-input` for search fields when you need a specific token.\n- **Errors:** With `xpl-input`, non-empty `error` sets `aria-invalid`, links the message with `aria-describedby`, and styles the shell from the parent host.\n- **Keyboard — standalone `xpl-input-search`:** An inner `<form>` wraps the shell when the host is not already inside a `<form>`. **Enter** submits that inner form (default prevented); the host emits a Stencil **`search`** event (trimmed value in **`detail`**). Listen with **`addEventListener('search', …)`** on **`xpl-input-search`**. **Tab** visits the input and the clear control when visible.\n- **Keyboard — inside a parent `<form>`:** The inner `<form>` is omitted. **Enter** uses native form submission; listen on the parent form’s **`submit`**. Use **`valueChange`** / **`inputEvent`** for live typing.\n- **Clear control:** The clear button exposes **`aria-label=\"Clear search\"`**. Activating it clears the value, emits **`valueChange`** / **`inputEvent`** with `''`, and refocuses the input. When **`disabled`** or **`readonly`** is true, the clear control is hidden and inert (no value mutation).\n",
|
|
@@ -8078,7 +8316,7 @@
|
|
|
8078
8316
|
}
|
|
8079
8317
|
},
|
|
8080
8318
|
{
|
|
8081
|
-
"filePath": "src/components/
|
|
8319
|
+
"filePath": "src/components/xpl-input/xpl-input-time/xpl-input-time.tsx",
|
|
8082
8320
|
"encapsulation": "none",
|
|
8083
8321
|
"tag": "xpl-input-time",
|
|
8084
8322
|
"readme": "# xpl-input-time\n\n\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-border-negative` — error state border color (unified with input-date / input-color)\n- `--xpl-icon-default` — leading clock icon color (matches input-date's calendar icon)\n- `--xpl-elevation-2` — time dropdown box-shadow (theme-aware; references the surface-transparent tokens, which flip to white-based transparency in dark mode)\n",
|
|
@@ -8525,7 +8763,7 @@
|
|
|
8525
8763
|
}
|
|
8526
8764
|
},
|
|
8527
8765
|
{
|
|
8528
|
-
"filePath": "src/components/
|
|
8766
|
+
"filePath": "src/components/xpl-large-card/xpl-large-card.tsx",
|
|
8529
8767
|
"encapsulation": "none",
|
|
8530
8768
|
"tag": "xpl-large-card",
|
|
8531
8769
|
"readme": "# xpl-large-card\n\nA card is a container and can contain any type of information. Cards contain actions and a content slot. Cards are flexible and can be arranged in grids or lists.\n\n## Design Tokens\n\nThe card is styled entirely with Apollo Foundation purpose-specific tokens (dark mode is automatic — no `.dark` overrides).\n\n| Element / state | Property | Token |\n| --- | --- | --- |\n| Host surface | `background-color` | `--xpl-background-surface-default` |\n| Host / anchor border | `border-color` | `--xpl-border-default` |\n| Host, header text | `color` | `--xpl-text-default` |\n| Header arrow (chevron) icon | `color` | `--xpl-icon-default` |\n| Description text | `color` | `--xpl-text-subdued` |\n| Anchor hover / active border | `border` | `--xpl-border-small` + `--xpl-background-action-primary-default` |\n| Anchor focus-visible border | `border` | `--xpl-border-small` + `--xpl-border-focus` (purple) |\n| Anchor focus-visible outline | `outline` | `--xpl-border-focus`, 2px width / 2px offset |\n| Anchor hover / focus-visible radius | `border-radius` | `--xpl-border-radius-default` |\n| Anchor hover shadow | `box-shadow` | `--xpl-elevation-2` (theme-aware) |\n| Header / tooltip / icon spacing | `margin` | `--xpl-space-4`, `--xpl-space-6`, `--xpl-space-8` |\n",
|
|
@@ -8643,12 +8881,16 @@
|
|
|
8643
8881
|
}
|
|
8644
8882
|
},
|
|
8645
8883
|
{
|
|
8646
|
-
"filePath": "src/components/
|
|
8884
|
+
"filePath": "src/components/xpl-list/xpl-list.tsx",
|
|
8647
8885
|
"encapsulation": "none",
|
|
8648
8886
|
"tag": "xpl-list",
|
|
8649
|
-
"readme": "# xpl-list\n\n## Description\n\n**`xpl-list`** is the list **container** (`role=\"list\"`). It coordinates **single selection** (shared radio group), **reordering** (drag-and-drop and keyboard), and assigns default **`item-id`** values when missing.\n\n**`xpl-list-item`** is one **row**. In **slot-based** mode, `role=\"listitem\"` is on the row surface inside the host (not on `<xpl-list-item>`), so list semantics work with the host’s `display: contents` layout. Legacy **`item`** rows keep `role=\"listitem\"` on the host. Place items **inside** **`xpl-list`** (default slot). Compose each row with **named slots** (recommended) or use the **legacy** `item` prop / list-level `items` array. Row-level props, events, and dependencies: [xpl-list-item readme](./xpl-list-item/readme.md).\n\nWhen the list is **`selectable`**, pressing **Escape** while focus is on the **selected** row clears the radio selection (same as **`clearSelection()`**). Clicking elsewhere does not clear selection. Row radios use the **title** slot for their accessible name when present; with no title slot, the label is **`Select <item-id>`** when **`item-id`** or **`id`** is set, otherwise a generic default.\n\n**Single-select vs multi-select:** **`selectable`** on **`xpl-list`** is for **exactly one chosen row** (implemented with **`xpl-radio`** and a shared group **`name`**). For **multi-select** or **independent** toggles per row, do **not** use this flag; compose **`xpl-checkbox`** (or your own controls) in row slots and manage state in the app.\n\n---\n\n## Slot-based vs legacy integration\n\n\n| | **Slot-based (recommended)** | **Legacy prop-based (deprecated)** |\n| ----------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |\n| **Where content lives** | Light DOM: named slots on each `<xpl-list-item>` | Data: `items` on `<xpl-list>` and/or `item` on `<xpl-list-item>` |\n| **Row markup** | You author `<xpl-list-item>` children with `slot=\"…\"` content | List renders rows from `items`, or item renders from `item` object |\n| **Flexibility** | Full UI composition (avatar, actions, errors, extras) | Fixed layout from `ListItem` fields |\n| **Identity** | Set `item-id` (or `id`) on each row | Legacy rows from `items` use `ListItem.id` when set, else `item-0`, `item-1`, … |\n| **Reordering** | `reorderable` on `xpl-list`: drag handle + keyboard on each slot row | **No reorder UI:** legacy `items` / `item` rows do not render a handle; use slots if you need reorder. |\n| **Notes** | Do not set `item` on rows in this mode | `items` logs a console warning when non-empty; mixing `items` **and** slotted children renders **both** (legacy rows first) |\n\n\n---\n\n## Slot-based integration\n\nPut one or more `<xpl-list-item>` elements **inside** `<xpl-list>`. Do **not** set the **`item`** prop on a row when using slots—if `item` is set, that row uses **legacy** rendering and ignores slot composition.\n\nOn **`xpl-list`**, set `selectable` and/or `reorderable` as needed; the list mirrors `radio-name`, `reorderable`, and `keyboard-active` onto **slot-based** direct child rows only (nested lists in slots are unchanged). Rows using the deprecated **`item`** prop or list-level **`items`** array are **legacy** markup: the list does **not** set `selectable`, `radio-name`, or `reorderable` on them, because that UI exists only in slot-based mode—migrate to slotted `<xpl-list-item>` children if you need selection or reorder.\n\n### Slots (on `xpl-list-item`)\n\nAll slots are **named**. Use `slot=\"<name>\"` on light-DOM children.\n\n\n| Slot | Role | HTML example |\n| ----------------- | --------------------------------------------------------- | ----------------------------------------------------------------- |\n| `title` | Primary title line | `<span slot=\"title\">Account name</span>` |\n| `metadata` | Secondary lines under the title | `<ul slot=\"metadata\"><li>Line one</li></ul>` |\n| `avatar` | Leading avatar or custom media | `<xpl-avatar slot=\"avatar\" name=\"JD\"></xpl-avatar>` |\n| `details` | Right column: supporting text | `<span slot=\"details\">Last updated</span>` |\n| `badges` | Right column: badges / tags | `<span slot=\"badges\"><xpl-badge>New</xpl-badge></span>` |\n| `actions` | Trailing actions; clicks do **not** follow `href` | `<span slot=\"actions\"><xpl-button type=\"button\" variant=\"tertiary\" size=\"sm\">Edit</xpl-button></span>` |\n| `error-text` | Message below the row; affects error styling when present | `<span slot=\"error-text\">This field is required.</span>` |\n| `stacked-extra-1` | Optional stacked block | `<div slot=\"stacked-extra-1\">Extra block 1</div>` |\n| `stacked-extra-2` | Second optional stacked block | `<div slot=\"stacked-extra-2\">Extra block 2</div>` |\n| `stacked-extra-3` | Third optional stacked block | `<div slot=\"stacked-extra-3\">Extra block 3</div>` |\n\n\n**Dot badge next to the title:** set **`title-badge-variant`** on **`xpl-list-item`** (same variants as `xpl-badge`), not inside the title slot.\n\n**Divider under the title row:** set **`show-divider`** on **`xpl-list-item`**.\n\n**Minimal example:**\n\n```html\n<xpl-list selectable reorderable>\n <xpl-list-item item-id=\"row-1\" href=\"/settings\">\n <xpl-avatar slot=\"avatar\" name=\"AC\"></xpl-avatar>\n <span slot=\"title\">Settings</span>\n <span slot=\"metadata\">Workspace</span>\n <span slot=\"details\">Updated today</span>\n <span slot=\"actions\"><xpl-button type=\"button\" variant=\"tertiary\" size=\"sm\">Open</xpl-button></span>\n </xpl-list-item>\n</xpl-list>\n```\n\n---\n\n### Attributes: where to set them\n\n#### `xpl-list` (container)\n\n\n| Attribute | Purpose |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------ |\n| `label` | Accessible name: sets `aria-label` on the list host when there is no visible heading. **Not used** if `labelled-by` is also set. |\n| `labelled-by` | Space-separated element ids: sets `aria-labelledby` on the host. Takes precedence over `label` so both are never applied together. |\n| `selectable` | Enables radio selection; list assigns shared `radio-name`. **Escape** on the **selected** row clears selection (no extra attribute). |\n| `reorderable` | Enables drag handles and reorder behavior on **slot-based** rows only (see legacy section). |\n\nUse **`label`** *or* **`labelled-by`**, not both. If both attributes are present, only **`labelled-by`** affects the accessible name.\n\n\n#### `xpl-list-item` (row, slot mode — omit `item`)\n\n\n| Attribute | Purpose |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |\n| `item-id` | Stable id for selection and reorder events (or use host `id`). If omitted, the list may assign `item-0`, `item-1`, … |\n| `href` | Optional: row acts as a link; `actions` / `avatar` clicks do not navigate. |\n| `disabled`, `error` | Row state: non-interactive row and/or error styling (border, `error-text` slot). |\n| `hidden` | Hides the row from layout and from visible-only list behavior; see **Hidden rows** below. |\n| `selected` | Controlled selected state when the list is `selectable`. |\n| `show-divider` | Divider under the title area. |\n| `title-badge-variant` | Dot badge beside the title. |\n\n\n#### Usually set by `xpl-list` on items (avoid overriding unless needed)\n\n\n| Attribute | Meaning |\n| --------------------------- | --------------------------------------------------- |\n| `selectable`, `reorderable` | Mirrored from the list (**slot-based** rows only; not legacy `item` / `items` rows). |\n| `radio-name` | Shared radio group when the list is `selectable` (slot-based rows only). |\n| `keyboard-active` | Set on the row in keyboard reorder mode (slot-based rows only). |\n\n\n### Hidden rows\n\nSet the **`hidden`** attribute (or **`hidden`** prop) on **`xpl-list-item`** when a row should not appear in the list or take up space, but you still want it in the DOM. Typical use cases:\n\n- **Filtering or search** — hide rows that do not match without tearing down markup or losing local state.\n- **Progressive disclosure or permissions** — keep a stable **`item-id`** and show the row only when a condition becomes true.\n- **Temporary removal** — same as filtering when the row may return without re-creating the element.\n\n**List behavior:** Hidden rows are omitted from **`orderChange`**’s **`orderedItemIds`** and from drag-and-drop / keyboard reorder among **visible** rows only (see tests and list implementation). They do not receive focus while hidden.\n\n**Accessibility:** Native **`hidden`** removes the row from the accessibility tree while it is hidden. If users need an equivalent announcement elsewhere (for example, “3 results hidden by filter”), provide that in your application UI.\n\n---\n\n### Events and programmatic API\n\n#### `xpl-list` — listen on the list host\n\n\n| Event | When | `detail` |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |\n| `itemSelect` | Radio selection changes; when clearing via **`clearSelection()`** or **Escape** on the selected row, emitted **once per** previously selected row (typically one) | `{ itemId?: string }` |\n| `orderChange` | After a successful reorder (drag/drop or keyboard); DOM is already updated | `{ itemId?: string; direction: 'up' \\| 'down'; orderedItemIds: string[] }` |\n\n\n**`orderedItemIds`:** visible rows only (DOM order); hidden `xpl-list-item` rows are omitted.\n\n**TypeScript:** `orderChange` detail is typed as **`XplListOrderChangeDetail`** (exported from `@xplortech/apollo-core` alongside **`ListItem`**).\n\n**Legacy:** `xplListReorder` may also fire (bubbles, composed). Prefer **`orderChange`** for new code. Legacy `detail` includes `orderedItemIds` as well.\n\n\n| Method | Notes |\n| ------------------ | --------------------------------------------------------------------------------------------------- |\n| `clearSelection()` | Promise. Clears radios when `selectable`. Same effect as **Escape** with focus on the selected row. |\n\n\n```html\n<xpl-list id=\"my-list\" selectable reorderable>...</xpl-list>\n<script type=\"module\">\n const list = document.getElementById('my-list');\n list.addEventListener('itemSelect', (e) => {\n /* handle selection: */ void e.detail.itemId;\n });\n list.addEventListener('orderChange', (e) => {\n /* handle reorder: */ void e.detail.direction;\n void e.detail.orderedItemIds;\n });\n</script>\n```\n\n#### `xpl-list-item` — optional row-level listeners\n\n\n| Event | When | `detail` |\n| --------------- | ---------------------------------------------- | ---------------------------------------- |\n| `itemSelect` | Radio change on this row | `{ itemId?: string }` |\n| `itemDragStart` | Drag started from reorder handle | `{ itemId?: string; item: HTMLElement }` |\n| `itemDragEnd` | Drag ended on this row (after drop or cancel) | `{ itemId?: string; item: HTMLElement }` |\n| `itemDrop` | Drop target during reorder | `{ itemId?: string; item: HTMLElement }` |\n\n\n---\n\n## Legacy prop-based integration\n\nUse only for migration or data-driven rows. **Prefer slots for new work.**\n\n### At-a-glance migration\n\n| | **Before (deprecated)** | **After (recommended)** |\n| --- | --- | --- |\n| **Data** | `items` array on `xpl-list`, or `item` object on each row | Light DOM: `<xpl-list-item>` children with named slots |\n| **Identity** | Optional `ListItem.id`; else `item-0`, `item-1`, … | Explicit `item-id` (or host `id`) per row |\n\n```html\n<!-- Before: data-driven rows -->\n<xpl-list id=\"legacy-list\"></xpl-list>\n<script type=\"module\">\n document.getElementById('legacy-list').items = [{ title: 'Acme Co.', href: '/acme' }];\n</script>\n\n<!-- After: slot-based rows -->\n<xpl-list>\n <xpl-list-item item-id=\"acme\" href=\"/acme\">\n <span slot=\"title\">Acme Co.</span>\n </xpl-list-item>\n</xpl-list>\n```\n\n### `xpl-list` — `items` (deprecated)\n\n\n| Prop | Type | Description |\n| ------- | ------------ | ------------------------------------------------------------------------------------------------------- |\n| `items` | `ListItem[]` | **Deprecated.** Renders internal `<xpl-list-item>` rows with `item={...}` and ids `item-0`, `item-1`, … |\n\n\nA **console warning** runs when `items` is non-empty. Using **`items`** and slotted children renders **both**.\n\n### `xpl-list-item` — `item` (deprecated)\n\n\n| Prop | Type | Description |\n| ------ | ---------- | ---------------------------------------------------------------------------- |\n| `item` | `ListItem` | **Deprecated.** Prop-driven row; **no named slots**. Prefer slot-based rows. |\n\n\n### `ListItem` (`listitem.ts`, deprecated)\n\n\n| Field | Type | Notes |\n| ---------- | -------------------------------- | ---------------------- |\n| `id` | `string` | Optional stable row id (`item-id` when rendered from `items`) |\n| `title` | `string` | Required |\n| `href` | `string` | Optional |\n| `avatar` | `string` | Image URL or icon name |\n| `metadata` | `string[]` or `{ icon, text }[]` | |\n| `subtext` | `string` | |\n| `avatars` | `string[]` | |\n| `badges` | `string[]` or badge objects | |\n\n\n**Legacy layout:** Rows rendered from the deprecated `item` / inner `.xpl-list-item` flex markup use the **same layout at all viewport widths** (there is no dedicated narrow-viewport stacking breakpoint in `list-item.css`). If you need stacked mobile behavior for legacy lists, handle it in the app (e.g. layout wrapper or scoped CSS).\n\n**Legacy reordering:** The list does **not** set `reorderable` (or `selectable` / `radio-name`) on legacy **`items`** / **`item`** rows—there is **no** drag handle or keyboard reorder entry point in prop-driven mode. Only **slot-composed** rows participate in reorder and list-level selection UI; migrate from `items` / `item` to slotted `<xpl-list-item>` children if you need those features.\n\n---\n\n## Dependencies\n\n- **Rows:** `xpl-list-item` uses [xpl-avatar](../xpl-avatar), [xpl-icon](../xpl-icon), [xpl-badge](../xpl-badge), [xpl-divider](../xpl-divider).\n\n```mermaid\ngraph TD;\n xpl-list-item --> xpl-avatar\n xpl-list-item --> xpl-icon\n xpl-list-item --> xpl-badge\n xpl-list-item --> xpl-divider\n xpl-list --> xpl-list-item\n```\n\n\n\n## Design tokens\n\nList styling is split across [`list.css`](https://github.com/xplor/apollo/blob/main/packages/apollo-core/src/css/list.css) (the `xpl-list` host), [`list-item.css`](https://github.com/xplor/apollo/blob/main/packages/apollo-core/src/css/list-item.css) (legacy vs slot-based row layout, error/disabled/hidden, title/metadata columns), and [`list-action.css`](https://github.com/xplor/apollo/blob/main/packages/apollo-core/src/css/list-action.css) (reorder handle, selectable radio chrome, legacy action-button modifiers). All are imported from the package `style` entry. Visual values use **Apollo Foundation** CSS variables (`--xpl-*`); no raw hex colors in those stylesheets.\n\n\n| Category | Tokens (representative) |\n| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Layout / spacing** | `--xpl-space-4`, `--xpl-space-8`, `--xpl-space-12`, `--xpl-space-16`, `--xpl-space-40` |\n| **Sizing** | `--xpl-size-050`, `--xpl-size-075`, `--xpl-size-350` |\n| **Borders** | `--xpl-border-small`, `--xpl-border-large`, `--xpl-border-default`, `--xpl-border-hover`, `--xpl-border-focus`, `--xpl-border-negative`, `--xpl-border-subtle`, `--xpl-border-strong` |\n| **Radius** | `--xpl-border-radius-default`, `--xpl-border-radius-small`, `--xpl-border-radius-full` |\n| **Text** | `--xpl-text-default`, `--xpl-text-subdued`, `--xpl-text-disabled`, `--xpl-text-negative` |\n| **Icons / surfaces** | `--xpl-icon-default`, `--xpl-icon-subtle`, `--xpl-background-surface-default`, `--xpl-background-action-disabled`, `--xpl-background-surface-subtle` |\n| **Typography** | `--xpl-font-family-default`, `--xpl-font-size-body`, `--xpl-font-size-title-5`, `--xpl-font-size-callout`, `--xpl-font-size-caption`, `--xpl-font-weight-normal`, `--xpl-font-weight-medium` |\n\n\n## Accessibility\n\n- **`xpl-list`** sets `role=\"list\"` on the host. Use **`label`** / **`labelled-by`** when the list has no visible caption.\n- **`xpl-list-item`**: **`role=\"listitem\"`** is on the **inner row surface** in **slot-based** mode (see intro above); **legacy** `item` rows keep it on the **host**. When the list is **`selectable`**, the row renders **`xpl-radio`** with a shared group **`name`** and visually hidden label text (from the title slot when present, else a default).\n- With **`selectable`**, **Escape** while focus is on the **selected** row **clears selection** (same behavior as **`clearSelection()`**).\n- **Reorder**: the drag handle is a native **`<button>`** inside **`xpl-button`** (focusable, with **`aria-pressed`** in keyboard reorder mode and **`aria-label`** instructions for keyboard vs drag). Row links use `:focus-visible` for focus indication.\n- **`hidden`** on a row removes it from layout and visible reorder semantics; see **[Hidden rows](#hidden-rows)** for use cases and accessibility notes.\n\n---\n",
|
|
8887
|
+
"readme": "# xpl-list\n\n## Description\n\n**`xpl-list`** is the list **container** (`role=\"list\"`). It coordinates **single selection** (shared radio group), **reordering** (drag-and-drop and keyboard), and assigns default **`item-id`** values when missing.\n\n**`xpl-list-item`** is one **row**. In **slot-based** mode, `role=\"listitem\"` is on the row surface inside the host (not on `<xpl-list-item>`), so list semantics work with the host’s `display: contents` layout. Legacy **`item`** rows keep `role=\"listitem\"` on the host. Place items **inside** **`xpl-list`** (default slot). Compose each row with **named slots** (recommended) or use the **legacy** `item` prop / list-level `items` array. Row-level props, events, and dependencies: [xpl-list-item readme](./xpl-list-item/readme.md).\n\nWhen the list is **`selectable`**, pressing **Escape** while focus is on the **selected** row clears the radio selection (same as **`clearSelection()`**). Clicking elsewhere does not clear selection. Row radios use the **title** slot for their accessible name when present; with no title slot, the label is **`Select <item-id>`** when **`item-id`** or **`id`** is set, otherwise a generic default.\n\n**Single-select vs multi-select:** **`selectable`** on **`xpl-list`** is for **exactly one chosen row** (implemented with **`xpl-radio`** and a shared group **`name`**). For **multi-select** or **independent** toggles per row, do **not** use this flag; compose **`xpl-checkbox`** (or your own controls) in row slots and manage state in the app.\n\n---\n\n## Slot-based vs legacy integration\n\n\n| | **Slot-based (recommended)** | **Legacy prop-based (deprecated)** |\n| ----------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |\n| **Where content lives** | Light DOM: named slots on each `<xpl-list-item>` | Data: `items` on `<xpl-list>` and/or `item` on `<xpl-list-item>` |\n| **Row markup** | You author `<xpl-list-item>` children with `slot=\"…\"` content | List renders rows from `items`, or item renders from `item` object |\n| **Flexibility** | Full UI composition (avatar, actions, errors, extras) | Fixed layout from `ListItem` fields |\n| **Identity** | Set `item-id` (or `id`) on each row | Legacy rows from `items` use `ListItem.id` when set, else `item-0`, `item-1`, … |\n| **Reordering** | `reorderable` on `xpl-list`: drag handle + keyboard on each slot row | **No reorder UI:** legacy `items` / `item` rows do not render a handle; use slots if you need reorder. |\n| **Notes** | Do not set `item` on rows in this mode | `items` logs a console warning when non-empty; mixing `items` **and** slotted children renders **both** (legacy rows first) |\n\n\n---\n\n## Slot-based integration\n\nPut one or more `<xpl-list-item>` elements **inside** `<xpl-list>`. Do **not** set the **`item`** prop on a row when using slots—if `item` is set, that row uses **legacy** rendering and ignores slot composition.\n\nOn **`xpl-list`**, set `selectable` and/or `reorderable` as needed; the list mirrors `radio-name`, `reorderable`, and `keyboard-active` onto **slot-based** direct child rows only (nested lists in slots are unchanged). Rows using the deprecated **`item`** prop or list-level **`items`** array are **legacy** markup: the list does **not** set `selectable`, `radio-name`, or `reorderable` on them, because that UI exists only in slot-based mode—migrate to slotted `<xpl-list-item>` children if you need selection or reorder.\n\n### Slots (on `xpl-list-item`)\n\nAll slots are **named**. Use `slot=\"<name>\"` on light-DOM children.\n\n\n| Slot | Role | HTML example |\n| ----------------- | --------------------------------------------------------- | ----------------------------------------------------------------- |\n| `title` | Primary title line | `<span slot=\"title\">Account name</span>` |\n| `metadata` | Secondary lines under the title | `<ul slot=\"metadata\"><li>Line one</li></ul>` |\n| `avatar` | Leading avatar or custom media | `<xpl-avatar slot=\"avatar\" name=\"JD\"></xpl-avatar>` |\n| `details` | Right column: supporting text | `<span slot=\"details\">Last updated</span>` |\n| `badges` | Right column: badges / tags | `<span slot=\"badges\"><xpl-badge>New</xpl-badge></span>` |\n| `actions` | Trailing actions; clicks do **not** follow `href` | `<span slot=\"actions\"><xpl-button type=\"button\" variant=\"tertiary\" size=\"sm\">Edit</xpl-button></span>` |\n| `error-text` | Message below the row; affects error styling when present | `<span slot=\"error-text\">This field is required.</span>` |\n| `stacked-extra-1` | Optional stacked block | `<div slot=\"stacked-extra-1\">Extra block 1</div>` |\n| `stacked-extra-2` | Second optional stacked block | `<div slot=\"stacked-extra-2\">Extra block 2</div>` |\n| `stacked-extra-3` | Third optional stacked block | `<div slot=\"stacked-extra-3\">Extra block 3</div>` |\n\n\n**Dot badge next to the title:** set **`title-badge-variant`** on **`xpl-list-item`** (same variants as `xpl-badge`), not inside the title slot.\n\n**Divider under the title row:** set **`show-divider`** on **`xpl-list-item`**.\n\n**Minimal example:**\n\n```html\n<xpl-list selectable reorderable>\n <xpl-list-item item-id=\"row-1\" href=\"/settings\">\n <xpl-avatar slot=\"avatar\" name=\"AC\"></xpl-avatar>\n <span slot=\"title\">Settings</span>\n <span slot=\"metadata\">Workspace</span>\n <span slot=\"details\">Updated today</span>\n <span slot=\"actions\"><xpl-button type=\"button\" variant=\"tertiary\" size=\"sm\">Open</xpl-button></span>\n </xpl-list-item>\n</xpl-list>\n```\n\n---\n\n### Attributes: where to set them\n\n#### `xpl-list` (container)\n\n\n| Attribute | Purpose |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------ |\n| `label` | Accessible name: sets `aria-label` on the list host when there is no visible heading. **Not used** if `labelled-by` is also set. |\n| `labelled-by` | Space-separated element ids: sets `aria-labelledby` on the host. Takes precedence over `label` so both are never applied together. |\n| `selectable` | Enables radio selection; list assigns shared `radio-name`. **Escape** on the **selected** row clears selection (no extra attribute). |\n| `reorderable` | Enables drag handles and reorder behavior on **slot-based** rows only (see legacy section). |\n\nUse **`label`** *or* **`labelled-by`**, not both. If both attributes are present, only **`labelled-by`** affects the accessible name.\n\n\n#### `xpl-list-item` (row, slot mode — omit `item`)\n\n\n| Attribute | Purpose |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |\n| `item-id` | Stable id for selection and reorder events (or use host `id`). If omitted, the list may assign `item-0`, `item-1`, … |\n| `href` | Optional: row acts as a link; `actions` / `avatar` clicks do not navigate. |\n| `disabled`, `error` | Row state: non-interactive row and/or error styling (border, `error-text` slot). |\n| `hidden` | Hides the row from layout and from visible-only list behavior; see **Hidden rows** below. |\n| `selected` | Controlled selected state when the list is `selectable`. |\n| `show-divider` | Divider under the title area. |\n| `title-badge-variant` | Dot badge beside the title. |\n\n\n#### Usually set by `xpl-list` on items (avoid overriding unless needed)\n\n\n| Attribute | Meaning |\n| --------------------------- | --------------------------------------------------- |\n| `selectable`, `reorderable` | Mirrored from the list (**slot-based** rows only; not legacy `item` / `items` rows). |\n| `radio-name` | Shared radio group when the list is `selectable` (slot-based rows only). |\n| `keyboard-active` | Set on the row in keyboard reorder mode (slot-based rows only). |\n\n\n### Hidden rows\n\nSet the **`hidden`** attribute (or **`hidden`** prop) on **`xpl-list-item`** when a row should not appear in the list or take up space, but you still want it in the DOM. Typical use cases:\n\n- **Filtering or search** — hide rows that do not match without tearing down markup or losing local state.\n- **Progressive disclosure or permissions** — keep a stable **`item-id`** and show the row only when a condition becomes true.\n- **Temporary removal** — same as filtering when the row may return without re-creating the element.\n\n**List behavior:** Hidden rows are omitted from **`orderChange`**’s **`orderedItemIds`** and from drag-and-drop / keyboard reorder among **visible** rows only (see tests and list implementation). They do not receive focus while hidden.\n\n**Accessibility:** Native **`hidden`** removes the row from the accessibility tree while it is hidden. If users need an equivalent announcement elsewhere (for example, “3 results hidden by filter”), provide that in your application UI.\n\n---\n\n### Events and programmatic API\n\n#### `xpl-list` — listen on the list host\n\n\n| Event | When | `detail` |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |\n| `itemSelect` | Radio selection changes; when clearing via **`clearSelection()`** or **Escape** on the selected row, emitted **once per** previously selected row (typically one) | `{ itemId?: string }` |\n| `orderChange` | After a successful reorder (drag/drop or keyboard); DOM is already updated | `{ itemId?: string; direction: 'up' \\| 'down'; orderedItemIds: string[] }` |\n\n\n**`orderedItemIds`:** visible rows only (DOM order); hidden `xpl-list-item` rows are omitted.\n\n**TypeScript:** `orderChange` detail is typed as **`XplListOrderChangeDetail`** (exported from `@xplortech/apollo-core` alongside **`ListItem`**).\n\n**Legacy:** `xplListReorder` may also fire (bubbles, composed). Prefer **`orderChange`** for new code. Legacy `detail` includes `orderedItemIds` as well.\n\n\n| Method | Notes |\n| ------------------ | --------------------------------------------------------------------------------------------------- |\n| `clearSelection()` | Promise. Clears radios when `selectable`. Same effect as **Escape** with focus on the selected row. |\n\n\n```html\n<xpl-list id=\"my-list\" selectable reorderable>...</xpl-list>\n<script type=\"module\">\n const list = document.getElementById('my-list');\n list.addEventListener('itemSelect', (e) => {\n /* handle selection: */ void e.detail.itemId;\n });\n list.addEventListener('orderChange', (e) => {\n /* handle reorder: */ void e.detail.direction;\n void e.detail.orderedItemIds;\n });\n</script>\n```\n\n#### `xpl-list-item` — optional row-level listeners\n\n\n| Event | When | `detail` |\n| --------------- | ---------------------------------------------- | ---------------------------------------- |\n| `itemSelect` | Radio change on this row | `{ itemId?: string }` |\n| `itemDragStart` | Drag started from reorder handle | `{ itemId?: string; item: HTMLElement }` |\n| `itemDragEnd` | Drag ended on this row (after drop or cancel) | `{ itemId?: string; item: HTMLElement }` |\n| `itemDrop` | Drop target during reorder | `{ itemId?: string; item: HTMLElement }` |\n\n\n---\n\n## Legacy prop-based integration\n\nUse only for migration or data-driven rows. **Prefer slots for new work.**\n\n### At-a-glance migration\n\n| | **Before (deprecated)** | **After (recommended)** |\n| --- | --- | --- |\n| **Data** | `items` array on `xpl-list`, or `item` object on each row | Light DOM: `<xpl-list-item>` children with named slots |\n| **Identity** | Optional `ListItem.id`; else `item-0`, `item-1`, … | Explicit `item-id` (or host `id`) per row |\n\n```html\n<!-- Before: data-driven rows -->\n<xpl-list id=\"legacy-list\"></xpl-list>\n<script type=\"module\">\n document.getElementById('legacy-list').items = [{ title: 'Acme Co.', href: '/acme' }];\n</script>\n\n<!-- After: slot-based rows -->\n<xpl-list>\n <xpl-list-item item-id=\"acme\" href=\"/acme\">\n <span slot=\"title\">Acme Co.</span>\n </xpl-list-item>\n</xpl-list>\n```\n\n### `xpl-list` — `items` (deprecated)\n\n\n| Prop | Type | Description |\n| ------- | ------------ | ------------------------------------------------------------------------------------------------------- |\n| `items` | `ListItem[]` | **Deprecated.** Renders internal `<xpl-list-item>` rows with `item={...}` and ids `item-0`, `item-1`, … |\n\n\nA **console warning** runs when `items` is non-empty. Using **`items`** and slotted children renders **both**.\n\n### `xpl-list-item` — `item` (deprecated)\n\n\n| Prop | Type | Description |\n| ------ | ---------- | ---------------------------------------------------------------------------- |\n| `item` | `ListItem` | **Deprecated.** Prop-driven row; **no named slots**. Prefer slot-based rows. |\n\n\n### `ListItem` (`listitem.ts`, deprecated)\n\n\n| Field | Type | Notes |\n| ---------- | -------------------------------- | ---------------------- |\n| `id` | `string` | Optional stable row id (`item-id` when rendered from `items`) |\n| `title` | `string` | Required |\n| `href` | `string` | Optional |\n| `avatar` | `string` | Image URL or icon name |\n| `metadata` | `string[]` or `{ icon, text }[]` | |\n| `subtext` | `string` | |\n| `avatars` | `string[]` | |\n| `badges` | `string[]` or badge objects | |\n\n\n**Legacy layout:** Rows rendered from the deprecated `item` / inner `.xpl-list-item` flex markup use the **same layout at all viewport widths** (there is no dedicated narrow-viewport stacking breakpoint in `list-item.css`). If you need stacked mobile behavior for legacy lists, handle it in the app (e.g. layout wrapper or scoped CSS).\n\n**Legacy reordering:** The list does **not** set `reorderable` (or `selectable` / `radio-name`) on legacy **`items`** / **`item`** rows—there is **no** drag handle or keyboard reorder entry point in prop-driven mode. Only **slot-composed** rows participate in reorder and list-level selection UI; migrate from `items` / `item` to slotted `<xpl-list-item>` children if you need those features.\n\n---\n\n## Dependencies\n\n- **Rows:** `xpl-list-item` uses [xpl-avatar](../xpl-avatar), [xpl-icon](../xpl-icon), [xpl-badge](../xpl-badge), [xpl-divider](../xpl-divider).\n\n```mermaid\ngraph TD;\n xpl-list-item --> xpl-avatar\n xpl-list-item --> xpl-icon\n xpl-list-item --> xpl-badge\n xpl-list-item --> xpl-divider\n xpl-list --> xpl-list-item\n```\n\n\n\n## Design tokens\n\nList styling is split across [`list.css`](https://github.com/xplor/apollo/blob/main/packages/apollo-core/src/components/xpl-list/list.css) (the `xpl-list` host), [`list-item.css`](https://github.com/xplor/apollo/blob/main/packages/apollo-core/src/components/xpl-list/xpl-list-item/list-item.css) (legacy vs slot-based row layout, error/disabled/hidden, title/metadata columns), and [`list-action.css`](https://github.com/xplor/apollo/blob/main/packages/apollo-core/src/components/xpl-list/list-action.css) (reorder handle, selectable radio chrome, legacy action-button modifiers). All are imported from the package `style` entry. Visual values use **Apollo Foundation** CSS variables (`--xpl-*`); no raw hex colors in those stylesheets.\n\n\n| Category | Tokens (representative) |\n| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Layout / spacing** | `--xpl-space-4`, `--xpl-space-8`, `--xpl-space-12`, `--xpl-space-16`, `--xpl-space-40` |\n| **Sizing** | `--xpl-size-050`, `--xpl-size-075`, `--xpl-size-350` |\n| **Borders** | `--xpl-border-small`, `--xpl-border-large`, `--xpl-border-default`, `--xpl-border-hover`, `--xpl-border-focus`, `--xpl-border-negative`, `--xpl-border-subtle`, `--xpl-border-strong` |\n| **Radius** | `--xpl-border-radius-default`, `--xpl-border-radius-small`, `--xpl-border-radius-full` |\n| **Text** | `--xpl-text-default`, `--xpl-text-subdued`, `--xpl-text-disabled`, `--xpl-text-negative` |\n| **Icons / surfaces** | `--xpl-icon-default`, `--xpl-icon-subtle`, `--xpl-background-surface-default`, `--xpl-background-action-disabled`, `--xpl-background-surface-subtle` |\n| **Typography** | `--xpl-font-family-default`, `--xpl-font-size-body`, `--xpl-font-size-title-5`, `--xpl-font-size-callout`, `--xpl-font-size-caption`, `--xpl-font-weight-normal`, `--xpl-font-weight-medium` |\n\n\n## Accessibility\n\n- **`xpl-list`** sets `role=\"list\"` on the host. Use **`label`** / **`labelled-by`** when the list has no visible caption.\n- **`xpl-list-item`**: **`role=\"listitem\"`** is on the **inner row surface** in **slot-based** mode (see intro above); **legacy** `item` rows keep it on the **host**. When the list is **`selectable`**, the row renders **`xpl-radio`** with a shared group **`name`** and visually hidden label text (from the title slot when present, else a default).\n- With **`selectable`**, **Escape** while focus is on the **selected** row **clears selection** (same behavior as **`clearSelection()`**).\n- **Reorder**: the drag handle is a native **`<button>`** inside **`xpl-button`** (focusable, with **`aria-pressed`** in keyboard reorder mode and **`aria-label`** instructions for keyboard vs drag). Row links use `:focus-visible` for focus indication.\n- **`hidden`** on a row removes it from layout and visible reorder semantics; see **[Hidden rows](#hidden-rows)** for use cases and accessibility notes.\n\n---\n",
|
|
8650
8888
|
"docs": "",
|
|
8651
8889
|
"docsTags": [
|
|
8890
|
+
{
|
|
8891
|
+
"name": "slot",
|
|
8892
|
+
"text": "- The list items (`xpl-list-item` elements)."
|
|
8893
|
+
},
|
|
8652
8894
|
{
|
|
8653
8895
|
"name": "since",
|
|
8654
8896
|
"text": "0.4.0"
|
|
@@ -8666,7 +8908,7 @@
|
|
|
8666
8908
|
"ListItem": {
|
|
8667
8909
|
"location": "import",
|
|
8668
8910
|
"path": "./listitem",
|
|
8669
|
-
"id": "src/components/
|
|
8911
|
+
"id": "src/components/xpl-list/listitem.ts::ListItem",
|
|
8670
8912
|
"referenceLocation": "ListItem"
|
|
8671
8913
|
}
|
|
8672
8914
|
}
|
|
@@ -8846,7 +9088,7 @@
|
|
|
8846
9088
|
"XplListOrderChangeDetail": {
|
|
8847
9089
|
"location": "import",
|
|
8848
9090
|
"path": "./listitem",
|
|
8849
|
-
"id": "src/components/
|
|
9091
|
+
"id": "src/components/xpl-list/listitem.ts::XplListOrderChangeDetail",
|
|
8850
9092
|
"referenceLocation": "XplListOrderChangeDetail"
|
|
8851
9093
|
}
|
|
8852
9094
|
}
|
|
@@ -8895,7 +9137,12 @@
|
|
|
8895
9137
|
}
|
|
8896
9138
|
],
|
|
8897
9139
|
"styles": [],
|
|
8898
|
-
"slots": [
|
|
9140
|
+
"slots": [
|
|
9141
|
+
{
|
|
9142
|
+
"name": "",
|
|
9143
|
+
"docs": "The list items (`xpl-list-item` elements)."
|
|
9144
|
+
}
|
|
9145
|
+
],
|
|
8899
9146
|
"parts": [],
|
|
8900
9147
|
"states": [],
|
|
8901
9148
|
"dependents": [],
|
|
@@ -8923,35 +9170,76 @@
|
|
|
8923
9170
|
}
|
|
8924
9171
|
},
|
|
8925
9172
|
{
|
|
8926
|
-
"filePath": "src/components/
|
|
9173
|
+
"filePath": "src/components/xpl-list/xpl-list-item/xpl-list-item.tsx",
|
|
8927
9174
|
"encapsulation": "none",
|
|
8928
9175
|
"tag": "xpl-list-item",
|
|
8929
9176
|
"readme": "# xpl-list-item\n\nSingle row for [`xpl-list`](../xpl-list/readme.md). **Slot-based** rows expose `role=\"listitem\"` on the inner row surface (`.xpl-list-item__wrapper` or `.xpl-list-item__listitem-shell` when `href` is set); **legacy** `item` rows use `role=\"listitem\"` on the host. Hand-written integration notes for slots, attributes, and events live in the [list readme](../xpl-list/readme.md); the section below is Stencil-generated API for this component.\n\n**Reorder handle (slot mode):** When `reorderable` is enabled and the row uses **slot-based** content, the handle is an **`xpl-button`** wrapping a native **`<button>`**. Reorder logic is wired on the **`xpl-button` host** (`mousedown` / `keydown`); those events originate on the inner `<button>` and **bubble** to the host, which is how the list item receives them today. If `xpl-button` ever stopped bubbling for those events, reorder handlers would need to attach directly to the inner button (similar to `componentDidRender` syncing `aria-*` on that element).\n\n**Legacy `item` prop:** Prop-driven rows **do not** render the reorder handle, radios, or keyboard reorder affordances. Parent `xpl-list` **does not** set `selectable`, `radio-name`, or `reorderable` on those rows (those attributes are removed so they are not mistaken for supported behavior). Use slots if you need selection, drag, or keyboard reorder.\n\n### Accessibility\n\n- **`role=\"listitem\"`** is on the inner row surface (`.xpl-list-item__wrapper` for non-link rows, `.xpl-list-item__listitem-shell` for link rows), not on the `<xpl-list-item>` host. This avoids older browser issues with `display: contents` and ARIA.\n- **Hidden rows** render an empty host with the native `hidden` attribute only — no `role=\"listitem\"` — so hidden rows are removed from the accessibility tree entirely.\n- **Selectable rows** render `xpl-radio` with an accessible label derived from the **title** slot text, falling back to `Select <item-id>`, then `Select list item`.\n- **Reorder handle** (`xpl-button`) syncs `aria-label` and `aria-pressed` on the inner native `<button>` via `componentDidRender`. Labels change between drag and keyboard modes.\n- **Focus indicators** use `:focus-visible` with `outline-color: var(--xpl-border-focus)` and `outline-2 outline-offset-2`.\n- **Disabled rows** use `--xpl-background-action-disabled` and `--xpl-text-disabled`; link anchors get `pointer-events: none`.\n- **Keyboard reorder**: Enter/Space activates mode, ArrowUp/ArrowDown moves the row, Escape exits.\n\n### Design tokens\n\n| Role | Token |\n|------|-------|\n| Row background | `--xpl-background-surface-default` |\n| Row border | `--xpl-border-default` (default), `--xpl-border-hover` (hover), `--xpl-border-negative` (error), `--xpl-border-focus` (focus/drag-over) |\n| Row border-radius | `--xpl-border-radius-default` |\n| Text | `--xpl-text-default` (primary), `--xpl-text-subdued` (metadata/details), `--xpl-text-negative` (error), `--xpl-text-disabled` |\n| Icon | `--xpl-icon-subtle` (chevron) |\n| Spacing | `--xpl-space-4` through `--xpl-space-40` (padding, gap, margins) |\n| Sizing | `--xpl-size-050` (dot badge), `--xpl-size-350` (min-height) |\n| Typography | `--xpl-font-size-body`, `--xpl-font-size-title-5`, `--xpl-font-size-callout`, `--xpl-font-size-caption` |\n| Disabled background | `--xpl-background-action-disabled` |\n| Selected background | `--xpl-background-surface-subtle` |\n| Drag opacity | `--xpl-opacity-75` (custom token in `:root`) |\n",
|
|
8930
9177
|
"docs": "Single row for [`xpl-list`](../xpl-list/readme.md). **Slot-based** rows expose `role=\"listitem\"` on the inner row surface (`.xpl-list-item__wrapper` or `.xpl-list-item__listitem-shell` when `href` is set); **legacy** `item` rows use `role=\"listitem\"` on the host. Hand-written integration notes for slots, attributes, and events live in the [list readme](../xpl-list/readme.md); the section below is Stencil-generated API for this component.\n\n**Reorder handle (slot mode):** When `reorderable` is enabled and the row uses **slot-based** content, the handle is an **`xpl-button`** wrapping a native **`<button>`**. Reorder logic is wired on the **`xpl-button` host** (`mousedown` / `keydown`); those events originate on the inner `<button>` and **bubble** to the host, which is how the list item receives them today. If `xpl-button` ever stopped bubbling for those events, reorder handlers would need to attach directly to the inner button (similar to `componentDidRender` syncing `aria-*` on that element).\n\n**Legacy `item` prop:** Prop-driven rows **do not** render the reorder handle, radios, or keyboard reorder affordances. Parent `xpl-list` **does not** set `selectable`, `radio-name`, or `reorderable` on those rows (those attributes are removed so they are not mistaken for supported behavior). Use slots if you need selection, drag, or keyboard reorder.",
|
|
8931
|
-
"docsTags": [
|
|
8932
|
-
"usage": {},
|
|
8933
|
-
"props": [
|
|
9178
|
+
"docsTags": [
|
|
8934
9179
|
{
|
|
8935
|
-
"name": "
|
|
8936
|
-
"
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
"
|
|
8944
|
-
"
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
"
|
|
8953
|
-
|
|
8954
|
-
|
|
9180
|
+
"name": "slot",
|
|
9181
|
+
"text": "avatar - Leading avatar/media cell."
|
|
9182
|
+
},
|
|
9183
|
+
{
|
|
9184
|
+
"name": "slot",
|
|
9185
|
+
"text": "title - The primary title text."
|
|
9186
|
+
},
|
|
9187
|
+
{
|
|
9188
|
+
"name": "slot",
|
|
9189
|
+
"text": "metadata - Secondary metadata row rendered below the title."
|
|
9190
|
+
},
|
|
9191
|
+
{
|
|
9192
|
+
"name": "slot",
|
|
9193
|
+
"text": "stacked-extra-1 - First additional stacked row, rendered below `metadata`."
|
|
9194
|
+
},
|
|
9195
|
+
{
|
|
9196
|
+
"name": "slot",
|
|
9197
|
+
"text": "stacked-extra-2 - Second additional stacked row, rendered below `stacked-extra-1`."
|
|
9198
|
+
},
|
|
9199
|
+
{
|
|
9200
|
+
"name": "slot",
|
|
9201
|
+
"text": "stacked-extra-3 - Third additional stacked row, rendered below `stacked-extra-2`."
|
|
9202
|
+
},
|
|
9203
|
+
{
|
|
9204
|
+
"name": "slot",
|
|
9205
|
+
"text": "details - Right-side details content."
|
|
9206
|
+
},
|
|
9207
|
+
{
|
|
9208
|
+
"name": "slot",
|
|
9209
|
+
"text": "badges - Right-side badges group."
|
|
9210
|
+
},
|
|
9211
|
+
{
|
|
9212
|
+
"name": "slot",
|
|
9213
|
+
"text": "actions - Right-side action controls."
|
|
9214
|
+
},
|
|
9215
|
+
{
|
|
9216
|
+
"name": "slot",
|
|
9217
|
+
"text": "error-text - Error message shown below the row; puts the item in the error state."
|
|
9218
|
+
}
|
|
9219
|
+
],
|
|
9220
|
+
"usage": {},
|
|
9221
|
+
"props": [
|
|
9222
|
+
{
|
|
9223
|
+
"name": "disabled",
|
|
9224
|
+
"type": "boolean",
|
|
9225
|
+
"complexType": {
|
|
9226
|
+
"original": "boolean",
|
|
9227
|
+
"resolved": "boolean",
|
|
9228
|
+
"references": {}
|
|
9229
|
+
},
|
|
9230
|
+
"mutable": false,
|
|
9231
|
+
"attr": "disabled",
|
|
9232
|
+
"reflectToAttr": false,
|
|
9233
|
+
"docs": "Whether the item is disabled.",
|
|
9234
|
+
"docsTags": [
|
|
9235
|
+
{
|
|
9236
|
+
"name": "default",
|
|
9237
|
+
"text": "false"
|
|
9238
|
+
}
|
|
9239
|
+
],
|
|
9240
|
+
"default": "false",
|
|
9241
|
+
"values": [
|
|
9242
|
+
{
|
|
8955
9243
|
"type": "boolean"
|
|
8956
9244
|
}
|
|
8957
9245
|
],
|
|
@@ -9051,7 +9339,7 @@
|
|
|
9051
9339
|
"ListItem": {
|
|
9052
9340
|
"location": "import",
|
|
9053
9341
|
"path": "../listitem",
|
|
9054
|
-
"id": "src/components/
|
|
9342
|
+
"id": "src/components/xpl-list/listitem.ts::ListItem",
|
|
9055
9343
|
"referenceLocation": "ListItem"
|
|
9056
9344
|
}
|
|
9057
9345
|
}
|
|
@@ -9271,7 +9559,7 @@
|
|
|
9271
9559
|
"BadgeVariantProp": {
|
|
9272
9560
|
"location": "import",
|
|
9273
9561
|
"path": "../../xpl-badge/xpl-badge",
|
|
9274
|
-
"id": "src/components/
|
|
9562
|
+
"id": "src/components/xpl-badge/xpl-badge.tsx::BadgeVariantProp",
|
|
9275
9563
|
"referenceLocation": "BadgeVariantProp"
|
|
9276
9564
|
}
|
|
9277
9565
|
}
|
|
@@ -9415,7 +9703,48 @@
|
|
|
9415
9703
|
}
|
|
9416
9704
|
],
|
|
9417
9705
|
"styles": [],
|
|
9418
|
-
"slots": [
|
|
9706
|
+
"slots": [
|
|
9707
|
+
{
|
|
9708
|
+
"name": "actions",
|
|
9709
|
+
"docs": "Right-side action controls."
|
|
9710
|
+
},
|
|
9711
|
+
{
|
|
9712
|
+
"name": "avatar",
|
|
9713
|
+
"docs": "Leading avatar/media cell."
|
|
9714
|
+
},
|
|
9715
|
+
{
|
|
9716
|
+
"name": "badges",
|
|
9717
|
+
"docs": "Right-side badges group."
|
|
9718
|
+
},
|
|
9719
|
+
{
|
|
9720
|
+
"name": "details",
|
|
9721
|
+
"docs": "Right-side details content."
|
|
9722
|
+
},
|
|
9723
|
+
{
|
|
9724
|
+
"name": "error-text",
|
|
9725
|
+
"docs": "Error message shown below the row; puts the item in the error state."
|
|
9726
|
+
},
|
|
9727
|
+
{
|
|
9728
|
+
"name": "metadata",
|
|
9729
|
+
"docs": "Secondary metadata row rendered below the title."
|
|
9730
|
+
},
|
|
9731
|
+
{
|
|
9732
|
+
"name": "stacked-extra-1",
|
|
9733
|
+
"docs": "First additional stacked row, rendered below `metadata`."
|
|
9734
|
+
},
|
|
9735
|
+
{
|
|
9736
|
+
"name": "stacked-extra-2",
|
|
9737
|
+
"docs": "Second additional stacked row, rendered below `stacked-extra-1`."
|
|
9738
|
+
},
|
|
9739
|
+
{
|
|
9740
|
+
"name": "stacked-extra-3",
|
|
9741
|
+
"docs": "Third additional stacked row, rendered below `stacked-extra-2`."
|
|
9742
|
+
},
|
|
9743
|
+
{
|
|
9744
|
+
"name": "title",
|
|
9745
|
+
"docs": "The primary title text."
|
|
9746
|
+
}
|
|
9747
|
+
],
|
|
9419
9748
|
"parts": [],
|
|
9420
9749
|
"states": [],
|
|
9421
9750
|
"dependents": [
|
|
@@ -9450,12 +9779,28 @@
|
|
|
9450
9779
|
}
|
|
9451
9780
|
},
|
|
9452
9781
|
{
|
|
9453
|
-
"filePath": "src/components/
|
|
9782
|
+
"filePath": "src/components/xpl-main-nav/xpl-main-nav.tsx",
|
|
9454
9783
|
"encapsulation": "none",
|
|
9455
9784
|
"tag": "xpl-main-nav",
|
|
9456
|
-
"readme": "# xpl-main-nav\n\nThe Main Nav component contains is split in 3 areas. The top area is where the branding goes. It's divided into 2 slots `logo` and `brand-name`.\nThe middle area is where the main navigation links go. It's a `<nav>` tag with a slot named `navigation`, where a `<ul slot=\"navigation\">` with `<xpl-nav-items>` should be rendered.\n\nThe bottom area is fixed to the bottom and should be used for actions. To render content within this area use the slot `footer` with a `<ul slot=\"footer\">` tag.\n\n### Design Tokens\n\n`xpl-main-nav` is the legacy always-dark side-nav rail; its surface never mode-switches, so colors resolve to the same dark-appropriate value in both page themes.\n\n**Color**\n- `--xpl-background-surface-inverse-on-light` — rail surface (neutral-1000, both modes; matches the application-shell nav host)\n- `--xpl-color-neutral-1100` — footer surface (primitive; no purpose token — see `TECH_DEBT.md`)\n- `--xpl-text-subdued` — rail on-surface base text and nav-item rest label (neutral-600 light / neutral-500 dark; Figma-confirmed; keeps text off the ambient page color on the dark rail)\n- `--xpl-text-inverse-on-dark` — brand name + footer primary text (white, both modes)\n- `--xpl-icon-subtle` — muted footer icon (neutral-500, both modes)\n\n**Typography**\n- `--xpl-font-size-body` — collapsed (`sm`/`md`) nav item label size\n\n**Layout**\n- Collapse-state widths (240 / 112 / 74px) and the 42px brand logo box are raw literals — no matching Foundation size token (see `TECH_DEBT.md`)\n",
|
|
9785
|
+
"readme": "# xpl-main-nav\n\nThe Main Nav component contains is split in 3 areas. The top area is where the branding goes. It's divided into 2 slots `logo` and `brand-name`.\nThe middle area is where the main navigation links go. It's a `<nav>` tag with a slot named `navigation`, where a `<ul slot=\"navigation\">` with `<xpl-nav-items>` should be rendered.\n\nThe bottom area is fixed to the bottom and should be used for actions. To render content within this area use the slot `footer` with a `<ul slot=\"footer\">` tag.\n\n### Design Tokens\n\n`xpl-main-nav` is the legacy always-dark side-nav rail; its surface never mode-switches, so colors resolve to the same dark-appropriate value in both page themes.\n\n**Color**\n- `--xpl-background-surface-inverse-on-light` — rail surface (neutral-1000, both modes; matches the application-shell nav host)\n- `--xpl-color-neutral-1100` — footer surface (primitive; no purpose token — see `TECH_DEBT.md`)\n- `--xpl-text-subdued` — rail on-surface base text and nav-item rest label (neutral-600 light / neutral-500 dark; Figma-confirmed; keeps text off the ambient page color on the dark rail)\n- `--xpl-text-inverse-on-dark` — brand name + footer primary text (white, both modes)\n- `--xpl-icon-subtle` — muted footer icon (neutral-500, both modes)\n\n**Typography**\n- `--xpl-font-size-body` — collapsed (`sm`/`md`) nav item label size\n- `--xpl-line-height-body` — collapsed (`sm`/`md`) nav item label line height\n- `--xpl-line-height-title-4` — brand lockup text line height (title-4)\n\n**Layout**\n- Collapse-state widths (240 / 112 / 74px) and the 42px brand logo box are raw literals — no matching Foundation size token (see `TECH_DEBT.md`)\n",
|
|
9457
9786
|
"docs": "The Main Nav component contains is split in 3 areas. The top area is where the branding goes. It's divided into 2 slots `logo` and `brand-name`.\nThe middle area is where the main navigation links go. It's a `<nav>` tag with a slot named `navigation`, where a `<ul slot=\"navigation\">` with `<xpl-nav-items>` should be rendered.\n\nThe bottom area is fixed to the bottom and should be used for actions. To render content within this area use the slot `footer` with a `<ul slot=\"footer\">` tag.",
|
|
9458
9787
|
"docsTags": [
|
|
9788
|
+
{
|
|
9789
|
+
"name": "slot",
|
|
9790
|
+
"text": "logo - Brand logo rendered in the sidebar header."
|
|
9791
|
+
},
|
|
9792
|
+
{
|
|
9793
|
+
"name": "slot",
|
|
9794
|
+
"text": "brand-name - Brand or product name rendered next to the logo in the sidebar header."
|
|
9795
|
+
},
|
|
9796
|
+
{
|
|
9797
|
+
"name": "slot",
|
|
9798
|
+
"text": "navigation - Primary navigation items."
|
|
9799
|
+
},
|
|
9800
|
+
{
|
|
9801
|
+
"name": "slot",
|
|
9802
|
+
"text": "footer - Footer content pinned to the bottom of the sidebar."
|
|
9803
|
+
},
|
|
9459
9804
|
{
|
|
9460
9805
|
"name": "since",
|
|
9461
9806
|
"text": "0.1.2"
|
|
@@ -9530,7 +9875,24 @@
|
|
|
9530
9875
|
],
|
|
9531
9876
|
"listeners": [],
|
|
9532
9877
|
"styles": [],
|
|
9533
|
-
"slots": [
|
|
9878
|
+
"slots": [
|
|
9879
|
+
{
|
|
9880
|
+
"name": "brand-name",
|
|
9881
|
+
"docs": "Brand or product name rendered next to the logo in the sidebar header."
|
|
9882
|
+
},
|
|
9883
|
+
{
|
|
9884
|
+
"name": "footer",
|
|
9885
|
+
"docs": "Footer content pinned to the bottom of the sidebar."
|
|
9886
|
+
},
|
|
9887
|
+
{
|
|
9888
|
+
"name": "logo",
|
|
9889
|
+
"docs": "Brand logo rendered in the sidebar header."
|
|
9890
|
+
},
|
|
9891
|
+
{
|
|
9892
|
+
"name": "navigation",
|
|
9893
|
+
"docs": "Primary navigation items."
|
|
9894
|
+
}
|
|
9895
|
+
],
|
|
9534
9896
|
"parts": [],
|
|
9535
9897
|
"states": [],
|
|
9536
9898
|
"dependents": [],
|
|
@@ -9538,7 +9900,7 @@
|
|
|
9538
9900
|
"dependencyGraph": {}
|
|
9539
9901
|
},
|
|
9540
9902
|
{
|
|
9541
|
-
"filePath": "src/components/
|
|
9903
|
+
"filePath": "src/components/xpl-modal/xpl-modal.tsx",
|
|
9542
9904
|
"encapsulation": "none",
|
|
9543
9905
|
"tag": "xpl-modal",
|
|
9544
9906
|
"readme": "# xpl-modal\n\nModals are dialogs that focus the user’s attention exclusively on one task or piece of information via a window layer above the current content.\n\nModals are disruptive and should only be used when disrupting the user’s flow is desired.\n\n## Token Use\n\n`xpl-modal` uses Apollo Foundation purpose-specific tokens; light and dark mode are handled by the token definitions, so the component has no `.dark` overrides.\n\n| Element | Property | Token |\n| ------- | -------- | ----- |\n| `&__dialog` | background | `--xpl-background-surface-default` |\n| `&__dialog` | text color | `--xpl-text-default` |\n| `&__dialog` | radius | `--xpl-border-radius-large` |\n| `&__dialog` | shadow | `--xpl-elevation-4` (theme-aware) |\n| `&__title` | typography (size / weight / line-height) | `@extend .xpl-text-title-3` → `title-3` / `bold` / `1.4` |\n| `&__subtitle` | color | `--xpl-text-subdued` |\n| `&__subtitle` | typography (size / weight / line-height) | `@extend .xpl-text-callout` → `callout` / `normal` / `1.3333` |\n| `&__body` | typography (size / weight / line-height) | `@extend .xpl-text-body` → `body` / `normal` / `1.4286` |\n| `&__alert-icon` | color | `--xpl-icon-negative` |\n\nModal widths are documented CSS literals: small `400px`, medium `600px`, large `800px`, mobile `350px` (see `modal.css` and `TECH_DEBT.md`).\n\n> **Elevation shadow:** the dialog uses `--xpl-elevation-4` (theme-aware), which matches Figma's \"Shadow 4\" style (`y=20`, `blur=25`, color `background-surface-transparent-10`). See `TECH_DEBT.md`.\n\n## Accessibility\n\n`xpl-modal` renders a native `<dialog>` shown via `showModal()`: focus is trapped inside the modal while it is open, and `Escape` closes it (emitting `modalClosed`).\n\nKeyboard tab order follows the DOM order of the footer slots: **close (×) → `primary` → `secondary` → `tertiary` → back to ×**. The footer's visual layout (tertiary pinned far-left, secondary and primary right-aligned) is produced with CSS `order` in `modal.css`, so the visual arrangement and the tab order are independent by design — do not reorder the `<slot>` elements in the component template to change the layout.\n\n### Accessible names\n\nThe dialog is named by the `title` slot: the component wraps that slot in `.xpl-modal__title-text`, gives it a per-instance id, and points the dialog's `aria-labelledby` at it. Always provide a `title` slot — without one the dialog is announced only as \"dialog\". The label deliberately references the title text rather than the whole `.xpl-modal__title` row, which would fold the close button's own name into the dialog's name.\n\nThe close (×) button carries `aria-label=\"Close modal\"`, so screen readers announce its purpose instead of the underlying icon name.\n\n## Mounting and unmounting\n\n`showModal()` promotes the dialog into the browser's top layer, where it survives the removal of its host element. `xpl-modal` closes the dialog when the host disconnects so a removed modal cannot leave a blocking overlay behind, and re-opens it — reattaching the `Escape` and backdrop listeners — if the host is connected again while `isOpen` is still `true`. Frameworks that move or reparent DOM nodes therefore get consistent state without extra work from the consumer.\n",
|
|
@@ -9742,12 +10104,16 @@
|
|
|
9742
10104
|
}
|
|
9743
10105
|
},
|
|
9744
10106
|
{
|
|
9745
|
-
"filePath": "src/components/
|
|
10107
|
+
"filePath": "src/components/xpl-top-nav/xpl-nav-header-menu/xpl-nav-header-menu.tsx",
|
|
9746
10108
|
"encapsulation": "none",
|
|
9747
10109
|
"tag": "xpl-nav-header-menu",
|
|
9748
|
-
"readme": "# xpl-nav-header-menu\n\nProfile block (username, email) and a default slot for menu rows. Typically inside **`xpl-popover`** or **`xpl-dropdown`** under a user trigger.\n\n**Styles** for this component live in **`packages/apollo-core/src/
|
|
10110
|
+
"readme": "# xpl-nav-header-menu\n\nProfile block (username, email) and a default slot for menu rows. Typically inside **`xpl-popover`** or **`xpl-dropdown`** under a user trigger.\n\n**Styles** for this component live in **`packages/apollo-core/src/components/xpl-top-nav/top-nav.css`** (with **`xpl-top-nav-item`** rules in the same file).\n\n## Usage\n\n```html\n<xpl-nav-header-menu username=\"Katie Wilson\" email=\"katie@example.com\">\n <xpl-top-nav-item label=\"View account\" icon=\"house-4\" href=\"/account\"></xpl-top-nav-item>\n <xpl-top-nav-item label=\"Log out\" icon=\"open-rect-arrow-out\" href=\"/logout\"></xpl-top-nav-item>\n</xpl-nav-header-menu>\n```\n\nOptional narrow-only duplicate of bar actions (e.g. Inbox) between the profile block and the list — use **`slot=\"right-aside-mobile\"`** with **`xpl-top-nav-item`** or **`xpl-button`**. That strip is visible by default only on **narrow viewports** (one pixel below Tailwind **`md`** — see **`top-nav.css`**).\n\n```html\n<xpl-nav-header-menu username=\"Katie Wilson\" email=\"katie@example.com\">\n <xpl-top-nav-item slot=\"right-aside-mobile\" label=\"Inbox\" icon=\"mail-1\" href=\"/inbox\"></xpl-top-nav-item>\n <xpl-top-nav-item label=\"Log out\" icon=\"open-rect-arrow-out\" href=\"/logout\"></xpl-top-nav-item>\n</xpl-nav-header-menu>\n```\n\n## Token Use\n\nSpacing, typography, and colors use Apollo Foundation **`var(--xpl-*)`** tokens (e.g. **`--xpl-text-strong`**, **`--xpl-space-*`**, **`--xpl-font-size-*`**). Panel width uses the component-scoped custom property **`--xpl-top-nav-panel-width`** on **`xpl-top-nav`** / **`xpl-nav-header-menu`** hosts (composed from **`--xpl-size-*`** in **`top-nav.css`**).\n\n## Accessibility\n\n- The default slot is wrapped in a container with **`role=\"list\"`**. Use **`xpl-top-nav-item`** for rows so each item exposes **`role=\"listitem\"`** and keyboard/focus behavior from **`xpl-top-nav-item`** (including **`Enter`** / **`Space`** on non-link controls and **`:focus-visible`** outline on the inner control).\n- The host may include Foundation’s **`dark`** class so purpose tokens match account menu contrast when the page root is light.\n- **`slot=\"right-aside-mobile\"`** is not a list; do not rely on **`role=\"list\"`** for that block.\n\n## Events\n\nThis component does not emit custom events. Use **`xpl-top-nav-item`** **`navItemClick`** (or native link navigation) for row actions.\n",
|
|
9749
10111
|
"docs": "Profile / account block (username, email, default slot for **`xpl-top-nav-item`** / **`xpl-divider`**).\nTag **`xpl-nav-header-menu`**; implementation folder **`xpl-nav-header-menu`**. **`.xpl-nav-header-menu__slot`** is\n**`role=\"list\"`** for slotted **`xpl-top-nav-item`** (**`role=\"listitem\"`**).\n\n**Slotted content:** do not add **`xpl-nav-header-menu__*`** BEM classes on nodes you pass into the default slot —\nprofile, list shell, and **`xpl-top-nav-item`** **`role=\"listitem\"`** are handled by the component. Use\n**`xpl-top-nav-item`** (or plain elements that are not Apollo **`xpl-*`** BEM hooks) in the slot only.\n\n**`slot=\"right-aside-mobile\"`** — optional block **between** the profile header and the default-slot list (e.g. narrow-only\nduplicate of **every** **`slot=\"right-aside\"`** control per Figma when **`xpl-top-nav`** hides **`right-aside`** on narrow viewports (always)).\nNot **`role=\"list\"`**; use **`xpl-button`** / **`xpl-top-nav-item`** as needed. Shown only on **narrow viewports** (one pixel below Tailwind **`md`** — **`top-nav.css`**) so bar actions stay in **`slot=\"right-aside\"`** on wider viewports.\nLight-DOM **`slotchange`** is unreliable; a host **`MutationObserver`** (child / subtree / **`slot`** attribute) keeps\n**`xpl-nav-header-menu--has-right-aside-mobile`** in sync when nodes are added or retargeted after mount (same pattern as **`xpl-top-nav`**).\nStencil **`newSpecPage`** / mock-doc does not define **`MutationObserver`**; slot presence still updates on the next\ndeferred flush (**`setTimeout(0)`** coalesced with **`componentDidRender`**). In real browsers the observer handles child /\n**`slot`** mutations without stacking uncancellable microtasks.\n\n**Theming:** The host always includes Foundation’s **`dark`** class so **`--xpl-*`** purpose tokens resolve to dark-mode\nvalues even when the page root is light (same contract as **`xpl-top-nav`** / **`xpl-top-nav-item`**).",
|
|
9750
10112
|
"docsTags": [
|
|
10113
|
+
{
|
|
10114
|
+
"name": "slot",
|
|
10115
|
+
"text": "- Menu items (**`xpl-top-nav-item`** rows and optional **`xpl-divider`** separators) rendered below the profile block."
|
|
10116
|
+
},
|
|
9751
10117
|
{
|
|
9752
10118
|
"name": "slot",
|
|
9753
10119
|
"text": "right-aside-mobile - Optional actions **below** **`username`** / **`email`** and **above** the default-slot list (e.g. mobile Inbox). Hidden on wide viewports by default (see **`top-nav.css`**)."
|
|
@@ -9807,6 +10173,10 @@
|
|
|
9807
10173
|
"listeners": [],
|
|
9808
10174
|
"styles": [],
|
|
9809
10175
|
"slots": [
|
|
10176
|
+
{
|
|
10177
|
+
"name": "",
|
|
10178
|
+
"docs": "Menu items (**`xpl-top-nav-item`** rows and optional **`xpl-divider`** separators) rendered below the profile block."
|
|
10179
|
+
},
|
|
9810
10180
|
{
|
|
9811
10181
|
"name": "right-aside-mobile",
|
|
9812
10182
|
"docs": "Optional actions **below** **`username`** / **`email`** and **above** the default-slot list (e.g. mobile Inbox). Hidden on wide viewports by default (see **`top-nav.css`**)."
|
|
@@ -9819,12 +10189,24 @@
|
|
|
9819
10189
|
"dependencyGraph": {}
|
|
9820
10190
|
},
|
|
9821
10191
|
{
|
|
9822
|
-
"filePath": "src/components/
|
|
10192
|
+
"filePath": "src/components/xpl-nav-item/xpl-nav-item.tsx",
|
|
9823
10193
|
"encapsulation": "none",
|
|
9824
10194
|
"tag": "xpl-nav-item",
|
|
9825
|
-
"readme": "# xpl-nav-item\n\nThis component should be used within sections of the `<xpl-main-nav>`. This component yields a slot named `link`, where a `<a>` tag should be used. Within the `<a>` tag, there are two slots, one named `icon`, where any svg can be placed. An an unnamed slot, where the link text should be placed.\n\n### Design Tokens\n\n`xpl-nav-item` renders on the legacy always-dark side-nav rail, so its colors resolve to the same dark-appropriate value in both light and dark page themes.\n\n**Color**\n- `--xpl-icon-subtle` — rest icon (neutral-500, both modes)\n- `--xpl-text-subdued` — rest label text (neutral-600 light / neutral-500 dark; Figma-confirmed)\n- `--xpl-text-inverse-on-dark` / `--xpl-icon-inverse-on-dark` — hover / focus / active / selected label and icon (white, both modes)\n- `--xpl-color-neutral-1200` — hover / focus / active background (primitive; no purpose token — see `TECH_DEBT.md`)\n- `--xpl-color-orange-400` — active brand accent border + icon (primitive; consult-Figma — see `TECH_DEBT.md`)\n\n**Border**\n-
|
|
10195
|
+
"readme": "# xpl-nav-item\n\nThis component should be used within sections of the `<xpl-main-nav>`. This component yields a slot named `link`, where a `<a>` tag should be used. Within the `<a>` tag, there are two slots, one named `icon`, where any svg can be placed. An an unnamed slot, where the link text should be placed.\n\n### Design Tokens\n\n`xpl-nav-item` renders on the legacy always-dark side-nav rail, so its colors resolve to the same dark-appropriate value in both light and dark page themes.\n\n**Color**\n- `--xpl-icon-subtle` — rest icon (neutral-500, both modes)\n- `--xpl-text-subdued` — rest label text (neutral-600 light / neutral-500 dark; Figma-confirmed)\n- `--xpl-text-inverse-on-dark` / `--xpl-icon-inverse-on-dark` — hover / focus / active / selected label and icon (white, both modes)\n- `--xpl-color-neutral-1200` — hover / focus / active background (primitive; no purpose token — see `TECH_DEBT.md`)\n- `--xpl-color-orange-400` — active brand accent border + icon (primitive; consult-Figma — see `TECH_DEBT.md`)\n\n**Border**\n- `--xpl-border-xlarge` — 4px active accent border width\n",
|
|
9826
10196
|
"docs": "This component should be used within sections of the `<xpl-main-nav>`. This component yields a slot named `link`, where a `<a>` tag should be used. Within the `<a>` tag, there are two slots, one named `icon`, where any svg can be placed. An an unnamed slot, where the link text should be placed.",
|
|
9827
10197
|
"docsTags": [
|
|
10198
|
+
{
|
|
10199
|
+
"name": "slot",
|
|
10200
|
+
"text": "link - Optional wrapper around the item content (e.g. an anchor element)."
|
|
10201
|
+
},
|
|
10202
|
+
{
|
|
10203
|
+
"name": "slot",
|
|
10204
|
+
"text": "icon - Leading icon content rendered before the label."
|
|
10205
|
+
},
|
|
10206
|
+
{
|
|
10207
|
+
"name": "slot",
|
|
10208
|
+
"text": "- The item label content."
|
|
10209
|
+
},
|
|
9828
10210
|
{
|
|
9829
10211
|
"name": "since",
|
|
9830
10212
|
"text": "0.1.2"
|
|
@@ -9890,7 +10272,20 @@
|
|
|
9890
10272
|
],
|
|
9891
10273
|
"listeners": [],
|
|
9892
10274
|
"styles": [],
|
|
9893
|
-
"slots": [
|
|
10275
|
+
"slots": [
|
|
10276
|
+
{
|
|
10277
|
+
"name": "",
|
|
10278
|
+
"docs": "The item label content."
|
|
10279
|
+
},
|
|
10280
|
+
{
|
|
10281
|
+
"name": "icon",
|
|
10282
|
+
"docs": "Leading icon content rendered before the label."
|
|
10283
|
+
},
|
|
10284
|
+
{
|
|
10285
|
+
"name": "link",
|
|
10286
|
+
"docs": "Optional wrapper around the item content (e.g. an anchor element)."
|
|
10287
|
+
}
|
|
10288
|
+
],
|
|
9894
10289
|
"parts": [],
|
|
9895
10290
|
"states": [],
|
|
9896
10291
|
"dependents": [],
|
|
@@ -9898,10 +10293,10 @@
|
|
|
9898
10293
|
"dependencyGraph": {}
|
|
9899
10294
|
},
|
|
9900
10295
|
{
|
|
9901
|
-
"filePath": "src/components/
|
|
10296
|
+
"filePath": "src/components/xpl-pagination/xpl-pagination.tsx",
|
|
9902
10297
|
"encapsulation": "none",
|
|
9903
10298
|
"tag": "xpl-pagination",
|
|
9904
|
-
"readme": "# xpl-pagination\n\nPagination bar allows users to navigate pages of content.\n\n> **Note:** This component is in beta. Use with caution and expect updates before the full release.\n\n## Design Tokens\n\nPagination themes with the app (light/dark) using Apollo Foundation tokens\n(`packages/apollo-core/src/
|
|
10299
|
+
"readme": "# xpl-pagination\n\nPagination bar allows users to navigate pages of content.\n\n> **Note:** This component is in beta. Use with caution and expect updates before the full release.\n\n## Design Tokens\n\nPagination themes with the app (light/dark) using Apollo Foundation tokens\n(`packages/apollo-core/src/components/xpl-pagination/pagination.css`):\n\n| Element / state | Property | Token | Resolves (light / dark) |\n| --- | --- | --- | --- |\n| Pager button surface | `background-color` | `--xpl-background-action-secondary-default` | neutral-0 / neutral-1000 |\n| Pager button border | `border-color` | `--xpl-border-strong` | neutral-600 / neutral-400 |\n| Pager arrow icon | `color` (icon) | `--xpl-icon-default` | neutral-1000 / neutral-0 |\n| Pager button hover/active border | `border-color` | `--xpl-background-action-primary-default` | purple-700 / purple-300 |\n| Pager button focus | `outline-color` | `--xpl-border-focus` (2px, 2px offset) | purple-800 / purple-400 |\n| Pager button disabled icon | `color` (icon) | `--xpl-icon-disabled` | neutral-600 / neutral-500 |\n| Pager button disabled bg | `background-color` | `--xpl-background-action-disabled` | neutral-100 / neutral-800 |\n| Pager container text | `color` | `--xpl-text-default` | neutral-900 / neutral-50 |\n| Rows-per-page label | `color` | `--xpl-text-default` | neutral-900 / neutral-50 |\n| Rows-per-page label | `font-size` / `font-weight` / `line-height` | `@extend .xpl-text-body` (14px, normal, 1.4286) | — |\n| Go-to-page value | `color` | `--xpl-text-link-default` | purple-700 / purple-300 |\n| Active page background | `background-color` | `--xpl-background-brand-secondary-surface` | purple-50 / purple-900 |\n| Pager button / page size | `width` / `height` | `--xpl-size-250` | 40px |\n| Prev / next radius | `border-radius` | `--xpl-border-radius-full` | pill |\n\n> **Accessibility:** keyboard focus uses the Foundation `:focus-visible` outline pattern\n> (`--xpl-border-focus`, 2px outline + 2px offset) instead of a Tailwind `ring`, so the\n> focus ring stays visible on the pager buttons in both themes.\n>\n> **Note:** the rows-per-page (72px), page-select (88px), and page-info (70px) min-widths\n> have no matching Foundation size token and remain literals — see `TECH_DEBT.md`.\n",
|
|
9905
10300
|
"docs": "Pagination bar allows users to navigate pages of content.\n\n> **Note:** This component is in beta. Use with caution and expect updates before the full release.",
|
|
9906
10301
|
"docsTags": [
|
|
9907
10302
|
{
|
|
@@ -10126,7 +10521,7 @@
|
|
|
10126
10521
|
}
|
|
10127
10522
|
},
|
|
10128
10523
|
{
|
|
10129
|
-
"filePath": "src/components/
|
|
10524
|
+
"filePath": "src/components/xpl-panel/xpl-panel.tsx",
|
|
10130
10525
|
"encapsulation": "none",
|
|
10131
10526
|
"tag": "xpl-panel",
|
|
10132
10527
|
"readme": "# xpl-panel\n\n`xpl-panel` is a stateless, composable container that defines a section on a page and can house any type of content. Panels are not dismissible and may show a colored top accent bar. Padding is applied evenly to **`.xpl-panel__content`** (all sides use the same spacing token).\n\n## Accessibility\n\nThe panel is a generic layout container: it does not define a landmark role or trap focus. Place interactive controls in the default slot. For a named region, wrap the panel (or its content) in an element with `role=\"region\"` and an accessible name (e.g. `aria-label`) when the panel represents a distinct section.\n\nWhen an accent is present, the accent bar is a decorative `div` with `aria-hidden=\"true\"` so assistive technologies ignore it; meaning comes from slot content.\n\n## Token use\n\n**Host (surface)**\n\n\n| Property | Token |\n| ------------- | --------------------------------------- |\n| Background | `var(--xpl-background-surface-default)` |\n| Border color | `var(--xpl-border-default)` |\n| Border width | `var(--xpl-border-small)` |\n| Border radius | `var(--xpl-border-radius-default)` |\n\n\n**Accent bar** (`accent` ≠ `none`): height `var(--xpl-size-050)`; top radii `var(--xpl-border-radius-default)`, bottom `var(--xpl-border-radius-none)`.\n\n\n| `accent` | Background token |\n| ----------- | ---------------------------------------- |\n| `primary` | `var(--xpl-background-brand-primary)` |\n| `secondary` | `var(--xpl-background-brand-secondary)` |\n| `positive` | `var(--xpl-background-accent-positive)` |\n| `negative` | `var(--xpl-background-accent-negative)` |\n| `highlight` | `var(--xpl-background-accent-highlight)` |\n\n\nLight and dark mode follow Apollo Foundation purpose-specific tokens; the component does not use `.dark` overrides in its CSS.\n\n## Content padding by viewport\n\nThe `padding` prop sets **content** padding via `var(--xpl-space-*)` on `.xpl-panel__content`. Two `max-width` media queries step values down on smaller viewports (`panel.css`).\n\n### Matrix: `padding` × viewport\n\n\n| Viewport | Approx. width | `padding=\"default\"` | `padding=\"tight\"` | `padding=\"loose\"` |\n| ---------- | ------------------- | ---------------------------- | ---------------------------- | ---------------------------- |\n| **Large** | > 768px | `var(--xpl-space-24)` · 24px | `var(--xpl-space-16)` · 16px | `var(--xpl-space-40)` · 40px |\n| **Tablet** | ≤ 768px and > 480px | same as large | same as large | `var(--xpl-space-32)` · 32px |\n| **Mobile** | ≤ 480px | `var(--xpl-space-16)` · 16px | `var(--xpl-space-8)` · 8px | `var(--xpl-space-24)` · 24px |\n\n\n**How the breakpoints stack**\n\n1. Base rules apply the **Large** row for all widths.\n2. At `max-width: 768px`, only **loose** changes (tablet row for that column).\n3. At `max-width: 480px`, **default**, **tight**, and **loose** all use the **Mobile** row.\n\nPixel values match the Foundation `space/`* scale; if tokens change in a future Foundation release, spacing updates without component code changes.\n\n## Usage\n\n### Web component\n\n```html\n<xpl-panel>\n <p>Any content goes here.</p>\n</xpl-panel>\n```\n\n```html\n<xpl-panel accent=\"primary\">\n <p>Content with a primary accent bar.</p>\n</xpl-panel>\n```\n\nAvailable accent values: `none` (default), `primary`, `secondary`, `positive`, `negative`, `highlight`.\n\n### Padding density\n\n```html\n<xpl-panel padding=\"tight\">\n <p>Tighter padding on small screens (see content padding matrix).</p>\n</xpl-panel>\n```\n\nUse `padding=\"default\"` | `\"tight\"` | `\"loose\"`. **default** and **tight** keep the same values from large screens through tablet; only at **≤480px** do they step down. **loose** steps down at **≤768px** (tablet) and again at **≤480px** (mobile).\n\n### HTML/CSS (no Stencil)\n\nUse the same BEM classes the component applies on the host. The accent bar must stay decorative (`aria-hidden=\"true\"`).\n\n```html\n<div class=\"xpl-panel xpl-panel--accent-primary xpl-panel--padding-default\">\n <div aria-hidden=\"true\" class=\"xpl-panel__accent\"></div>\n <div class=\"xpl-panel__content\">\n <p>Panel body</p>\n </div>\n</div>\n```\n\nOmit `xpl-panel--accent-*` when `accent` is `none`; do not render `.xpl-panel__accent`.\n\n### Composing with other components\n\n```html\n<xpl-panel accent=\"secondary\" padding=\"loose\">\n <xpl-accordion header=\"Details\">\n <div slot=\"content\">Accordion inside a panel.</div>\n </xpl-accordion>\n</xpl-panel>\n```\n\n### Content styling\n\nThe panel intentionally does **not** apply default typography or color styles to slotted content. It provides the surface (background, border, accent) and content padding — nothing more. This means text inside the panel inherits whatever styles the surrounding page defines.\n\nTo ensure consistent, theme-aware content you should use Apollo Foundation tokens on elements inside the slot:\n\n```html\n<xpl-panel>\n <h3 class=\"xpl-text-title-4\" style=\"color: var(--xpl-text-strong)\">Section title</h3>\n <p class=\"xpl-text-body\" style=\"color: var(--xpl-text-default)\">\n Body copy that adapts to light and dark mode automatically.\n </p>\n <p class=\"xpl-text-caption\" style=\"color: var(--xpl-text-subdued)\">\n Subdued helper text.\n </p>\n</xpl-panel>\n```\n\n| Purpose | Recommended token |\n| ------- | ----------------- |\n| Primary text | `var(--xpl-text-default)` |\n| Headings / emphasis | `var(--xpl-text-strong)` |\n| Secondary / helper text | `var(--xpl-text-subdued)` |\n| Disabled text | `var(--xpl-text-disabled)` |\n| Links | `var(--xpl-text-link-default)` |\n\nUsing purpose-specific text tokens guarantees content switches correctly in dark mode. If slot content uses raw colors (e.g. `color: #333`) or relies on browser defaults, text will **not** adapt when the panel's ancestor has the `dark` class.\n\n### Dark mode\n\nUse an ancestor with the `dark` class — surface, border, and accent tokens update via Foundation.\n\n## Design\n\n- [Figma: xpl-panel](https://www.figma.com/design/MjjYek73MFnHmVNdm45Sd1/Apollo-Web?node-id=1546-136120&p=f)\n",
|
|
@@ -10249,7 +10644,7 @@
|
|
|
10249
10644
|
"dependencyGraph": {}
|
|
10250
10645
|
},
|
|
10251
10646
|
{
|
|
10252
|
-
"filePath": "src/components/
|
|
10647
|
+
"filePath": "src/components/xpl-popover/xpl-popover.tsx",
|
|
10253
10648
|
"encapsulation": "none",
|
|
10254
10649
|
"tag": "xpl-popover",
|
|
10255
10650
|
"readme": "# xpl-popover\n\nA popover is an overlay that pops up over all other layers and is triggered by a click or tap, and dismissed by clicking outside the popover or a dismiss icon. Popovers can contain additional actions and allow those actions to be triggered.\n\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-background-surface-default` — content panel background and arrow fill\n- `--xpl-elevation-2` — content panel shadow (theme-aware)\n- `--xpl-text-default` — content text color\n- `--xpl-border-default` — content panel border and arrow stroke\n\n**Spacing**\n- `--xpl-space-8` — popover margin (offset from trigger), via `--xpl-popover-margin`\n- `--xpl-space-16` — content panel padding (Figma `padding/tight`; corrected from the legacy 24px during the Foundation migration — see `TECH_DEBT.md`)\n\n**Border**\n- `--xpl-border-small` — border width (1px)\n- `--xpl-border-radius-default` — content panel corner radius (8px)\n\n**Z-index**\n- `--xpl-z-index-100` — content panel stacking order\n- `--xpl-z-index-900` — arrow stacking order\n",
|
|
@@ -10371,8 +10766,8 @@
|
|
|
10371
10766
|
"references": {
|
|
10372
10767
|
"PopoverPosition": {
|
|
10373
10768
|
"location": "local",
|
|
10374
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
10375
|
-
"id": "src/components/
|
|
10769
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-popover/xpl-popover.tsx",
|
|
10770
|
+
"id": "src/components/xpl-popover/xpl-popover.tsx::PopoverPosition"
|
|
10376
10771
|
}
|
|
10377
10772
|
}
|
|
10378
10773
|
},
|
|
@@ -10463,6 +10858,10 @@
|
|
|
10463
10858
|
"listeners": [],
|
|
10464
10859
|
"styles": [],
|
|
10465
10860
|
"slots": [
|
|
10861
|
+
{
|
|
10862
|
+
"name": "",
|
|
10863
|
+
"docs": "The default slot"
|
|
10864
|
+
},
|
|
10466
10865
|
{
|
|
10467
10866
|
"name": "Inner Content",
|
|
10468
10867
|
"docs": "Content inside the popover"
|
|
@@ -10489,7 +10888,7 @@
|
|
|
10489
10888
|
}
|
|
10490
10889
|
},
|
|
10491
10890
|
{
|
|
10492
|
-
"filePath": "src/components/
|
|
10891
|
+
"filePath": "src/components/xpl-progress-bar/xpl-progress-bar.tsx",
|
|
10493
10892
|
"encapsulation": "none",
|
|
10494
10893
|
"tag": "xpl-progress-bar",
|
|
10495
10894
|
"readme": "# xpl-progress-bar\n\nThe `xpl-progress-bar` component displays the progress of an operation, such as file uploads, form completion, or loading states. It supports multiple visual variants including default, success, error, and indeterminate states, with optional label and helper text.\n\n## Usage\n\n### Basic progress bar\n\n```html\n<xpl-progress-bar label=\"Uploading...\" value=\"45\"></xpl-progress-bar>\n```\n\n### With helper text\n\n```html\n<xpl-progress-bar\n label=\"Uploading file...\"\n value=\"65\"\n helper-text=\"2.4 MB of 5 MB\">\n</xpl-progress-bar>\n```\n\n### Error state\n\n```html\n<xpl-progress-bar\n label=\"Upload failed\"\n value=\"30\"\n variant=\"error\"\n helper-text=\"Network error. Please check your connection.\">\n</xpl-progress-bar>\n```\n\n### Indeterminate loading\n\n```html\n<xpl-progress-bar label=\"Processing...\" variant=\"indeterminate\"></xpl-progress-bar>\n```\n\n### Small size\n\n```html\n<xpl-progress-bar value=\"60\" size=\"sm\"></xpl-progress-bar>\n```\n\n### Custom max value\n\n```html\n<xpl-progress-bar value=\"75\" max=\"150\" label=\"75 of 150 items\"></xpl-progress-bar>\n```\n\n## Variants\n\n| Variant | Description |\n|---------|-------------|\n| `default` | Standard progress bar with accent color fill. Shows a checkmark icon when value reaches max. |\n| `success` | Explicit success state with positive color. Shows a checkmark icon. |\n| `error` | Error state with negative color. Shows an error (x-mark) icon. Helper text is recommended for this state. |\n| `indeterminate` | Used when the progress duration is unknown. Displays an animated sliding bar instead of a fill percentage. |\n\n## Sizes\n\n- `lg` (default): 6px height\n- `sm`: 4px height\n\n## Icon Mapping\n\nThe component automatically renders status icons based on the variant or completion state:\n\n| State | xpl-icon name |\n|-------|---------------|\n| Complete (default variant when value equals max) | `circle-check-1` |\n| Success variant | `circle-check-1` |\n| Error variant | `circle-xmark-1` |\n\n## Design Tokens\n\nThe following Apollo Foundation tokens are used by this component:\n\n### Background Colors (Fill)\n- `--xpl-background-accent-default` - Default variant fill\n- `--xpl-background-accent-positive-bold` - Success/complete fill\n- `--xpl-background-accent-negative-bold` - Error fill\n- `--xpl-background-accent-neutral` - Track background\n\n### Icon Colors\n- `--xpl-icon-positive` - Success/complete icon\n- `--xpl-icon-negative` - Error icon\n\n### Text Colors\n- `--xpl-text-default` - Label text\n- `--xpl-text-subdued` - Helper text\n- `--xpl-text-negative` - Error helper text\n\n### Typography\n- `--xpl-font-size-callout` - Label font size\n- `--xpl-font-size-caption` - Helper text font size\n- `--xpl-font-weight-normal` - Label and helper font weight\n\n### Spacing & Sizing\n- `--xpl-space-8` - Gap between elements\n- `--xpl-size-025` (4px) - Small bar height\n- `--xpl-size-0375` (6px) - Large bar height\n- `--xpl-border-radius-full` - Bar border radius\n\n## Accessibility\n\n- **Determinate variants** (default, success, error) use the native HTML `<progress>` element, which provides:\n - Native `role=\"progressbar\"` semantics\n - Automatic `aria-valuenow`, `aria-valuemin`, `aria-valuemax` handling\n - Native value/max API with built-in clamping\n- **Indeterminate variant** uses a custom `<div role=\"progressbar\">` since native `<progress>` indeterminate state cannot be styled cross-browser\n- The `aria-label` is set from the `label` prop, or falls back to `'Progress'` when no label is provided\n",
|
|
@@ -10701,7 +11100,7 @@
|
|
|
10701
11100
|
}
|
|
10702
11101
|
},
|
|
10703
11102
|
{
|
|
10704
|
-
"filePath": "src/components/
|
|
11103
|
+
"filePath": "src/components/xpl-progress-indicator/xpl-progress-indicator.tsx",
|
|
10705
11104
|
"encapsulation": "none",
|
|
10706
11105
|
"tag": "xpl-progress-indicator",
|
|
10707
11106
|
"readme": "# xpl-progress-indicator\n\nA progress indicator that guides users through linear, multi-step tasks by displaying completed, current, and future steps. Progress indicators help manage user expectations by showing their position in a multi-step process, the total number of steps, and overall progress toward task completion.\n\n## Usage\n\n```html\n<!-- Basic horizontal progress with numbered steps -->\n<xpl-progress-indicator steps='[\"Details\", \"Location\", \"Review\"]' current-step=\"1\"></xpl-progress-indicator>\n\n<!-- Vertical layout for side navigation -->\n<xpl-progress-indicator steps='[\"Step 1\", \"Step 2\", \"Step 3\"]' current-step=\"0\" layout=\"vertical\"></xpl-progress-indicator>\n\n<!-- Dots only (no numbers) with labels -->\n<xpl-progress-indicator steps='[\"Upload\", \"Process\", \"Complete\"]' current-step=\"1\" show-numbers=\"false\"></xpl-progress-indicator>\n\n<!-- Numbers only (no labels) -->\n<xpl-progress-indicator steps='[\"Step 1\", \"Step 2\", \"Step 3\"]' current-step=\"1\" show-labels=\"false\"></xpl-progress-indicator>\n\n<!-- Minimal dots only -->\n<xpl-progress-indicator steps='[\"Step 1\", \"Step 2\", \"Step 3\"]' current-step=\"1\" show-numbers=\"false\" show-labels=\"false\"></xpl-progress-indicator>\n```\n\n## Layouts\n\n### Horizontal (Default)\n\nThe horizontal layout displays steps in a row with a 16px gap between each step. Steps are connected by absolute-positioned lines that maintain consistent spacing from circle edges. Step labels appear below the circles and wrap naturally when the container narrows. This layout is ideal for page headers and top-level step navigation in desktop applications.\n\nThe layout is responsive: steps distribute equally via `flex: 1`, with a minimum width of 32px (the circle size) to prevent overlap. Labels wrap within their column using `overflow-wrap: break-word`. When the container becomes too narrow for all steps, the progress indicator will overflow horizontally rather than squashing elements together.\n\n```html\n<xpl-progress-indicator steps='[\"Details\", \"Location\", \"Instructor\", \"Review\"]' current-step=\"1\"></xpl-progress-indicator>\n```\n\n### Vertical\n\nThe vertical layout stacks steps vertically with connecting lines running downward. Labels appear to the right of each circle. This layout works well for side navigation panels and narrow spaces.\n\n```html\n<xpl-progress-indicator steps='[\"Step 1\", \"Step 2\", \"Step 3\"]' current-step=\"1\" layout=\"vertical\"></xpl-progress-indicator>\n```\n\n## Display Options\n\n### Step Numbers\n\nBy default, each step circle displays its index number (1, 2, 3, etc.). Set `show-numbers=\"false\"` to display dots instead of numbers for a more minimal appearance.\n\n| Option | Visual |\n|--------|--------|\n| `show-numbers=\"true\"` (default) | Numbered circles |\n| `show-numbers=\"false\"` | Dots for waiting/active, checkmark for finished |\n\n### Step Labels\n\nStep labels appear below (horizontal) or beside (vertical) each circle by default. Set `show-labels=\"false\"` to hide labels and show only the step indicators.\n\nIn horizontal mode, labels are constrained to the width of their step column and will wrap naturally using `overflow-wrap: break-word` when the container narrows. This prevents labels from colliding with neighboring steps.\n\n| Option | Horizontal | Vertical |\n|--------|------------|----------|\n| `show-labels=\"true\"` (default) | Labels below circles, wrap when narrow | Labels beside circles |\n| `show-labels=\"false\"` | Circles only | Circles only |\n\n## Step States\n\nEach step can be in one of three states, determined by comparing the step index to `current-step`:\n\n| State | Visual | Description |\n|-------|--------|-------------|\n| **Waiting** | Gray circle/dot | Steps after the current step |\n| **Active** | Purple bordered circle | The current step (`current-step` index) |\n| **Finished** | Filled purple circle with checkmark | Steps before the current step |\n\n## Icon Mapping\n\nThe progress component uses `xpl-icon` for the finished step indicator:\n\n| State | Icon Name |\n|-------|-----------|\n| Finished | `check-2` |\n\n## Design Tokens\n\nThe progress component uses the following Apollo Foundation tokens:\n\n### Horizontal Layout\n\n| Element | Property | Token/Value |\n|---------|----------|-------------|\n| Container | Min width | `0px` (fluid) |\n| | Width | `100%` |\n| | Padding horizontal | `--xpl-space-16` (16px) |\n| | Gap (between steps) | `--xpl-space-16` (16px) |\n| | Flex | `1` (equal width distribution) |\n| Step Circle | Width/Height | `--xpl-size-200` (32px) |\n| | Border | `--xpl-border-default` (waiting), `--xpl-border-focus` (active) |\n| | Border radius | `--xpl-border-radius-full` |\n| | Font size | `--xpl-font-size-title-5` |\n| | Font weight | `--xpl-font-weight-medium` |\n| Connector Line | Position | Absolute, from circle edge to edge |\n| | Height | `--xpl-size-0125` (2px) |\n| | Margins | `--xpl-space-4` (4px) from circle edges |\n| | Color (waiting) | `--xpl-border-default` |\n| | Color (finished) | `--xpl-background-action-primary-default` |\n| Step Label | Font size | `--xpl-font-size-title-5` |\n| | Color (waiting) | `--xpl-text-subdued` |\n| | Color (active) | `--xpl-text-default` |\n| | Layout | In normal flow, wraps at narrow widths |\n| | Max width | `100%` of step column |\n\n### Vertical Layout\n\n| Element | Property | Token/Value |\n|---------|----------|-------------|\n| Container | Min width | `--xpl-size-0` (0px) |\n| | Min height | `0px` (fluid) |\n| | Height | `100%` |\n| Connector Line | Width | `--xpl-size-0125` (2px) |\n| | Color (waiting) | `--xpl-border-default` |\n| | Color (finished) | `--xpl-background-action-primary-default` |\n| Step Label | Margin left | `--xpl-space-8` (8px) |\n\n### Step States\n\n| State | Circle Background | Circle Border | Circle Text |\n|-------|-------------------|---------------|-------------|\n| Waiting | Transparent | `--xpl-border-default` | `--xpl-text-subdued` |\n| Active | Transparent | `--xpl-border-focus` | `--xpl-text-link-default` |\n| Finished | `--xpl-background-action-primary-default` | `--xpl-border-accent-default` | `--xpl-text-inverse` |\n\n## Accessibility\n\n### ARIA structure\n\nThe host element uses `role=\"group\"` with a dynamic `aria-label` that announces the current position:\n\n| Condition | `aria-label` value |\n|-----------|-------------------|\n| Steps in progress | `\"Progress: step 2 of 5\"` |\n| All steps complete | `\"Progress: all 5 steps complete\"` |\n| No steps provided | `\"Progress\"` |\n\nSteps are wrapped in a container with `role=\"list\"`, and each step is a `role=\"listitem\"`. The active step receives `aria-current=\"step\"`; non-active steps do not carry `aria-current`.\n\n### Keyboard interaction\n\nThis component is a display-only progress indicator and does not require keyboard interaction. It is typically used alongside form navigation controls (e.g., Previous/Next buttons) that manage step changes.\n\n### Visual distinction\n\n- State changes use both color and shape differences (numbered circles, dots, and checkmark icons) to support colorblind users.\n- The `xpl-icon` component with icon `check-2` provides the finished-step checkmark at an accessible size (20px).\n\n## HTML/CSS Usage\n\nWhen building the progress component in plain HTML, use the following structure:\n\n```html\n<!-- Horizontal progress -->\n<div class=\"xpl-progress-indicator xpl-progress-indicator-horizontal\" role=\"group\" aria-label=\"Progress: step 2 of 3\">\n<div class=\"xpl-progress-indicator-container\" role=\"list\">\n <!-- Step 1: Finished -->\n<div class=\"xpl-progress-indicator-step xpl-progress-indicator-step-finished\" role=\"listitem\" aria-label=\"Details, completed\">\n<div class=\"xpl-progress-indicator-step-content\">\n<div class=\"xpl-progress-indicator-step-circle\">\n <xpl-icon icon=\"check-2\" size=\"20\"></xpl-icon>\n </div>\n<div class=\"xpl-progress-indicator-step-text\">Details</div>\n </div>\n </div>\n <!-- Step 2: Active -->\n<div class=\"xpl-progress-indicator-step xpl-progress-indicator-step-active\" role=\"listitem\" aria-label=\"Location, current\" aria-current=\"step\">\n<div class=\"xpl-progress-indicator-step-content\">\n<div class=\"xpl-progress-indicator-step-circle\">2</div>\n<div class=\"xpl-progress-indicator-step-text\">Location</div>\n </div>\n </div>\n <!-- Step 3: Waiting -->\n<div class=\"xpl-progress-indicator-step\" role=\"listitem\" aria-label=\"Review, upcoming\">\n<div class=\"xpl-progress-indicator-step-content\">\n<div class=\"xpl-progress-indicator-step-circle\">3</div>\n<div class=\"xpl-progress-indicator-step-text\">Review</div>\n </div>\n </div>\n </div>\n</div>\n\n<!-- Vertical progress -->\n<div class=\"xpl-progress-indicator xpl-progress-indicator-vertical\" role=\"group\" aria-label=\"Progress: step 2 of 3\">\n<div class=\"xpl-progress-indicator-container\" role=\"list\">\n <!-- Step 1: Finished -->\n<div class=\"xpl-progress-indicator-step xpl-progress-indicator-step-finished\" role=\"listitem\" aria-label=\"Step 1, completed\">\n<div class=\"xpl-progress-indicator-step-circle\">\n <xpl-icon icon=\"check-2\" size=\"20\"></xpl-icon>\n </div>\n<div class=\"xpl-progress-indicator-step-text\">Step 1</div>\n </div>\n <!-- ... additional steps ... -->\n </div>\n</div>\n```\n",
|
|
@@ -10876,12 +11275,16 @@
|
|
|
10876
11275
|
}
|
|
10877
11276
|
},
|
|
10878
11277
|
{
|
|
10879
|
-
"filePath": "src/components/
|
|
11278
|
+
"filePath": "src/components/xpl-radio/xpl-radio.tsx",
|
|
10880
11279
|
"encapsulation": "none",
|
|
10881
11280
|
"tag": "xpl-radio",
|
|
10882
11281
|
"readme": "# xpl-radio\n\nRadio buttons allow users to make selections or choices. Radios are always single select, and can also act as controls.\n\n## Design Tokens\n\nThe radio component uses the following Apollo Foundation tokens:\n\n| Token | Usage |\n|-------|-------|\n| `--xpl-background-surface-default` | Disabled checked state background; styled label background (resting/hover/focused) |\n| `--xpl-background-action-disabled` | Disabled state background; disabled label background (styled variant) |\n| `--xpl-background-surface-information` | Checked label background (styled variant) |\n| `--xpl-border-strong` | Resting (unchecked) border color |\n| `--xpl-border-hover` | Checked/hover/active border color; styled container hover/focus border |\n| `--xpl-border-default` | Disabled state border color |\n| `--xpl-border-focus` | Focus visible outline |\n| `--xpl-border-radius-small` | Styled container corner radius (4px) |\n| `--xpl-border-small` | Default border width (1px) |\n| `--xpl-size-100` | Radio dimensions (16px) |\n\n### Label tokens (shared `label.css`)\n\nThe radio label and description are styled by the shared `.xpl-label` / `.xpl-description` classes.\n\n| Token | Usage |\n|-------|-------|\n| `--xpl-text-strong` | Label text color (matches `.xpl-input-label`; resolves to white in dark mode) |\n| `--xpl-text-disabled` | Disabled label text color |\n| `--xpl-text-subdued` | Description text color (enabled and disabled) |\n| `.xpl-text-body` | Label typography: `--xpl-font-size-body` (14px) / normal / 1.4286 line-height |\n| `.xpl-text-callout` | Description typography: `--xpl-font-size-callout` (12px) / normal / 1.3333 line-height |\n",
|
|
10883
11282
|
"docs": "Radio buttons allow users to make selections or choices. Radios are always single select, and can also act as controls.",
|
|
10884
11283
|
"docsTags": [
|
|
11284
|
+
{
|
|
11285
|
+
"name": "slot",
|
|
11286
|
+
"text": "- The radio label content."
|
|
11287
|
+
},
|
|
10885
11288
|
{
|
|
10886
11289
|
"name": "since",
|
|
10887
11290
|
"text": "0.1.1"
|
|
@@ -11093,7 +11496,12 @@
|
|
|
11093
11496
|
],
|
|
11094
11497
|
"listeners": [],
|
|
11095
11498
|
"styles": [],
|
|
11096
|
-
"slots": [
|
|
11499
|
+
"slots": [
|
|
11500
|
+
{
|
|
11501
|
+
"name": "",
|
|
11502
|
+
"docs": "The radio label content."
|
|
11503
|
+
}
|
|
11504
|
+
],
|
|
11097
11505
|
"parts": [],
|
|
11098
11506
|
"states": [],
|
|
11099
11507
|
"dependents": [
|
|
@@ -11111,12 +11519,16 @@
|
|
|
11111
11519
|
}
|
|
11112
11520
|
},
|
|
11113
11521
|
{
|
|
11114
|
-
"filePath": "src/components/
|
|
11522
|
+
"filePath": "src/components/xpl-secondary-nav/xpl-secondary-nav.tsx",
|
|
11115
11523
|
"encapsulation": "none",
|
|
11116
11524
|
"tag": "xpl-secondary-nav",
|
|
11117
|
-
"readme": "# secondary-nav\n\nThe Secondary Nav component is a component that allows navigation within the content area. It yields one slot where a <ul> element with <xpl-nav-item> elements should be rendered.\n\n## Design Tokens\n\nThe secondary nav uses Apollo Foundation purpose-specific tokens, which theme automatically in light and dark mode (no `.dark` overrides).\n\n| Element / state | Property | Token |\n| --- | --- | --- |\n| `nav`, `ul`, host, item | `background` | `--xpl-background-surface-default` |\n| item (default) | `color` | `--xpl-text-subdued` |\n| item | `font-size` | `--xpl-font-size-body` (0.875rem / 14px) |\n| item | `font-weight` | `--xpl-font-weight-normal` (400) |\n| item hover | `color` | `--xpl-text-strong` |\n| item hover | `background` | `--xpl-background-surface-transparent-0` |\n| item active | `color` | `--xpl-text-strong` |\n| item active | `background` | `--xpl-background-brand-primary-surface` |\n| item active | accent `border-color` | `--xpl-border-accent-brand` |\n| item `:focus-visible` | `outline-color` | `--xpl-border-focus` |\n| item `:focus-visible` | `z-index` (above scroll fade) | `--xpl-z-index-200` |\n| item accent border | `border-width` (
|
|
11525
|
+
"readme": "# secondary-nav\n\nThe Secondary Nav component is a component that allows navigation within the content area. It yields one slot where a <ul> element with <xpl-nav-item> elements should be rendered.\n\n## Design Tokens\n\nThe secondary nav uses Apollo Foundation purpose-specific tokens, which theme automatically in light and dark mode (no `.dark` overrides).\n\n| Element / state | Property | Token |\n| --- | --- | --- |\n| `nav`, `ul`, host, item | `background` | `--xpl-background-surface-default` |\n| item (default) | `color` | `--xpl-text-subdued` |\n| item | `font-size` | `--xpl-font-size-body` (0.875rem / 14px) |\n| item | `font-weight` | `--xpl-font-weight-normal` (400) |\n| item hover | `color` | `--xpl-text-strong` |\n| item hover | `background` | `--xpl-background-surface-transparent-0` |\n| item active | `color` | `--xpl-text-strong` |\n| item active | `background` | `--xpl-background-brand-primary-surface` |\n| item active | accent `border-color` | `--xpl-border-accent-brand` |\n| item `:focus-visible` | `outline-color` | `--xpl-border-focus` |\n| item `:focus-visible` | `z-index` (above scroll fade) | `--xpl-z-index-200` |\n| item | `padding` | `--xpl-space-16` / `--xpl-space-24` |\n| item accent border (inactive) | `border-width` (0) | `--xpl-border-none` |\n| item accent border | `border-width` (4px) | `--xpl-border-xlarge` |\n| item (desktop) | `height` (48px) | `--xpl-size-300` |\n| scroll fade `nav::after` | `z-index` (below focused item) | `--xpl-z-index-100` |\n\nThe horizontal-scroll fade (`nav::after`, mobile only) fills a strip with `--xpl-background-surface-default` and fades it out with an alpha-only `mask-image`, so it blends into the themed nav background in both modes. It is `pointer-events: none` and sits at `--xpl-z-index-100`, below a keyboard-focused item (`--xpl-z-index-200`), so it never intercepts taps or hides an item's `:focus-visible` ring.\n\n**Known token gaps** (see [`TECH_DEBT.md`](../../../../../../TECH_DEBT.md)): the item `height` (52px) and desktop `width` (200px) have no matching Foundation size token; the scroll-fade gradient stops have no dedicated Foundation tokens.\n",
|
|
11118
11526
|
"docs": "The Secondary Nav component is a component that allows navigation within the content area. It yields one slot where a <ul> element with <xpl-nav-item> elements should be rendered.",
|
|
11119
11527
|
"docsTags": [
|
|
11528
|
+
{
|
|
11529
|
+
"name": "slot",
|
|
11530
|
+
"text": "- The navigation items."
|
|
11531
|
+
},
|
|
11120
11532
|
{
|
|
11121
11533
|
"name": "since",
|
|
11122
11534
|
"text": "0.3.0"
|
|
@@ -11128,7 +11540,12 @@
|
|
|
11128
11540
|
"events": [],
|
|
11129
11541
|
"listeners": [],
|
|
11130
11542
|
"styles": [],
|
|
11131
|
-
"slots": [
|
|
11543
|
+
"slots": [
|
|
11544
|
+
{
|
|
11545
|
+
"name": "",
|
|
11546
|
+
"docs": "The navigation items."
|
|
11547
|
+
}
|
|
11548
|
+
],
|
|
11132
11549
|
"parts": [],
|
|
11133
11550
|
"states": [],
|
|
11134
11551
|
"dependents": [],
|
|
@@ -11136,12 +11553,16 @@
|
|
|
11136
11553
|
"dependencyGraph": {}
|
|
11137
11554
|
},
|
|
11138
11555
|
{
|
|
11139
|
-
"filePath": "src/components/
|
|
11556
|
+
"filePath": "src/components/xpl-select/xpl-select.tsx",
|
|
11140
11557
|
"encapsulation": "none",
|
|
11141
11558
|
"tag": "xpl-select",
|
|
11142
11559
|
"readme": "# xpl-select\n\nSelect allows users to make a single selection or multiple selections from a list of options. Items can be a simple list, grouped, simple multi-select. User selections typically appear within the Select Box once created unless multiple selections are made, where truncation or another method of showing these selections is required.\n\n***When the list of options contains “Actions”, use a ***[Dropdown component](https://apollo.xplordocs.com/?path=/story/components-dropdown--simple).\n\nThe `selectIcon` property accepts icon names as strings. See [xpl-icon available icons](../xpl-icon/ICONS.md) for the complete list.\n\n---\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-icon-default` — chevron icon color\n- `--xpl-text-subdued` — trigger and placeholder value color (empty state)\n- `--xpl-text-default` — selected value color (`.has-value`)\n\nThe options panel surface, borders, and option states are styled by [xpl-dropdown](../xpl-dropdown) — see its Design Tokens section.\n\n**Note:** the trigger `height` (44px) and `.xpl-input-wrapper` `min-height` (46px) are kept as literals — no `--xpl-size` token matches (250 = 40px, 300 = 48px). See `TECH_DEBT.md`.\n",
|
|
11143
11560
|
"docs": "Select allows users to make a single selection or multiple selections from a list of options. Items can be a simple list, grouped, simple multi-select. User selections typically appear within the Select Box once created unless multiple selections are made, where truncation or another method of showing these selections is required.\n\n***When the list of options contains “Actions”, use a ***[Dropdown component](https://apollo.xplordocs.com/?path=/story/components-dropdown--simple).\n\nThe `selectIcon` property accepts icon names as strings. See [xpl-icon available icons](../xpl-icon/ICONS.md) for the complete list.\n\n---",
|
|
11144
11561
|
"docsTags": [
|
|
11562
|
+
{
|
|
11563
|
+
"name": "slot",
|
|
11564
|
+
"text": "custom-display-value - Custom content rendered as the selected-value display. Only rendered when the `customDisplayValue` prop is set."
|
|
11565
|
+
},
|
|
11145
11566
|
{
|
|
11146
11567
|
"name": "since",
|
|
11147
11568
|
"text": "0.4.0"
|
|
@@ -11159,7 +11580,7 @@
|
|
|
11159
11580
|
"DropdownItem": {
|
|
11160
11581
|
"location": "import",
|
|
11161
11582
|
"path": "../xpl-dropdown/dropdown-option",
|
|
11162
|
-
"id": "src/components/
|
|
11583
|
+
"id": "src/components/xpl-dropdown/dropdown-option.ts::DropdownItem",
|
|
11163
11584
|
"referenceLocation": "DropdownItem"
|
|
11164
11585
|
}
|
|
11165
11586
|
}
|
|
@@ -11700,7 +12121,12 @@
|
|
|
11700
12121
|
}
|
|
11701
12122
|
],
|
|
11702
12123
|
"styles": [],
|
|
11703
|
-
"slots": [
|
|
12124
|
+
"slots": [
|
|
12125
|
+
{
|
|
12126
|
+
"name": "custom-display-value",
|
|
12127
|
+
"docs": "Custom content rendered as the selected-value display. Only rendered when the `customDisplayValue` prop is set."
|
|
12128
|
+
}
|
|
12129
|
+
],
|
|
11704
12130
|
"parts": [],
|
|
11705
12131
|
"states": [],
|
|
11706
12132
|
"dependents": [
|
|
@@ -11742,7 +12168,7 @@
|
|
|
11742
12168
|
}
|
|
11743
12169
|
},
|
|
11744
12170
|
{
|
|
11745
|
-
"filePath": "src/components/
|
|
12171
|
+
"filePath": "src/components/xpl-side-nav/xpl-side-nav.tsx",
|
|
11746
12172
|
"encapsulation": "none",
|
|
11747
12173
|
"tag": "xpl-side-nav",
|
|
11748
12174
|
"readme": "# xpl-side-nav\n\nSlot-based sidebar for app navigation: a scrollable `nav-header` + `section` area and a fixed footer. Compose with [`xpl-side-nav-item`](./xpl-side-nav-item) for rows in the section and footer.\n\n## Slots\n\n| Slot | Description |\n| ---- | ----------- |\n| `nav-header` | Optional header row — place an [`xpl-side-nav-header-item`](./xpl-side-nav-header-item) inside. Hidden entirely (no wrapper, no border) when the slot is empty. |\n| `section` | Primary navigation. Place `xpl-side-nav-item` elements (or wrappers) inside this slot; layout uses internal section markup. |\n| `nav-footer` | Footer actions (e.g. Help, Logout). Same item component; typically smaller label styling via CSS. |\n\n## Usage\n\nUse the **`label`** prop for a unique accessible name on the `<nav>` when multiple landmarks exist on the page (see **Multi-Navigation Layouts** below).\n\n```html\n<xpl-side-nav label=\"Main navigation\">\n <div slot=\"nav-header\">\n <xpl-side-nav-header-item type=\"sub-account\" label=\"Acme Inc\" icon=\"office-3\"></xpl-side-nav-header-item>\n </div>\n <div slot=\"section\">\n <xpl-side-nav-item label=\"Dashboard\" icon=\"house-4\" selected></xpl-side-nav-item>\n <xpl-side-nav-item has-children label=\"Settings\" expanded>\n <xpl-side-nav-item label=\"Profile\"></xpl-side-nav-item>\n </xpl-side-nav-item>\n </div>\n <div slot=\"nav-footer\">\n <xpl-side-nav-item label=\"Help\" icon=\"headset\"></xpl-side-nav-item>\n </div>\n</xpl-side-nav>\n```\n\n**Link rows:** use `xpl-side-nav-item` with `link` when the row needs to be a real `<a>` element (framework router components, right-click / open-in-new-tab, semantic link role). For typical in-app navigation, the default button mode is simpler. See [xpl-side-nav-item](./xpl-side-nav-item) **Link mode** for usage and styling guidance.\n\n## Mobile behavior\n\nBelow the Tailwind `md` breakpoint (768px) the sidebar collapses to a ~56px top bar with a built-in toggle button (`sidebar-left-show` / `sidebar-left-hide`). Activating the toggle opens a drawer containing the `section` + `nav-footer` content over an [`xpl-backdrop`](../xpl-backdrop) scrim. Above `md` the toggle and backdrop are hidden and the sidebar renders inline — no markup changes are needed for either layout.\n\n**Keyboard / focus:**\n- **Escape** closes the drawer and returns focus to the toggle.\n- A **backdrop click** closes the drawer.\n- **Focus is trapped** inside the open drawer — Tab cycles only through the toggle and drawer rows.\n- The toggle exposes `aria-expanded` and a dynamic `aria-label` (\"Open/Close navigation menu\").\n\n**Row-level responsive scaling (applied automatically inside the drawer):**\n\n| Property | Desktop (≥ 768px) | Mobile (< 768px) |\n|---|---|---|\n| Tap target (`xpl-side-nav-item` wrapper) | — (inner button sized by content) | `min-height: 48px; padding: 6px 8px` |\n| Leading / trailing icon size | 16px | 24px |\n| Top-level label typography | `title-4` (16px, medium) | `title-3` (20px, medium) |\n| Child item label typography | `title-5` | `title-4` (16px, medium) |\n| Footer item label typography | `title-5` | `title-4` (16px, medium) |\n| Footer row min-height | `28px` | `--xpl-size-200` (32px) |\n| Footer leading / trailing icon | 16px | 20px |\n\nNo markup or props are needed for these changes — they are driven entirely by CSS.\n\n### Open state API\n\nThe `open` prop, `openChange` event, and `toggle()` / `setOpen()` methods control and observe the drawer. The component works **uncontrolled** (the built-in toggle flips `open`) or **controlled** (the consumer owns `open`).\n\n**Uncontrolled** — the built-in toggle manages everything; listen to `openChange` if you need to react:\n\n```html\n<xpl-side-nav label=\"Main navigation\" id=\"nav\">\n <div slot=\"section\">…</div>\n <div slot=\"nav-footer\">…</div>\n</xpl-side-nav>\n<script>\n document.getElementById('nav').addEventListener('openChange', (e) => {\n console.log('drawer open:', e.detail);\n });\n</script>\n```\n\n**Controlled** — own `open` and update it from `openChange` (and/or the imperative methods):\n\n```html\n<xpl-side-nav label=\"Main navigation\" id=\"nav\" open>…</xpl-side-nav>\n<script>\n const nav = document.getElementById('nav');\n // Keep your state in sync with user-driven changes (toggle, Escape, backdrop):\n nav.addEventListener('openChange', (e) => {\n nav.open = e.detail;\n });\n // Programmatic control:\n await nav.toggle();\n await nav.setOpen(false);\n</script>\n```\n\n> **v2 breaking change (beta):** the mobile toggle + drawer are now built in. Consumers who previously wrapped their own toggle around `xpl-side-nav` should remove it.\n\n### Implementation details (mobile drawer)\n\n- **Host class hooks** — when the drawer is open the host carries `xpl-side-nav--open` alongside `xpl-side-nav`. Useful for app-level CSS that needs to react (e.g. lock body scroll).\n- **Drawer transition** — `transform` + `opacity` + `visibility` over **300 ms** with `ease-out`. Closed state is `translateX(-100%)` + `opacity: 0` + `visibility: hidden`; the `visibility` flip is delayed 300 ms on close so the slide is visible.\n- **Backdrop transition** — `opacity` + `visibility` over **500 ms** with `ease-in-out`. Open state uses `opacity-50` (matches the native `xpl-backdrop` value, not full opaque). Visibility delayed 500 ms on close. `pointer-events: none` applies immediately on close so page content is tappable while the scrim fades out.\n- **Drawer geometry** — width `80vw` with a `min-width: 300px` floor (Figma spec; no Foundation token yet — see `TECH_DEBT.md`). The remaining `20vw` shows the backdrop scrim.\n- **Toggle styling overrides** — the built-in `xpl-button` toggle uses `padding-inline: var(--xpl-space-12)` on its inner `<button>` and renders its icon at `var(--xpl-size-200)` (32 px) so the icon's left edge aligns with the drawer's nav-item icon column.\n\n### Multi-Navigation Layouts (Accessibility)\n\nWhen multiple navigation landmarks exist on a page (e.g., side nav, top nav, breadcrumbs), use the `label` prop to provide a unique accessible name for each `<nav>` element. This helps screen reader users distinguish between them.\n\n```html\n<!-- Main side navigation -->\n<xpl-side-nav label=\"Main navigation\">\n ...\n</xpl-side-nav>\n\n<!-- Top navigation (different component) -->\n<xpl-top-nav label=\"User menu\">\n ...\n</xpl-top-nav>\n\n<!-- Breadcrumbs (different component) -->\n<xpl-breadcrumbs label=\"Breadcrumb\">\n ...\n</xpl-breadcrumbs>\n```\n\n**WCAG Note:** When a page has multiple `<nav>` landmarks, each should have a unique accessible name via `aria-label`.\n\n## Related components\n\n- [xpl-side-nav-item](./xpl-side-nav-item) — Navigation rows for section and footer: leaf button, expandable parent, or link (real `<a>`) mode.\n",
|
|
@@ -11928,7 +12354,7 @@
|
|
|
11928
12354
|
}
|
|
11929
12355
|
},
|
|
11930
12356
|
{
|
|
11931
|
-
"filePath": "src/components/
|
|
12357
|
+
"filePath": "src/components/xpl-side-nav/xpl-side-nav-header-item/xpl-side-nav-header-item.tsx",
|
|
11932
12358
|
"encapsulation": "none",
|
|
11933
12359
|
"tag": "xpl-side-nav-header-item",
|
|
11934
12360
|
"readme": "# xpl-side-nav-header-item\n\nHeader row sub-component for [`xpl-side-nav`](../xpl-side-nav)'s `slot=\"nav-header\"` (Figma navHeaderItem, node `51299-9007`).\n\n## Usage\n\n### Product label (static)\n\n```html\n<xpl-side-nav-header-item type=\"product-label\" label=\"My Product\"></xpl-side-nav-header-item>\n```\n\n### Sub account (interactive)\n\n```html\n<xpl-side-nav-header-item\n type=\"sub-account\"\n label=\"Acme Inc\"\n icon=\"pin\"\n></xpl-side-nav-header-item>\n<script>\n document\n .querySelector('xpl-side-nav-header-item[type=\"sub-account\"]')\n .addEventListener('navigate', () => {\n // open a location / account switcher, e.g. a modal\n });\n</script>\n```\n\n### Selected sub account\n\n```html\n<xpl-side-nav-header-item\n type=\"sub-account\"\n label=\"Acme Inc\"\n selected\n></xpl-side-nav-header-item>\n```\n\n### Custom trailing icon (replaces the auto chevron)\n\n```html\n<xpl-side-nav-header-item type=\"sub-account\" label=\"Xplor Growth\">\n <xpl-icon slot=\"trailing\" icon=\"external-link\" size=\"16\" aria-hidden=\"true\"></xpl-icon>\n</xpl-side-nav-header-item>\n```\n\n## Rules\n\n| Topic | Behavior |\n|---|---|\n| **Leading / trailing columns** | Unlike `xpl-side-nav-item`, these are **not** unconditionally reserved — they only render when there is an `icon` prop or slotted content, matching the Figma variants where the leading icon is an optional toggle. |\n| **Auto chevron** | `sub-account` auto-renders `chevron-expand-y` (a static dual-arrow glyph) in the trailing column when no `slot=\"trailing\"` content is provided. It does not rotate. |\n| **`selected`** | Only meaningful on `sub-account` — wraps the label + trailing chevron in an information-surface pill. Ignored on `product-label`. |\n| **Selected + leading icon** | Figma's selected variant absolute-positions the leading icon over the pill's edge (an auto-layout artifact, not a deliberate detail). This component keeps the leading icon in normal flow outside the pill for a simpler, more maintainable DOM structure. |\n\n## Accessibility\n\n- `product-label` renders a plain, non-interactive `<div>` — no button semantics, since there is nothing to activate.\n- `sub-account` renders a real `<button type=\"button\">`, so Enter/Space activation and focus are native. Activation emits the `navigate` event (pointer or keyboard).\n- **Selected state** — a selected `sub-account` exposes `aria-current=\"true\"` on the button so assistive tech announces which sub-account is active (the pill is a visual-only cue). `'true'` is used rather than `'page'` because a sub-account switcher is not a page.\n- **Accessible name** — the `label` supplies the button's accessible name, so a `label` is strongly recommended for `sub-account`. When `label` is omitted (icon-only), the leading icon is decorative and the auto chevron is `aria-hidden`, so the component falls back to `aria-label=\"Sub-account\"` to guarantee the button is never unnamed. Provide a meaningful `label` for a better experience.\n- The decorative auto chevron carries `aria-hidden=\"true\"`; a custom `slot=\"trailing\"` icon is left to the consumer to label appropriately.\n\n## Token reference\n\n| Token | Usage |\n|---|---|\n| `--xpl-text-subdued` | `product-label` label color |\n| `--xpl-text-strong` | `sub-account` label color |\n| `--xpl-icon-default` | Leading / non-auto trailing icon color |\n| `--xpl-icon-subtle` | Auto chevron color |\n| `--xpl-background-surface-information` | Selected pill background |\n| `--xpl-background-surface-transparent-10` | `sub-account` hover background |\n| `--xpl-border-focus` | Focus outline color |\n| `--xpl-space-4` / `--xpl-space-8` / `--xpl-space-16` | Row / pill padding and gap |\n| `--xpl-size-100` / `--xpl-size-150` | Leading/trailing icon box: 16px desktop, 24px mobile |\n| `--xpl-size-200` | Row `min-height` (32px) |\n\n## Related\n\n- [xpl-side-nav](../xpl-side-nav) — Sidebar container.\n- [xpl-side-nav-item](../xpl-side-nav-item) — Navigation row (shares the leading/trailing slot + icon-prop convention).\n",
|
|
@@ -12097,12 +12523,25 @@
|
|
|
12097
12523
|
}
|
|
12098
12524
|
},
|
|
12099
12525
|
{
|
|
12100
|
-
"filePath": "src/components/
|
|
12526
|
+
"filePath": "src/components/xpl-side-nav/xpl-side-nav-item/xpl-side-nav-item.tsx",
|
|
12101
12527
|
"encapsulation": "none",
|
|
12102
12528
|
"tag": "xpl-side-nav-item",
|
|
12103
12529
|
"readme": "# xpl-side-nav-item\n\nRow for [`xpl-side-nav`](../xpl-side-nav): place items in `slot=\"section\"` or `slot=\"nav-footer\"`. Supports **leaf** (button), **expandable** (`has-children`), and **link** (slot-only) modes, plus `selected`, `disabled`, and `hidden`.\n\n## Changes in v2 (breaking)\n\n`xpl-side-nav` is in **beta**. v2 makes the following breaking changes — no compat shims are provided.\n\n### Migration table\n\n| API | v1 (before) | v2 (after) | Action required |\n|---|---|---|---|\n| Leading icon slot | `slot=\"icon\"` | `slot=\"leading\"` | Rename the `slot` attribute on slotted icon elements |\n| Parent leading icon | Not rendered (chevron only) | Rendered alongside the trailing chevron | Pass `icon` prop or `slot=\"leading\"` content to parent rows |\n| Trailing slot | Not available | `slot=\"trailing\"` | Add to leaf items for custom trailing content |\n| Chevron position | Leading (left side) | Trailing (right side), auto-rendered for parents | No action needed for auto chevron; remove manual chevron markup if any |\n| Chevron override | Not possible | `slot=\"trailing\"` content replaces auto chevron on parents | Pass `slot=\"trailing\"` to customize the trailing column on a parent |\n| Leaf click event | `navClick` event | `navigate` event | Rename listeners: `navClick` → `navigate` (React `onNavClick` → `onNavigate`) |\n\n### Before / after examples\n\n**Leading icon slot rename:**\n```html\n<!-- v1 -->\n<xpl-side-nav-item label=\"Dashboard\">\n <xpl-icon slot=\"icon\" icon=\"house-4\" size=\"16\"></xpl-icon>\n</xpl-side-nav-item>\n\n<!-- v2 -->\n<xpl-side-nav-item label=\"Dashboard\">\n <xpl-icon slot=\"leading\" icon=\"house-4\" size=\"16\"></xpl-icon>\n</xpl-side-nav-item>\n<!-- or use the icon prop shorthand -->\n<xpl-side-nav-item label=\"Dashboard\" icon=\"house-4\"></xpl-side-nav-item>\n```\n\n**Parent rows now show leading icon + chevron:**\n```html\n<!-- v1: icon prop was ignored on parents -->\n<xpl-side-nav-item has-children label=\"Settings\" icon=\"gear\">...</xpl-side-nav-item>\n\n<!-- v2: icon prop renders in the leading slot; chevron auto-renders in trailing -->\n<xpl-side-nav-item has-children label=\"Settings\" icon=\"gear\">...</xpl-side-nav-item>\n```\n\n**Adding a trailing icon to a leaf item:**\n```html\n<!-- v2: slot=\"trailing\" for custom trailing content -->\n<xpl-side-nav-item label=\"Xplor Growth\" icon=\"chart-line-up\">\n <xpl-icon slot=\"trailing\" icon=\"external-link\" size=\"16\" aria-hidden=\"true\"></xpl-icon>\n</xpl-side-nav-item>\n```\n\n**Leaf click event rename:**\n```js\n// v1\nitem.addEventListener('navClick', handler);\n// v2\nitem.addEventListener('navigate', handler);\n```\nIn React the prop changes from `onNavClick` to `onNavigate`.\n\n---\n\n## Modes\n\n- **Leaf (default)** — Button with optional `label`, `icon` prop / `slot=\"leading\"`, and `slot=\"trailing\"`. Activation (click or keyboard) emits **`navigate`**.\n- **Expandable (`has-children`)** — Put nested `xpl-side-nav-item` elements in the **default slot**. Row renders **leading icon** (from `icon` prop or `slot=\"leading\"`) **+ label + auto chevron** in the trailing position (**`chevron-down`** when collapsed, **`chevron-up`** when expanded). The chevron is replaced if `slot=\"trailing\"` content is provided. Click toggles **`expanded`** and emits **`expandedChange`**.\n- **Link (`link`)** — **Default slot only**: renders a bare `<slot>` with no inner button. Use when the row must be a real `<a>` element — for framework router components, browser right-click / open-in-new-tab behaviour, or when semantic link vs. button distinction matters for screen readers. For typical in-app navigation the default button mode is simpler. The `label` and `icon` props are ignored in link mode; supply all content in your slotted anchor. **Cannot** be combined with `has-children`.\n\n## Rules\n\n| Topic | Behavior |\n|---|---|\n| **`link` vs `has-children`** | Mutually exclusive. When **`link`** is true, **`hasChildren`** is always false; if both attributes appear in markup, `has-children` is cleared. |\n| **Leading icon** | `icon` prop / `slot=\"leading\"` apply to all item types including parents. Nested sub-items (inside a parent) have the leading column hidden in CSS — use label only. |\n| **Trailing chevron** | Auto-rendered for `has-children` items when `slot=\"trailing\"` is empty. Providing `slot=\"trailing\"` content replaces the auto chevron. |\n| **Events** | **`navigate`** — leaf button rows (pointer or keyboard activation). **`expandedChange`** — expandable rows only (detail = new `expanded` boolean). |\n\n## Usage\n\n### Leaf (icon prop)\n```html\n<xpl-side-nav-item label=\"Dashboard\" icon=\"house-4\" selected></xpl-side-nav-item>\n```\n\n### Leaf (slot=\"leading\")\n```html\n<xpl-side-nav-item label=\"Dashboard\">\n <xpl-icon slot=\"leading\" icon=\"house-4\" size=\"16\"></xpl-icon>\n</xpl-side-nav-item>\n```\n\n### Leaf with trailing icon\n```html\n<xpl-side-nav-item label=\"Xplor Growth\" icon=\"chart-line-up\">\n <xpl-icon slot=\"trailing\" icon=\"external-link\" size=\"16\" aria-hidden=\"true\"></xpl-icon>\n</xpl-side-nav-item>\n```\n\n### Expandable parent (leading icon + auto chevron)\n```html\n<xpl-side-nav-item has-children label=\"Settings\" icon=\"gear\" expanded>\n <xpl-side-nav-item label=\"Profile\"></xpl-side-nav-item>\n <xpl-side-nav-item label=\"Billing\"></xpl-side-nav-item>\n</xpl-side-nav-item>\n```\n\n### Link (slot-only)\n\nWrap the anchor's children in the component CSS classes to match the icon color, label color, and spacing of button-mode items. Avoid whitespace text nodes between flex children — they render as a space character and add an unwanted gap.\n\n```html\n<xpl-side-nav-item link>\n <!-- No whitespace between __leading / __label spans and the closing </a> -->\n <a href=\"/reports\" class=\"xpl-side-nav-item__link\"><span class=\"xpl-side-nav-item__leading\"><xpl-icon icon=\"chart-line\" size=\"16\"></xpl-icon></span><span class=\"xpl-side-nav-item__label\">Reports</span></a>\n</xpl-side-nav-item>\n```\n\n### Disabled and hidden\n```html\n<xpl-side-nav-item label=\"Disabled\" disabled></xpl-side-nav-item>\n<xpl-side-nav-item label=\"Hidden\" hidden></xpl-side-nav-item>\n```\n\n## Slots\n\n| Slot | Description |\n|---|---|\n| `leading` | Leading icon column. Default content is an `xpl-icon` from the `icon` prop. Override with slotted content. Applies to all item types including parents. Renamed from `icon` in v2. |\n| `trailing` | Trailing content (e.g. `xpl-icon icon=\"external-link\"`). On `has-children` items, the auto chevron is rendered here when this slot is empty (`chevron-down` collapsed, `chevron-up` expanded); slotted content replaces the chevron. |\n| *(default)* | **`has-children`:** nested `xpl-side-nav-item` children. **`link`:** one `<a>` (or router link component) containing all row content. Unused in leaf button mode. |\n\n## Link mode checklist\n\n- Do **not** use `label` or `icon` props — they are ignored in link mode. Put all text and icons inside your slotted anchor.\n- Use **`class=\"xpl-side-nav-item__link\"`** on the anchor, **`class=\"xpl-side-nav-item__leading\"`** on the icon wrapper, and **`class=\"xpl-side-nav-item__label\"`** on the text span for consistent icon color, label typography, hover, and focus styling.\n- **No whitespace between flex children** — ensure no newlines or spaces sit between `__leading`, `__label`, and the `</a>` tag. Whitespace between flex items renders as a space character and shifts the label to the right.\n- Set **`aria-current=\"page\"`** on the anchor (not the host) when the route is active.\n- For **disabled** links: set `disabled` on the host and `aria-disabled=\"true\"` + `tabindex=\"-1\"` on the anchor (see **Accessibility**).\n\n## Accessibility\n\n- **Selected (non-link):** `aria-current=\"page\"` on the `button` (leaf or expandable row).\n- **Selected (link):** set `aria-current=\"page\"` on your slotted anchor.\n- **Expandable:** `aria-expanded` on the parent `button` matches `expanded`.\n- **Trailing decorative icons:** add `aria-hidden=\"true\"` to trailing `xpl-icon` elements. If the trailing icon conveys meaning (e.g. external link), provide accessible labeling in the surrounding context.\n- **Disabled:** use the `disabled` prop on non-link rows; for link mode, coordinate host `disabled` with the anchor as above.\n- **Hidden:** `hidden` hides the row; it does not disable interaction by itself — use `disabled` when appropriate.\n\n## Mobile behavior (below `md` / 768px)\n\nInside the `xpl-side-nav` mobile drawer, items are automatically restyled by CSS — no props or markup changes needed.\n\n| Property | Desktop | Mobile |\n|---|---|---|\n| Outer wrapper tap target | — | `min-height: 48px; padding: 6px 8px` |\n| Inner button `min-height` | 32px | 0 (tap target comes from wrapper) |\n| Leading / trailing icon size | 16px (`--xpl-size-100`) | 24px (`--xpl-size-150`) |\n| Top-level label | `title-4` (16px, medium, lh 1.5) | `title-3` (20px, medium, lh 1.4) |\n| Child item label | `title-5` | `title-4` (16px, medium, lh 1.5) |\n| Footer item label | `title-5` | `title-4` (16px, medium, lh 1.5) |\n| Footer row min-height | `28px` (one step smaller than section rows) | `--xpl-size-200` (32px) |\n| Footer leading / trailing icon | 16px (`--xpl-size-100`) | 20px (`--xpl-size-125`) |\n| Child label alignment offset | `padding-left: var(--xpl-side-nav-child-indent)` (32px) | Same — child labels stay aligned with the parent label column on every viewport |\n\n**Link mode and mobile icons:** in button mode the component automatically adjusts the `xpl-icon` `size` prop to 24 below `md`. In link mode, where the consumer controls the anchor content, the CSS scales the `svg` element inside `__leading` / `__trailing` via a presentational-attribute override — no `size` prop change needed.\n\n## Token reference\n\n| Token | Usage |\n|---|---|\n| `--xpl-icon-default` | Leading and trailing icon color (default, hover, selected) |\n| `--xpl-icon-disabled` | Leading, trailing, and label color when disabled |\n| `--xpl-text-strong` | Label color |\n| `--xpl-text-disabled` | Label color when disabled |\n| `--xpl-background-brand-secondary-surface` | Selected row background |\n| `--xpl-background-surface-transparent-10` | Hover row background |\n| `--xpl-border-focus` | Focus outline color |\n| `--xpl-space-8` | `margin-right` on the leading icon box (spacing between icon and label); `margin-left` on the trailing box |\n| `--xpl-size-100` | Leading / trailing icon box: 16px on desktop |\n| `--xpl-size-150` | Leading / trailing icon box on mobile (overrides `--xpl-size-100` below `md`) |\n| `--xpl-size-200` | `min-height` of the inner link / button (32px desktop) |\n| `--xpl-size-300` | `min-height` of the outer row wrapper on mobile (48px tap target) |\n\n## Related\n\n- [xpl-side-nav](../xpl-side-nav) — Sidebar container (`slot=\"section\"`, `slot=\"nav-footer\"`).\n",
|
|
12104
12530
|
"docs": "Navigation row for `xpl-side-nav`. Renders a button (default) or a slot-only\nanchor container (`link` mode). Three slot positions are available:\n\n- `slot=\"leading\"` — leading icon column (renamed from `slot=\"icon\"` in v2).\n The `icon` prop is a convenience shorthand that renders an `xpl-icon` here\n when no slotted `leading` content is present.\n- `slot=\"trailing\"` — trailing content (e.g. `xpl-icon icon=\"external-link\"`).\n When `has-children` is true and no `trailing` slot content is provided, an\n auto chevron is rendered automatically in this position: `chevron-down` when\n collapsed, `chevron-up` when expanded.\n- default slot — nested `xpl-side-nav-item` children (expandable parents only).\n\n**v2 breaking changes (beta):**\n- `slot=\"icon\"` renamed to `slot=\"leading\"` — no alias kept.\n- Parent rows (`has-children`) now render the leading icon alongside the chevron.\n Previously parents showed chevron + label only (no leading icon).\n- The chevron has moved from the leading position to the trailing position.\n- A slotted `slot=\"trailing\"` replaces the auto chevron on parent rows.\n\n**Migration:**\n| Before (v1) | After (v2) | Action |\n|---|---|---|\n| `slot=\"icon\"` | `slot=\"leading\"` | Rename the slot attribute |\n| Parent row: chevron only (no leading) | Parent row: leading icon + chevron | Pass `icon` prop or `slot=\"leading\"` |\n| (no trailing slot) | `slot=\"trailing\"` | Add for custom trailing content |",
|
|
12105
|
-
"docsTags": [
|
|
12531
|
+
"docsTags": [
|
|
12532
|
+
{
|
|
12533
|
+
"name": "slot",
|
|
12534
|
+
"text": "leading - Leading icon column. The `icon` prop renders an `xpl-icon` here when no slotted `leading` content is present."
|
|
12535
|
+
},
|
|
12536
|
+
{
|
|
12537
|
+
"name": "slot",
|
|
12538
|
+
"text": "trailing - Trailing content (e.g. `xpl-icon icon=\"external-link\"`). On parent rows (`has-children`), an auto chevron renders here when no `trailing` slot content is provided."
|
|
12539
|
+
},
|
|
12540
|
+
{
|
|
12541
|
+
"name": "slot",
|
|
12542
|
+
"text": "- Nested `xpl-side-nav-item` children (expandable parents only)."
|
|
12543
|
+
}
|
|
12544
|
+
],
|
|
12106
12545
|
"usage": {},
|
|
12107
12546
|
"props": [
|
|
12108
12547
|
{
|
|
@@ -12359,7 +12798,20 @@
|
|
|
12359
12798
|
],
|
|
12360
12799
|
"listeners": [],
|
|
12361
12800
|
"styles": [],
|
|
12362
|
-
"slots": [
|
|
12801
|
+
"slots": [
|
|
12802
|
+
{
|
|
12803
|
+
"name": "",
|
|
12804
|
+
"docs": "Nested `xpl-side-nav-item` children (expandable parents only)."
|
|
12805
|
+
},
|
|
12806
|
+
{
|
|
12807
|
+
"name": "leading",
|
|
12808
|
+
"docs": "Leading icon column. The `icon` prop renders an `xpl-icon` here when no slotted `leading` content is present."
|
|
12809
|
+
},
|
|
12810
|
+
{
|
|
12811
|
+
"name": "trailing",
|
|
12812
|
+
"docs": "Trailing content (e.g. `xpl-icon icon=\"external-link\"`). On parent rows (`has-children`), an auto chevron renders here when no `trailing` slot content is provided."
|
|
12813
|
+
}
|
|
12814
|
+
],
|
|
12363
12815
|
"parts": [],
|
|
12364
12816
|
"states": [],
|
|
12365
12817
|
"dependents": [],
|
|
@@ -12373,12 +12825,21 @@
|
|
|
12373
12825
|
}
|
|
12374
12826
|
},
|
|
12375
12827
|
{
|
|
12376
|
-
"filePath": "src/components/
|
|
12828
|
+
"filePath": "src/components/xpl-side-nav/xpl-side-nav-section/xpl-side-nav-section.tsx",
|
|
12377
12829
|
"encapsulation": "none",
|
|
12378
12830
|
"tag": "xpl-side-nav-section",
|
|
12379
12831
|
"readme": "# xpl-side-nav-section\n\nGrouping / accordion header for [`xpl-side-nav`](../xpl-side-nav). Wraps nested `xpl-side-nav-item` (and optional divider separators) elements in the default slot and collapses them as a unit.\n\n## Usage\n\n### Collapsible (default)\n\n```html\n<xpl-side-nav-section heading=\"Settings\">\n <xpl-side-nav-item label=\"Location\" icon=\"pin\"></xpl-side-nav-item>\n <xpl-side-nav-item label=\"Schedule\" icon=\"calendar\"></xpl-side-nav-item>\n</xpl-side-nav-section>\n```\n\n### Static (label only, `collapsible=false`)\n\n```html\n<xpl-side-nav-section heading=\"Product\" collapsible=\"false\">\n <xpl-side-nav-item label=\"Location\" icon=\"pin\"></xpl-side-nav-item>\n</xpl-side-nav-section>\n```\n\n### With a badge (`slot=\"badge\"`)\n\nCompose the existing `xpl-badge` — there is no `badge` boolean prop. The wrapper is suppressed automatically when the slot is empty.\n\n```html\n<xpl-side-nav-section heading=\"Updates\">\n <xpl-badge slot=\"badge\" variant=\"purple\" size=\"small\">4</xpl-badge>\n <xpl-side-nav-item label=\"Webhooks\"></xpl-side-nav-item>\n</xpl-side-nav-section>\n```\n\n## Rules\n\n| Topic | Behavior |\n|---|---|\n| **Child indent** | Unlike `xpl-side-nav-item[has-children]`, section children are **not indented** — they align with top-level items at the same leading-icon column, and keep their own leading icon. |\n| **Dividers** | Sections do **not** render their own dividers. Place an `<hr class=\"xpl-side-nav-divider\">` as a sibling (e.g. above and below a closed section) when a visual break is needed — no dedicated component. |\n| **Coordination** | Sections behave independently — there is no built-in single-open accordion coordination between sibling sections. |\n| **Chevron** | Auto-rendered for collapsible sections: `chevron-right` collapsed / `chevron-down` expanded (the glyph swaps, no rotation). Not rendered when `collapsible=\"false\"`. |\n\n## Accessibility\n\n- The collapsible header is a real `<button type=\"button\">` with `aria-expanded` (mirrors `expanded`) and `aria-controls` pointing to the children region's `id`.\n- The button's accessible name comes from the visible `heading` text or `slot=\"badge\"` content. It falls back to `aria-label=\"Toggle section\"` only when both are absent or whitespace-only; the chevron is `aria-hidden`.\n- The decorative chevron carries `aria-hidden=\"true\"` — the button's `aria-expanded` already conveys state.\n- Collapsed children are marked `inert`, removing them from the tab order (not just visually hidden) — same pattern as `xpl-side-nav-item[has-children]`.\n- The static variant (`collapsible=\"false\"`) renders a plain `<div>` header — no button semantics, since there is nothing to toggle.\n\n## Token reference\n\n| Token | Usage |\n|---|---|\n| `--xpl-text-subdued` | Title color |\n| `--xpl-icon-subtle` | Chevron color |\n| `--xpl-font-weight-bold` | Title font weight (extends `.xpl-text-callout` for size/line-height) |\n| `--xpl-space-8` | Title-row gap; horizontal header padding (desktop, reconciled against the parent section's own 8px padding) |\n| `--xpl-space-24` / `--xpl-space-4` | Header vertical padding (closed: 24/24; expanded or static: 24/4) |\n| `--xpl-size-100` / `--xpl-size-150` | Chevron box: 16px desktop, 24px mobile |\n| `--xpl-size-250` | Header `min-height` (40px) |\n| `--xpl-border-focus` | Focus outline color |\n\n## Related\n\n- [xpl-side-nav](../xpl-side-nav) — Sidebar container (`slot=\"section\"`, `slot=\"nav-footer\"`).\n- [xpl-side-nav-item](../xpl-side-nav-item) — Navigation row.\n- `<hr class=\"xpl-side-nav-divider\">` — Standalone separator (no dedicated component), often placed around a section.\n- [xpl-badge](../../xpl-badge) — Composed via `slot=\"badge\"`.\n",
|
|
12380
12832
|
"docs": "Grouping / accordion header for `xpl-side-nav`. Wraps nested `xpl-side-nav-item`\n(and optional divider separators) elements in the default slot and collapses\nthem as a unit.\n\nTwo variants:\n- **Collapsible (default, `collapsible=true`)** — a `<button>` header with a\n chevron (`chevron-right` collapsed / `chevron-down` expanded, no rotation —\n the glyph itself swaps). Click toggles `expanded` and emits `expandedChange`.\n- **Static (`collapsible=false`)** — a non-interactive title row with no chevron;\n children are always shown. Used for a static section label (e.g. a future\n product-name / location-changer header).\n\nUnlike `xpl-side-nav-item[has-children]`, section children are **not indented**\n— they align with top-level items at the same leading-icon column.\n\n`slot=\"badge\"` renders an optional badge (e.g. `xpl-badge`) in the header title\nrow. The wrapper is suppressed when the slot is empty.",
|
|
12381
|
-
"docsTags": [
|
|
12833
|
+
"docsTags": [
|
|
12834
|
+
{
|
|
12835
|
+
"name": "slot",
|
|
12836
|
+
"text": "- Section children (nested `xpl-side-nav-item` elements, optionally separated by dividers)."
|
|
12837
|
+
},
|
|
12838
|
+
{
|
|
12839
|
+
"name": "slot",
|
|
12840
|
+
"text": "badge - Optional badge (e.g. `xpl-badge`) rendered in the header title row. The wrapper is suppressed when the slot is empty."
|
|
12841
|
+
}
|
|
12842
|
+
],
|
|
12382
12843
|
"usage": {},
|
|
12383
12844
|
"props": [
|
|
12384
12845
|
{
|
|
@@ -12482,7 +12943,16 @@
|
|
|
12482
12943
|
],
|
|
12483
12944
|
"listeners": [],
|
|
12484
12945
|
"styles": [],
|
|
12485
|
-
"slots": [
|
|
12946
|
+
"slots": [
|
|
12947
|
+
{
|
|
12948
|
+
"name": "",
|
|
12949
|
+
"docs": "Section children (nested `xpl-side-nav-item` elements, optionally separated by dividers)."
|
|
12950
|
+
},
|
|
12951
|
+
{
|
|
12952
|
+
"name": "badge",
|
|
12953
|
+
"docs": "Optional badge (e.g. `xpl-badge`) rendered in the header title row. The wrapper is suppressed when the slot is empty."
|
|
12954
|
+
}
|
|
12955
|
+
],
|
|
12486
12956
|
"parts": [],
|
|
12487
12957
|
"states": [],
|
|
12488
12958
|
"dependents": [],
|
|
@@ -12496,7 +12966,7 @@
|
|
|
12496
12966
|
}
|
|
12497
12967
|
},
|
|
12498
12968
|
{
|
|
12499
|
-
"filePath": "src/components/
|
|
12969
|
+
"filePath": "src/components/xpl-skeleton/xpl-skeleton.tsx",
|
|
12500
12970
|
"encapsulation": "none",
|
|
12501
12971
|
"tag": "xpl-skeleton",
|
|
12502
12972
|
"readme": "# xpl-skeleton\n\nSkeleton components are progress indicators used for full page loading states that reduce the perception of long loading times and provide both reassurance to the user as well as clues for how the page will ultimately look. \n\nIncludes:\nComponents - Text, Shape, Data\nVariants - Text: Display, Title, Body Shape: rectangle, pill, circle, square\nProperties - Text/Body: show 1, 2 or 3 lines\n\n**Note: The “shimmer” effect uses Tailwind’s `animated-pulse` for the duration skeletons are present. The [animated pulse](https://tailwindcss.com/docs/animation#adding-a-pulse-animation) animates the color between our `color-background-surface-transparent-10` and `color-background-surface-transparent-5` variables. \n\n",
|
|
@@ -12748,12 +13218,40 @@
|
|
|
12748
13218
|
"dependencyGraph": {}
|
|
12749
13219
|
},
|
|
12750
13220
|
{
|
|
12751
|
-
"filePath": "src/components/
|
|
13221
|
+
"filePath": "src/components/xpl-slideout/xpl-slideout.tsx",
|
|
12752
13222
|
"encapsulation": "none",
|
|
12753
13223
|
"tag": "xpl-slideout",
|
|
12754
13224
|
"readme": "# xpl-slideout\n\nContent and Footer subcomponents are optional and can be hidden. Slideout always has a header with an X close button upper right. Slide Out Panel OPTIONALLY uses the [<xpl-backdrop>](https://apollo.xplordocs.com/?path=/story/components-backdrop--backdrop) component to overlay content and create focus on the Slide Out Panel content.\n\n## Token Use\n\n`xpl-slideout` uses Apollo Foundation purpose-specific tokens; light and dark mode are handled by the token definitions, so the component has no `.dark` overrides.\n\n| Element | Property | Token |\n| ------- | -------- | ----- |\n| `.slideout` | background | `--xpl-background-surface-default` |\n| `.slideout` | shadow color | `--xpl-color-transparent-neutral-10` / `--xpl-color-transparent-neutral-5` |\n| `.title` | color | `--xpl-text-default` |\n| `.title` | typography (size / weight / line-height) | `@extend .xpl-text-title-3` → `title-3` / `bold` / `1.4` |\n| `.subtitle` | color | `--xpl-text-subdued` |\n| `.subtitle` | typography (size / weight / line-height) | `@extend .xpl-text-body` → `body` / `normal` / `1.4286` |\n| `.content` | text color | `--xpl-text-default` |\n| `.content.has-shadow` | scroll-overflow shadow (top/bottom only) | `--xpl-color-transparent-neutral-10` / `--xpl-color-transparent-neutral-5` |\n| search `.xpl-input-wrapper` | background | `--xpl-background-surface-default` |\n| search `input` | color | `--xpl-text-default` |\n\nPanel widths are documented CSS literals: `min-width: 21.5rem`, `max-width: 37.5rem` (see `slideout.css` and `TECH_DEBT.md`).\n\nThe `.content.has-shadow` shadow is a scroll affordance applied only to the top and bottom edges (per Figma node 52462-9896) to signal that content is hidden behind the header/footer when it overflows.\n\n> **Elevation shadow (documented deviation):** the panel shadow is a custom single-edge shadow cast left onto the page content (`-10px 0 15px -3px`, `4px 0 6px -2px` over `--xpl-color-transparent-neutral-10 / -5`). Figma specs a leading-edge-only shadow for this right-anchored panel; the shared `--xpl-elevation-*` tokens are vertical (bottom-cast) and do not fit a side-anchored panel, so the hand-authored geometry is kept — see `TECH_DEBT.md`.\n",
|
|
12755
13225
|
"docs": "Content and Footer subcomponents are optional and can be hidden. Slideout always has a header with an X close button upper right. Slide Out Panel OPTIONALLY uses the [<xpl-backdrop>](https://apollo.xplordocs.com/?path=/story/components-backdrop--backdrop) component to overlay content and create focus on the Slide Out Panel content.",
|
|
12756
13226
|
"docsTags": [
|
|
13227
|
+
{
|
|
13228
|
+
"name": "slot",
|
|
13229
|
+
"text": "title - The slideout header title."
|
|
13230
|
+
},
|
|
13231
|
+
{
|
|
13232
|
+
"name": "slot",
|
|
13233
|
+
"text": "subtitle - Subtitle content rendered below the title."
|
|
13234
|
+
},
|
|
13235
|
+
{
|
|
13236
|
+
"name": "slot",
|
|
13237
|
+
"text": "search - Search content rendered in the header."
|
|
13238
|
+
},
|
|
13239
|
+
{
|
|
13240
|
+
"name": "slot",
|
|
13241
|
+
"text": "content - The main scrollable body content."
|
|
13242
|
+
},
|
|
13243
|
+
{
|
|
13244
|
+
"name": "slot",
|
|
13245
|
+
"text": "tertiary - The tertiary footer action. Rendered only when `showFooter` is set."
|
|
13246
|
+
},
|
|
13247
|
+
{
|
|
13248
|
+
"name": "slot",
|
|
13249
|
+
"text": "secondary - The secondary footer action. Rendered only when `showFooter` is set."
|
|
13250
|
+
},
|
|
13251
|
+
{
|
|
13252
|
+
"name": "slot",
|
|
13253
|
+
"text": "primary - The primary footer action. Rendered only when `showFooter` is set."
|
|
13254
|
+
},
|
|
12757
13255
|
{
|
|
12758
13256
|
"name": "since",
|
|
12759
13257
|
"text": "1.1.0"
|
|
@@ -12909,7 +13407,36 @@
|
|
|
12909
13407
|
}
|
|
12910
13408
|
],
|
|
12911
13409
|
"styles": [],
|
|
12912
|
-
"slots": [
|
|
13410
|
+
"slots": [
|
|
13411
|
+
{
|
|
13412
|
+
"name": "content",
|
|
13413
|
+
"docs": "The main scrollable body content."
|
|
13414
|
+
},
|
|
13415
|
+
{
|
|
13416
|
+
"name": "primary",
|
|
13417
|
+
"docs": "The primary footer action. Rendered only when `showFooter` is set."
|
|
13418
|
+
},
|
|
13419
|
+
{
|
|
13420
|
+
"name": "search",
|
|
13421
|
+
"docs": "Search content rendered in the header."
|
|
13422
|
+
},
|
|
13423
|
+
{
|
|
13424
|
+
"name": "secondary",
|
|
13425
|
+
"docs": "The secondary footer action. Rendered only when `showFooter` is set."
|
|
13426
|
+
},
|
|
13427
|
+
{
|
|
13428
|
+
"name": "subtitle",
|
|
13429
|
+
"docs": "Subtitle content rendered below the title."
|
|
13430
|
+
},
|
|
13431
|
+
{
|
|
13432
|
+
"name": "tertiary",
|
|
13433
|
+
"docs": "The tertiary footer action. Rendered only when `showFooter` is set."
|
|
13434
|
+
},
|
|
13435
|
+
{
|
|
13436
|
+
"name": "title",
|
|
13437
|
+
"docs": "The slideout header title."
|
|
13438
|
+
}
|
|
13439
|
+
],
|
|
12913
13440
|
"parts": [],
|
|
12914
13441
|
"states": [],
|
|
12915
13442
|
"dependents": [],
|
|
@@ -12932,10 +13459,10 @@
|
|
|
12932
13459
|
}
|
|
12933
13460
|
},
|
|
12934
13461
|
{
|
|
12935
|
-
"filePath": "src/components/
|
|
13462
|
+
"filePath": "src/components/xpl-spotlight/xpl-spotlight.tsx",
|
|
12936
13463
|
"encapsulation": "none",
|
|
12937
13464
|
"tag": "xpl-spotlight",
|
|
12938
|
-
"readme": "# xpl-spotlight\n\n`xpl-spotlight` renders a guided-tour callout with an anchor dot, optional media, step messaging, and prop-driven footer actions. It can either render inline using the requested `anchorPosition` or attach to a target element with Floating UI when `target` is provided.\n\n## Usage Examples\n\nUse the built-in title/body props and default actions for a simple tour step:\n\n```html\n<xpl-spotlight\n heading=\"Review recent activity\"\n body=\"Check status updates here before moving to the next step.\"\n action-layout=\"default\"\n anchor-position=\"top-right\"\n current-step=\"2\"\n total-steps=\"5\"\n is-dismissible=\"true\"\n is-open=\"true\"\n primary-action-label=\"Next\"\n secondary-action-label=\"Back\"\n show-actions=\"true\"\n show-image=\"true\"\n show-steps=\"true\"\n target=\"\"\n></xpl-spotlight>\n```\n\nAnchor the spotlight to a specific element and provide custom media content:\n\n```html\n<button id=\"dashboard-filter-button\" type=\"button\">Filters</button>\n\n<xpl-spotlight\n target=\"#dashboard-filter-button\"\n heading=\"Narrow the results\"\n body=\"Use filters to focus on the accounts or activity that matter most.\"\n current-step=\"1\"\n total-steps=\"3\"\n primary-action-label=\"Next\"\n secondary-action-label=\"Skip\"\n>\n <div slot=\"image\">\n <img src=\"/assets/spotlight-filter-preview.png\" alt=\"Preview of filter controls\" />\n </div>\n</xpl-spotlight>\n```\n\n\nControl visibility from the parent with `is-open` and close it by responding to `dismiss`:\n\n```html\n<xpl-spotlight\n id=\"guided-tour-step\"\n is-open=\"true\"\n heading=\"Review recent activity\"\n body=\"Check status updates here before moving to the next step.\"\n></xpl-spotlight>\n\n<script>\n const spotlight = document.getElementById('guided-tour-step');\n\n spotlight?.addEventListener('dismiss', () => {\n spotlight.setAttribute('is-open', 'false');\n });\n</script>\n```\n\nMirror the same layout in plain HTML when documenting or prototyping the component structure outside the custom element:\n\n```html\n<div class=\"xpl-spotlight xpl-spotlight--top-left xpl-spotlight--visible\"\n role=\"dialog\" aria-modal=\"false\" aria-labelledby=\"spotlight-title\" tabindex=\"-1\">\n <button type=\"button\" class=\"xpl-spotlight__target\" aria-label=\"Spotlight indicator\">\n <div class=\"xpl-spotlight__target-outer\"></div>\n <div class=\"xpl-spotlight__target-inner\"></div>\n </button>\n <div class=\"xpl-spotlight__dismiss\">\n <xpl-button variant=\"secondary\" size=\"sm\" icon-only aria-label=\"Dismiss tour step\">\n <xpl-icon icon=\"xmark\" size=\"16\"></xpl-icon>\n </xpl-button>\n </div>\n <div class=\"xpl-spotlight__frame\">\n <div class=\"xpl-spotlight__image-container\">\n <img src=\"/assets/spotlight-preview.png\" alt=\"Feature preview\" />\n </div>\n <div class=\"xpl-spotlight__content\">\n <div class=\"xpl-spotlight__header\">\n <span class=\"xpl-spotlight__title\" id=\"spotlight-title\">Tour Title</span>\n <p class=\"xpl-spotlight__body\">Copy about the feature and/or functionality the dot is pointing to.</p>\n </div>\n <div class=\"xpl-spotlight__actions xpl-spotlight__actions--dual xpl-spotlight__actions--with-steps\">\n <div class=\"xpl-spotlight__action-slot xpl-spotlight__action-slot--secondary\">\n <xpl-button variant=\"secondary\">Back</xpl-button>\n </div>\n <span class=\"xpl-spotlight__step-text\">2 of 5</span>\n <div class=\"xpl-spotlight__action-slot xpl-spotlight__action-slot--primary\">\n <xpl-button variant=\"primary\">Next</xpl-button>\n </div>\n </div>\n </div>\n </div>\n</div>\n```\n\n## Accessibility\n\n`xpl-spotlight` renders with `role=\"dialog\"` and `aria-modal=\"false\"` so assistive technologies treat it as a **non-modal** tour callout: focus is not trapped inside the card, and users can tab to the rest of the page while the step is open. The accessible name comes from the title region:\n\n- When the default title is used, the generated heading element receives the internal `aria-labelledby` id.\n- When a custom `title` slot is provided, the component assigns that same id to the first slotted title element if it does not already have one. If the slotted element already has an `id`, that value is kept and `aria-labelledby` references it (the host does not point at a missing id).\n- When neither a `heading` prop nor a `title` slot is provided, the dialog falls back to `aria-label=\"Tour step\"` so that assistive technologies always have an accessible name.\n\n### Keyboard navigation\n\n| Key | Behavior |\n|-----|----------|\n| `Tab` / `Shift+Tab` | Moves focus between interactive controls (dismiss button, secondary action, primary action). Focus is **not** trapped — users can tab out of the spotlight to the rest of the page. |\n| `Escape` | Emits `dismiss` when `isDismissible` is true and focus is inside the spotlight. Does nothing when focus is outside the component or the spotlight is closed. |\n| `Enter` / `Space` | Activates the focused button (dismiss, primary, or secondary action) via standard `xpl-button` behavior. |\n\n### Focus management\n\n- **On open:** focus moves automatically to the dismiss button (if `isDismissible` is true) or the first action button. When neither a dismiss button nor action buttons are rendered, the host element itself receives focus via `tabindex=\"-1\"`.\n- **On close:** focus returns to the element that was focused before the spotlight opened, provided that element is still in the DOM.\n- The decorative anchor dot (`.xpl-spotlight__target`) is marked `aria-hidden=\"true\"` so it is not announced or focusable.\n\n\n## Design Tokens\n\nThe component relies on Foundation purpose tokens in `spotlight.css` so light/dark mode works without component-level `.dark` overrides.\n\n| Property | Token |\n|----------|-------|\n| Card width | `var(--xpl-spotlight-width)` on the host (defined in `spotlight.css`; design-specific width until shared layout tokens exist — see `TECH_DEBT.md`) |\n| Image region min-height | `var(--xpl-spotlight-image-min-height)` on `.xpl-spotlight__image-container` (same note as card width) |\n| Card background | `var(--xpl-background-surface-default)` |\n| Card shadow | `var(--xpl-elevation-3)` (theme-aware elevation token) |\n| Host stacking | `var(--xpl-z-index-800)` |\n| Placeholder pattern | `var(--xpl-background-surface-subtle)` |\n| Heading text | `var(--xpl-text-default)` |\n| Body text | `var(--xpl-text-default)` |\n| Step text | `var(--xpl-text-subdued)` |\n| Open/closed visibility | `opacity` transition on `.xpl-spotlight--visible` |\n| Anchor outer ring | `var(--xpl-background-surface-information-bold)` |\n| Anchor inner dot | `var(--xpl-background-accent-default)` |\n| Image placeholder icon/text | `var(--xpl-icon-subtle)` |\n| Focus outline | `var(--xpl-border-focus)` |\n| Anchored host (when `target` is set) | `position: fixed` via `.xpl-spotlight--anchored`; `left` / `top` set from Floating UI (`strategy: 'fixed'`) |\n\n## Icon Mapping\n\n`xpl-spotlight` uses Apollo icons for fixed controls and fallback media placeholders:\n\n| UI area | `xpl-icon` name |\n|---------|------------------|\n| Dismiss button | `xmark` |\n| Empty image placeholder, image affordance | `photo` |\n| Empty image placeholder, video affordance | `video` |\n\n## Deprecated props\n\nNone.\n\n## Notes\n\n- `showImage=\"false\"` hides the media region even if `slot=\"image\"` content is present.\n- When `showImage` is left enabled and no `slot=\"image\"` content is provided, the component renders the built-in placeholder instead of collapsing the media region.\n- `showActions=\"false\"` removes the default actions row entirely.\n- `is-open=\"false\"` keeps the host element mounted but renders no spotlight UI until it is opened again.\n- `action-layout` defaults to `\"default\"`. `action-layout=\"default\"` renders the Back/Next pair with **disabled** edge buttons at step boundaries (Back disabled on step 1, Next disabled on the last step). `action-layout=\"dual\"` renders the Back/Next pair with **hidden** edge buttons at step boundaries. `action-layout=\"single\"` renders a single primary action.\n- `primary-action-label` and `secondary-action-label` control the default button text without needing action slots.\n- `target` enables Floating UI positioning with `offset`, `flip`, `shift`, and `autoUpdate` so the spotlight follows the referenced element on resize and scroll. Default offset and shift padding match Foundation spacing (`--xpl-space-12` / `--xpl-space-8`).\n- If `target` is missing or contains an invalid CSS selector, the component safely falls back to the requested `anchor-position` instead of throwing.\n- **Storybook:** open **Components → Spotlight** to adjust props via controls. Set `target` to `#spotlight-story-anchor` to preview Floating UI anchoring against the demo button on the canvas. The **Design** addon links to the Apollo Web Figma file (replace the `node-id` in Storybook with the Spotlight frame when Design publishes a dedicated link).\n",
|
|
13465
|
+
"readme": "# xpl-spotlight\n\n`xpl-spotlight` renders a guided-tour callout with an anchor dot, optional media, step messaging, and prop-driven footer actions. It can either render inline using the requested `anchorPosition` or attach to a target element with Floating UI when `target` is provided.\n\n## Usage Examples\n\nUse the built-in title/body props and default actions for a simple tour step:\n\n```html\n<xpl-spotlight\n heading=\"Review recent activity\"\n body=\"Check status updates here before moving to the next step.\"\n action-layout=\"default\"\n anchor-position=\"top-right\"\n current-step=\"2\"\n total-steps=\"5\"\n is-dismissible=\"true\"\n is-open=\"true\"\n primary-action-label=\"Next\"\n secondary-action-label=\"Back\"\n show-actions=\"true\"\n show-image=\"true\"\n show-steps=\"true\"\n target=\"\"\n></xpl-spotlight>\n```\n\nAnchor the spotlight to a specific element and provide custom media content:\n\n```html\n<button id=\"dashboard-filter-button\" type=\"button\">Filters</button>\n\n<xpl-spotlight\n target=\"#dashboard-filter-button\"\n heading=\"Narrow the results\"\n body=\"Use filters to focus on the accounts or activity that matter most.\"\n current-step=\"1\"\n total-steps=\"3\"\n primary-action-label=\"Next\"\n secondary-action-label=\"Skip\"\n>\n <div slot=\"image\">\n <img src=\"/assets/spotlight-filter-preview.png\" alt=\"Preview of filter controls\" />\n </div>\n</xpl-spotlight>\n```\n\n\nControl visibility from the parent with `is-open` and close it by responding to `dismiss`:\n\n```html\n<xpl-spotlight\n id=\"guided-tour-step\"\n is-open=\"true\"\n heading=\"Review recent activity\"\n body=\"Check status updates here before moving to the next step.\"\n></xpl-spotlight>\n\n<script>\n const spotlight = document.getElementById('guided-tour-step');\n\n spotlight?.addEventListener('dismiss', () => {\n spotlight.setAttribute('is-open', 'false');\n });\n</script>\n```\n\nMirror the same layout in plain HTML when documenting or prototyping the component structure outside the custom element:\n\n```html\n<div class=\"xpl-spotlight xpl-spotlight--top-left xpl-spotlight--visible\"\n role=\"dialog\" aria-modal=\"false\" aria-labelledby=\"spotlight-title\" tabindex=\"-1\">\n <button type=\"button\" class=\"xpl-spotlight__target\" aria-label=\"Spotlight indicator\">\n <div class=\"xpl-spotlight__target-outer\"></div>\n <div class=\"xpl-spotlight__target-inner\"></div>\n </button>\n <div class=\"xpl-spotlight__dismiss\">\n <xpl-button variant=\"secondary\" size=\"sm\" icon-only aria-label=\"Dismiss tour step\">\n <xpl-icon icon=\"xmark\" size=\"16\"></xpl-icon>\n </xpl-button>\n </div>\n <div class=\"xpl-spotlight__frame\">\n <div class=\"xpl-spotlight__image-container\">\n <img src=\"/assets/spotlight-preview.png\" alt=\"Feature preview\" />\n </div>\n <div class=\"xpl-spotlight__content\">\n <div class=\"xpl-spotlight__header\">\n <span class=\"xpl-spotlight__title\" id=\"spotlight-title\">Tour Title</span>\n <p class=\"xpl-spotlight__body\">Copy about the feature and/or functionality the dot is pointing to.</p>\n </div>\n <div class=\"xpl-spotlight__actions xpl-spotlight__actions--dual xpl-spotlight__actions--with-steps\">\n <div class=\"xpl-spotlight__action-slot xpl-spotlight__action-slot--secondary\">\n <xpl-button variant=\"secondary\">Back</xpl-button>\n </div>\n <span class=\"xpl-spotlight__step-text\">2 of 5</span>\n <div class=\"xpl-spotlight__action-slot xpl-spotlight__action-slot--primary\">\n <xpl-button variant=\"primary\">Next</xpl-button>\n </div>\n </div>\n </div>\n </div>\n</div>\n```\n\n## Accessibility\n\n`xpl-spotlight` renders with `role=\"dialog\"` and `aria-modal=\"false\"` so assistive technologies treat it as a **non-modal** tour callout: focus is not trapped inside the card, and users can tab to the rest of the page while the step is open. The accessible name comes from the title region:\n\n- When the default title is used, the generated heading element receives the internal `aria-labelledby` id.\n- When a custom `title` slot is provided, the component assigns that same id to the first slotted title element if it does not already have one. If the slotted element already has an `id`, that value is kept and `aria-labelledby` references it (the host does not point at a missing id).\n- When neither a `heading` prop nor a `title` slot is provided, the dialog falls back to `aria-label=\"Tour step\"` so that assistive technologies always have an accessible name.\n\n### Keyboard navigation\n\n| Key | Behavior |\n|-----|----------|\n| `Tab` / `Shift+Tab` | Moves focus between interactive controls (dismiss button, secondary action, primary action). Focus is **not** trapped — users can tab out of the spotlight to the rest of the page. |\n| `Escape` | Emits `dismiss` when `isDismissible` is true and focus is inside the spotlight. Does nothing when focus is outside the component or the spotlight is closed. |\n| `Enter` / `Space` | Activates the focused button (dismiss, primary, or secondary action) via standard `xpl-button` behavior. |\n\n### Focus management\n\n- **On open:** focus moves automatically to the dismiss button (if `isDismissible` is true) or the first action button. When neither a dismiss button nor action buttons are rendered, the host element itself receives focus via `tabindex=\"-1\"`.\n- **On close:** focus returns to the element that was focused before the spotlight opened, provided that element is still in the DOM.\n- The decorative anchor dot (`.xpl-spotlight__target`) is marked `aria-hidden=\"true\"` so it is not announced or focusable.\n\n\n## Design Tokens\n\nThe component relies on Foundation purpose tokens in `spotlight.css` so light/dark mode works without component-level `.dark` overrides.\n\n| Property | Token |\n|----------|-------|\n| Card width | `var(--xpl-spotlight-width)` on the host (defined in `spotlight.css`; design-specific width until shared layout tokens exist — see `TECH_DEBT.md`) |\n| Image region min-height | `var(--xpl-spotlight-image-min-height)` on `.xpl-spotlight__image-container` (same note as card width) |\n| Card background | `var(--xpl-background-surface-default)` |\n| Card shadow | `var(--xpl-elevation-3)` (theme-aware elevation token) |\n| Host stacking | `var(--xpl-z-index-800)` |\n| Placeholder pattern | `var(--xpl-background-surface-subtle)` |\n| Heading text | `var(--xpl-text-default)` |\n| Heading line-height | `var(--xpl-line-height-title-3)` (title-3) |\n| Body text | `var(--xpl-text-default)` |\n| Step text | `var(--xpl-text-subdued)` |\n| Open/closed visibility | `opacity` transition on `.xpl-spotlight--visible` |\n| Anchor outer ring | `var(--xpl-background-surface-information-bold)` |\n| Anchor inner dot | `var(--xpl-background-accent-default)` |\n| Image placeholder icon/text | `var(--xpl-icon-subtle)` |\n| Focus outline | `var(--xpl-border-focus)` |\n| Anchored host (when `target` is set) | `position: fixed` via `.xpl-spotlight--anchored`; `left` / `top` set from Floating UI (`strategy: 'fixed'`) |\n\n## Icon Mapping\n\n`xpl-spotlight` uses Apollo icons for fixed controls and fallback media placeholders:\n\n| UI area | `xpl-icon` name |\n|---------|------------------|\n| Dismiss button | `xmark` |\n| Empty image placeholder, image affordance | `photo` |\n| Empty image placeholder, video affordance | `video` |\n\n## Deprecated props\n\nNone.\n\n## Notes\n\n- `showImage=\"false\"` hides the media region even if `slot=\"image\"` content is present.\n- When `showImage` is left enabled and no `slot=\"image\"` content is provided, the component renders the built-in placeholder instead of collapsing the media region.\n- `showActions=\"false\"` removes the default actions row entirely.\n- `is-open=\"false\"` keeps the host element mounted but renders no spotlight UI until it is opened again.\n- `action-layout` defaults to `\"default\"`. `action-layout=\"default\"` renders the Back/Next pair with **disabled** edge buttons at step boundaries (Back disabled on step 1, Next disabled on the last step). `action-layout=\"dual\"` renders the Back/Next pair with **hidden** edge buttons at step boundaries. `action-layout=\"single\"` renders a single primary action.\n- `primary-action-label` and `secondary-action-label` control the default button text without needing action slots.\n- `target` enables Floating UI positioning with `offset`, `flip`, `shift`, and `autoUpdate` so the spotlight follows the referenced element on resize and scroll. Default offset and shift padding match Foundation spacing (`--xpl-space-12` / `--xpl-space-8`).\n- If `target` is missing or contains an invalid CSS selector, the component safely falls back to the requested `anchor-position` instead of throwing.\n- **Storybook:** open **Components → Spotlight** to adjust props via controls. Set `target` to `#spotlight-story-anchor` to preview Floating UI anchoring against the demo button on the canvas. The **Design** addon links to the Apollo Web Figma file (replace the `node-id` in Storybook with the Spotlight frame when Design publishes a dedicated link).\n",
|
|
12939
13466
|
"docs": "`xpl-spotlight` renders a guided-tour callout with an anchor dot, optional media, step messaging, and prop-driven footer actions. It can either render inline using the requested `anchorPosition` or attach to a target element with Floating UI when `target` is provided.",
|
|
12940
13467
|
"docsTags": [
|
|
12941
13468
|
{
|
|
@@ -12966,8 +13493,8 @@
|
|
|
12966
13493
|
"references": {
|
|
12967
13494
|
"SpotlightActionLayout": {
|
|
12968
13495
|
"location": "local",
|
|
12969
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
12970
|
-
"id": "src/components/
|
|
13496
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-spotlight/xpl-spotlight.tsx",
|
|
13497
|
+
"id": "src/components/xpl-spotlight/xpl-spotlight.tsx::SpotlightActionLayout"
|
|
12971
13498
|
}
|
|
12972
13499
|
}
|
|
12973
13500
|
},
|
|
@@ -13010,8 +13537,8 @@
|
|
|
13010
13537
|
"references": {
|
|
13011
13538
|
"SpotlightAnchorPosition": {
|
|
13012
13539
|
"location": "local",
|
|
13013
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
13014
|
-
"id": "src/components/
|
|
13540
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-spotlight/xpl-spotlight.tsx",
|
|
13541
|
+
"id": "src/components/xpl-spotlight/xpl-spotlight.tsx::SpotlightAnchorPosition"
|
|
13015
13542
|
}
|
|
13016
13543
|
}
|
|
13017
13544
|
},
|
|
@@ -13480,7 +14007,7 @@
|
|
|
13480
14007
|
}
|
|
13481
14008
|
},
|
|
13482
14009
|
{
|
|
13483
|
-
"filePath": "src/components/
|
|
14010
|
+
"filePath": "src/components/xpl-tab/xpl-tab.tsx",
|
|
13484
14011
|
"encapsulation": "none",
|
|
13485
14012
|
"tag": "xpl-tab",
|
|
13486
14013
|
"readme": "# xpl-tab\n\n`xpl-tab` is the **label / trigger** for one tab in an `xpl-tabs` group. Place each instance in the **`heading`** slot of `xpl-tabs`. The **`target`** string links this tab to the matching **`xpl-tab-panel`** (same `target` value). The parent sets **`selected`** and syncs **`value`**; you normally do not set `selected` by hand.\n\nUnderline tabs render a native **`<button role=\"tab\">`**; segment tabs render **`xpl-button`** with the same tab semantics on the inner control. For variant-specific examples, icon usage, and token tables, see the matching section on the **Tabs** or **Segment control** Storybook page.\n\n**`group-disabled`** is applied by `xpl-tabs` when the group has **`disabled`**; it keeps pills and underline buttons in a disabled state together with the parent.\n\n## Accessibility\n\n- **IDs and ARIA:** With a parent **`xpl-tabs`**, the tab control and matching **`xpl-tab-panel`** share scoped DOM ids derived from **`data-tabs-instance-id`** on the group and each pair’s **`target`** (see **`xpl-tabs`** accessibility notes). Underline tabs set **`id`**, **`role=\"tab\"`**, **`aria-controls`**, and **`aria-selected`** on the native `<button>`. Segment tabs wrap **`xpl-button`**, which forwards **`id`**, **`role`**, and **`aria-*`** attributes to its inner `<button>` so focus and **`aria-labelledby`** stay correct.\n- Underline tabs expose a **single focusable button** per tab.\n- Segment tabs delegate rendering to **`xpl-button`** with the same tab semantics as underline mode; activation follows the same **`tabChange`** event.\n- Disabled tabs are skipped when moving with arrow keys.\n",
|
|
@@ -13530,7 +14057,7 @@
|
|
|
13530
14057
|
"BadgePalette": {
|
|
13531
14058
|
"location": "import",
|
|
13532
14059
|
"path": "../xpl-badge/xpl-badge",
|
|
13533
|
-
"id": "src/components/
|
|
14060
|
+
"id": "src/components/xpl-badge/xpl-badge.tsx::BadgePalette",
|
|
13534
14061
|
"referenceLocation": "BadgePalette"
|
|
13535
14062
|
}
|
|
13536
14063
|
}
|
|
@@ -13794,7 +14321,7 @@
|
|
|
13794
14321
|
}
|
|
13795
14322
|
},
|
|
13796
14323
|
{
|
|
13797
|
-
"filePath": "src/components/
|
|
14324
|
+
"filePath": "src/components/xpl-tab-panel/xpl-tab-panel.tsx",
|
|
13798
14325
|
"encapsulation": "none",
|
|
13799
14326
|
"tag": "xpl-tab-panel",
|
|
13800
14327
|
"readme": "# xpl-tab-panel\n\n`xpl-tab-panel` is the **content region** for one tab. Place each panel in the **`panel`** slot of `xpl-tabs` and set **`target`** to the same string as its paired **`xpl-tab`**. Only the panel whose `target` matches the group’s selection is visible; others stay hidden via CSS until selected.\n\n## When to use\n\n- One panel per tab in the same `xpl-tabs` as the corresponding `xpl-tab`.\n- Put any markup or other components in the **default slot** (panel body).\n\n## Usage\n\n```html\n<xpl-tabs value=\"overview\">\n <xpl-tab slot=\"heading\" target=\"overview\">Overview</xpl-tab>\n <xpl-tab slot=\"heading\" target=\"activity\">Activity</xpl-tab>\n <xpl-tab-panel slot=\"panel\" target=\"overview\">\n <p class=\"xpl-text-body\">Overview content.</p>\n </xpl-tab-panel>\n <xpl-tab-panel slot=\"panel\" target=\"activity\">\n <p class=\"xpl-text-body\">Activity content.</p>\n </xpl-tab-panel>\n</xpl-tabs>\n```\n\nThe parent **`xpl-tabs`** updates each panel’s **`selected`** state from **`value`** / user interaction; consumers typically only set **`target`** and slot content.\n\n## Accessibility\n\n- The host sets **`role=\"tabpanel\"`**, a stable **`id`** (`…-panel-<target>` scoped by the parent **`xpl-tabs`** instance), and **`aria-labelledby`** referencing the paired tab control’s **`id`**. Use the same **`target`** on **`xpl-tab`** and **`xpl-tab-panel`** so the references stay aligned (see **`xpl-tabs`** accessibility section for the full id pattern).\n- Hidden panels use display toggling (`xpl-tab-panel` / `--selected` in `tabs.css`), not `aria-hidden` on the host; panel content stays in the DOM for simpler state sync.\n\n## Token use\n\n| Part | Token / approach |\n| ---- | ---------------- |\n| Panel visibility | `tabs.css`: hidden unless `xpl-tab-panel--selected` (`display` via Tailwind `@apply`) |\n| Default padding | `py-6` in `tabs.css` on `.xpl-tab-panel` |\n| Inner content | Use typography classes (`xpl-text-body`, etc.) and Foundation tokens as elsewhere in Apollo |\n",
|
|
@@ -13881,10 +14408,10 @@
|
|
|
13881
14408
|
"dependencyGraph": {}
|
|
13882
14409
|
},
|
|
13883
14410
|
{
|
|
13884
|
-
"filePath": "src/components/
|
|
14411
|
+
"filePath": "src/components/xpl-table/xpl-table.tsx",
|
|
13885
14412
|
"encapsulation": "none",
|
|
13886
14413
|
"tag": "xpl-table",
|
|
13887
|
-
"readme": "# xpl-table\r\n\r\nTables are used to organize and display information from a data set.\r\n\r\n## Rendering modes\r\n\r\n1. **Compositional (recommended)** — Provide `xpl-table-header`, `xpl-table-body`, and optional `xpl-table-footer` with `xpl-table-row` / `xpl-table-header-cell` / `xpl-table-cell` / `xpl-table-footer-cell`. The host uses CSS grid (`role=\"grid\"`). Column widths come from each **`xpl-table-header-cell`** (`width` in px, or `column-width` for any grid track; default `auto` / content-sized). Use `label` for an accessible name. **Sorting:** set `sortable` (and optional `sort-key`) on label header cells; `xpl-table` emits **`sortChanged`** with sort-key slugs → `asc` / `desc` / `null`. The host does **not** reorder row DOM — listen and update your data (or reorder nodes yourself), same as the main Table Storybook demo.\r\n2. **Legacy data-driven** — Set `columns`, `data`, and optionally `footer` for a built-in `<table>` implementation. That path supports `isSortable` / `sortableColumns`, `multiselect`, and emits `sortChanged` / `tableSelect` (legacy can reorder rows unless you `preventDefault`). Prefer compositional markup for new work.\r\n\r\nComposable **selection** (`selectable`), **toolbar**, and copy-paste examples live under **[Usage](#usage)** below (read the breaking-change note first if you are migrating from auto-injected selection cells).\r\n\r\n### Row reorder (`row-reorderable`, managed grip column)\r\n\r\nWhen `row-reorderable` is set, Apollo can **inject** a leading reorder column with a native **button** + optional `xpl-icon` on each body row (unless you author that column yourself). Keyboard and pointer reorder share the same grip; **keyboard mode** is indicated by `aria-pressed`, updated labels, the class `xpl-table__row-drag-handle--keyboard-mode`, and optionally a **different icon**.\r\n\r\n**Pointer drag (full row):** Body rows use CSS **`subgrid`** so `xpl-table-row` is a real grid box (like `xpl-list-item`’s row surface). When `CSS.supports('grid-template-columns','subgrid')` is true, **`draggable`** is set on **`xpl-table-row`** so the browser’s drag image matches the whole row; drag still **starts only from the grip** (pointer-down there sets the drag token—dragging from other cells is ignored). Engines without subgrid keep **`draggable`** on the grip button only.\r\n\r\n| Attribute | When it applies | Purpose |\r\n| --------- | ---------------- | ------- |\r\n| `reorder-handle-icon` | Default / drag affordance | Icon name for `xpl-icon` (default `grip-dots-vertical`). Use `reorder-handle-icon=\"\"` to omit the injected icon and use CSS or your own markup in a **custom** reorder cell instead. |\r\n| `reorder-handle-icon-keyboard` | While that row is in **keyboard reorder mode** (Enter or Space on the grip) | Icon name for the same grip when the user is using **Arrow Up/Down** to move the row (default `caret-expand-y`, matching `xpl-list`). Use `reorder-handle-icon-keyboard=\"\"` to show **no** icon in keyboard mode only. |\r\n\r\n**Recommended for product UIs:** Set **both** attributes to your design-system icon names so drag vs keyboard modes are visually distinct. You can still add styles targeting `.xpl-table__row-drag-handle--keyboard-mode` (e.g. outline) for extra clarity.\r\n\r\n**Interaction:** Focus the grip → **Enter** or **Space** → **Arrow Up/Down** to reorder → **Escape** to exit. Pointer down on the row exits keyboard mode; starting a drag also exits keyboard mode.\r\n\r\n**Custom reorder column:** If you add reorder cells in your own template (not injected), **you** own icons, keyboard behavior, and `rowOrderChange` — these attributes apply only to **managed** injected grips.\r\n\r\n## Usage\r\n\r\n### Breaking change — compositional `selectable`\r\n\r\n**Before:** Setting `selectable` alone caused the table to **inject** selection header/body/footer cells into the light DOM (including nodes marked `data-xpl-selection-managed`).\r\n\r\n**After:** You **must** add the selection column in your own markup (see **Selection** below). `xpl-table` no longer creates or removes those cells; it only syncs selection state and emits events. If you previously relied on automatic injection, add the header checkbox column, per-row checkbox cells, and (when using a footer) leading footer cells so column counts match.\r\n\r\n### Selection (`selectable`) and `rowSelectionChange`\r\n\r\nSet `selectable` on `xpl-table` and **author the selection column in your template** so the framework that renders the table owns every cell node.\r\n\r\n**Required pieces:**\r\n\r\n- **Header:** one [`xpl-table-header-cell`](xpl-table-header-cell) with `type=\"checkbox\"` (tri-state “select all”).\r\n- **Body:** in each `xpl-table-row`, a cell aligned with that column containing **`xpl-checkbox`** (value is driven from `row-id` on the row).\r\n- **Footer:** if you use `xpl-table-footer`, add a leading `xpl-table-footer-cell` per row for the selection column (often empty) so column counts stay aligned.\r\n\r\n**Behavior:** After `customElements.whenDefined('xpl-table')`, listen for **`rowSelectionChange`** on the **same** `<xpl-table>` element (`bubbles: false`, `composed: true`). The event payload is `{ selectedRowIds: string[] }`. The host maintains `selectedRowIds`, syncs `checked` / `indeterminate` on the header and row checkboxes, sets `selected` on rows, and shows the bulk toolbar while at least one row is selected. Row checkbox **`aria-label`** is derived from the first **non-selection** data cell in that row (e.g. `Select row, Jordan Lee`); the header uses “Select all rows” unless you set **`checkbox-aria-label`** on the checkbox header cell.\r\n\r\n**Example (web component):**\r\n\r\n```html\r\n<xpl-table id=\"roster\" selectable label=\"Team roster\">\r\n <xpl-table-header>\r\n <xpl-table-row>\r\n <xpl-table-header-cell type=\"checkbox\"></xpl-table-header-cell>\r\n <xpl-table-header-cell label=\"Name\" sortable sort-key=\"name\"></xpl-table-header-cell>\r\n </xpl-table-row>\r\n </xpl-table-header>\r\n <xpl-table-body>\r\n <xpl-table-row row-id=\"1\">\r\n <xpl-table-cell><xpl-checkbox></xpl-checkbox></xpl-table-cell>\r\n <xpl-table-cell>Ada</xpl-table-cell>\r\n </xpl-table-row>\r\n </xpl-table-body>\r\n</xpl-table>\r\n<script type=\"module\">\r\n await customElements.whenDefined('xpl-table');\r\n document.getElementById('roster')?.addEventListener('rowSelectionChange', (e) => {\r\n console.log(e.detail.selectedRowIds);\r\n });\r\n</script>\r\n```\r\n\r\n#### Framework notes (Vue / React / etc.)\r\n\r\nUse **`xpl-checkbox`** in the selection column so `xpl-table` can sync `checked`, `indeterminate`, and `value` from `row-id`. On **`xpl-table-header-cell`**, the selection header uses **`type=\"checkbox\"`**; the prop is **reflected** to the host attribute so Vue bindings like `:type=\"'checkbox'\"` still expose `type=\"checkbox\"` in the DOM for the table’s column detection and CSS.\r\n\r\n### Legacy (`columns` / `data`)\r\n\r\nSet `columns`, `data`, and optional `footer` as **properties** after `customElements.whenDefined('xpl-table')`, or use attributes where your bundler passes JSON strings.\r\n\r\n```html\r\n<xpl-table id=\"legacy\"></xpl-table>\r\n<script type=\"module\">\r\n await customElements.whenDefined('xpl-table');\r\n const t = document.getElementById('legacy');\r\n t.columns = ['Name', 'Score'];\r\n t.data = [\r\n ['Ada', '100'],\r\n ['Bob', '95'],\r\n ];\r\n t.multiselect = true;\r\n t.addEventListener('tableSelect', (e) => console.log(e.detail));\r\n</script>\r\n```\r\n\r\n## Accessibility\r\n\r\n| Concern | Behavior |\r\n| ------- | -------- |\r\n| Table landmark | Compositional host uses **`role=\"grid\"`**; set **`label`** (maps to `aria-label`). |\r\n| Columns | Header cells use **`role=\"columnheader\"`** with `aria-colindex`; sortable label headers expose sort state via **`aria-sort`**. |\r\n| Selection | Checkbox column: header reflects **checked / mixed** via `aria-checked`; row checkboxes get **`aria-label`** from the first non-selection cell’s text (or override with `checkbox-aria-label` on the checkbox header cell). |\r\n| Sort | Sorting is a **`<button type=\"button\">`** inside the header cell; focus uses **`:focus-visible`** with focus tokens in `table-header-cell.css`. |\r\n| Row reorder | Managed grip is a **`<button>`** with `aria-label` / `aria-pressed` for keyboard reorder mode; live region announces reorder when enabled. |\r\n\r\nKeyboard: **Tab** through sort buttons, checkboxes, reorder grips, and cell actions. **Enter** / **Space** activate sort and the reorder grip per native button semantics.\r\n\r\n## Design Tokens\r\n\r\nCompositional grid layout tokens live in `table.css`; cell, row, header, and toolbar tokens are split across sibling CSS files.\r\n\r\n| Element | Property | Token | Light | Dark |\r\n| ------- | -------- | ----- | ----- | ---- |\r\n| Host (compositional) | border | `--xpl-border-small`, `--xpl-border-default` | neutral-200 | neutral-800 |\r\n| Host (compositional) | border-radius | `--xpl-border-radius-default` | 8px | 8px |\r\n| Host (compositional) | grid columns | `--column-widths` (runtime from header cells) | — | — |\r\n| Selection toolbar | sticky z-index | `--xpl-z-index-200` | 200 | 200 |\r\n| Selection toolbar | min-height | `--xpl-size-350` | 56px | 56px |\r\n| Freeze shadow | gradient | `--xpl-background-surface-transparent-10` → `-0` | near-black 10% | near-white 10% |\r\n| Freeze column | sticky z-index | `--xpl-z-index-100` | 100 | 100 |\r\n| Freeze scroll hint | width | `--xpl-space-24` | 24px | 24px |\r\n| Striped even rows | cell background | `--xpl-background-surface-subtlest` | neutral-50 | neutral-950 |\r\n| Striped + selected | cell background | `--xpl-background-surface-information-bold` | blue-100 | blue-900 |\r\n\r\n## Icon mapping\r\n\r\nWhen Apollo **injects** the reorder column, icons come from table props (override with `\"\"` to omit):\r\n\r\n| Context | Default `xpl-icon` `icon` value |\r\n| ------- | -------------------------------- |\r\n| Pointer / idle grip | `grip-dots-vertical` |\r\n| Keyboard reorder mode | `caret-expand-y` |\r\n\r\nSort direction uses **`xpl-icon`** names from header-cell internals (`graph`, carets, etc.) — see Storybook **Components → Table**.\r\n\r",
|
|
14414
|
+
"readme": "# xpl-table\r\n\r\nTables are used to organize and display information from a data set.\r\n\r\n## Rendering modes\r\n\r\n1. **Compositional (recommended)** — Provide `xpl-table-header`, `xpl-table-body`, and optional `xpl-table-footer` with `xpl-table-row` / `xpl-table-header-cell` / `xpl-table-cell` / `xpl-table-footer-cell`. The host uses CSS grid (`role=\"grid\"`). Column widths come from each **`xpl-table-header-cell`** (`width` in px, or `column-width` for any grid track; default `auto` / content-sized). Use `label` for an accessible name. **Sorting:** set `sortable` (and optional `sort-key`) on label header cells; `xpl-table` emits **`sortChanged`** with sort-key slugs → `asc` / `desc` / `null`. The host does **not** reorder row DOM — listen and update your data (or reorder nodes yourself), same as the main Table Storybook demo.\r\n2. **Legacy data-driven** — Set `columns`, `data`, and optionally `footer` for a built-in `<table>` implementation. That path supports `isSortable` / `sortableColumns`, `multiselect`, and emits `sortChanged` / `tableSelect` (legacy can reorder rows unless you `preventDefault`). Prefer compositional markup for new work.\r\n\r\nComposable **selection** (`selectable`), **toolbar**, and copy-paste examples live under **[Usage](#usage)** below (read the breaking-change note first if you are migrating from auto-injected selection cells).\r\n\r\n### Breaking change — global table class names (Apollo Core 3.0.0)\r\n\r\nApollo Core 3.0.0 introduced the compositional table ([#982](https://github.com/xplor/apollo/pull/982)) and ships global CSS for `.xpl-table`, `.xpl-table-row`, `.xpl-table-cell`, `.xpl-table-header-*`, `.xpl-table-body`, and `.xpl-table-footer-*`. In 2.x many of these class names had **no Apollo styles** (or only applied on native `<table>` via `.xpl-table`). These styles are **not scoped** to the `<xpl-table>` element — any element carrying these class names picks them up. If your application used these names as styling hooks on its own native table markup, upgrading to 3.x can break layout.\r\n\r\n| Symptom | Typical cause | Fix |\r\n| --- | --- | --- |\r\n| All table rows render side by side in one line | `xpl-table-row` class hook on native `<tr>` applies `display: contents` | Remove the hook class from native rows, or migrate to `<xpl-table-row>` inside `<xpl-table>` |\r\n| Native `<table class=\"xpl-table\">` layout is destroyed | Compositional grid targets the `.xpl-table` **class** (`display: grid` + `grid-template-columns`), so it also matches native `<table class=\"xpl-table\">` | Add `xpl-table--legacy`: `<table class=\"xpl-table xpl-table--legacy\">` |\r\n| Sticky freeze column lost on native tables | Compositional `.xpl-table--freeze` sticky rules target compositional cell classes (`.xpl-table-cell` etc.); the 2.x native-table freeze lives under `.xpl-table--legacy.xpl-table--freeze` | Add `xpl-table--legacy` to the native `<table>` |\r\n\r\n**`xpl-table--legacy`:** opt-in class for native `<table>` markup (or the deprecated `columns` / `data` render path) that restores pre-compositional Apollo table styling. Scheduled for removal in **Apollo Core 4.0.0** — migrate to compositional `<xpl-table>` or application-owned table styles before then.\r\n\r\n### Row reorder (`row-reorderable`, managed grip column)\r\n\r\nWhen `row-reorderable` is set, Apollo can **inject** a leading reorder column with a native **button** + optional `xpl-icon` on each body row (unless you author that column yourself). Keyboard and pointer reorder share the same grip; **keyboard mode** is indicated by `aria-pressed`, updated labels, the class `xpl-table__row-drag-handle--keyboard-mode`, and optionally a **different icon**.\r\n\r\n**Pointer drag (full row):** Body rows use CSS **`subgrid`** so `xpl-table-row` is a real grid box (like `xpl-list-item`’s row surface). When `CSS.supports('grid-template-columns','subgrid')` is true, **`draggable`** is set on **`xpl-table-row`** so the browser’s drag image matches the whole row; drag still **starts only from the grip** (pointer-down there sets the drag token—dragging from other cells is ignored). Engines without subgrid keep **`draggable`** on the grip button only.\r\n\r\n| Attribute | When it applies | Purpose |\r\n| --------- | ---------------- | ------- |\r\n| `reorder-handle-icon` | Default / drag affordance | Icon name for `xpl-icon` (default `grip-dots-vertical`). Use `reorder-handle-icon=\"\"` to omit the injected icon and use CSS or your own markup in a **custom** reorder cell instead. |\r\n| `reorder-handle-icon-keyboard` | While that row is in **keyboard reorder mode** (Enter or Space on the grip) | Icon name for the same grip when the user is using **Arrow Up/Down** to move the row (default `caret-expand-y`, matching `xpl-list`). Use `reorder-handle-icon-keyboard=\"\"` to show **no** icon in keyboard mode only. |\r\n\r\n**Recommended for product UIs:** Set **both** attributes to your design-system icon names so drag vs keyboard modes are visually distinct. You can still add styles targeting `.xpl-table__row-drag-handle--keyboard-mode` (e.g. outline) for extra clarity.\r\n\r\n**Interaction:** Focus the grip → **Enter** or **Space** → **Arrow Up/Down** to reorder → **Escape** to exit. Pointer down on the row exits keyboard mode; starting a drag also exits keyboard mode.\r\n\r\n**Custom reorder column:** If you add reorder cells in your own template (not injected), **you** own icons, keyboard behavior, and `rowOrderChange` — these attributes apply only to **managed** injected grips.\r\n\r\n## Usage\r\n\r\n### Breaking change — compositional `selectable`\r\n\r\n**Before:** Setting `selectable` alone caused the table to **inject** selection header/body/footer cells into the light DOM (including nodes marked `data-xpl-selection-managed`).\r\n\r\n**After:** You **must** add the selection column in your own markup (see **Selection** below). `xpl-table` no longer creates or removes those cells; it only syncs selection state and emits events. If you previously relied on automatic injection, add the header checkbox column, per-row checkbox cells, and (when using a footer) leading footer cells so column counts match.\r\n\r\n### Selection (`selectable`) and `rowSelectionChange`\r\n\r\nSet `selectable` on `xpl-table` and **author the selection column in your template** so the framework that renders the table owns every cell node.\r\n\r\n**Required pieces:**\r\n\r\n- **Header:** one [`xpl-table-header-cell`](xpl-table-header-cell) with `type=\"checkbox\"` (tri-state “select all”).\r\n- **Body:** in each `xpl-table-row`, a cell aligned with that column containing **`xpl-checkbox`** (value is driven from `row-id` on the row).\r\n- **Footer:** if you use `xpl-table-footer`, add a leading `xpl-table-footer-cell` per row for the selection column (often empty) so column counts stay aligned.\r\n\r\n**Behavior:** After `customElements.whenDefined('xpl-table')`, listen for **`rowSelectionChange`** on the **same** `<xpl-table>` element (`bubbles: false`, `composed: true`). The event payload is `{ selectedRowIds: string[] }`. The host maintains `selectedRowIds`, syncs `checked` / `indeterminate` on the header and row checkboxes, sets `selected` on rows, and shows the bulk toolbar while at least one row is selected. Row checkbox **`aria-label`** is derived from the first **non-selection** data cell in that row (e.g. `Select row, Jordan Lee`); the header uses “Select all rows” unless you set **`checkbox-aria-label`** on the checkbox header cell.\r\n\r\n**Example (web component):**\r\n\r\n```html\r\n<xpl-table id=\"roster\" selectable label=\"Team roster\">\r\n <xpl-table-header>\r\n <xpl-table-row>\r\n <xpl-table-header-cell type=\"checkbox\"></xpl-table-header-cell>\r\n <xpl-table-header-cell label=\"Name\" sortable sort-key=\"name\"></xpl-table-header-cell>\r\n </xpl-table-row>\r\n </xpl-table-header>\r\n <xpl-table-body>\r\n <xpl-table-row row-id=\"1\">\r\n <xpl-table-cell><xpl-checkbox></xpl-checkbox></xpl-table-cell>\r\n <xpl-table-cell>Ada</xpl-table-cell>\r\n </xpl-table-row>\r\n </xpl-table-body>\r\n</xpl-table>\r\n<script type=\"module\">\r\n await customElements.whenDefined('xpl-table');\r\n document.getElementById('roster')?.addEventListener('rowSelectionChange', (e) => {\r\n console.log(e.detail.selectedRowIds);\r\n });\r\n</script>\r\n```\r\n\r\n#### Framework notes (Vue / React / etc.)\r\n\r\nUse **`xpl-checkbox`** in the selection column so `xpl-table` can sync `checked`, `indeterminate`, and `value` from `row-id`. On **`xpl-table-header-cell`**, the selection header uses **`type=\"checkbox\"`**; the prop is **reflected** to the host attribute so Vue bindings like `:type=\"'checkbox'\"` still expose `type=\"checkbox\"` in the DOM for the table’s column detection and CSS.\r\n\r\n### Legacy (`columns` / `data`)\r\n\r\nSet `columns`, `data`, and optional `footer` as **properties** after `customElements.whenDefined('xpl-table')`, or use attributes where your bundler passes JSON strings.\r\n\r\n```html\r\n<xpl-table id=\"legacy\"></xpl-table>\r\n<script type=\"module\">\r\n await customElements.whenDefined('xpl-table');\r\n const t = document.getElementById('legacy');\r\n t.columns = ['Name', 'Score'];\r\n t.data = [\r\n ['Ada', '100'],\r\n ['Bob', '95'],\r\n ];\r\n t.multiselect = true;\r\n t.addEventListener('tableSelect', (e) => console.log(e.detail));\r\n</script>\r\n```\r\n\r\n## Accessibility\r\n\r\n| Concern | Behavior |\r\n| ------- | -------- |\r\n| Table landmark | Compositional host uses **`role=\"grid\"`**; set **`label`** (maps to `aria-label`). |\r\n| Columns | Header cells use **`role=\"columnheader\"`** with `aria-colindex`; sortable label headers expose sort state via **`aria-sort`**. |\r\n| Selection | Checkbox column: header reflects **checked / mixed** via `aria-checked`; row checkboxes get **`aria-label`** from the first non-selection cell’s text (or override with `checkbox-aria-label` on the checkbox header cell). |\r\n| Sort | Sorting is a **`<button type=\"button\">`** inside the header cell; focus uses **`:focus-visible`** with focus tokens in `table-header-cell.css`. |\r\n| Row reorder | Managed grip is a **`<button>`** with `aria-label` / `aria-pressed` for keyboard reorder mode; live region announces reorder when enabled. |\r\n\r\nKeyboard: **Tab** through sort buttons, checkboxes, reorder grips, and cell actions. **Enter** / **Space** activate sort and the reorder grip per native button semantics.\r\n\r\n## Design Tokens\r\n\r\nCompositional grid layout tokens live in `table.css`; cell, row, header, and toolbar tokens are split across sibling CSS files.\r\n\r\n| Element | Property | Token | Light | Dark |\r\n| ------- | -------- | ----- | ----- | ---- |\r\n| Host (compositional) | border | `--xpl-border-small`, `--xpl-border-default` | neutral-200 | neutral-800 |\r\n| Host (compositional) | border-radius | `--xpl-border-radius-default` | 8px | 8px |\r\n| Host (compositional) | grid columns | `--column-widths` (runtime from header cells) | — | — |\r\n| Selection toolbar | sticky z-index | `--xpl-z-index-200` | 200 | 200 |\r\n| Selection toolbar | min-height | `--xpl-size-350` | 56px | 56px |\r\n| Freeze shadow | gradient | `--xpl-background-surface-transparent-10` → `-0` | near-black 10% | near-white 10% |\r\n| Freeze column | sticky z-index | `--xpl-z-index-100` | 100 | 100 |\r\n| Freeze scroll hint | width | `--xpl-space-24` | 24px | 24px |\r\n| Striped even rows | cell background | `--xpl-background-surface-subtlest` | neutral-50 | neutral-950 |\r\n| Striped + selected | cell background | `--xpl-background-surface-information-bold` | blue-100 | blue-900 |\r\n\r\n## Icon mapping\r\n\r\nWhen Apollo **injects** the reorder column, icons come from table props (override with `\"\"` to omit):\r\n\r\n| Context | Default `xpl-icon` `icon` value |\r\n| ------- | -------------------------------- |\r\n| Pointer / idle grip | `grip-dots-vertical` |\r\n| Keyboard reorder mode | `caret-expand-y` |\r\n\r\nSort direction uses **`xpl-icon`** names from header-cell internals (`graph`, carets, etc.) — see Storybook **Components → Table**.\r\n\r",
|
|
13888
14415
|
"docs": "Compositional tables use CSS grid on the host (`role=\"grid\"`). Legacy mode uses a `<table>`.",
|
|
13889
14416
|
"docsTags": [
|
|
13890
14417
|
{
|
|
@@ -14299,8 +14826,8 @@
|
|
|
14299
14826
|
"references": {
|
|
14300
14827
|
"XplTableRowOrderChangeDetail": {
|
|
14301
14828
|
"location": "local",
|
|
14302
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
14303
|
-
"id": "src/components/
|
|
14829
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-table/xpl-table.tsx",
|
|
14830
|
+
"id": "src/components/xpl-table/xpl-table.tsx::XplTableRowOrderChangeDetail"
|
|
14304
14831
|
}
|
|
14305
14832
|
}
|
|
14306
14833
|
},
|
|
@@ -14333,8 +14860,8 @@
|
|
|
14333
14860
|
"references": {
|
|
14334
14861
|
"XplTableSortChangedDetail": {
|
|
14335
14862
|
"location": "local",
|
|
14336
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
14337
|
-
"id": "src/components/
|
|
14863
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-table/xpl-table.tsx",
|
|
14864
|
+
"id": "src/components/xpl-table/xpl-table.tsx::XplTableSortChangedDetail"
|
|
14338
14865
|
}
|
|
14339
14866
|
}
|
|
14340
14867
|
},
|
|
@@ -14458,19 +14985,29 @@
|
|
|
14458
14985
|
}
|
|
14459
14986
|
},
|
|
14460
14987
|
{
|
|
14461
|
-
"filePath": "src/components/
|
|
14988
|
+
"filePath": "src/components/xpl-table/xpl-table-body/xpl-table-body.tsx",
|
|
14462
14989
|
"encapsulation": "none",
|
|
14463
14990
|
"tag": "xpl-table-body",
|
|
14464
14991
|
"readme": "# xpl-table-body\n\nRow group for compositional table body content. Uses `display: contents` so slotted rows participate in the parent grid layout.\n\n## Design Tokens\n\n| Element | Property | Token | Light | Dark |\n| ------- | -------- | ----- | ----- | ---- |\n| Host | display | — | `contents` | `contents` |\n",
|
|
14465
14992
|
"docs": "Row group for compositional table body content. Uses `display: contents` so slotted rows participate in the parent grid layout.",
|
|
14466
|
-
"docsTags": [
|
|
14993
|
+
"docsTags": [
|
|
14994
|
+
{
|
|
14995
|
+
"name": "slot",
|
|
14996
|
+
"text": "- The body rows (`xpl-table-row` elements)."
|
|
14997
|
+
}
|
|
14998
|
+
],
|
|
14467
14999
|
"usage": {},
|
|
14468
15000
|
"props": [],
|
|
14469
15001
|
"methods": [],
|
|
14470
15002
|
"events": [],
|
|
14471
15003
|
"listeners": [],
|
|
14472
15004
|
"styles": [],
|
|
14473
|
-
"slots": [
|
|
15005
|
+
"slots": [
|
|
15006
|
+
{
|
|
15007
|
+
"name": "",
|
|
15008
|
+
"docs": "The body rows (`xpl-table-row` elements)."
|
|
15009
|
+
}
|
|
15010
|
+
],
|
|
14474
15011
|
"parts": [],
|
|
14475
15012
|
"states": [],
|
|
14476
15013
|
"dependents": [],
|
|
@@ -14478,12 +15015,17 @@
|
|
|
14478
15015
|
"dependencyGraph": {}
|
|
14479
15016
|
},
|
|
14480
15017
|
{
|
|
14481
|
-
"filePath": "src/components/
|
|
15018
|
+
"filePath": "src/components/xpl-table/xpl-table-cell/xpl-table-cell.tsx",
|
|
14482
15019
|
"encapsulation": "none",
|
|
14483
15020
|
"tag": "xpl-table-cell",
|
|
14484
15021
|
"readme": "# xpl-table-cell\n\nBody cell for compositional [`xpl-table`](../readme.md). Place content in the default slot; use `align`, `bold`, and `underline` for typography. Interactive controls inside the cell inherit `disabled` when the parent [`xpl-table-row`](../xpl-table-row) is disabled.\n\n## Design Tokens\n\nExtends `.xpl-table-cell-base` (`table-cell-base.css`); row states (selected, disabled, striped) are applied from `table-row.css`.\n\n| Element | Property | Token | Light | Dark |\n| ------- | -------- | ----- | ----- | ---- |\n| Cell | background | `--xpl-background-surface-default` | neutral-0 | neutral-1000 |\n| Cell | text | `--xpl-text-default` | neutral-900 | neutral-50 |\n| Cell | border (right/bottom) | `--xpl-border-small`, `--xpl-border-default` | 1px, neutral-200 | 1px, neutral-800 |\n| Cell | padding | `--xpl-space-10`, `--xpl-space-16` | 10px / 16px | 10px / 16px |\n| Cell | min-height | `--xpl-size-350` | 56px | 56px |\n| Cell | typography | `@extend .xpl-text-title-5` | title-5 / medium | title-5 / medium |\n| Bold text | font-weight | `--xpl-font-weight-semibold` | 600 | 600 |\n| Disabled | text | `--xpl-text-disabled` | neutral-400 | neutral-600 |\n| Caption slot | text | `--xpl-text-subdued` | neutral-600 | neutral-400 |\n| Icon | color | `--xpl-icon-default` | neutral-900 | neutral-50 |\n| Reorder grip | color | `--xpl-icon-subtle` | neutral-600 | neutral-400 |\n| Reorder grip focus | outline | `--xpl-border-focus` | purple-500 | purple-400 |\n| Checkbox-only column | padding | `--xpl-space-16` + `--xpl-space-4` | 20px / 16px | 20px / 16px |\n",
|
|
14485
15022
|
"docs": "Body cell for compositional [`xpl-table`](../readme.md). Place content in the default slot; use `align`, `bold`, and `underline` for typography. Interactive controls inside the cell inherit `disabled` when the parent [`xpl-table-row`](../xpl-table-row) is disabled.",
|
|
14486
|
-
"docsTags": [
|
|
15023
|
+
"docsTags": [
|
|
15024
|
+
{
|
|
15025
|
+
"name": "slot",
|
|
15026
|
+
"text": "- The cell content."
|
|
15027
|
+
}
|
|
15028
|
+
],
|
|
14487
15029
|
"usage": {},
|
|
14488
15030
|
"props": [
|
|
14489
15031
|
{
|
|
@@ -14616,7 +15158,12 @@
|
|
|
14616
15158
|
"events": [],
|
|
14617
15159
|
"listeners": [],
|
|
14618
15160
|
"styles": [],
|
|
14619
|
-
"slots": [
|
|
15161
|
+
"slots": [
|
|
15162
|
+
{
|
|
15163
|
+
"name": "",
|
|
15164
|
+
"docs": "The cell content."
|
|
15165
|
+
}
|
|
15166
|
+
],
|
|
14620
15167
|
"parts": [],
|
|
14621
15168
|
"states": [],
|
|
14622
15169
|
"dependents": [
|
|
@@ -14630,19 +15177,29 @@
|
|
|
14630
15177
|
}
|
|
14631
15178
|
},
|
|
14632
15179
|
{
|
|
14633
|
-
"filePath": "src/components/
|
|
15180
|
+
"filePath": "src/components/xpl-table/xpl-table-footer/xpl-table-footer.tsx",
|
|
14634
15181
|
"encapsulation": "none",
|
|
14635
15182
|
"tag": "xpl-table-footer",
|
|
14636
15183
|
"readme": "# xpl-table-footer\n\nRow group for compositional table footer content. Uses `display: contents` so slotted footer rows participate in the parent grid layout.\n\n## Design Tokens\n\n| Element | Property | Token | Light | Dark |\n| ------- | -------- | ----- | ----- | ---- |\n| Host | display | — | `contents` | `contents` |\n",
|
|
14637
15184
|
"docs": "Row group for compositional table footer content. Uses `display: contents` so slotted footer rows participate in the parent grid layout.",
|
|
14638
|
-
"docsTags": [
|
|
15185
|
+
"docsTags": [
|
|
15186
|
+
{
|
|
15187
|
+
"name": "slot",
|
|
15188
|
+
"text": "- The footer content (`xpl-table-footer-cell` elements)."
|
|
15189
|
+
}
|
|
15190
|
+
],
|
|
14639
15191
|
"usage": {},
|
|
14640
15192
|
"props": [],
|
|
14641
15193
|
"methods": [],
|
|
14642
15194
|
"events": [],
|
|
14643
15195
|
"listeners": [],
|
|
14644
15196
|
"styles": [],
|
|
14645
|
-
"slots": [
|
|
15197
|
+
"slots": [
|
|
15198
|
+
{
|
|
15199
|
+
"name": "",
|
|
15200
|
+
"docs": "The footer content (`xpl-table-footer-cell` elements)."
|
|
15201
|
+
}
|
|
15202
|
+
],
|
|
14646
15203
|
"parts": [],
|
|
14647
15204
|
"states": [],
|
|
14648
15205
|
"dependents": [],
|
|
@@ -14650,12 +15207,17 @@
|
|
|
14650
15207
|
"dependencyGraph": {}
|
|
14651
15208
|
},
|
|
14652
15209
|
{
|
|
14653
|
-
"filePath": "src/components/
|
|
15210
|
+
"filePath": "src/components/xpl-table/xpl-table-footer-cell/xpl-table-footer-cell.tsx",
|
|
14654
15211
|
"encapsulation": "none",
|
|
14655
15212
|
"tag": "xpl-table-footer-cell",
|
|
14656
15213
|
"readme": "# xpl-table-footer-cell\n\nFooter cell for compositional tables. Extends the shared `.xpl-table-cell-base` styles with footer-row border rules from `table.css`.\n\n## Design Tokens\n\n| Element | Property | Token | Light | Dark |\n| ------- | -------- | ----- | ----- | ---- |\n| Cell | extends | `.xpl-table-cell-base` | (shared compositional cell base) | (shared compositional cell base) |\n| Cell | background | `--xpl-background-surface-default` | neutral-0 | neutral-1000 |\n| Cell | text | `--xpl-text-default` | neutral-900 | neutral-50 |\n| Cell | border (right/bottom) | `--xpl-border-small`, `--xpl-border-default` | 1px, neutral-200 | 1px, neutral-800 |\n| Last footer row | border-bottom | none (host draws frame) | — | — |\n",
|
|
14657
15214
|
"docs": "Footer cell for compositional tables. Extends the shared `.xpl-table-cell-base` styles with footer-row border rules from `table.css`.",
|
|
14658
|
-
"docsTags": [
|
|
15215
|
+
"docsTags": [
|
|
15216
|
+
{
|
|
15217
|
+
"name": "slot",
|
|
15218
|
+
"text": "- The footer cell content."
|
|
15219
|
+
}
|
|
15220
|
+
],
|
|
14659
15221
|
"usage": {},
|
|
14660
15222
|
"props": [
|
|
14661
15223
|
{
|
|
@@ -14701,7 +15263,12 @@
|
|
|
14701
15263
|
"events": [],
|
|
14702
15264
|
"listeners": [],
|
|
14703
15265
|
"styles": [],
|
|
14704
|
-
"slots": [
|
|
15266
|
+
"slots": [
|
|
15267
|
+
{
|
|
15268
|
+
"name": "",
|
|
15269
|
+
"docs": "The footer cell content."
|
|
15270
|
+
}
|
|
15271
|
+
],
|
|
14705
15272
|
"parts": [],
|
|
14706
15273
|
"states": [],
|
|
14707
15274
|
"dependents": [
|
|
@@ -14715,12 +15282,16 @@
|
|
|
14715
15282
|
}
|
|
14716
15283
|
},
|
|
14717
15284
|
{
|
|
14718
|
-
"filePath": "src/components/
|
|
15285
|
+
"filePath": "src/components/xpl-table-header/xpl-table-header.tsx",
|
|
14719
15286
|
"encapsulation": "none",
|
|
14720
15287
|
"tag": "xpl-table-header",
|
|
14721
15288
|
"readme": "# xpl-table-header\n\nComponent parts used to assemble the Dynamic Table.\n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\n",
|
|
14722
15289
|
"docs": "Component parts used to assemble the Dynamic Table.\n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.",
|
|
14723
15290
|
"docsTags": [
|
|
15291
|
+
{
|
|
15292
|
+
"name": "slot",
|
|
15293
|
+
"text": "- The header content (`xpl-table-header-cell` elements)."
|
|
15294
|
+
},
|
|
14724
15295
|
{
|
|
14725
15296
|
"name": "since",
|
|
14726
15297
|
"text": "1.0.0"
|
|
@@ -14732,7 +15303,12 @@
|
|
|
14732
15303
|
"events": [],
|
|
14733
15304
|
"listeners": [],
|
|
14734
15305
|
"styles": [],
|
|
14735
|
-
"slots": [
|
|
15306
|
+
"slots": [
|
|
15307
|
+
{
|
|
15308
|
+
"name": "",
|
|
15309
|
+
"docs": "The header content (`xpl-table-header-cell` elements)."
|
|
15310
|
+
}
|
|
15311
|
+
],
|
|
14736
15312
|
"parts": [],
|
|
14737
15313
|
"states": [],
|
|
14738
15314
|
"dependents": [],
|
|
@@ -14740,12 +15316,17 @@
|
|
|
14740
15316
|
"dependencyGraph": {}
|
|
14741
15317
|
},
|
|
14742
15318
|
{
|
|
14743
|
-
"filePath": "src/components/
|
|
15319
|
+
"filePath": "src/components/xpl-table/xpl-table-header-cell/xpl-table-header-cell.tsx",
|
|
14744
15320
|
"encapsulation": "none",
|
|
14745
15321
|
"tag": "xpl-table-header-cell",
|
|
14746
15322
|
"readme": "# xpl-table-header-cell\r\n\r\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\r\n\r\nThe `icon` property accepts icon names as strings. See [xpl-icon available icons](../xpl-icon/ICONS.md) for the complete list.\r\n\r\nWhen this cell is used inside a compositional [`xpl-table`](../xpl-table) with `selectable`, **you** add a `type=\"checkbox\"` header cell for select-all; `xpl-table` keeps `checked` and `indeterminate` in sync with row selection.\r\n\r\n**Frameworks (Vue / etc.):** `type` is **reflected** to the DOM. You may bind with `:type=\"'checkbox'\"` or `type=\"checkbox\"`; the host will still expose `type=\"checkbox\"` as an attribute so the table’s selection column logic and styles stay correct.\r\n\r\nFor **sortable** columns (`type=\"label\"`), set **`sortable`** and optionally **`sort-key`**; the parent table emits **`sortChanged`** (see [`xpl-table` events](../xpl-table#events)).\r\n\r\n**Column width (compositional grid):** Each header cell defines one grid column on the parent `xpl-table`. By default the track is **`auto`** (sizes from content). Set **`width`** for a fixed pixel width (minimum 48px), or **`column-width`** for any CSS grid track string (`1fr`, `minmax(120px, 1fr)`, etc.). When both are set, **`column-width` wins**.\r\n\r\n## Design Tokens\r\n\r\n| Element | Property | Token | Light | Dark |\r\n| ------- | -------- | ----- | ----- | ---- |\r\n| Cell | background | `--xpl-background-surface-subtlest` | neutral-50 | neutral-950 |\r\n| Cell | text | `--xpl-text-subdued` | neutral-600 | neutral-400 |\r\n| Cell | border (right/bottom) | `--xpl-border-small`, `--xpl-border-default` | 1px, neutral-200 | 1px, neutral-800 |\r\n| Cell | min-width | `--xpl-size-300` | 48px | 48px |\r\n| Cell | min-height | `--xpl-size-350` | 56px | 56px |\r\n| Cell | typography | `@extend .xpl-text-title-5` | title-5 / medium | title-5 / medium |\r\n| Sort button | padding | `--xpl-space-12`, `--xpl-space-16` | 12px / 16px | 12px / 16px |\r\n| Sort button focus | outline | `--xpl-border-focus` | purple-500 | purple-400 |\r\n| Sort icon (default) | color | `--xpl-text-subdued` | neutral-600 | neutral-400 |\r\n| Sort icon (active) | color | `--xpl-icon-information` | blue-500 | blue-400 |\r\n| Checkbox column | padding | `--xpl-space-16` + `--xpl-space-4` | 20px / 16px | 20px / 16px |\r\n\r\n---\r\n\r",
|
|
14747
15323
|
"docs": "> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\r\n\r\nThe `icon` property accepts icon names as strings. See [xpl-icon available icons](../xpl-icon/ICONS.md) for the complete list.\r\n\r\nWhen this cell is used inside a compositional [`xpl-table`](../xpl-table) with `selectable`, **you** add a `type=\"checkbox\"` header cell for select-all; `xpl-table` keeps `checked` and `indeterminate` in sync with row selection.\r\n\r\n**Frameworks (Vue / etc.):** `type` is **reflected** to the DOM. You may bind with `:type=\"'checkbox'\"` or `type=\"checkbox\"`; the host will still expose `type=\"checkbox\"` as an attribute so the table’s selection column logic and styles stay correct.\r\n\r\nFor **sortable** columns (`type=\"label\"`), set **`sortable`** and optionally **`sort-key`**; the parent table emits **`sortChanged`** (see [`xpl-table` events](../xpl-table#events)).\r\n\r\n**Column width (compositional grid):** Each header cell defines one grid column on the parent `xpl-table`. By default the track is **`auto`** (sizes from content). Set **`width`** for a fixed pixel width (minimum 48px), or **`column-width`** for any CSS grid track string (`1fr`, `minmax(120px, 1fr)`, etc.). When both are set, **`column-width` wins**.",
|
|
14748
|
-
"docsTags": [
|
|
15324
|
+
"docsTags": [
|
|
15325
|
+
{
|
|
15326
|
+
"name": "slot",
|
|
15327
|
+
"text": "- The header cell content (column label)."
|
|
15328
|
+
}
|
|
15329
|
+
],
|
|
14749
15330
|
"usage": {},
|
|
14750
15331
|
"props": [
|
|
14751
15332
|
{
|
|
@@ -15114,8 +15695,8 @@
|
|
|
15114
15695
|
"references": {
|
|
15115
15696
|
"HeaderSortChangeDetail": {
|
|
15116
15697
|
"location": "local",
|
|
15117
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
15118
|
-
"id": "src/components/
|
|
15698
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-table/xpl-table-header-cell/xpl-table-header-cell.tsx",
|
|
15699
|
+
"id": "src/components/xpl-table/xpl-table-header-cell/xpl-table-header-cell.tsx::HeaderSortChangeDetail"
|
|
15119
15700
|
}
|
|
15120
15701
|
}
|
|
15121
15702
|
},
|
|
@@ -15127,7 +15708,12 @@
|
|
|
15127
15708
|
],
|
|
15128
15709
|
"listeners": [],
|
|
15129
15710
|
"styles": [],
|
|
15130
|
-
"slots": [
|
|
15711
|
+
"slots": [
|
|
15712
|
+
{
|
|
15713
|
+
"name": "",
|
|
15714
|
+
"docs": "The header cell content (column label)."
|
|
15715
|
+
}
|
|
15716
|
+
],
|
|
15131
15717
|
"parts": [],
|
|
15132
15718
|
"states": [],
|
|
15133
15719
|
"dependents": [
|
|
@@ -15148,12 +15734,17 @@
|
|
|
15148
15734
|
}
|
|
15149
15735
|
},
|
|
15150
15736
|
{
|
|
15151
|
-
"filePath": "src/components/
|
|
15737
|
+
"filePath": "src/components/xpl-table/xpl-table-row/xpl-table-row.tsx",
|
|
15152
15738
|
"encapsulation": "none",
|
|
15153
15739
|
"tag": "xpl-table-row",
|
|
15154
15740
|
"readme": "# xpl-table-row\n\nData row for compositional tables. Uses `display: contents` by default so cells align to the parent grid; when the body supports subgrid, the row becomes a full-width subgrid for drag interactions.\n\n## Design Tokens\n\nRow state styles target descendant `.xpl-table-cell` nodes (see `table-row.css`).\n\n| Element | Property | Token | Light | Dark |\n| ------- | -------- | ----- | ----- | ---- |\n| Host (default) | display | — | `contents` | `contents` |\n| Host (subgrid body) | display | — | `grid` with `subgrid` | `grid` with `subgrid` |\n| Disabled row | background | `--xpl-background-surface-subtlest` | neutral-50 | neutral-950 |\n| Disabled row | text | `--xpl-text-disabled` | neutral-400 | neutral-600 |\n| Dragging row | background | `--xpl-background-surface-subtle` | neutral-100 | neutral-900 |\n| Dragging row | opacity | `--xpl-opacity-75` | 0.75 | 0.75 |\n| Selected row | background | `--xpl-background-surface-information` | blue-50 | blue-950 |\n| Selected grip (reorder) | icon color | `--xpl-icon-information` | blue-500 | blue-400 |\n| Drag-over outline | inset ring | `--xpl-border-focus`, `--xpl-border-small` | purple-500 | purple-400 |\n| Striped even | background | `--xpl-background-surface-subtlest` | neutral-50 | neutral-950 |\n| Striped selected | background | `--xpl-background-surface-information-bold` | blue-100 | blue-900 |\n| Keyboard reorder grip | outline | `--xpl-border-focus` | purple-500 | purple-400 |\n",
|
|
15155
15741
|
"docs": "Data row for compositional tables. Uses `display: contents` by default so cells align to the parent grid; when the body supports subgrid, the row becomes a full-width subgrid for drag interactions.",
|
|
15156
|
-
"docsTags": [
|
|
15742
|
+
"docsTags": [
|
|
15743
|
+
{
|
|
15744
|
+
"name": "slot",
|
|
15745
|
+
"text": "- The row cells (`xpl-table-cell` elements)."
|
|
15746
|
+
}
|
|
15747
|
+
],
|
|
15157
15748
|
"usage": {},
|
|
15158
15749
|
"props": [
|
|
15159
15750
|
{
|
|
@@ -15242,7 +15833,12 @@
|
|
|
15242
15833
|
"events": [],
|
|
15243
15834
|
"listeners": [],
|
|
15244
15835
|
"styles": [],
|
|
15245
|
-
"slots": [
|
|
15836
|
+
"slots": [
|
|
15837
|
+
{
|
|
15838
|
+
"name": "",
|
|
15839
|
+
"docs": "The row cells (`xpl-table-cell` elements)."
|
|
15840
|
+
}
|
|
15841
|
+
],
|
|
15246
15842
|
"parts": [],
|
|
15247
15843
|
"states": [],
|
|
15248
15844
|
"dependents": [],
|
|
@@ -15250,7 +15846,7 @@
|
|
|
15250
15846
|
"dependencyGraph": {}
|
|
15251
15847
|
},
|
|
15252
15848
|
{
|
|
15253
|
-
"filePath": "src/components/
|
|
15849
|
+
"filePath": "src/components/xpl-tabs/xpl-tabs.tsx",
|
|
15254
15850
|
"encapsulation": "none",
|
|
15255
15851
|
"tag": "xpl-tabs",
|
|
15256
15852
|
"readme": "# xpl-tabs\n\n`xpl-tabs` groups related views into a single surface: users pick a **tab** to show the matching **panel**. It implements the WAI-ARIA tabs pattern with a horizontal tab list, optional full-width layout, and two visual styles—**underline** (`type=\"tabs\"`, default) and **segment** (`type=\"segment\"`, pill controls in a bordered track)—selected with the **`type`** prop. On narrow viewports the heading row is replaced by an `xpl-select` so the same targets and keyboard behavior stay consistent.\n\nThe **Tabs** and **Segment control** Storybook entries document this **one component** with different defaults and Figma references. Each page adds variant-specific guidance (when to use, examples, tokens); the sections below describe behavior that is **the same for both** styles.\n\nPair **`xpl-tab` (slot `heading`)** with **`xpl-tab-panel` (slot `panel`)** and use the same **`target`** string on each pair so selection stays in sync.\n\n## Usage\n\n### Web component (`<xpl-tabs>`)\n\nMinimal group with two tabs: each `xpl-tab` and `xpl-tab-panel` shares a `target` value. Set `value` on `xpl-tabs` to control the selected tab (defaults to the first tab’s `target` if omitted).\n\n```html\n<xpl-tabs value=\"one\">\n <xpl-tab slot=\"heading\" target=\"one\">First</xpl-tab>\n <xpl-tab slot=\"heading\" target=\"two\">Second</xpl-tab>\n <xpl-tab-panel slot=\"panel\" target=\"one\">Content for first tab.</xpl-tab-panel>\n <xpl-tab-panel slot=\"panel\" target=\"two\">Content for second tab.</xpl-tab-panel>\n</xpl-tabs>\n```\n\nListen for selection changes with the **`tabChange`** event (detail is the selected `target` string):\n\n```html\n<xpl-tabs id=\"demo\" value=\"a\">\n <xpl-tab slot=\"heading\" target=\"a\">A</xpl-tab>\n <xpl-tab slot=\"heading\" target=\"b\">B</xpl-tab>\n <xpl-tab-panel slot=\"panel\" target=\"a\">…</xpl-tab-panel>\n <xpl-tab-panel slot=\"panel\" target=\"b\">…</xpl-tab-panel>\n</xpl-tabs>\n<script>\n document.getElementById('demo').addEventListener('tabChange', (e) => {\n console.log(e.detail); // \"a\" | \"b\"\n });\n</script>\n```\n\nDisable the entire group (headings, mobile select, and segment pills) with **`disabled`** on `xpl-tabs`. Disable individual tabs with **`disabled`** on `xpl-tab`.\n\n### Plain HTML (BEM classes)\n\nWhen styling with `tabs.css` without the Stencil component, mirror the structure: `xpl-tabs`, `xpl-tabs__headings` with `role=\"tablist\"` and `aria-orientation=\"horizontal\"`, `xpl-tabs__active-bar` for the underline variant (position/size normally set by JS), **`button.xpl-tab__button`** with **`role=\"tab\"`** (not links), and **`xpl-tab-panel`** for panels. For **segment** (`xpl-tabs--segment`), each heading is **`xpl-tab.xpl-tab--segment`** wrapping **`xpl-button`** (not `.xpl-tab__button`). On small viewports, include **`xpl-tabs__mobile-select`** with **`xpl-select`** for parity with the component.\n\n## Accessibility\n\n- Each **`xpl-tabs`** root gets a unique **`data-tabs-instance-id`** (for example `xpl-tg-1`). **`xpl-tab`** and **`xpl-tab-panel`** derive matching DOM **`id`** values from that id plus the shared **`target`** string: the tab control is **`…-tab-<target>`**, the panel is **`…-panel-<target>`** (with `target` sanitized for HTML `id` rules). The tab exposes **`aria-controls`** pointing at the panel id, **`aria-selected`**, and the panel uses **`aria-labelledby`** pointing at the tab id. **Segment (pill) tabs** render **`xpl-button`**; because **`xpl-button`** does not forward **`id`** / **`role`** / **`aria-*`** to its inner `<button>`, **`xpl-tab`** sets those on the native button after render so focus order and **`aria-labelledby`** stay correct (same pattern as underline tabs, different host element).\n- The tab list container is **`role=\"tablist\"`** with **`aria-orientation=\"horizontal\"`**. Underline tabs use **`role=\"tab\"`** on the inner `<button>`; panels use **`role=\"tabpanel\"`** on **`xpl-tab-panel`**.\n- **Roving tabindex:** only the active tab’s control is in the tab order (`tabindex=\"0\"`); others use `tabindex=\"-1\"` until focused with arrows.\n- **Keyboard:** **Arrow Left/Right** (and **Arrow Up/Down** as next/previous), **Home**, and **End** move between enabled tabs; **Enter** and **Space** activate (via `xpl-button` in segment mode). Direction mirrors in **RTL**.\n- When **`disabled`** is set on `xpl-tabs`, tab keyboard navigation and selection are suppressed for the group.\n\nVariant-specific Foundation mappings for underline vs. segment live in the **Tabs** and **Segment control** Storybook pages. The **`xpl-select`** mobile row reuses **`xpl-select`** / **`xpl-dropdown`** tokens from those components.\n",
|
|
@@ -15456,12 +16052,16 @@
|
|
|
15456
16052
|
}
|
|
15457
16053
|
},
|
|
15458
16054
|
{
|
|
15459
|
-
"filePath": "src/components/
|
|
16055
|
+
"filePath": "src/components/xpl-tag/xpl-tag.tsx",
|
|
15460
16056
|
"encapsulation": "none",
|
|
15461
16057
|
"tag": "xpl-tag",
|
|
15462
|
-
"readme": "# xpl-tag\n\nTags represent a set of interactive keywords that help label, organize, and categorize objects. Tags can be added or removed from an object by the user. Unlike Badges, Tags are clickable, used in dropdowns, multi-select, search bars, etc.\n\n## Usage Examples\n\n### Basic tag with dismiss\n\n```html\n<xpl-tag>Label</xpl-tag>\n```\n\n### Small size variant\n\n```html\n<xpl-tag size=\"sm\">Small Tag</xpl-tag>\n```\n\n### Non-dismissible tag (no close button)\n\n```html\n<xpl-tag dismissible=\"false\">Static Tag</xpl-tag>\n```\n\n### Disabled tag\n\n```html\n<xpl-tag disabled>Disabled Tag</xpl-tag>\n```\n\n### Handling events\n\n> **⚠️ Deprecation Notice:** The `close` event is **deprecated** and will be removed in a future major version. Use `tagRemove` for dismiss button clicks only.\n\n#### Why This Change?\n\nThe `close` event name conflicts with a **native HTML event** used by `<dialog>` elements. The React wrapper's `isCoveredByReact()` function detects `onclose` as a native event and passes handlers to React's synthetic event system — but React doesn't actually handle `close` events this way, so handlers silently fail in React applications.\n\n**Why `tagRemove` works:** `ontagremove` is not a native event, so the wrapper correctly falls back to `addEventListener`.\n\n#### Event Behavior\n\n| Interaction | `close` (deprecated) | `tagRemove` (use this) |\n|-------------|------------------------|------------------------|\n| Dismiss (×) button clicked | ✅ Fires | ✅ Fires |\n| Content clicked (non-draggable) | ✅ Fires | ❌ Does NOT fire |\n| Content clicked (draggable) | ❌ Does NOT fire | ❌ Does NOT fire |\n| Keyboard Space/Enter on content (non-draggable) | ✅ Fires | ❌ Does NOT fire |\n| Keyboard Space/Enter on draggable label | ❌ Does NOT fire | ❌ Does NOT fire |\n\n#### Migration Examples\n\n**Before (deprecated):**\n```tsx\n// React — this may silently fail!\n<XplTag onClose={() => tag.remove()}>Label</XplTag>\n\n// Vanilla JS\nconst tag = document.querySelector('xpl-tag');\ntag.addEventListener('close', () => tag.remove());\n```\n\n**After (recommended):**\n```tsx\n// React — works reliably\n<XplTag onTagRemove={() => tag.remove()}>Label</XplTag>\n\n// Vanilla JS — same pattern, clearer intent\nconst tag = document.querySelector('xpl-tag');\ntag.addEventListener('tagRemove', () => tag.remove());\n```\n\n**React with Refs (if you must use deprecated `close`):**\n```tsx\nimport { useEffect, useRef } from 'react';\nimport { XplTag } from '@xplortech/apollo-react';\n\nfunction MyComponent() {\n const tagRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n const el = tagRef.current;\n if (!el) return;\n\n const handleClose = () => el.remove();\n el.addEventListener('close', handleClose);\n return () => el.removeEventListener('close', handleClose);\n }, []);\n\n return <XplTag ref={tagRef}>Label</XplTag>;\n}\n```\n\n## Drag and drop\n\nTags support **native HTML5 drag and drop**. Set the boolean prop **`isDraggable`** (HTML attribute **`is-draggable`**) to enable dragging. Optionally set **`tag-id`** so `dataTransfer` and `tagDragStart` / `tagDragEnd` detail carry a stable id.\n\n### How it works (important for handlers)\n\n- The **drag source** is an inner **label** element (a `div` with `role=\"button\"`), not the `<xpl-tag>` host. Browsers do not start drags reliably on the custom element host; the **`is-draggable`** prop does **not** mirror the native host **`draggable`** attribute (see the `isDraggable` prop docs below).\n- On **`dragstart`**, the component uses **`setDragImage`** so the floating preview (“ghost”) looks like the **whole tag** (label + dismiss control), not only the label strip.\n- **Start the drag from the label text**, not from the dismiss (×) button.\n- In container listeners, **`dragstart`** may bubble with `event.target` equal to that inner node. Resolve the tag with:\n\n```js\nconst tag = event.target instanceof Element ? event.target.closest('xpl-tag') : null;\n```\n\n### Making a tag draggable\n\n```html\n<xpl-tag is-draggable>Draggable tag</xpl-tag>\n\n<xpl-tag is-draggable tag-id=\"my-tag-1\">Design</xpl-tag>\n```\n\n### Reordering tags within a container\n\n```html\n<div id=\"tag-container\" style=\"display: flex; flex-wrap: wrap; gap: 8px\">\n <xpl-tag tag-id=\"t1\" is-draggable>Design</xpl-tag>\n <xpl-tag tag-id=\"t2\" is-draggable>Development</xpl-tag>\n <xpl-tag tag-id=\"t3\" is-draggable>QA</xpl-tag>\n</div>\n\n<script>\n const container = document.getElementById('tag-container');\n let draggedEl = null;\n\n container.addEventListener('dragstart', (e) => {\n const tag = e.target instanceof Element ? e.target.closest('xpl-tag') : null;\n if (tag) draggedEl = tag;\n });\n\n container.addEventListener('dragend', () => {\n draggedEl = null;\n });\n\n container.addEventListener('dragover', (e) => {\n e.preventDefault();\n if (!draggedEl) return;\n const afterEl = getDragAfterElement(container, e.clientX);\n if (afterEl == null) container.appendChild(draggedEl);\n else container.insertBefore(draggedEl, afterEl);\n });\n\n function getDragAfterElement(container, x) {\n const tags = [...container.querySelectorAll('xpl-tag')].filter((el) => el !== draggedEl);\n return tags.reduce(\n (closest, child) => {\n const box = child.getBoundingClientRect();\n const offset = x - box.left - box.width / 2;\n return offset < 0 && offset > closest.offset ? { offset, element: child } : closest;\n },\n { offset: Number.NEGATIVE_INFINITY },\n ).element;\n }\n</script>\n```\n\n### Dragging tags between containers\n\n```html\n<div\n class=\"drop-zone\"\n style=\"display: flex; gap: 8px; padding: 16px; border: 2px dashed var(--xpl-border-default); border-radius: 8px\"\n>\n <xpl-tag tag-id=\"a1\" is-draggable>Frontend</xpl-tag>\n <xpl-tag tag-id=\"a2\" is-draggable>Backend</xpl-tag>\n</div>\n\n<div\n class=\"drop-zone\"\n style=\"\n display: flex;\n gap: 8px;\n padding: 16px;\n border: 2px dashed var(--xpl-border-default);\n border-radius: 8px;\n margin-top: 8px;\n \"\n>\n <xpl-tag tag-id=\"b1\" is-draggable>DevOps</xpl-tag>\n</div>\n\n<script>\n document.querySelectorAll('.drop-zone').forEach((zone) => {\n let draggedEl = null;\n\n zone.addEventListener('dragstart', (e) => {\n const tag = e.target instanceof Element ? e.target.closest('xpl-tag') : null;\n if (tag) draggedEl = tag;\n });\n\n zone.addEventListener('dragend', () => {\n draggedEl = null;\n });\n\n zone.addEventListener('dragover', (e) => e.preventDefault());\n\n zone.addEventListener('drop', (e) => {\n e.preventDefault();\n if (draggedEl && draggedEl.parentNode !== zone) zone.appendChild(draggedEl);\n });\n });\n</script>\n```\n\n### `tagDragStart` / `tagDragEnd` events\n\nThe component emits **`tagDragStart`** and **`tagDragEnd`** (Stencil camelCase). They bubble and are composed.\n\n```html\n<xpl-tag is-draggable tag-id=\"my-tag\">Drag me</xpl-tag>\n\n<script>\n const tag = document.querySelector('xpl-tag[tag-id=\"my-tag\"]');\n\n tag.addEventListener('tagDragStart', (e) => {\n const { tagId, content, originalEvent } = e.detail;\n });\n\n tag.addEventListener('tagDragEnd', (e) => {\n const { dropped, tagId, originalEvent } = e.detail;\n if (dropped) {\n /* dropEffect was 'move' */\n }\n });\n</script>\n```\n\n### React (`@xplortech/apollo-react`)\n\nEnsure the app loads Apollo **defineCustomElements** (see the main React package docs). Import **`XplTag`** and use **`isDraggable`**, **`tagId`**, and children for the label.\n\n`HTMLXplTagElement` is provided by Apollo’s Stencil typings (the same setup that types `defineCustomElements`). If your editor cannot resolve it, use `useRef<HTMLElement | null>(null)` and attach listeners on `ref.current`.\n\n`XplTag` is a thin wrapper around the web component. Custom events use the same names as in the DOM (`tagDragStart`, `tagDragEnd`, `tagRemove`). If your TypeScript definitions use different prop names for listeners, attach them with a **ref** (always works):\n\n```tsx\nimport { useEffect, useRef } from 'react';\nimport { XplTag } from '@xplortech/apollo-react';\n\nfunction TagBoard() {\n const tagRef = useRef<HTMLXplTagElement | null>(null);\n\n useEffect(() => {\n const el = tagRef.current;\n if (!el) return;\n\n const onDragStart = (e: CustomEvent) => {\n const { tagId, content } = e.detail;\n };\n const onDragEnd = (e: CustomEvent) => {\n const { dropped, tagId } = e.detail;\n };\n const onTagRemove = () => {\n el.remove(); // Handle dismiss button click\n };\n\n el.addEventListener('tagDragStart', onDragStart as EventListener);\n el.addEventListener('tagDragEnd', onDragEnd as EventListener);\n el.addEventListener('tagRemove', onTagRemove);\n return () => {\n el.removeEventListener('tagDragStart', onDragStart as EventListener);\n el.removeEventListener('tagDragEnd', onDragEnd as EventListener);\n el.removeEventListener('tagRemove', onTagRemove);\n };\n }, []);\n\n return (\n <XplTag ref={tagRef} isDraggable tagId=\"react-1\">\n Movable\n </XplTag>\n );\n}\n```\n\nReorder / multi-container logic is unchanged: listen for native `dragstart`, `dragover`, `drop` on a React parent `div` (use refs) and call `closest('xpl-tag')` as in the HTML examples.\n\n### `DataTransfer` payload\n\n| MIME type | Value | Purpose |\n|-----------|-------|---------|\n| `application/x-tag-id` | `tag-id` prop, if set | Identify the tag in drop handlers |\n| `text/plain` | Trimmed text content of the tag | Fallback for external targets |\n\n`effectAllowed` is set to `move`.\n\n**`originalEvent` in `tagDragStart` / `tagDragEnd`:** the native `DragEvent` is included for convenience, but browsers may clear `dataTransfer` after the synchronous handler completes. Use `tagId`, `content`, and `dropped` from the custom event detail for anything needed after the current turn; only read `originalEvent.dataTransfer` synchronously in the listener.\n\n### Disabled tags\n\n`disabled` wins: the tag is not draggable and keep using a normal `<button>` label (no HTML5 drag on the host).\n\n```html\n<xpl-tag is-draggable disabled>Cannot drag</xpl-tag>\n```\n\n## Design Tokens\n\n| Property | Token |\n|----------|-------|\n| Border (default) | `var(--xpl-border-accent-information)` |\n| Border (disabled) | `var(--xpl-border-accent-subtle)` |\n| Background (default) | `var(--xpl-background-surface-default)` |\n| Background (hover) | `var(--xpl-background-surface-information-bold)` |\n| Background (disabled) | `var(--xpl-background-surface-subtle)` |\n| Text | `var(--xpl-text-strong)` |\n| Text (disabled) | `var(--xpl-text-disabled)` |\n| Dismiss icon | `var(--xpl-icon-default)` |\n| Dismiss icon (disabled) | `var(--xpl-icon-disabled)` |\n| Spacing (default) | `var(--xpl-space-2)` vertical, `var(--xpl-space-12)` horizontal |\n| Spacing (small) | `var(--xpl-space-2)` vertical, `var(--xpl-space-8)` horizontal |\n| Height (default) | `var(--xpl-size-150)` (24px) |\n| Height (small) | `var(--xpl-size-125)` (20px) |\n| Border radius | `var(--xpl-border-radius-button)` |\n| Typography (default) | `var(--xpl-font-size-body)` / `var(--xpl-font-weight-normal)` |\n| Typography (small) | `var(--xpl-font-size-callout)` / `var(--xpl-font-weight-semibold)` |\n| Background (dragging) | `var(--xpl-background-surface-information-bold)` |\n| Cursor (draggable) | `cursor: grab` → `cursor: grabbing` while dragging |\n\n## Accessibility\n\n### Keyboard Navigation\n\n| Key | Action |\n|-----|--------|\n| Tab | Focus tag content or dismiss button |\n| Enter/Space | Activate the focused control: on **dismiss**, emits deprecated `close` and `tagRemove`; on **content**, emits deprecated `close` only when the tag is **not** in drag mode (native `<button>` behavior). |\n\n### Drag mode\n\n- With `isDraggable`, focus moves to the **label** (`role=\"button\"`). Enter/Space on the label does **not** dismiss the tag (same as click on draggable content).\n- Start drags from the **label**; the dismiss control remains a separate focus stop and is not the drag handle.\n\n### ARIA Attributes\n\n- Dismiss button sets `aria-label` to `Dismiss` plus the host element’s `textContent` (trimmed), or the word `tag` when empty, so multiple tags stay distinguishable in screen readers\n- When `disabled={true}`, buttons have `disabled` attribute preventing interaction\n- When `isDraggable` is set, **`aria-grabbed`** on the **label** reflects drag state (`\"false\"` at rest, `\"true\"` while dragging)\n\n### Icon Mapping\n\n| Element | Icon |\n|---------|------|\n| Dismiss button | `xmark` (size 10) |\n\n## Backward Compatibility (CSS class aliases)\n\nThe refactored component preserves legacy CSS classes so existing consumer selectors keep working:\n\n| Legacy class | Element | Replaces / alias for |\n|---|---|---|\n| `xpl-tag-container` | Host (`<xpl-tag>`) | Old root class — now an alias; styles come from `.xpl-tag` |\n| `xpl-tag` | Content `<button>` / `<div>` | Old content selector (`button.xpl-tag`) — kept so `.xpl-tag-container .xpl-tag` selectors match |\n| `xpl-tag__close` | Dismiss `<button>` | Old dismiss selector — alias for `.xpl-tag__dismiss` |\n\nThese aliases will be removed in a future major version. New code should target `.xpl-tag`, `.xpl-tag__content`, and `.xpl-tag__dismiss`.\n",
|
|
16058
|
+
"readme": "# xpl-tag\n\nTags represent a set of interactive keywords that help label, organize, and categorize objects. Tags can be added or removed from an object by the user. Unlike Badges, Tags are clickable, used in dropdowns, multi-select, search bars, etc.\n\n## Usage Examples\n\n### Basic tag with dismiss\n\n```html\n<xpl-tag>Label</xpl-tag>\n```\n\n### Small size variant\n\n```html\n<xpl-tag size=\"sm\">Small Tag</xpl-tag>\n```\n\n### Non-dismissible tag (no close button)\n\n```html\n<xpl-tag dismissible=\"false\">Static Tag</xpl-tag>\n```\n\n### Disabled tag\n\n```html\n<xpl-tag disabled>Disabled Tag</xpl-tag>\n```\n\n### Handling events\n\n> **⚠️ Deprecation Notice:** The `close` event is **deprecated** and will be removed in a future major version. Use `tagRemove` for dismiss button clicks only.\n\n#### Why This Change?\n\nThe `close` event name conflicts with a **native HTML event** used by `<dialog>` elements. The React wrapper's `isCoveredByReact()` function detects `onclose` as a native event and passes handlers to React's synthetic event system — but React doesn't actually handle `close` events this way, so handlers silently fail in React applications.\n\n**Why `tagRemove` works:** `ontagremove` is not a native event, so the wrapper correctly falls back to `addEventListener`.\n\n#### Event Behavior\n\n| Interaction | `close` (deprecated) | `tagRemove` (use this) |\n|-------------|------------------------|------------------------|\n| Dismiss (×) button clicked | ✅ Fires | ✅ Fires |\n| Content clicked (non-draggable) | ✅ Fires | ❌ Does NOT fire |\n| Content clicked (draggable) | ❌ Does NOT fire | ❌ Does NOT fire |\n| Keyboard Space/Enter on content (non-draggable) | ✅ Fires | ❌ Does NOT fire |\n| Keyboard Space/Enter on draggable label | ❌ Does NOT fire | ❌ Does NOT fire |\n\n#### Migration Examples\n\n**Before (deprecated):**\n```tsx\n// React — this may silently fail!\n<XplTag onClose={() => tag.remove()}>Label</XplTag>\n\n// Vanilla JS\nconst tag = document.querySelector('xpl-tag');\ntag.addEventListener('close', () => tag.remove());\n```\n\n**After (recommended):**\n```tsx\n// React — works reliably\n<XplTag onTagRemove={() => tag.remove()}>Label</XplTag>\n\n// Vanilla JS — same pattern, clearer intent\nconst tag = document.querySelector('xpl-tag');\ntag.addEventListener('tagRemove', () => tag.remove());\n```\n\n**React with Refs (if you must use deprecated `close`):**\n```tsx\nimport { useEffect, useRef } from 'react';\nimport { XplTag } from '@xplortech/apollo-react';\n\nfunction MyComponent() {\n const tagRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n const el = tagRef.current;\n if (!el) return;\n\n const handleClose = () => el.remove();\n el.addEventListener('close', handleClose);\n return () => el.removeEventListener('close', handleClose);\n }, []);\n\n return <XplTag ref={tagRef}>Label</XplTag>;\n}\n```\n\n## Drag and drop\n\nTags support **native HTML5 drag and drop**. Set the boolean prop **`isDraggable`** (HTML attribute **`is-draggable`**) to enable dragging. Optionally set **`tag-id`** so `dataTransfer` and `tagDragStart` / `tagDragEnd` detail carry a stable id.\n\n### How it works (important for handlers)\n\n- The **drag source** is an inner **label** element (a `div` with `role=\"button\"`), not the `<xpl-tag>` host. Browsers do not start drags reliably on the custom element host; the **`is-draggable`** prop does **not** mirror the native host **`draggable`** attribute (see the `isDraggable` prop docs below).\n- On **`dragstart`**, the component uses **`setDragImage`** so the floating preview (“ghost”) looks like the **whole tag** (label + dismiss control), not only the label strip.\n- **Start the drag from the label text**, not from the dismiss (×) button.\n- In container listeners, **`dragstart`** may bubble with `event.target` equal to that inner node. Resolve the tag with:\n\n```js\nconst tag = event.target instanceof Element ? event.target.closest('xpl-tag') : null;\n```\n\n### Making a tag draggable\n\n```html\n<xpl-tag is-draggable>Draggable tag</xpl-tag>\n\n<xpl-tag is-draggable tag-id=\"my-tag-1\">Design</xpl-tag>\n```\n\n### Reordering tags within a container\n\n```html\n<div id=\"tag-container\" style=\"display: flex; flex-wrap: wrap; gap: 8px\">\n <xpl-tag tag-id=\"t1\" is-draggable>Design</xpl-tag>\n <xpl-tag tag-id=\"t2\" is-draggable>Development</xpl-tag>\n <xpl-tag tag-id=\"t3\" is-draggable>QA</xpl-tag>\n</div>\n\n<script>\n const container = document.getElementById('tag-container');\n let draggedEl = null;\n\n container.addEventListener('dragstart', (e) => {\n const tag = e.target instanceof Element ? e.target.closest('xpl-tag') : null;\n if (tag) draggedEl = tag;\n });\n\n container.addEventListener('dragend', () => {\n draggedEl = null;\n });\n\n container.addEventListener('dragover', (e) => {\n e.preventDefault();\n if (!draggedEl) return;\n const afterEl = getDragAfterElement(container, e.clientX);\n if (afterEl == null) container.appendChild(draggedEl);\n else container.insertBefore(draggedEl, afterEl);\n });\n\n function getDragAfterElement(container, x) {\n const tags = [...container.querySelectorAll('xpl-tag')].filter((el) => el !== draggedEl);\n return tags.reduce(\n (closest, child) => {\n const box = child.getBoundingClientRect();\n const offset = x - box.left - box.width / 2;\n return offset < 0 && offset > closest.offset ? { offset, element: child } : closest;\n },\n { offset: Number.NEGATIVE_INFINITY },\n ).element;\n }\n</script>\n```\n\n### Dragging tags between containers\n\n```html\n<div\n class=\"drop-zone\"\n style=\"display: flex; gap: 8px; padding: 16px; border: 2px dashed var(--xpl-border-default); border-radius: 8px\"\n>\n <xpl-tag tag-id=\"a1\" is-draggable>Frontend</xpl-tag>\n <xpl-tag tag-id=\"a2\" is-draggable>Backend</xpl-tag>\n</div>\n\n<div\n class=\"drop-zone\"\n style=\"\n display: flex;\n gap: 8px;\n padding: 16px;\n border: 2px dashed var(--xpl-border-default);\n border-radius: 8px;\n margin-top: 8px;\n \"\n>\n <xpl-tag tag-id=\"b1\" is-draggable>DevOps</xpl-tag>\n</div>\n\n<script>\n document.querySelectorAll('.drop-zone').forEach((zone) => {\n let draggedEl = null;\n\n zone.addEventListener('dragstart', (e) => {\n const tag = e.target instanceof Element ? e.target.closest('xpl-tag') : null;\n if (tag) draggedEl = tag;\n });\n\n zone.addEventListener('dragend', () => {\n draggedEl = null;\n });\n\n zone.addEventListener('dragover', (e) => e.preventDefault());\n\n zone.addEventListener('drop', (e) => {\n e.preventDefault();\n if (draggedEl && draggedEl.parentNode !== zone) zone.appendChild(draggedEl);\n });\n });\n</script>\n```\n\n### `tagDragStart` / `tagDragEnd` events\n\nThe component emits **`tagDragStart`** and **`tagDragEnd`** (Stencil camelCase). They bubble and are composed.\n\n```html\n<xpl-tag is-draggable tag-id=\"my-tag\">Drag me</xpl-tag>\n\n<script>\n const tag = document.querySelector('xpl-tag[tag-id=\"my-tag\"]');\n\n tag.addEventListener('tagDragStart', (e) => {\n const { tagId, content, originalEvent } = e.detail;\n });\n\n tag.addEventListener('tagDragEnd', (e) => {\n const { dropped, tagId, originalEvent } = e.detail;\n if (dropped) {\n /* dropEffect was 'move' */\n }\n });\n</script>\n```\n\n### React (`@xplortech/apollo-react`)\n\nEnsure the app loads Apollo **defineCustomElements** (see the main React package docs). Import **`XplTag`** and use **`isDraggable`**, **`tagId`**, and children for the label.\n\n`HTMLXplTagElement` is provided by Apollo’s Stencil typings (the same setup that types `defineCustomElements`). If your editor cannot resolve it, use `useRef<HTMLElement | null>(null)` and attach listeners on `ref.current`.\n\n`XplTag` is a thin wrapper around the web component. Custom events use the same names as in the DOM (`tagDragStart`, `tagDragEnd`, `tagRemove`). If your TypeScript definitions use different prop names for listeners, attach them with a **ref** (always works):\n\n```tsx\nimport { useEffect, useRef } from 'react';\nimport { XplTag } from '@xplortech/apollo-react';\n\nfunction TagBoard() {\n const tagRef = useRef<HTMLXplTagElement | null>(null);\n\n useEffect(() => {\n const el = tagRef.current;\n if (!el) return;\n\n const onDragStart = (e: CustomEvent) => {\n const { tagId, content } = e.detail;\n };\n const onDragEnd = (e: CustomEvent) => {\n const { dropped, tagId } = e.detail;\n };\n const onTagRemove = () => {\n el.remove(); // Handle dismiss button click\n };\n\n el.addEventListener('tagDragStart', onDragStart as EventListener);\n el.addEventListener('tagDragEnd', onDragEnd as EventListener);\n el.addEventListener('tagRemove', onTagRemove);\n return () => {\n el.removeEventListener('tagDragStart', onDragStart as EventListener);\n el.removeEventListener('tagDragEnd', onDragEnd as EventListener);\n el.removeEventListener('tagRemove', onTagRemove);\n };\n }, []);\n\n return (\n <XplTag ref={tagRef} isDraggable tagId=\"react-1\">\n Movable\n </XplTag>\n );\n}\n```\n\nReorder / multi-container logic is unchanged: listen for native `dragstart`, `dragover`, `drop` on a React parent `div` (use refs) and call `closest('xpl-tag')` as in the HTML examples.\n\n### `DataTransfer` payload\n\n| MIME type | Value | Purpose |\n|-----------|-------|---------|\n| `application/x-tag-id` | `tag-id` prop, if set | Identify the tag in drop handlers |\n| `text/plain` | Trimmed text content of the tag | Fallback for external targets |\n\n`effectAllowed` is set to `move`.\n\n**`originalEvent` in `tagDragStart` / `tagDragEnd`:** the native `DragEvent` is included for convenience, but browsers may clear `dataTransfer` after the synchronous handler completes. Use `tagId`, `content`, and `dropped` from the custom event detail for anything needed after the current turn; only read `originalEvent.dataTransfer` synchronously in the listener.\n\n### Disabled tags\n\n`disabled` wins: the tag is not draggable and keep using a normal `<button>` label (no HTML5 drag on the host).\n\n```html\n<xpl-tag is-draggable disabled>Cannot drag</xpl-tag>\n```\n\n## Design Tokens\n\n| Property | Token |\n|----------|-------|\n| Border (default) | `var(--xpl-border-accent-information)` |\n| Border (disabled) | `var(--xpl-border-accent-subtle)` |\n| Background (default) | `var(--xpl-background-surface-default)` |\n| Background (hover) | `var(--xpl-background-surface-information-bold)` |\n| Background (disabled) | `var(--xpl-background-surface-subtle)` |\n| Text | `var(--xpl-text-strong)` |\n| Text (disabled) | `var(--xpl-text-disabled)` |\n| Dismiss icon | `var(--xpl-icon-default)` |\n| Dismiss icon (disabled) | `var(--xpl-icon-disabled)` |\n| Spacing (default) | `var(--xpl-space-2)` vertical, `var(--xpl-space-12)` horizontal |\n| Spacing (small) | `var(--xpl-space-2)` vertical, `var(--xpl-space-8)` horizontal |\n| Height (default) | `var(--xpl-size-150)` (24px) |\n| Height (small) | `var(--xpl-size-125)` (20px) |\n| Border radius | `var(--xpl-border-radius-button)` |\n| Typography (default) | `var(--xpl-font-size-body)` / `var(--xpl-font-weight-normal)` / `var(--xpl-line-height-body)` |\n| Typography (small) | `var(--xpl-font-size-callout)` / `var(--xpl-font-weight-semibold)` / `var(--xpl-line-height-callout)` |\n| Background (dragging) | `var(--xpl-background-surface-information-bold)` |\n| Cursor (draggable) | `cursor: grab` → `cursor: grabbing` while dragging |\n\n## Accessibility\n\n### Keyboard Navigation\n\n| Key | Action |\n|-----|--------|\n| Tab | Focus tag content or dismiss button |\n| Enter/Space | Activate the focused control: on **dismiss**, emits deprecated `close` and `tagRemove`; on **content**, emits deprecated `close` only when the tag is **not** in drag mode (native `<button>` behavior). |\n\n### Drag mode\n\n- With `isDraggable`, focus moves to the **label** (`role=\"button\"`). Enter/Space on the label does **not** dismiss the tag (same as click on draggable content).\n- Start drags from the **label**; the dismiss control remains a separate focus stop and is not the drag handle.\n\n### ARIA Attributes\n\n- Dismiss button sets `aria-label` to `Dismiss` plus the host element’s `textContent` (trimmed), or the word `tag` when empty, so multiple tags stay distinguishable in screen readers\n- When `disabled={true}`, buttons have `disabled` attribute preventing interaction\n- When `isDraggable` is set, **`aria-grabbed`** on the **label** reflects drag state (`\"false\"` at rest, `\"true\"` while dragging)\n\n### Icon Mapping\n\n| Element | Icon |\n|---------|------|\n| Dismiss button | `xmark` (size 10) |\n\n## Backward Compatibility (CSS class aliases)\n\nThe refactored component preserves legacy CSS classes so existing consumer selectors keep working:\n\n| Legacy class | Element | Replaces / alias for |\n|---|---|---|\n| `xpl-tag-container` | Host (`<xpl-tag>`) | Old root class — now an alias; styles come from `.xpl-tag` |\n| `xpl-tag` | Content `<button>` / `<div>` | Old content selector (`button.xpl-tag`) — kept so `.xpl-tag-container .xpl-tag` selectors match |\n| `xpl-tag__close` | Dismiss `<button>` | Old dismiss selector — alias for `.xpl-tag__dismiss` |\n\nThese aliases will be removed in a future major version. New code should target `.xpl-tag`, `.xpl-tag__content`, and `.xpl-tag__dismiss`.\n",
|
|
15463
16059
|
"docs": "Tags represent a set of interactive keywords that help label, organize, and categorize objects. Tags can be added or removed from an object by the user. Unlike Badges, Tags are clickable, used in dropdowns, multi-select, search bars, etc.",
|
|
15464
16060
|
"docsTags": [
|
|
16061
|
+
{
|
|
16062
|
+
"name": "slot",
|
|
16063
|
+
"text": "- The tag label content."
|
|
16064
|
+
},
|
|
15465
16065
|
{
|
|
15466
16066
|
"name": "since",
|
|
15467
16067
|
"text": "0.4.0"
|
|
@@ -15646,8 +16246,8 @@
|
|
|
15646
16246
|
"references": {
|
|
15647
16247
|
"TagDragEndDetail": {
|
|
15648
16248
|
"location": "local",
|
|
15649
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
15650
|
-
"id": "src/components/
|
|
16249
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-tag/xpl-tag.tsx",
|
|
16250
|
+
"id": "src/components/xpl-tag/xpl-tag.tsx::TagDragEndDetail"
|
|
15651
16251
|
}
|
|
15652
16252
|
}
|
|
15653
16253
|
},
|
|
@@ -15666,8 +16266,8 @@
|
|
|
15666
16266
|
"references": {
|
|
15667
16267
|
"TagDragStartDetail": {
|
|
15668
16268
|
"location": "local",
|
|
15669
|
-
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/
|
|
15670
|
-
"id": "src/components/
|
|
16269
|
+
"path": "/home/runner/work/apollo/apollo/packages/apollo-core/src/components/xpl-tag/xpl-tag.tsx",
|
|
16270
|
+
"id": "src/components/xpl-tag/xpl-tag.tsx::TagDragStartDetail"
|
|
15671
16271
|
}
|
|
15672
16272
|
}
|
|
15673
16273
|
},
|
|
@@ -15693,7 +16293,12 @@
|
|
|
15693
16293
|
],
|
|
15694
16294
|
"listeners": [],
|
|
15695
16295
|
"styles": [],
|
|
15696
|
-
"slots": [
|
|
16296
|
+
"slots": [
|
|
16297
|
+
{
|
|
16298
|
+
"name": "",
|
|
16299
|
+
"docs": "The tag label content."
|
|
16300
|
+
}
|
|
16301
|
+
],
|
|
15697
16302
|
"parts": [],
|
|
15698
16303
|
"states": [],
|
|
15699
16304
|
"dependents": [
|
|
@@ -15712,12 +16317,20 @@
|
|
|
15712
16317
|
}
|
|
15713
16318
|
},
|
|
15714
16319
|
{
|
|
15715
|
-
"filePath": "src/components/
|
|
16320
|
+
"filePath": "src/components/xpl-toast/xpl-toast.tsx",
|
|
15716
16321
|
"encapsulation": "none",
|
|
15717
16322
|
"tag": "xpl-toast",
|
|
15718
16323
|
"readme": "# xpl-toast\n\nToasts are brief, non-disruptive messages that provide quick, at-a-glance feedback. They can have 3 sentiments; neutral, positive and negative and contain actions such as a button or link, or a close button. Messaging can include a title and caption limited to 85 characters. Keep your toast messaging short and to the point and tone in line with the sentiment of the Toast. \n\nThe Toast component is configurable by Sentiment plus show/hide properties for Icon, Caption, Button and Dismissible. Use the nested component’s properties to customize further as needed. \n\nWhen possible, Toasts should auto-dismiss after 8 seconds. When an action is present, it may not be desirable to time out the Toast depending on your specific context. \n\nMatch your messaging with the sentiment of the toast. Most messages will have a neutral sentiment. Reserve negative sentiments for when an explicit failure has occurred. Give users the information they need to correct the issue. \n\nToasts only support a single action and up to 85 characters. If multiple actions can be taken, or the message is longer than a few words, use a [Modal component](https://apollo.xplordocs.com/?path=/story/components-modal--modal) instead.\n\n## Usage\n\n```html\n<!-- Neutral toast with a caption, auto-dismissing after the default 8s -->\n<xpl-toast caption=\"Your changes have been saved.\">\n <p slot=\"title\">Saved</p>\n</xpl-toast>\n\n<!-- With an action. Auto-dismiss is suppressed while the action slot has content -->\n<xpl-toast variant=\"warning\" caption=\"We couldn't reach the server.\">\n <p slot=\"title\">Sync failed</p>\n <xpl-button slot=\"action\" size=\"sm\">Retry</xpl-button>\n</xpl-toast>\n\n<!-- No close button; disable auto-dismiss with timeout=\"0\" -->\n<xpl-toast dismissible=\"false\" timeout=\"0\">\n <p slot=\"title\">Uploading…</p>\n</xpl-toast>\n```\n\n## Deprecations\n\n### `dismissable` → `dismissible`\n\nThe **`dismissable`** prop is misspelled and is **deprecated**. Use **`dismissible`** instead.\n\n```html\n<!-- Before -->\n<xpl-toast dismissable=\"false\">…</xpl-toast>\n\n<!-- After -->\n<xpl-toast dismissible=\"false\">…</xpl-toast>\n```\n\nBoth props are supported during the deprecation window, so no consumer change is required immediately:\n\n| `dismissable` | `dismissible` | Close button shown | Notes |\n| ------------- | ------------- | ------------------ | ----- |\n| unset | unset | ✅ | Default (`dismissible` defaults to `true`) |\n| unset | `false` | ❌ | Recommended usage |\n| `false` | unset | ❌ | Existing markup keeps working |\n| `false` | `true` | ❌ | `dismissable` wins while it exists |\n\n`dismissable` has **no default** (`undefined` when unset) so the component can tell \"not set\" from \"set to `false`\". When it is used, the component logs a one-time deprecation warning to the console. `dismissable` will be removed in the next major version, at which point `dismissible` becomes the only option.\n\n## Positioning\n\nThe default position is arbitrarily set to `40px` from top and `40px` from right of the browser viewport on desktop and bottom-center on mobile. This position should be adjusted to ensure it's not covering your App's header. Apollo, by design, does not prescribe a position for toasts because this will be dependent on the app that it is being used in.\n\nPositioning of toasts should be global to your app. For example, if it is decided that your app will always position the toast in the top right corner, then this convention should be followed throughout. It should not be positioned top-right on one screen and bottom-center on another.\n\n*****Consult your designer for the best placement for your product.**\n\n### Overriding the default position\n\nThe toast uses `position: fixed` and can be repositioned by overriding the `.xpl-toast` CSS class in your app's stylesheet. Set `top`, `right`, `bottom`, and `left` as needed and use `unset` or `initial` to clear any defaults you don't want.\n\n**Top-left example:**\n```css\n.xpl-toast {\n top: 24px;\n right: unset;\n left: 24px;\n}\n```\n\n**Bottom-right example:**\n```css\n.xpl-toast {\n top: unset;\n right: 24px;\n bottom: 24px;\n}\n```\n\n**Centered at the top:**\n```css\n.xpl-toast {\n top: 24px;\n right: unset;\n left: 50%;\n transform: translateX(-50%);\n}\n```\n\nThe mobile breakpoint (≤ 768px) resets the toast to bottom-center. If your app needs a different mobile position, override the media query as well:\n\n```css\n@media screen and (max-width: 768px) {\n .xpl-toast {\n /* your mobile overrides */\n bottom: 16px;\n left: 50%;\n transform: translateX(-50%);\n }\n}\n```\n\n> **Tip:** Place these overrides in a global stylesheet so every toast in your app appears in the same location.\n\n## Token Use\n\n`xpl-toast` follows the same messaging-component token pattern as [`xpl-banner`](../xpl-banner) (background `--xpl-background-messaging-*` + accent/sentiment border). Light and dark mode are handled by the Foundation token definitions, so the component has no `.dark` overrides.\n\n| Variant / element | Property | Token |\n| ----------------- | -------- | ----- |\n| `neutral` (default) | background | `--xpl-background-messaging-information` |\n| `neutral` (default) | border | `--xpl-border-accent-information` |\n| `&--warning` | background | `--xpl-background-messaging-negative` |\n| `&--warning` | border | `--xpl-border-negative` |\n| `&--success` | background | `--xpl-background-messaging-positive` |\n| `&--success` | border | `--xpl-border-positive` |\n| `&__icon--neutral` | color | `--xpl-icon-default` |\n| `&__icon--warning` | color | `--xpl-icon-negative` |\n| `&__icon--success` | color | `--xpl-icon-positive` |\n| `&` | body radius | `--xpl-border-radius-small` |\n| `&` | shadow | `--xpl-elevation-3` (theme-aware) |\n| `&__title` | typography (size / weight / line-height) | `@extend .xpl-text-title-5` → `title-5` / `medium` / `1.4286` |\n| `&__caption` | typography (size / weight / line-height) | `@extend .xpl-text-callout` → `callout` / `normal` / `1.3333` |\n| `&__close` | margin | `@apply ml-4` |\n\nThe close control is an [`xpl-button`](../xpl-button) (`variant=\"tertiary\"`, `size=\"sm\"`, `iconOnly`), so its radius, colors, and hover / focus / active states come from `button.css` rather than `toast.css`.\n\nLike `xpl-banner`, the messaging backgrounds resolve to transparent in dark mode; the sentiment border and page surface carry the visual treatment in that theme.\n\n## Accessibility\n\n- The close control is an [`xpl-button`](../xpl-button), so it is focusable and keyboard-activable (Tab, then Enter or Space) and gets the shared `:focus-visible` outline.\n- It carries `aria-label=\"Dismiss notification\"` and `type=\"button\"` — the explicit type keeps a toast rendered inside a `<form>` from submitting it when the toast is closed.\n- Toast content is projected through the `title` and `action` slots. Provide the title as text (e.g. `<p slot=\"title\">`) so screen readers announce the message.\n- Dismissing runs a fade-out animation and then removes the host element from the DOM, so a dismissed toast leaves nothing behind in the accessibility tree.\n\n> **Elevation shadow:** the toast uses `--xpl-elevation-3` (theme-aware), re-specified by design during the elevation 1–4 formalization — an earlier note citing the single \"Shadow 4\" style was superseded. See `TECH_DEBT.md`.\n",
|
|
15719
16324
|
"docs": "Toasts are brief, non-disruptive messages that provide quick, at-a-glance feedback. They can have 3 sentiments; neutral, positive and negative and contain actions such as a button or link, or a close button. Messaging can include a title and caption limited to 85 characters. Keep your toast messaging short and to the point and tone in line with the sentiment of the Toast. \n\nThe Toast component is configurable by Sentiment plus show/hide properties for Icon, Caption, Button and Dismissible. Use the nested component’s properties to customize further as needed. \n\nWhen possible, Toasts should auto-dismiss after 8 seconds. When an action is present, it may not be desirable to time out the Toast depending on your specific context. \n\nMatch your messaging with the sentiment of the toast. Most messages will have a neutral sentiment. Reserve negative sentiments for when an explicit failure has occurred. Give users the information they need to correct the issue. \n\nToasts only support a single action and up to 85 characters. If multiple actions can be taken, or the message is longer than a few words, use a [Modal component](https://apollo.xplordocs.com/?path=/story/components-modal--modal) instead.",
|
|
15720
16325
|
"docsTags": [
|
|
16326
|
+
{
|
|
16327
|
+
"name": "slot",
|
|
16328
|
+
"text": "title - The toast title text."
|
|
16329
|
+
},
|
|
16330
|
+
{
|
|
16331
|
+
"name": "slot",
|
|
16332
|
+
"text": "action - Optional action content (e.g. a button) rendered on the right side of the toast."
|
|
16333
|
+
},
|
|
15721
16334
|
{
|
|
15722
16335
|
"name": "since",
|
|
15723
16336
|
"text": "1.2.0"
|
|
@@ -15913,7 +16526,16 @@
|
|
|
15913
16526
|
"events": [],
|
|
15914
16527
|
"listeners": [],
|
|
15915
16528
|
"styles": [],
|
|
15916
|
-
"slots": [
|
|
16529
|
+
"slots": [
|
|
16530
|
+
{
|
|
16531
|
+
"name": "action",
|
|
16532
|
+
"docs": "Optional action content (e.g. a button) rendered on the right side of the toast."
|
|
16533
|
+
},
|
|
16534
|
+
{
|
|
16535
|
+
"name": "title",
|
|
16536
|
+
"docs": "The toast title text."
|
|
16537
|
+
}
|
|
16538
|
+
],
|
|
15917
16539
|
"parts": [],
|
|
15918
16540
|
"states": [],
|
|
15919
16541
|
"dependents": [],
|
|
@@ -15932,7 +16554,7 @@
|
|
|
15932
16554
|
}
|
|
15933
16555
|
},
|
|
15934
16556
|
{
|
|
15935
|
-
"filePath": "src/components/
|
|
16557
|
+
"filePath": "src/components/xpl-toggle/xpl-toggle.tsx",
|
|
15936
16558
|
"encapsulation": "none",
|
|
15937
16559
|
"tag": "xpl-toggle",
|
|
15938
16560
|
"readme": "# xpl-toggle\n\nA Toggle is a type of form control that is used to switch between enabled and disabled states of an element.\n\n## Usage\n\n```html\n<xpl-toggle heading=\"Notifications\" label=\"Email me\" checked></xpl-toggle>\n<xpl-toggle label=\"Compact\" variant=\"small\"></xpl-toggle>\n<xpl-toggle label=\"Unavailable\" disabled></xpl-toggle>\n```\n\n## Design Tokens\n\nThe toggle uses Apollo Foundation purpose-specific tokens so it themes automatically\nin light and dark mode (no `.dark` overrides).\n\n| Element / state | Property | Token |\n| --- | --- | --- |\n| Track (off) | `background-color` | `--xpl-background-accent-neutral` |\n| Track (off, hover) | `background-color` | `--xpl-background-accent-neutral-bold` |\n| Track (on) | `background-color` | `--xpl-background-action-primary-default` |\n| Track (on, hover) | `background-color` | `--xpl-background-action-primary-hover` |\n| Track (disabled, on/off) | `background-color` | `--xpl-background-action-disabled` |\n| Track border | `border-color` | `--xpl-border-default` |\n| Knob (all states) | `background-color` | `--xpl-background-surface-inverse-on-dark` (always-light — resolves to neutral-0 in both modes) |\n| Knob shadow | `box-shadow` | `--xpl-elevation-1` (theme-aware) |\n| Focus ring | `outline-color` | `--xpl-border-focus` (2px outline, 2px offset) |\n| Heading | `color` | `--xpl-text-strong` |\n| Heading | typography | `@extend .xpl-text-title-5` — 14px / medium / 1.4286 (via shared `label.css`) |\n| Trailing label | `color` | `--xpl-text-strong` |\n| Trailing label | typography | `@extend .xpl-text-body` — 14px / normal / 1.4286 |\n| Label (disabled) | `color` | `--xpl-text-disabled` |\n| Description (`small`) | `color` | `--xpl-text-subdued` |\n| Description (`small`) | typography | `@extend .xpl-text-callout` — 12px / normal / 1.3333 (via shared `label.css`) |\n\n**Sizing:** knob (`--xpl-size-125` / small `--xpl-size-075`), default track height\n(`--xpl-size-150`), small track height/radius (`--xpl-size-100` / `--xpl-border-radius-default`),\ndefault track + knob radius (`--xpl-border-radius-full`), inset (`--xpl-space-2`), knob travel\n(`translateX(--xpl-size-125)` / small `--xpl-size-075`). The `44px`/`28px` track widths have no\nmatching Foundation token and remain literals (see TECH_DEBT.md).\n\nThe knob glyphs (X / check marks) remain hardcoded data-URI SVGs; a `mask-image` +\n`var(--xpl-icon-*)` refactor is tracked in TECH_DEBT.md.\n\n## Accessibility\n\nThe toggle renders a native `<input type=\"checkbox\">`, so it is keyboard-focusable and\noperable with Tab and Space. The `:focus-visible` outline is applied to the control itself.\n",
|
|
@@ -16145,12 +16767,20 @@
|
|
|
16145
16767
|
"dependencyGraph": {}
|
|
16146
16768
|
},
|
|
16147
16769
|
{
|
|
16148
|
-
"filePath": "src/components/
|
|
16770
|
+
"filePath": "src/components/xpl-toolbar/xpl-toolbar.tsx",
|
|
16149
16771
|
"encapsulation": "none",
|
|
16150
16772
|
"tag": "xpl-toolbar",
|
|
16151
|
-
"readme": "# xpl-toolbar\n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\n## Design Tokens\n\nThe toolbar is an **always-dark** selection bar (nav-rail pattern) — its surface stays dark\nin both light and dark themes. Styling comes from Apollo Foundation tokens\n(`packages/apollo-core/src/
|
|
16773
|
+
"readme": "# xpl-toolbar\n\n> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.\n\n## Design Tokens\n\nThe toolbar is an **always-dark** selection bar (nav-rail pattern) — its surface stays dark\nin both light and dark themes. Styling comes from Apollo Foundation tokens\n(`packages/apollo-core/src/components/xpl-toolbar/toolbar.css`):\n\n| Element | Property | Token | Resolves (light / dark) |\n| --- | --- | --- | --- |\n| `.toolbar` surface | `background-color` | `--xpl-background-surface-inverse-on-light` | neutral-1000 / neutral-1000 |\n| `.toolbar` top/bottom border | `border-color` | `--xpl-border-default` | neutral-600 (always-dark host) |\n| `.toolbar` elevation | `box-shadow` | `--xpl-elevation-1` | theme-aware (near-black light / near-white dark) |\n| `.toolbar` height | `height` | `--xpl-size-350` | 56px |\n| `.selected-item-count` text | `color` | `--xpl-text-inverse-on-dark` | white / white |\n| `.selected-item-count` divider | `border-color` | `--xpl-border-default` | neutral-600 (always-dark host) |\n| `.selected-item-count` label | `font-size` / `font-weight` / `line-height` | `@extend .xpl-text-title-5` (14px, medium, 1.4286) | — |\n\n> **Design note:** the always-dark surface decision is confirmed (there is no\n> toolbar node in `figma-manifest.json`). The elevation uses the theme-aware\n> `--xpl-elevation-1` token: in dark mode the shadow color flips to near-white, so\n> the always-dark bar gets a light halo beneath it — flagged for design verification\n> (see `TECH_DEBT.md`).\n",
|
|
16152
16774
|
"docs": "> **Note:** This component is currently in beta. Use with caution as it may have breaking changes in future releases.",
|
|
16153
16775
|
"docsTags": [
|
|
16776
|
+
{
|
|
16777
|
+
"name": "slot",
|
|
16778
|
+
"text": "actions-left - Actions rendered in the left group of the toolbar."
|
|
16779
|
+
},
|
|
16780
|
+
{
|
|
16781
|
+
"name": "slot",
|
|
16782
|
+
"text": "actions-right - Actions rendered in the right group of the toolbar."
|
|
16783
|
+
},
|
|
16154
16784
|
{
|
|
16155
16785
|
"name": "since",
|
|
16156
16786
|
"text": "1.2.0"
|
|
@@ -16199,7 +16829,16 @@
|
|
|
16199
16829
|
}
|
|
16200
16830
|
],
|
|
16201
16831
|
"styles": [],
|
|
16202
|
-
"slots": [
|
|
16832
|
+
"slots": [
|
|
16833
|
+
{
|
|
16834
|
+
"name": "actions-left",
|
|
16835
|
+
"docs": "Actions rendered in the left group of the toolbar."
|
|
16836
|
+
},
|
|
16837
|
+
{
|
|
16838
|
+
"name": "actions-right",
|
|
16839
|
+
"docs": "Actions rendered in the right group of the toolbar."
|
|
16840
|
+
}
|
|
16841
|
+
],
|
|
16203
16842
|
"parts": [],
|
|
16204
16843
|
"states": [],
|
|
16205
16844
|
"dependents": [],
|
|
@@ -16207,12 +16846,16 @@
|
|
|
16207
16846
|
"dependencyGraph": {}
|
|
16208
16847
|
},
|
|
16209
16848
|
{
|
|
16210
|
-
"filePath": "src/components/
|
|
16849
|
+
"filePath": "src/components/xpl-tooltip/xpl-tooltip.tsx",
|
|
16211
16850
|
"encapsulation": "none",
|
|
16212
16851
|
"tag": "xpl-tooltip",
|
|
16213
16852
|
"readme": "# xpl-tooltip\n\nTooltips are intended to be short one to two sentence messages adding contextual information for the user. Keep messages short and to the point. Tooltips are static and do not contain actions, and only appear when the context is hovered.\n\nTooltip variants control one of 8 arrow positions indicating the direction the tooltip will appear in relation to it's trigger:\n\"bottom-left\" | \"bottom-middle\" | \"bottom-right\" | \"left\" | \"right\" | \"top-left\" | \"top-middle\" | \"top-right\"\n\n\n### Design Tokens\n\nTokens used by this component from `@xplortech/apollo-foundation`.\n\n**Color**\n- `--xpl-background-surface-default` — tooltip background and arrow fill\n- `--xpl-elevation-3` — tooltip shadow (theme-aware)\n- `--xpl-text-default` — tooltip text color\n- `--xpl-border-default` — tooltip border and arrow stroke (keeps the arrow edge theme-aware in dark mode)\n\n**Spacing**\n- `--xpl-space-6` — vertical padding\n- `--xpl-space-8` — horizontal padding\n- `--xpl-space-12` — offset from trigger, via `--xpl-tooltip-margin`\n\n**Typography**\n- `.xpl-text-callout` — text style (via `@extend`)\n\n**Border**\n- `--xpl-border-small` — border width (1px)\n- `--xpl-border-radius-small` — corner radius (4px)\n\n**Z-index**\n- `--xpl-z-index-900` — tooltip stacking order\n- `--xpl-z-index-100` — arrow base stacking order (elevated to `--xpl-z-index-900` per position variant)\n",
|
|
16214
16853
|
"docs": "Tooltips are intended to be short one to two sentence messages adding contextual information for the user. Keep messages short and to the point. Tooltips are static and do not contain actions, and only appear when the context is hovered.\n\nTooltip variants control one of 8 arrow positions indicating the direction the tooltip will appear in relation to it's trigger:\n\"bottom-left\" | \"bottom-middle\" | \"bottom-right\" | \"left\" | \"right\" | \"top-left\" | \"top-middle\" | \"top-right\"",
|
|
16215
16854
|
"docsTags": [
|
|
16855
|
+
{
|
|
16856
|
+
"name": "slot",
|
|
16857
|
+
"text": "- The trigger element the tooltip is attached to."
|
|
16858
|
+
},
|
|
16216
16859
|
{
|
|
16217
16860
|
"name": "since",
|
|
16218
16861
|
"text": "1.7.0"
|
|
@@ -16335,7 +16978,12 @@
|
|
|
16335
16978
|
"events": [],
|
|
16336
16979
|
"listeners": [],
|
|
16337
16980
|
"styles": [],
|
|
16338
|
-
"slots": [
|
|
16981
|
+
"slots": [
|
|
16982
|
+
{
|
|
16983
|
+
"name": "",
|
|
16984
|
+
"docs": "The trigger element the tooltip is attached to."
|
|
16985
|
+
}
|
|
16986
|
+
],
|
|
16339
16987
|
"parts": [],
|
|
16340
16988
|
"states": [],
|
|
16341
16989
|
"dependents": [
|
|
@@ -16349,7 +16997,7 @@
|
|
|
16349
16997
|
}
|
|
16350
16998
|
},
|
|
16351
16999
|
{
|
|
16352
|
-
"filePath": "src/components/
|
|
17000
|
+
"filePath": "src/components/xpl-top-nav/xpl-top-nav.tsx",
|
|
16353
17001
|
"encapsulation": "none",
|
|
16354
17002
|
"tag": "xpl-top-nav",
|
|
16355
17003
|
"readme": "# xpl-top-nav\n\nTop navigation shell for navigating between Xplor applications and account controls — brand, cross-app navigation, right-side actions, and an optional account menu. In Xplor's primary use case it switches between Xplor products within one account, while the side navigation handles primary navigation within a single app.\n\n## Usage\n\nUse slots only for layout content. The component provides the internal wrappers for the right rail and user menu. The right side renders `right-aside` then the user menu (built-in trigger + panel). `left-aside` is intended for `xpl-top-nav-item` links (each item should use **`slot=\"left-aside\"`** so they are direct children of the internal **`role=\"list\"`** — avoid wrapping them in a single container with that slot). Set the **`child-account-label`** attribute (or **`childAccountLabel`** in React) for the built-in menu trigger label beside the chevron; use **`slot=\"user-menu-trigger\"`** to replace that trigger entirely. If `brand-href` is set, the brand uses native link navigation. If not, the component emits `brandClick`.\n\n### Web component (typical layout)\n\n```html\n<xpl-top-nav\n brand-name=\"My App\"\n brand-href=\"/\"\n label=\"Main navigation\"\n child-account-label=\"Account\"\n nav-control\n>\n <xpl-top-nav-item slot=\"left-aside\" label=\"Home\" href=\"/\" icon=\"house-4\"></xpl-top-nav-item>\n <xpl-top-nav-item slot=\"left-aside\" label=\"Reports\" href=\"/reports\"></xpl-top-nav-item>\n\n <xpl-button slot=\"right-aside\" variant=\"secondary\">Help</xpl-button>\n <xpl-nav-header-menu slot=\"user-menu\" username=\"Alex User\" email=\"alex@example.com\">\n <xpl-top-nav-item slot=\"right-aside-mobile\" label=\"Help\" href=\"/help\"></xpl-top-nav-item>\n <xpl-top-nav-item label=\"Profile\" href=\"/profile\" icon=\"person-1\"></xpl-top-nav-item>\n <xpl-top-nav-item label=\"Sign out\" href=\"/logout\" icon=\"open-rect-arrow-out\"></xpl-top-nav-item>\n </xpl-nav-header-menu>\n</xpl-top-nav>\n```\n\n### Logo from URL and SPA brand (no `brand-href`)\n\n```html\n<xpl-top-nav brand-logo=\"https://example.com/logo.svg\" brand-name=\"Apollo\">\n <xpl-top-nav-item slot=\"left-aside\" label=\"Dashboard\" href=\"#\"></xpl-top-nav-item>\n</xpl-top-nav>\n```\n\nListen for `brandClick` on the host when `brand-href` is omitted.\n\n### Plain HTML (static documentation)\n\nUse the same tags in any HTML page that loads Apollo styles and the component bundle. Prefer slots and `xpl-top-nav-item` rather than copying internal BEM classes.\n\n## Responsive behavior\n\n- `nav-control` enables the mobile drawer toggle. The control is only visible on **narrow viewports** (see **`top-nav.css`**: one pixel below Tailwind **`md`**; hidden from **`md`** / **768px** width upward at default Tailwind).\n- Below **`md`**, **`slot=\"left-aside\"`** (`.xpl-nav-left`) is **hidden** unless **`nav-control`** is set **and** the drawer is open (`xpl-top-nav--nav-control` + `xpl-top-nav--open`). **Without `nav-control` there is no mobile drawer** — primary links are not shown in the narrow bar (duplicate into **`xpl-nav-header-menu`** or widen the viewport if they must stay reachable).\n- Pressing `Escape` closes nested dropdowns first, then closes the mobile drawer if it is still open (when `nav-control` is set). Focus then returns to the hamburger toggle. **Escape** is ignored for closing the drawer while **any** descendant **`xpl-popover`** is open (including the account menu or a consumer-slotted popover in **`left-aside`** / **`right-aside`**).\n- Opening the built-in **account** popover while the mobile drawer is open **closes the drawer** and emits **`navOpen(false)`** so the two surfaces do not stack.\n- On **narrow viewports**, **`slot=\"right-aside\"`** is hidden in the bar. Duplicate those actions into **`xpl-nav-header-menu`** **`slot=\"right-aside-mobile\"`** (narrow-only strip below profile, above the list) so they stay reachable from the account menu.\n- On **`xpl-top-nav-item`**, use **`selected`** for the current page (**`aria-current=\"page\"`**) and optional **`active`** for extra accent styling; see the item readme for modifier details.\n- **`slot=\"dropdown\"`** does not implement arrow-key roving focus; put focusable elements inside the panel or treat full “menu” keyboard behavior as a future enhancement.\n- **Grouping nav items:** put an **`xpl-top-nav-menu`** in a parent **`xpl-top-nav-item`**'s **`slot=\"dropdown\"`** to render a desktop flyout of **`xpl-top-nav-item`** rows (e.g. grouping by product). The same markup also drives the **mobile cascade** below — see **`xpl-top-nav-menu`**'s readme for the full interaction model (back row, focus management, Escape / drawer-close lifecycle).\n- **Mobile cascade:** below **`md`**, tapping a **`left-aside`** parent that has a menu swaps the drawer's Level 1 list for that group's Level 2 rows **in place** (no second panel) — the group's **`xpl-top-nav-menu`** auto-renders a back row (leading `chevron-left` + its `label`) as the first row. Tapping the back row, or pressing **Escape** once, pops back to Level 1; a second **Escape**, or the hamburger toggle, closes the drawer (and resets any still-drilled-in group so the drawer reopens at Level 1). Cascade depth is capped at 2 levels and is mobile-only — the desktop flyout is always a single level of links.\n- **Child-location context on small screens:** for a \"Change Account\" style row (a plain **`xpl-top-nav-item`** you author in **`slot=\"user-menu\"`**), set **`description`** to the current child-location's name so it reads e.g. \"Change Account\" / \"Acme Corp — Downtown Location\" on narrow viewports where that context isn't otherwise visible in the bar. This is a content pattern (see the **`TopNavigation`** story), not a separate framework feature — **`description`** already exists on **`xpl-top-nav-item`**.\n\n## Theming\n\n- The host applies the Foundation `dark` scope so the bar and its slotted children resolve dark-mode purpose tokens automatically.\n- Floating overlays rendered outside the host, such as teleported popover content, may need their own `dark` class if they should match the shell.\n\n## Icon Mapping\n\n| Location | Icon name | Notes |\n| -------- | --------- | ----- |\n| Mobile nav toggle (`nav-control`) | `menu` | Shown inside the bar control when `nav-control` is set. |\n| Built-in account trigger | `chevron-down` | `xpl-button` `icon` prop (end). |\n| Dropdown row (`xpl-top-nav-item` with `slot=\"dropdown\"`) | `chevron-down` | Trailing indicator on the row control. |\n\nConsumer-provided `icon` props on `xpl-top-nav-item` use names from `@xplortech/apollo-icons`.\n\n## Token use\n\n| Area | Token / variable |\n| ---- | ---------------- |\n| Bar surface | `var(--xpl-background-surface-default)` |\n| Bar text (default) | `var(--xpl-text-subdued)` |\n| Bar height | `var(--xpl-size-350)` |\n| Bar padding | `var(--xpl-space-8)` / `var(--xpl-space-16)` |\n| Bottom border | `var(--xpl-border-small)` `var(--xpl-border-default)` |\n| Focus ring | `var(--xpl-border-focus)` with `outline-2` / `outline-offset-2` (see `top-nav.css`) |\n| Panel / drawer width | `var(--xpl-top-nav-panel-width)` (component custom property in `top-nav.css`) |\n| Account popover offset | `var(--xpl-space-16)` below bar (`margin-top` on menu content) |\n\n## Accessibility\n\n- **`nav` landmark:** The `label` prop maps to `aria-label` on the inner `<nav>`. If omitted, it defaults to **`top-navigation-bar`**. Use a unique label when multiple navigation regions exist (e.g. side nav + top nav).\n- **Mobile control:** With `nav-control`, the toggle is a native `<button>` with `aria-expanded` reflecting the drawer and an accessible name for open/close.\n- **Account menu:** The built-in `xpl-button` trigger sets `aria-haspopup=\"dialog\"` to match the internal `xpl-popover` trigger. Chevron-only mode (no `child-account-label` text) adds `aria-label=\"Open account menu\"`. The popover's internal wrapper `<span>` is hidden via CSS `visibility: hidden` so the `xpl-button` is the **single tab stop** — click and keyboard events still bubble to the popover. Custom triggers via `slot=\"user-menu-trigger\"` should set their own accessible name and `aria-haspopup`.\n- **Primary links:** Brand and items use `xpl-top-nav-item` (native `<a>` or `role=\"button\"`) with keyboard activation (Enter / Space where applicable).\n- **Dropdown items:** Items with `slot=\"dropdown\"` expose `aria-expanded` on the inner control; **Escape** closes the dropdown (document capture). **Escape** on the shell closes the mobile drawer only after dropdowns and **any** open descendant **`xpl-popover`** are closed (document capture vs bubble ordering). Arrow-key navigation within the dropdown panel is not built in.\n- **Icon-only items:** With **`icon`** and no **`label`** or default-slot text, the inner control gets **`aria-label`** (**`item-aria-label`** to override, else **`Navigation item`**).\n- **Lists:** `left-aside` is wrapped in `role=\"list\"`; each primary link `xpl-top-nav-item` uses `role=\"listitem\"`. The built-in brand row (`xpl-top-nav__brand`) omits `listitem` because it sits outside that list; `slot=\"right-aside-mobile\"` rows omit it as well. `xpl-nav-header-menu` default-slot rows still use `listitem` (menu list contract).\n",
|
|
@@ -16606,12 +17254,16 @@
|
|
|
16606
17254
|
}
|
|
16607
17255
|
},
|
|
16608
17256
|
{
|
|
16609
|
-
"filePath": "src/components/
|
|
17257
|
+
"filePath": "src/components/xpl-top-nav/xpl-top-nav-item/xpl-top-nav-item.tsx",
|
|
16610
17258
|
"encapsulation": "none",
|
|
16611
17259
|
"tag": "xpl-top-nav-item",
|
|
16612
17260
|
"readme": "# xpl-top-nav-item\n\n## Behavior\n\n- **Plain item:** **`label`** / **`icon`** (or **`slot=\"leading-icon\"`**), default slot, or **`href`** link. Renders a native **`<button type=\"button\">`** (or **`<a href>`** in link mode) and fires **`navItemClick`** (**`detail`**: **`MouseEvent`**) on click and **Enter** / **Space** — the native button handles keyboard activation, and link-mode **Space** maps to a programmatic **`.click()`**.\n- **Dropdown trigger:** Put content in **`slot=\"dropdown\"`** (e.g. `<xpl-top-nav-menu>`). Shows an auto **`chevron-down`** (unless **`slot=\"trailing-icon\"`** is provided) and toggles **`.xpl-top-nav-item__dropdown`** in the host light DOM — **not** **`xpl-dropdown`** / **`xpl-popover`**; use those for standalone floating menus (e.g. account in top-nav stories). **`navItemClick`** is not emitted. See **`TECH_DEBT.md`** for tradeoffs.\n- **Disclosure ARIA:** A dropdown trigger's inner control carries **`aria-expanded`** (open state), **`aria-haspopup=\"true\"`**, and **`aria-controls`** pointing at the **`.xpl-top-nav-item__dropdown`** panel's generated id. Plain items omit all three. **`aria-haspopup`** is the generic **`true`** (disclosure), not **`menu`** — the panel (**`xpl-top-nav-menu`**) is a **`role=\"list\"`** of link rows navigated by **Tab**, not an ARIA menu with arrow-key roving.\n- **Menu row:** The same component reused inside **`xpl-nav-header-menu`** / **`xpl-top-nav-menu`** — add **`description`** for a two-line row, and **`slot=\"trailing-icon\"`** for a functional icon (e.g. `external-link` for \"opens in new window\").\n- **Open API:** **`open`** (controlled/uncontrolled, reflected) + **`openChange`** event + **`openMenu()`** / **`closeMenu()`** / **`toggleMenu()`** methods — all equivalent ways to drive the dropdown panel.\n- **`openMode`:** **`click`** (default) or **`hover`** — hover only activates on hover-capable, fine-pointer, **`md`**-and-up devices; keyboard (Enter/Space) always toggles regardless.\n- **One open dropdown:** Outside click uses **`ownerDocument`** capture; siblings close via internal **`CustomEvent`** (reliable with JSDOM / **`stopPropagation`**).\n- **Escape:** Document **capture** **`keydown`** — **`preventDefault`** / **`stopPropagation`** so parent shells (**`xpl-top-nav`** mobile drawer, **`xpl-popover`**, modal) do not also react on the same keypress, then returns focus to the trigger control. **`xpl-top-nav`** closes its drawer on **Escape** in **bubble** phase, after this handler runs.\n\n## Host modifier classes (BEM)\n\n| Class | Source |\n| --- | --- |\n| **`xpl-top-nav-item--selected`** | **`selected`** prop |\n| **`xpl-top-nav-item--has-dropdown`** | **`slot=\"dropdown\"`** content present |\n| **`xpl-top-nav-item--dropdown-open`** | Dropdown panel is open (**`open`** prop) |\n| **`xpl-top-nav-item--active`** | **`active`** prop (or add the class on the host for edge cases) |\n| **`xpl-top-nav-item--has-active-descendant`** | A descendant row inside **`slot=\"dropdown\"`** is **`active`** / **`selected`** — accents the trigger like **`--active`**. Synced at connect / load / this item's own re-renders, not via a live descendant-class observer (see the JSDoc on **`hasActiveDescendant`** for why). |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| (default) | Custom trigger when **`label`** is omitted. |\n| `leading-icon` | Illustrative icon before the label. Overrides the **`icon`** prop when present. |\n| `trailing-icon` | Functional icon after the label. Overrides the auto **`chevron-down`** on a dropdown trigger. |\n| `dropdown` | Panel content (e.g. `<xpl-top-nav-menu>…</xpl-top-nav-menu>`). |\n",
|
|
16613
17261
|
"docs": "Single nav row for **`xpl-top-nav`** / **`xpl-nav-header-menu`** / **`xpl-top-nav-menu`**. The host uses\n**`role=\"listitem\"`** when the row participates in a list: a **`role=\"list\"`** parent, **`slot=\"left-aside\"`** on\n**`xpl-top-nav`** (list host is **`.xpl-top-nav__left-primary`** while slotted nodes stay light-DOM children of\n**`xpl-top-nav`**), or default-slot rows under **`xpl-nav-header-menu`** / **`xpl-top-nav-menu`**. That flag is\nkept in **`@State`** and refreshed after render plus via **`MutationObserver`** on the host (**`class`**, **`slot`**) and\non **`parentElement`** (**`role`**) or on **`.xpl-top-nav__left-primary`** (**`role`**) for **`slot=\"left-aside\"`** under **`xpl-top-nav`**) so DOM context changes\nwithout a full reconnect still re-sync. The internal\n**`xpl-top-nav__brand`** row omits **`listitem`** (it sits in **`.xpl-top-nav__brand-bar`**, not **`.xpl-top-nav__left-primary`**),\nas do **`slot=\"right-aside-mobile\"`** rows (not a list). **`slot=\"dropdown\"`** uses a local **`.xpl-top-nav-item__dropdown`**\npanel (not **`xpl-dropdown`**); see **`TECH_DEBT.md`**.\n\n**This component does triple duty:** a plain bar item, a dropdown trigger (**`slot=\"dropdown\"`** present), and a\ndropdown/menu **row** (nested inside **`xpl-nav-header-menu`** or **`xpl-top-nav-menu`**). The **`description`** prop\nonly applies in the row context — bar items and triggers do not show it in Figma.\n\n**Default slot (no `label`):** do not put **`xpl-top-nav-item__inner`** or other **`xpl-top-nav-item__*`** classes on\ncustom trigger content — the component renders the inner wrapper and BEM elements.\n\n**Theming:** The host always includes Foundation’s **`dark`** class so **`--xpl-*`** purpose tokens resolve to dark-mode\nvalues even when the page root is light (consistent with **`xpl-top-nav`**).",
|
|
16614
17262
|
"docsTags": [
|
|
17263
|
+
{
|
|
17264
|
+
"name": "slot",
|
|
17265
|
+
"text": "- The row label content. Used when the **`label`** prop is not set."
|
|
17266
|
+
},
|
|
16615
17267
|
{
|
|
16616
17268
|
"name": "slot",
|
|
16617
17269
|
"text": "leading-icon - Illustrative icon before the label. Overrides the **`icon`** prop when present."
|
|
@@ -16982,6 +17634,10 @@
|
|
|
16982
17634
|
],
|
|
16983
17635
|
"styles": [],
|
|
16984
17636
|
"slots": [
|
|
17637
|
+
{
|
|
17638
|
+
"name": "",
|
|
17639
|
+
"docs": "The row label content. Used when the **`label`** prop is not set."
|
|
17640
|
+
},
|
|
16985
17641
|
{
|
|
16986
17642
|
"name": "dropdown",
|
|
16987
17643
|
"docs": "Panel content (e.g. `<xpl-top-nav-menu>`). Presence of this slot makes the row a disclosure trigger."
|
|
@@ -17017,7 +17673,7 @@
|
|
|
17017
17673
|
}
|
|
17018
17674
|
},
|
|
17019
17675
|
{
|
|
17020
|
-
"filePath": "src/components/
|
|
17676
|
+
"filePath": "src/components/xpl-top-nav/xpl-top-nav-menu/xpl-top-nav-menu.tsx",
|
|
17021
17677
|
"encapsulation": "none",
|
|
17022
17678
|
"tag": "xpl-top-nav-menu",
|
|
17023
17679
|
"readme": "# xpl-top-nav-menu\n\n## Behavior\n\n- **Thin grouping container only.** No item logic lives here — put **`xpl-top-nav-item`** rows in the default slot. This component owns list semantics (**`role=\"list\"`**) and shared panel chrome (width, surface, shadow, radius, padding), nothing else.\n- **One authoring markup, two renderings:** the same **`<xpl-top-nav-menu>`** renders as the **desktop flyout** (nested in a parent **`xpl-top-nav-item`**'s **`slot=\"dropdown\"`** — the panel opens absolutely-positioned under the trigger) and, below the **`md`** breakpoint, drives the **mobile cascade**: the parent's dropdown content swaps in **in place** of the top-level nav list (no second panel), with an auto **back row** as the first row.\n- **`label`** is the accessible name for the list (**`aria-label`**) and, on mobile, the text shown in the auto-rendered back row (leading **`chevron-left`**) when drilling back out of this group. Tapping the back row calls **`closeMenu()`** on the parent trigger (pop to Level 1) and restores focus to it.\n- The back row only renders below **`md`** (synced from a **`matchMedia`** listener) — desktop never sees it, since the flyout there is a single level of links.\n- **Cascade lifecycle** (owned by **`xpl-top-nav`**, the shell): pressing **Escape** while drilled in pops the cascade before it closes the mobile drawer (two separate presses); closing the drawer via the hamburger toggle while still drilled in resets the group closed so the drawer reopens at Level 1 next time.\n\n## Usage\n\n```html\n<xpl-top-nav-item slot=\"left-aside\" label=\"Xplor Ops\" open-mode=\"hover\">\n <xpl-top-nav-menu slot=\"dropdown\" label=\"Xplor Ops\">\n <xpl-top-nav-item label=\"Payroll\" href=\"/payroll\"></xpl-top-nav-item>\n <xpl-top-nav-item label=\"Capital\" href=\"/capital\">\n <xpl-icon slot=\"trailing-icon\" icon=\"open-rect-arrow-out\"></xpl-icon>\n </xpl-top-nav-item>\n </xpl-top-nav-menu>\n</xpl-top-nav-item>\n```\n\n## Host modifier classes (BEM)\n\nNone on the host itself. Row-level state (`active`, `selected`, description, icons) lives entirely on the slotted `xpl-top-nav-item` rows.\n\n| Class | Source |\n| --- | --- |\n| `.xpl-top-nav-menu__back` | Auto-rendered on the back-row `xpl-top-nav-item` (mobile only, `label` set). Not a hook to restyle — it uses the same row treatment as any other `xpl-top-nav-item` in this list. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| (default) | `xpl-top-nav-item` rows. |\n",
|
|
@@ -17059,6 +17715,10 @@
|
|
|
17059
17715
|
"listeners": [],
|
|
17060
17716
|
"styles": [],
|
|
17061
17717
|
"slots": [
|
|
17718
|
+
{
|
|
17719
|
+
"name": "",
|
|
17720
|
+
"docs": "The default slot"
|
|
17721
|
+
},
|
|
17062
17722
|
{
|
|
17063
17723
|
"name": "(default)",
|
|
17064
17724
|
"docs": "**`xpl-top-nav-item`** rows."
|
|
@@ -17082,12 +17742,20 @@
|
|
|
17082
17742
|
}
|
|
17083
17743
|
},
|
|
17084
17744
|
{
|
|
17085
|
-
"filePath": "src/components/
|
|
17745
|
+
"filePath": "src/components/xpl-utility-bar/xpl-utility-bar.tsx",
|
|
17086
17746
|
"encapsulation": "none",
|
|
17087
17747
|
"tag": "xpl-utility-bar",
|
|
17088
17748
|
"readme": "# xpl-utility-bar\n\nThe utility bar is a top navigation bar. It contains 2 slots:\n\n`<slot name=\"main\"></slot>`\n\n- appears on the left side of the bar\n- items are justified to the start\n\n`<slot name=\"aside\"></slot>`\n\n- appears on the right side of the bar\n- items are justified to the end\n\nThe utility bar can have navigation items in just one or both slots.\nTo add content to the slots, just create a `<ul>` tag and target the desired slot:\n\n`<ul slot=\"main\">...</ul>`\n\n`<ul slot=\"aside\">...</ul>`\n\n## Design Tokens\n\nThe utility bar uses Apollo Foundation purpose-specific tokens, which theme automatically in light and dark mode (no `.dark` overrides).\n\n| Element | Property | Token |\n| --- | --- | --- |\n| `.xpl-utility-bar` | `background-color` | `--xpl-background-surface-default` |\n| `.xpl-utility-bar` | `color` (muted text) | `--xpl-text-subdued` |\n| `.xpl-utility-nav__bars` | `color` (nav-control icon) | `--xpl-icon-default` |\n| `.xpl-utility-nav__bars` | `height` | `--xpl-size-100` |\n| `.xpl-utility-bar__nav-control` `:focus-visible` | `outline-color` | `--xpl-border-focus` |\n",
|
|
17089
17749
|
"docs": "The utility bar is a top navigation bar. It contains 2 slots:\n\n`<slot name=\"main\"></slot>`\n\n- appears on the left side of the bar\n- items are justified to the start\n\n`<slot name=\"aside\"></slot>`\n\n- appears on the right side of the bar\n- items are justified to the end\n\nThe utility bar can have navigation items in just one or both slots.\nTo add content to the slots, just create a `<ul>` tag and target the desired slot:\n\n`<ul slot=\"main\">...</ul>`\n\n`<ul slot=\"aside\">...</ul>`",
|
|
17090
17750
|
"docsTags": [
|
|
17751
|
+
{
|
|
17752
|
+
"name": "slot",
|
|
17753
|
+
"text": "aside - Content rendered at the start of the bar, next to the nav-control toggle when present."
|
|
17754
|
+
},
|
|
17755
|
+
{
|
|
17756
|
+
"name": "slot",
|
|
17757
|
+
"text": "main - Main content of the utility bar."
|
|
17758
|
+
},
|
|
17091
17759
|
{
|
|
17092
17760
|
"name": "since",
|
|
17093
17761
|
"text": "0.1.1"
|
|
@@ -17176,7 +17844,16 @@
|
|
|
17176
17844
|
],
|
|
17177
17845
|
"listeners": [],
|
|
17178
17846
|
"styles": [],
|
|
17179
|
-
"slots": [
|
|
17847
|
+
"slots": [
|
|
17848
|
+
{
|
|
17849
|
+
"name": "aside",
|
|
17850
|
+
"docs": "Content rendered at the start of the bar, next to the nav-control toggle when present."
|
|
17851
|
+
},
|
|
17852
|
+
{
|
|
17853
|
+
"name": "main",
|
|
17854
|
+
"docs": "Main content of the utility bar."
|
|
17855
|
+
}
|
|
17856
|
+
],
|
|
17180
17857
|
"parts": [],
|
|
17181
17858
|
"states": [],
|
|
17182
17859
|
"dependents": [],
|
|
@@ -17191,115 +17868,120 @@
|
|
|
17191
17868
|
}
|
|
17192
17869
|
],
|
|
17193
17870
|
"typeLibrary": {
|
|
17194
|
-
"src/components/
|
|
17871
|
+
"src/components/xpl-badge/xpl-badge.tsx::BadgeVariantProp": {
|
|
17195
17872
|
"declaration": "export type BadgeVariantProp = BadgePalette | 'success' | 'warning' | 'inactive' | 'error';",
|
|
17196
17873
|
"docstring": "",
|
|
17197
|
-
"path": "src/components/
|
|
17874
|
+
"path": "src/components/xpl-badge/xpl-badge.tsx"
|
|
17198
17875
|
},
|
|
17199
|
-
"src/components/
|
|
17876
|
+
"src/components/xpl-avatar/xpl-avatar.tsx::AvatarColor": {
|
|
17200
17877
|
"declaration": "export type AvatarColor = 'green' | 'yellow' | 'pink' | 'primary' | 'secondary';",
|
|
17201
17878
|
"docstring": "",
|
|
17202
|
-
"path": "src/components/
|
|
17879
|
+
"path": "src/components/xpl-avatar/xpl-avatar.tsx"
|
|
17203
17880
|
},
|
|
17204
|
-
"src/components/
|
|
17881
|
+
"src/components/xpl-avatar/xpl-avatar.tsx::AvatarGroupItem": {
|
|
17205
17882
|
"declaration": "export interface AvatarGroupItem {\n /** Image URL for this avatar */\n src?: string;\n /** Name used for alt text and initials when no src */\n name?: string;\n /** Placeholder background color when there is no image */\n color?: AvatarColor;\n}",
|
|
17206
17883
|
"docstring": "",
|
|
17207
|
-
"path": "src/components/
|
|
17884
|
+
"path": "src/components/xpl-avatar/xpl-avatar.tsx"
|
|
17208
17885
|
},
|
|
17209
|
-
"src/components/
|
|
17886
|
+
"src/components/xpl-avatar/xpl-avatar.tsx::AvatarStatus": {
|
|
17210
17887
|
"declaration": "export type AvatarStatus = 'active' | 'inactive' | 'warning' | BadgePalette;",
|
|
17211
17888
|
"docstring": "",
|
|
17212
|
-
"path": "src/components/
|
|
17889
|
+
"path": "src/components/xpl-avatar/xpl-avatar.tsx"
|
|
17213
17890
|
},
|
|
17214
|
-
"src/components/
|
|
17891
|
+
"src/components/xpl-avatar/xpl-avatar.tsx::AvatarVariant": {
|
|
17215
17892
|
"declaration": "export type AvatarVariant = 'profile' | 'group' | 'with-text';",
|
|
17216
17893
|
"docstring": "",
|
|
17217
|
-
"path": "src/components/
|
|
17894
|
+
"path": "src/components/xpl-avatar/xpl-avatar.tsx"
|
|
17218
17895
|
},
|
|
17219
|
-
"src/components/
|
|
17896
|
+
"src/components/xpl-choicelist/choice.ts::Choice": {
|
|
17220
17897
|
"declaration": "export interface Choice {\n checked?: boolean;\n children?: Choice[];\n description?: string;\n label?: string;\n value?: string;\n}",
|
|
17221
17898
|
"docstring": "",
|
|
17222
|
-
"path": "src/components/
|
|
17899
|
+
"path": "src/components/xpl-choicelist/choice.ts"
|
|
17223
17900
|
},
|
|
17224
|
-
"src/components/
|
|
17901
|
+
"src/components/xpl-dropdown/dropdown-option.ts::DropdownItem": {
|
|
17225
17902
|
"declaration": "{\n [P in keyof T]?: T[P];\n}",
|
|
17226
17903
|
"docstring": "",
|
|
17227
|
-
"path": "src/components/
|
|
17904
|
+
"path": "src/components/xpl-dropdown/dropdown-option.ts"
|
|
17228
17905
|
},
|
|
17229
|
-
"src/
|
|
17230
|
-
"declaration": "
|
|
17906
|
+
"src/utils/floating.ts::Placement": {
|
|
17907
|
+
"declaration": "export declare type Placement = Prettify<Side | AlignedPlacement>;",
|
|
17231
17908
|
"docstring": "",
|
|
17232
|
-
"path": "src/
|
|
17909
|
+
"path": "src/utils/floating.ts"
|
|
17233
17910
|
},
|
|
17234
17911
|
"../../node_modules/@stencil/core/internal/stencil-core/index.d.ts::Event": {
|
|
17235
|
-
"declaration": "any",
|
|
17236
|
-
"docstring": "",
|
|
17912
|
+
"declaration": "interface Event {\n /**\n * Returns true or false depending on how event was initialized. True if event goes through its target's ancestors in reverse tree order, and false otherwise.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/bubbles)\n */\n readonly bubbles: boolean;\n /**\n * @deprecated\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/cancelBubble)\n */\n cancelBubble: boolean;\n /**\n * Returns true or false depending on how event was initialized. Its return value does not always carry meaning, but true can indicate that part of the operation during which event was dispatched, can be canceled by invoking the preventDefault() method.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/cancelable)\n */\n readonly cancelable: boolean;\n /**\n * Returns true or false depending on how event was initialized. True if event invokes listeners past a ShadowRoot node that is the root of its target, and false otherwise.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/composed)\n */\n readonly composed: boolean;\n /**\n * Returns the object whose event listener's callback is currently being invoked.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/currentTarget)\n */\n readonly currentTarget: EventTarget | null;\n /**\n * Returns true if preventDefault() was invoked successfully to indicate cancelation, and false otherwise.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/defaultPrevented)\n */\n readonly defaultPrevented: boolean;\n /**\n * Returns the event's phase, which is one of NONE, CAPTURING_PHASE, AT_TARGET, and BUBBLING_PHASE.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/eventPhase)\n */\n readonly eventPhase: number;\n /**\n * Returns true if event was dispatched by the user agent, and false otherwise.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/isTrusted)\n */\n readonly isTrusted: boolean;\n /**\n * @deprecated\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/returnValue)\n */\n returnValue: boolean;\n /**\n * @deprecated\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/srcElement)\n */\n readonly srcElement: EventTarget | null;\n /**\n * Returns the object to which event is dispatched (its target).\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/target)\n */\n readonly target: EventTarget | null;\n /**\n * Returns the event's timestamp as the number of milliseconds measured relative to the time origin.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/timeStamp)\n */\n readonly timeStamp: DOMHighResTimeStamp;\n /**\n * Returns the type of event, e.g. \"click\", \"hashchange\", or \"submit\".\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/type)\n */\n readonly type: string;\n /**\n * Returns the invocation target objects of event's path (objects on which listeners will be invoked), except for any nodes in shadow trees of which the shadow root's mode is \"closed\" that are not reachable from event's currentTarget.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/composedPath)\n */\n composedPath(): EventTarget[];\n /**\n * @deprecated\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/initEvent)\n */\n initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;\n /**\n * If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)\n */\n preventDefault(): void;\n /**\n * Invoking this method prevents event from reaching any registered event listeners after the current one finishes running and, when dispatched in a tree, also prevents event from reaching any other objects.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/stopImmediatePropagation)\n */\n stopImmediatePropagation(): void;\n /**\n * When dispatched in a tree, invoking this method prevents event from reaching any objects other than the current object.\n *\n * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/stopPropagation)\n */\n stopPropagation(): void;\n readonly NONE: 0;\n readonly CAPTURING_PHASE: 1;\n readonly AT_TARGET: 2;\n readonly BUBBLING_PHASE: 3;\n}",
|
|
17913
|
+
"docstring": "An event which takes place in the DOM.\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/API/Event)",
|
|
17237
17914
|
"path": "../../node_modules/@stencil/core/internal/stencil-core/index.d.ts"
|
|
17238
17915
|
},
|
|
17239
|
-
"src/components/
|
|
17916
|
+
"src/components/xpl-dropdown/xpl-dropdown.tsx::Dropdown": {
|
|
17917
|
+
"declaration": "@Component({ tag: 'xpl-dropdown' })\nexport class Dropdown {\n /** Exclusive last rendered option index when virtual scrolling is active. */\n @State() private virtualEnd = 0;\n\n /** First rendered option index when virtual scrolling is active. */\n @State() private virtualStart = 0;\n\n /** text to display as heading */\n @Prop({ attribute: 'open', mutable: true, reflect: true }) isOpen = false;\n\n /** options that are listed */\n @Prop() closeOnSelect = true;\n\n /** constant representing number of options that can be selected */\n @Prop() mode: 'single' | 'multi' = 'single';\n\n /** options that are listed */\n @Prop({ mutable: true }) options?: DropdownItem[];\n\n @Watch('options')\n onOptionsChanged() {\n // A selection toggle reassigns `options` with the same length (only\n // `isSelected` flips), whereas a genuinely new dataset changes the\n // count. Track it so only real list replacements recenter — in-place\n // selection updates must never move the user's scroll position (in\n // multi mode that could otherwise jump to the first selected row via\n // `findIndex`).\n const total = this.options?.length ?? 0;\n const listReplaced = total !== this.previousOptionCount;\n this.previousOptionCount = total;\n\n // When the list shrinks, cached range/scroll can point past the new\n // end (render would clamp `start` to `total` and slice to empty, or\n // leave a high scroll offset showing blank space). Reset for\n // non-virtualized lists and otherwise clamp scroll + recompute range.\n if (!this.isVirtualized) {\n this.virtualStart = 0;\n this.virtualEnd = 0;\n return;\n }\n\n const list = this.listEl;\n if (list) {\n const maxScroll = Math.max(0, total * VIRTUAL_LIST.rowHeight - list.clientHeight);\n if (list.scrollTop > maxScroll) {\n list.scrollTop = maxScroll;\n }\n\n // If the menu is open and a newly assigned list left the selected\n // row outside the current window (e.g. a large list assigned\n // asynchronously leaves scrollTop at 0), recenter so the selected\n // option is mounted. Gated on `listReplaced` so selection toggles\n // never trigger it.\n if (this.isOpen && listReplaced) {\n const selectedIndex = this.options?.findIndex((option) => option.isSelected) ?? -1;\n const outOfWindow =\n selectedIndex >= 0 &&\n (selectedIndex < this.virtualStart || selectedIndex >= this.virtualEnd);\n if (outOfWindow) {\n this.scrollSelectedIntoView();\n }\n }\n }\n\n this.updateVirtualRange();\n }\n\n /** whether to anchor the dropdown to the trigger element, requires triggerId to be set */\n @Prop() anchorToTrigger = false;\n\n @Watch('anchorToTrigger')\n onAnchorToTriggerChanged() {\n if (this.isOpen) {\n this.startPositioning();\n }\n }\n\n /**\n * When `anchorToTrigger` is true, additional placements to try when the\n * default `placement` does not fit (passed to Floating UI `flip`).\n */\n @Prop() flipFallbackPlacements?: Placement[];\n\n @Watch('flipFallbackPlacements')\n onFlipFallbackPlacementsChanged() {\n if (this.isOpen && this.anchorToTrigger) {\n this.startPositioning();\n }\n }\n\n /**\n * Floating UI placement when `anchorToTrigger` is true (e.g. `bottom-start`, `top-start`).\n */\n @Prop() placement: Placement = 'bottom-start';\n\n @Watch('placement')\n onPlacementChanged() {\n if (this.isOpen && this.anchorToTrigger) {\n this.startPositioning();\n }\n }\n\n /**\n * The currently selected value(s) in the dropdown.\n */\n @Prop() selectedValues?: string | string[];\n\n /** whether selection should be made when focusing on interactive element */\n @Prop() selectOnFocus = false;\n\n /** the id for the element that triggers the open state */\n @Prop() triggerId: string;\n\n @Watch('triggerId')\n onTriggerIdChanged() {\n if (this.isOpen) {\n this.startPositioning();\n }\n }\n\n /**\n * @callback update\n * @param {Object} e - event object\n * @param {Object} options - component\n */\n /** call back function invoked when a selection is made */\n @Prop() update?: (e: Event | null, context: { component: Dropdown }) => void;\n\n @Element() hostElement: HTMLXplDropdownElement;\n\n /** Emitted when the open state of the dropdown changes. */\n @Event() isOpenChange: EventEmitter<boolean>;\n\n private floating: FloatingController | null = null;\n\n private virtualScrollRaf: number | null = null;\n\n private openAlignmentRaf: number | null = null;\n\n private listEl?: HTMLElement;\n\n private listResizeObserver?: ResizeObserver;\n\n private previousOptionCount = 0;\n\n @Watch('selectedValues')\n onSelectedValuesChanged(newValues: string | string[], initialRender = false) {\n if (this.options && this.options.length > 0) {\n // Flatten options to handle both grouped and individual options\n const flatOptions = this.options.flatMap((curr) =>\n curr.groupName && curr.options ? curr.options : [curr],\n );\n\n // Update isSelected flags based on new selected values\n flatOptions.forEach((option) => {\n const optionValue = option.value || option.label || '';\n\n if (this.mode === 'single') {\n option.isSelected = optionValue === newValues;\n } else {\n const selectedArray = Array.isArray(newValues) ? newValues : [];\n option.isSelected = selectedArray.includes(optionValue);\n }\n });\n\n // Update the options array to trigger re-render\n const mapOptions = (option: DropdownItem): DropdownItem => {\n option.options = option.groupName ? option.options?.map(mapOptions) : undefined;\n return option;\n };\n this.options = this.options.map(mapOptions);\n\n // Call update callback if it exists\n if (this.update && !initialRender) {\n this.update(null, { component: this });\n }\n }\n }\n\n @Watch('isOpen')\n onIsOpenStateChange(newValue: boolean) {\n this.isOpenChange.emit(newValue);\n if (newValue) {\n this.startPositioning();\n this.alignOnOpen();\n } else {\n this.stopPositioning();\n this.cancelVirtualScroll();\n this.virtualStart = 0;\n this.virtualEnd = 0;\n }\n }\n\n connectedCallback() {\n if (!isBrowser()) {\n return;\n }\n\n document.addEventListener('mousedown', this.handleClickOutside);\n document.addEventListener('keydown', this.handleKeyDown);\n }\n\n disconnectedCallback() {\n document.removeEventListener('mousedown', this.handleClickOutside);\n document.removeEventListener('keydown', this.handleKeyDown);\n this.stopPositioning();\n this.cancelVirtualScroll();\n this.listResizeObserver?.disconnect();\n }\n\n componentWillLoad() {\n this.handleSelect = this.handleSelect.bind(this);\n if (this.selectedValues) {\n this.onSelectedValuesChanged(this.selectedValues, true);\n }\n // Seed the baseline so the first in-place selection change isn't\n // mistaken for a list replacement.\n this.previousOptionCount = this.options?.length ?? 0;\n }\n\n componentDidLoad() {\n if (this.isOpen) {\n // The `isOpen` watcher does not fire for an initial `open` attribute,\n // so align here too once the list has rendered.\n this.startPositioning();\n this.alignOnOpen();\n }\n }\n\n /**\n * called on dropdown option click and keydown events to update isSelected states\n */\n @Method()\n async handleSelect(e: Event | null, { component }: DropdownSelectContext): Promise<void> {\n const { hostElement, mode, options, update } = this;\n const isSingle = mode === 'single';\n const isMulti = mode === 'multi';\n\n if (options) {\n const targetValue = component.hostElement.value || component.hostElement.label;\n const hasGroups = options.some((option) => option.groupName);\n\n if (!hasGroups) {\n // Fast path for flat lists (e.g. very large selects): a single\n // linear pass plus a shallow copy to trigger the re-render,\n // instead of flatten + forEach + map over every option.\n options.forEach((option) => {\n const isMatch = (option.value || option.label) === targetValue;\n if (isSingle) {\n option.isSelected = isMatch;\n if (isMatch) component.hostElement.isSelected = true;\n } else if (isMulti && isMatch) {\n option.isSelected = !option.isSelected;\n component.hostElement.isSelected = option.isSelected;\n }\n });\n this.options = [...options];\n } else {\n const flatOptions = options.flatMap((curr) =>\n curr.groupName && curr.options ? curr.options : [curr],\n );\n\n flatOptions.forEach((option) => {\n const isMatch = (option.value || option.label) === targetValue;\n if (isSingle) {\n option.isSelected = isMatch;\n component.hostElement.isSelected = true;\n } else if (isMulti && isMatch) {\n option.isSelected = !option.isSelected;\n component.hostElement.isSelected = option.isSelected;\n }\n });\n\n const mapOptions = (option: DropdownItem): DropdownItem => {\n option.options = option.groupName ? option.options?.map(mapOptions) : undefined;\n return option;\n };\n this.options = options.map(mapOptions);\n }\n } else if (isSingle) {\n const optionNodes = Array.from(\n hostElement.querySelectorAll<HTMLXplDropdownOptionElement>('xpl-dropdown-option'),\n );\n optionNodes.forEach((node) => {\n node.isSelected = node === component.hostElement;\n });\n } else if (isMulti) {\n component.isSelected = !component.isSelected;\n }\n\n if (update) update(e, { component: this });\n }\n\n private startPositioning() {\n if (!this.anchorToTrigger || !this.triggerId) {\n return;\n }\n\n const triggerEl = document.getElementById(this.triggerId);\n if (!triggerEl) return;\n\n this.stopPositioning();\n\n this.floating = startFloating(triggerEl, this.hostElement, {\n placement: this.placement,\n strategy: 'fixed',\n middleware: dropdownMiddleware({\n flipFallbackPlacements: this.flipFallbackPlacements,\n sizeApply: ({ availableHeight, rects }) => {\n const listEl =\n this.hostElement.querySelector<HTMLElement>('.xpl-dropdown-list');\n let usedBeforeList = 0;\n if (listEl) {\n const children = Array.from(this.hostElement.children);\n const listIndex = children.indexOf(listEl);\n children.slice(0, listIndex).forEach((child) => {\n if (child instanceof HTMLElement) {\n usedBeforeList += child.offsetHeight;\n }\n });\n }\n const cs = getComputedStyle(this.hostElement);\n const hostVerticalChrome =\n parseFloat(cs.paddingTop) +\n parseFloat(cs.paddingBottom) +\n parseFloat(cs.borderTopWidth) +\n parseFloat(cs.borderBottomWidth);\n const cssMaxHeight = listEl\n ? parseFloat(\n getComputedStyle(listEl).getPropertyValue(\n '--xpl-dropdown-list-max-height',\n ),\n )\n : Infinity;\n const listMaxHeight = Math.min(\n cssMaxHeight,\n Math.max(0, availableHeight - usedBeforeList - hostVerticalChrome),\n );\n Object.assign(this.hostElement.style, {\n width: `${rects.reference.width}px`,\n });\n if (listEl) {\n listEl.style.maxHeight = `${listMaxHeight}px`;\n }\n },\n }),\n onPosition: ({ x, y, placement: resolvedPlacement }) => {\n if (!this.floating) {\n return;\n }\n\n const isAbove = getSide(resolvedPlacement) === 'top';\n\n Object.assign(this.hostElement.style, {\n left: `${x}px`,\n top: `${y}px`,\n });\n\n this.hostElement.classList.toggle('xpl-dropdown--above', isAbove);\n this.hostElement.classList.toggle('xpl-dropdown--below', !isAbove);\n },\n onReferenceHidden: () => {\n this.isOpen = false;\n return true;\n },\n });\n }\n\n private stopPositioning() {\n this.floating?.stop();\n this.floating = null;\n\n this.hostElement.style.left = '';\n this.hostElement.style.top = '';\n this.hostElement.style.width = '';\n this.hostElement\n .querySelector<HTMLElement>('.xpl-dropdown-list')\n ?.style.removeProperty('max-height');\n this.hostElement.classList.remove('xpl-dropdown--above', 'xpl-dropdown--below');\n }\n\n private handleClickOutside = ({ target }: MouseEvent): void => {\n const { triggerId } = this;\n const targetEl = target as HTMLElement | null;\n const triggerElement = triggerId ? document.getElementById(triggerId) : null;\n const isTriggerOrChild = triggerElement?.contains(targetEl);\n const isInside = this.hostElement.contains(targetEl);\n\n // A `<label for=\"{triggerId}\">` is part of the trigger: clicking it\n // forwards a synthetic click to the trigger to toggle the menu. Treating\n // its `mousedown` as an outside click would close the menu here, and the\n // forwarded click would immediately reopen it — so the label could only\n // ever open, never close. Exclude the associated label from outside detection.\n const labelEl = targetEl?.closest('label');\n const isTriggerLabel =\n !!labelEl && !!triggerId && labelEl.getAttribute('for') === triggerId;\n\n if (!isInside && !isTriggerOrChild && !isTriggerLabel && this.isOpen) {\n this.isOpen = false;\n }\n };\n\n private handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && this.isOpen) {\n this.isOpen = false;\n }\n };\n\n /**\n * Recomputes the rendered range from the scroll position. Throttled to one\n * update per animation frame.\n */\n private handleVirtualScroll = () => {\n if (this.virtualScrollRaf !== null) return;\n\n this.virtualScrollRaf = requestAnimationFrame(() => {\n this.virtualScrollRaf = null;\n this.updateVirtualRange();\n });\n };\n\n private cancelVirtualScroll() {\n if (this.virtualScrollRaf !== null) {\n cancelAnimationFrame(this.virtualScrollRaf);\n this.virtualScrollRaf = null;\n }\n if (this.openAlignmentRaf !== null) {\n cancelAnimationFrame(this.openAlignmentRaf);\n this.openAlignmentRaf = null;\n }\n }\n\n /**\n * Tracks the list element and observes its size. Floating UI's `size`\n * middleware (and viewport/layout changes) can grow or shrink the list\n * `clientHeight` without firing a scroll event, which would otherwise\n * leave a stale visible range until the user scrolls. Recompute the range\n * (throttled via the tracked scroll scheduler) whenever the list resizes.\n */\n private setListEl = (el?: HTMLElement) => {\n if (el === this.listEl) return;\n\n this.listEl = el;\n this.listResizeObserver?.disconnect();\n\n if (el && typeof ResizeObserver !== 'undefined') {\n this.listResizeObserver ??= new ResizeObserver(() => {\n if (this.isVirtualized) this.handleVirtualScroll();\n });\n this.listResizeObserver.observe(el);\n }\n };\n\n /**\n * Align the virtualized viewport to the selected option when the menu\n * opens. Shared by the `isOpen` watcher and `componentDidLoad` (the watcher\n * does not fire for an initial `open` attribute).\n */\n private alignOnOpen() {\n // Align synchronously so the first paint already renders the window\n // around the selected option. The list is always in the DOM with its\n // CSS max-height applied, so the scroll math is correct for\n // non-anchored lists and a close approximation for anchored ones.\n this.scrollSelectedIntoView();\n this.updateVirtualRange();\n // Re-align after layout, once the size middleware has set the final\n // list height. Routed through the tracked scroll scheduler so the frame\n // is cancelled on close/teardown.\n this.scheduleOpenAlignment();\n }\n\n /**\n * On open, align the viewport to the selected option (once the list has\n * been laid out) and recompute the rendered range. Uses its own tracked\n * frame (not the scroll slot) so the synchronous scroll fired by\n * `scrollSelectedIntoView` cannot let `handleVirtualScroll` preempt it and\n * skip the post-layout centering. Cancelled on close/teardown.\n */\n private scheduleOpenAlignment = () => {\n if (this.openAlignmentRaf !== null) return;\n\n this.openAlignmentRaf = requestAnimationFrame(() => {\n this.openAlignmentRaf = null;\n this.scrollSelectedIntoView();\n this.updateVirtualRange();\n });\n };\n\n /**\n * Scrolls the virtualized list so the selected option is centered in the\n * viewport. No-op for non-virtualized lists (their rows have natural\n * heights and the browser handles visibility).\n */\n private scrollSelectedIntoView() {\n const { listEl: list, options } = this;\n\n if (!list || !options?.length || !this.isVirtualized) return;\n\n const selectedIndex = options.findIndex((option) => option.isSelected);\n if (selectedIndex < 0) return;\n\n const { rowHeight } = VIRTUAL_LIST;\n const centered = selectedIndex * rowHeight - (list.clientHeight - rowHeight) / 2;\n const maxScroll = Math.max(0, options.length * rowHeight - list.clientHeight);\n\n list.scrollTop = Math.max(0, Math.min(centered, maxScroll));\n }\n\n private updateVirtualRange() {\n const list = this.listEl;\n const total = this.options?.length ?? 0;\n\n if (!list || !total) return;\n\n const { rowHeight, overscan } = VIRTUAL_LIST;\n const firstVisible = Math.floor(list.scrollTop / rowHeight);\n const visibleCount = Math.ceil(list.clientHeight / rowHeight) || 1;\n\n const start = Math.max(0, firstVisible - overscan);\n const end = Math.min(total, firstVisible + visibleCount + overscan);\n\n if (start !== this.virtualStart || end !== this.virtualEnd) {\n this.virtualStart = start;\n this.virtualEnd = end;\n }\n }\n\n private get isVirtualized(): boolean {\n const { options } = this;\n\n return (\n !!options &&\n options.length > VIRTUAL_LIST.virtualizeFrom &&\n // Virtualized rows use a fixed `rowHeight` with `overflow: hidden`,\n // which would silently clip subtitles. Exclude grouped and\n // subtitled lists so they keep their natural row height.\n options.every((option) => !option.groupName && !option.subtitle)\n );\n }\n\n render() {\n const { isOpen, mode, options } = this;\n\n const hasOptions = !!(options && options.length);\n const shouldVirtualize = this.isVirtualized;\n\n let listContent;\n if (!hasOptions) {\n listContent = <slot name=\"options\"></slot>;\n } else if (shouldVirtualize) {\n const { rowHeight, overscan } = VIRTUAL_LIST;\n const total = options.length;\n const start = Math.min(this.virtualStart, total);\n\n // Fall back to a sensible window before the list has been measured\n // (e.g. the very first render right after opening).\n const fallbackEnd = Math.min(total, Math.ceil(300 / rowHeight) + overscan * 2);\n const end = this.virtualEnd > start ? this.virtualEnd : fallbackEnd;\n\n listContent = (\n <li\n class=\"xpl-dropdown__virtual-sizer\"\n style={{ height: `${total * rowHeight}px` }}\n >\n {options.slice(start, end).map((option, i) => renderOption(option, start + i))}\n </li>\n );\n } else {\n listContent = options.map((option) => renderOption(option));\n }\n\n return (\n <Host\n aria-expanded={isOpen ? 'true' : 'false'}\n class={{\n 'xpl-dropdown': true,\n 'xpl-dropdown--multi': mode === 'multi',\n 'xpl-dropdown--open': isOpen,\n 'xpl-dropdown--anchor-to-trigger': this.anchorToTrigger,\n 'xpl-dropdown--virtualized': shouldVirtualize,\n }}\n role=\"listbox\"\n >\n <slot name=\"header\"></slot>\n <ul\n class=\"xpl-dropdown-list\"\n ref={(el) => {\n this.setListEl(el);\n }}\n onScroll={shouldVirtualize ? this.handleVirtualScroll : undefined}\n >\n {listContent}\n </ul>\n </Host>\n );\n }\n}",
|
|
17918
|
+
"docstring": "",
|
|
17919
|
+
"path": "src/components/xpl-dropdown/xpl-dropdown.tsx"
|
|
17920
|
+
},
|
|
17921
|
+
"src/components/xpl-dropdown/dropdown-option.ts::DropdownOptionGroup": {
|
|
17240
17922
|
"declaration": "export interface DropdownOptionGroup {\n groupName: string;\n options: DropdownItem[];\n}",
|
|
17241
17923
|
"docstring": "",
|
|
17242
|
-
"path": "src/components/
|
|
17924
|
+
"path": "src/components/xpl-dropdown/dropdown-option.ts"
|
|
17243
17925
|
},
|
|
17244
|
-
"src/components/
|
|
17926
|
+
"src/components/xpl-list/listitem.ts::ListItem": {
|
|
17245
17927
|
"declaration": "export interface ListItem {\n /** Optional stable id for legacy rows (keys and `item-id` when rendering from `items`). */\n id?: string;\n avatar?: string;\n avatars?: string[];\n badges?:\n | string[]\n | {\n dot?: boolean;\n text: string;\n variant?: string;\n }[];\n href?: string;\n title: string;\n metadata?:\n | string[]\n | {\n icon: string;\n text: string;\n }[];\n subtext?: string;\n}",
|
|
17246
17928
|
"docstring": "",
|
|
17247
|
-
"path": "src/components/
|
|
17929
|
+
"path": "src/components/xpl-list/listitem.ts"
|
|
17248
17930
|
},
|
|
17249
|
-
"src/components/
|
|
17931
|
+
"src/components/xpl-list/listitem.ts::XplListOrderChangeDetail": {
|
|
17250
17932
|
"declaration": "export interface XplListOrderChangeDetail {\n /** Identifier of the item that was moved. */\n itemId?: string;\n /** Direction of the move. */\n direction: 'up' | 'down';\n /**\n * Visible row IDs in DOM order after reorder. Hidden `xpl-list-item` rows are omitted.\n */\n orderedItemIds: string[];\n}",
|
|
17251
17933
|
"docstring": "Payload for the `orderChange` event on `xpl-list`.",
|
|
17252
|
-
"path": "src/components/
|
|
17934
|
+
"path": "src/components/xpl-list/listitem.ts"
|
|
17253
17935
|
},
|
|
17254
|
-
"src/components/
|
|
17936
|
+
"src/components/xpl-popover/xpl-popover.tsx::PopoverPosition": {
|
|
17255
17937
|
"declaration": "export type PopoverPosition =\n | 'top-left'\n | 'middle-left'\n | 'bottom-left'\n | 'top-right'\n | 'middle-right'\n | 'bottom-right'\n | 'top-start'\n | 'top-middle'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-middle'\n | 'bottom-end';",
|
|
17256
17938
|
"docstring": "",
|
|
17257
|
-
"path": "src/components/
|
|
17939
|
+
"path": "src/components/xpl-popover/xpl-popover.tsx"
|
|
17258
17940
|
},
|
|
17259
17941
|
"../../node_modules/@floating-ui/dom/dist/floating-ui.dom.d.mts::Placement": {
|
|
17260
|
-
"declaration": "
|
|
17942
|
+
"declaration": "export declare type Placement = Prettify<Side | AlignedPlacement>;",
|
|
17261
17943
|
"docstring": "",
|
|
17262
17944
|
"path": "../../node_modules/@floating-ui/dom/dist/floating-ui.dom.d.mts"
|
|
17263
17945
|
},
|
|
17264
|
-
"src/components/
|
|
17946
|
+
"src/components/xpl-spotlight/xpl-spotlight.tsx::SpotlightActionLayout": {
|
|
17265
17947
|
"declaration": "export type SpotlightActionLayout = 'default' | 'dual' | 'single';",
|
|
17266
17948
|
"docstring": "",
|
|
17267
|
-
"path": "src/components/
|
|
17949
|
+
"path": "src/components/xpl-spotlight/xpl-spotlight.tsx"
|
|
17268
17950
|
},
|
|
17269
|
-
"src/components/
|
|
17951
|
+
"src/components/xpl-spotlight/xpl-spotlight.tsx::SpotlightAnchorPosition": {
|
|
17270
17952
|
"declaration": "export type SpotlightAnchorPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';",
|
|
17271
17953
|
"docstring": "",
|
|
17272
|
-
"path": "src/components/
|
|
17954
|
+
"path": "src/components/xpl-spotlight/xpl-spotlight.tsx"
|
|
17273
17955
|
},
|
|
17274
|
-
"src/components/
|
|
17956
|
+
"src/components/xpl-badge/xpl-badge.tsx::BadgePalette": {
|
|
17275
17957
|
"declaration": "export type BadgePalette = 'purple' | 'green' | 'yellow' | 'orange' | 'gray' | 'red' | 'blue';",
|
|
17276
17958
|
"docstring": "",
|
|
17277
|
-
"path": "src/components/
|
|
17959
|
+
"path": "src/components/xpl-badge/xpl-badge.tsx"
|
|
17278
17960
|
},
|
|
17279
|
-
"src/components/
|
|
17961
|
+
"src/components/xpl-table/xpl-table.tsx::XplTableRowOrderChangeDetail": {
|
|
17280
17962
|
"declaration": "export interface XplTableRowOrderChangeDetail {\n /** Stable id of the moved row (`row-id`). */\n rowId: string;\n direction: 'up' | 'down';\n /** Visible body row ids in DOM order after the move. */\n orderedRowIds: string[];\n fromIndex: number;\n toIndex: number;\n}",
|
|
17281
17963
|
"docstring": "",
|
|
17282
|
-
"path": "src/components/
|
|
17964
|
+
"path": "src/components/xpl-table/xpl-table.tsx"
|
|
17283
17965
|
},
|
|
17284
|
-
"src/components/
|
|
17966
|
+
"src/components/xpl-table/xpl-table.tsx::XplTableSortChangedDetail": {
|
|
17285
17967
|
"declaration": "export interface XplTableSortChangedDetail {\n /**\n * @deprecated Prefer slug keys on this object. Index of the column whose sort was toggled (legacy tables).\n */\n colNum?: number;\n /**\n * @deprecated Prefer slug keys. Legacy **slugified** column title for `colNum` (same rules as sort-key slugs).\n */\n colName?: string;\n /**\n * @deprecated Prefer slug keys. Per-column sort state in visual column order (`null` when unsorted / N/A).\n */\n sortTypeArr?: ('asc' | 'desc' | null)[];\n [slug: string]: 'asc' | 'desc' | null | number | string | ('asc' | 'desc' | null)[] | undefined;\n}",
|
|
17286
17968
|
"docstring": "`sortChanged` event detail: sort-key slug → direction, plus **legacy** fields for consumers that\nstill read `colNum` / `colName` / `sortTypeArr` from the data-driven table API.\n\nIndex signature allows slug keys alongside legacy properties (cannot use `Record<>` alone without conflicting\nwith `colNum`).",
|
|
17287
|
-
"path": "src/components/
|
|
17969
|
+
"path": "src/components/xpl-table/xpl-table.tsx"
|
|
17288
17970
|
},
|
|
17289
|
-
"src/components/
|
|
17971
|
+
"src/components/xpl-table/xpl-table-header-cell/xpl-table-header-cell.tsx::HeaderSortChangeDetail": {
|
|
17290
17972
|
"declaration": "export interface HeaderSortChangeDetail {\n columnIndex: number;\n sortKey: string;\n}",
|
|
17291
17973
|
"docstring": "",
|
|
17292
|
-
"path": "src/components/
|
|
17974
|
+
"path": "src/components/xpl-table/xpl-table-header-cell/xpl-table-header-cell.tsx"
|
|
17293
17975
|
},
|
|
17294
|
-
"src/components/
|
|
17976
|
+
"src/components/xpl-tag/xpl-tag.tsx::TagDragEndDetail": {
|
|
17295
17977
|
"declaration": "export interface TagDragEndDetail {\n tagId?: string;\n dropped: boolean;\n originalEvent: DragEvent;\n}",
|
|
17296
17978
|
"docstring": "Detail for drag end event",
|
|
17297
|
-
"path": "src/components/
|
|
17979
|
+
"path": "src/components/xpl-tag/xpl-tag.tsx"
|
|
17298
17980
|
},
|
|
17299
|
-
"src/components/
|
|
17981
|
+
"src/components/xpl-tag/xpl-tag.tsx::TagDragStartDetail": {
|
|
17300
17982
|
"declaration": "export interface TagDragStartDetail {\n tagId?: string;\n content: string;\n originalEvent: DragEvent;\n}",
|
|
17301
17983
|
"docstring": "Detail for drag start event",
|
|
17302
|
-
"path": "src/components/
|
|
17984
|
+
"path": "src/components/xpl-tag/xpl-tag.tsx"
|
|
17303
17985
|
}
|
|
17304
17986
|
}
|
|
17305
17987
|
}
|