@lion/ui 0.18.1 → 0.20.0-menu-system.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/collapsible.js +1 -0
- package/components/button/src/LionButton.js +4 -0
- package/components/button/test-suites/LionButton.suite.js +1 -0
- package/components/calendar/src/LionCalendar.js +2 -0
- package/components/collapsible/src/DisclosureMixin.js +313 -0
- package/components/collapsible/test-suites/DisclosureMixin.suite.js +30 -0
- package/components/collapsible/types/DisclosureMixinTypes.ts +48 -0
- package/components/combobox/test/lion-combobox.test.js +1 -0
- package/components/form-core/src/form-group/FormGroupMixin.js +7 -0
- package/components/form-core/src/registration/FormRegistrarMixin.js +11 -0
- package/components/form-core/test/FormControlMixin.test.js +1 -0
- package/components/form-core/test/validate/Validator.test.js +2 -0
- package/components/form-core/test-suites/ValidateMixin.suite.js +2 -0
- package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +1 -0
- package/components/input-amount-dropdown/src/LionInputAmountDropdown.js +6 -4
- package/components/input-amount-dropdown/test/LionInputAmountDropdown.test.js +20 -1
- package/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.js +24 -0
- package/components/input-datepicker/src/localizeNamespaceLoader.js +1 -0
- package/components/input-datepicker/test/lion-input-datepicker.test.js +5 -6
- package/components/localize/test/date/formatDate.test.js +1 -0
- package/components/menu/CHANGELOG.md +37 -0
- package/components/menu/README.md +335 -0
- package/components/menu/index.js +2 -0
- package/components/menu/lion-menu-overlay.js +3 -0
- package/components/menu/lion-menu.js +3 -0
- package/components/menu/lion-spinbutton.js +3 -0
- package/components/menu/lion-toolbar.js +3 -0
- package/components/menu/lion-tree.js +3 -0
- package/components/menu/package.json +46 -0
- package/components/menu/requirements.temp.md +12 -0
- package/components/menu/src/InteractiveListMixin.js +840 -0
- package/components/menu/src/LionMenu.js +250 -0
- package/components/menu/src/LionMenuHybrid.js +46 -0
- package/components/menu/src/LionMenuOverlay.js +155 -0
- package/components/menu/src/LionSpinbutton.js +213 -0
- package/components/menu/src/LionToolbar.js +94 -0
- package/components/menu/src/LionTree.js +52 -0
- package/components/menu/src/MoreButtonMenuMixin.js +278 -0
- package/components/menu/src/MultiLevelListMixin.js +311 -0
- package/components/menu/src/utils/isInView.js +26 -0
- package/components/menu/src/utils/listItemInteractions.js +124 -0
- package/components/menu/test/InteractiveListMixin.test.js +3 -0
- package/components/menu/test/MoreButtonMenuMixin.test.js +4 -0
- package/components/menu/test/MultiLevelListMixin.test.js +3 -0
- package/components/menu/test/lion-menu-hybrid.test.js +3 -0
- package/components/menu/test/lion-menu.test.js +11 -0
- package/components/menu/test/lion-toolbar.test.js +8 -0
- package/components/menu/test/lion-tree.test.js +7 -0
- package/components/menu/test-helpers/mimicKeyPress.js +9 -0
- package/components/menu/test-suites/InteractiveListMixin.suite.js +454 -0
- package/components/menu/test-suites/LionMenu.suite.js +113 -0
- package/components/menu/test-suites/LionMenuHybrid.suite.js +583 -0
- package/components/menu/test-suites/MoreButtonMenuMixin.suite.js +372 -0
- package/components/menu/test-suites/MultiLevelListMixin.suite.js +303 -0
- package/components/menu/types/InteractiveListMixinTypes.d.ts +84 -0
- package/components/navigation-bar/README.md +1 -0
- package/components/navigation-bar/src/LionNavigationBar.js +439 -0
- package/components/navigation-bar/src/types.js +41 -0
- package/components/overlays/NEXT.md +49 -0
- package/components/overlays/src/OverlayController.js +278 -110
- package/components/overlays/src/OverlayMixin.js +58 -11
- package/components/overlays/src/OverlaysManager.js +2 -2
- package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js +100 -26
- package/components/overlays/src/utils/adopt-styles.js +3 -2
- package/components/overlays/src/utils/get-focusable-elements.js +4 -0
- package/components/overlays/src/utils/is-equal-config.js +10 -6
- package/components/overlays/test/OverlayController.test.js +127 -14
- package/components/overlays/test/utils-tests/is-equal-config.test.js +1 -1
- package/components/overlays/test/withHoverInteraction.test.js +90 -0
- package/components/overlays/test-suites/OverlayMixin.suite.js +8 -8
- package/components/overlays/types/ArrowMixinTypes.ts +3 -1
- package/components/overlays/types/OverlayConfig.ts +20 -5
- package/components/overlays/types/OverlayMixinTypes.ts +2 -0
- package/components/select-rich/test/lion-select-rich.test.js +3 -0
- package/custom-elements.json +30446 -17381
- package/dist-types/components/button/src/LionButton.d.ts +1 -0
- package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
- package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
- package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
- package/dist-types/components/collapsible/src/DisclosureMixin.d.ts +3 -0
- package/dist-types/components/collapsible/src/DisclosureMixin.d.ts.map +1 -0
- package/dist-types/components/collapsible/test-suites/DisclosureMixin.suite.d.ts +2 -0
- package/dist-types/components/collapsible/test-suites/DisclosureMixin.suite.d.ts.map +1 -0
- package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts +24 -0
- package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts.map +1 -0
- package/dist-types/components/combobox/src/LionCombobox.d.ts +1 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts +6 -2
- package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
- package/dist-types/components/form-core/src/form-group/FormGroupMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/registration/FormRegistrarMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
- package/dist-types/components/input-amount-dropdown/src/LionInputAmountDropdown.d.ts +0 -9
- package/dist-types/components/input-amount-dropdown/src/LionInputAmountDropdown.d.ts.map +1 -1
- package/dist-types/components/input-amount-dropdown/test/LionInputAmountDropdown.test.d.ts.map +1 -1
- package/dist-types/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +1 -1
- package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -1
- package/dist-types/components/menu/index.d.ts +3 -0
- package/dist-types/components/menu/index.d.ts.map +1 -0
- package/dist-types/components/menu/lion-menu-overlay.d.ts +2 -0
- package/dist-types/components/menu/lion-menu-overlay.d.ts.map +1 -0
- package/dist-types/components/menu/lion-menu.d.ts +2 -0
- package/dist-types/components/menu/lion-menu.d.ts.map +1 -0
- package/dist-types/components/menu/lion-spinbutton.d.ts +2 -0
- package/dist-types/components/menu/lion-spinbutton.d.ts.map +1 -0
- package/dist-types/components/menu/lion-toolbar.d.ts +2 -0
- package/dist-types/components/menu/lion-toolbar.d.ts.map +1 -0
- package/dist-types/components/menu/lion-tree.d.ts +2 -0
- package/dist-types/components/menu/lion-tree.d.ts.map +1 -0
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts +617 -0
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenu.d.ts +635 -0
- package/dist-types/components/menu/src/LionMenu.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenuHybrid.d.ts +19 -0
- package/dist-types/components/menu/src/LionMenuHybrid.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts +1015 -0
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionSpinbutton.d.ts +58 -0
- package/dist-types/components/menu/src/LionSpinbutton.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionToolbar.d.ts +8 -0
- package/dist-types/components/menu/src/LionToolbar.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionTree.d.ts +447 -0
- package/dist-types/components/menu/src/LionTree.d.ts.map +1 -0
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts +39 -0
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +503 -0
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/utils/isInView.d.ts +9 -0
- package/dist-types/components/menu/src/utils/isInView.d.ts.map +1 -0
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts +48 -0
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +1 -0
- package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-menu-hybrid.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-menu-hybrid.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-menu.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-menu.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-toolbar.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-toolbar.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-tree.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-tree.test.d.ts.map +1 -0
- package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts +7 -0
- package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +14 -0
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts +9 -0
- package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/LionMenuHybrid.suite.d.ts +5 -0
- package/dist-types/components/menu/test-suites/LionMenuHybrid.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts +14 -0
- package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts +11 -0
- package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts.map +1 -0
- package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts +238 -0
- package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts.map +1 -0
- package/dist-types/components/navigation-bar/src/types.d.ts +85 -0
- package/dist-types/components/navigation-bar/src/types.d.ts.map +1 -0
- package/dist-types/components/overlays/src/OverlayController.d.ts +24 -12
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts +8 -2
- package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/get-focusable-elements.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/is-equal-config.d.ts.map +1 -1
- package/dist-types/components/overlays/test/withHoverInteraction.test.d.ts +2 -0
- package/dist-types/components/overlays/test/withHoverInteraction.test.d.ts.map +1 -0
- package/dist-types/components/overlays/types/ArrowMixinTypes.d.ts.map +1 -1
- package/dist-types/components/overlays/types/OverlayConfig.d.ts +12 -2
- package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
- package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts +1 -0
- package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +11 -3
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/components/tooltip/src/LionTooltip.d.ts +1 -1
- package/dist-types/exports/define/lion-item.d.ts +2 -0
- package/dist-types/exports/define/lion-item.d.ts.map +1 -0
- package/dist-types/exports/define/lion-menu-overlay.d.ts +2 -0
- package/dist-types/exports/define/lion-menu-overlay.d.ts.map +1 -0
- package/dist-types/exports/define/lion-menu.d.ts +2 -0
- package/dist-types/exports/define/lion-menu.d.ts.map +1 -0
- package/dist-types/exports/define/lion-navigation-bar.d.ts +2 -0
- package/dist-types/exports/define/lion-navigation-bar.d.ts.map +1 -0
- package/dist-types/exports/define/lion-toolbar.d.ts +2 -0
- package/dist-types/exports/define/lion-toolbar.d.ts.map +1 -0
- package/dist-types/exports/define/lion-tree.d.ts +2 -0
- package/dist-types/exports/define/lion-tree.d.ts.map +1 -0
- package/dist-types/exports/menu-test-suites.d.ts +4 -0
- package/dist-types/exports/menu-test-suites.d.ts.map +1 -0
- package/dist-types/exports/menu.d.ts +7 -0
- package/dist-types/exports/menu.d.ts.map +1 -0
- package/dist-types/exports/navigation-bar.d.ts +2 -0
- package/dist-types/exports/navigation-bar.d.ts.map +1 -0
- package/dist-types/exports/overlays.d.ts +3 -0
- package/dist-types/exports/overlays.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/overview.md +1 -1
- package/docs/components/combobox/api-table.md +21 -8
- package/docs/components/combobox/overview.md +1 -1
- package/docs/components/combobox/use-cases.md +1 -1
- package/docs/components/dialog/api-table.md +31 -6
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- package/docs/components/form/use-cases.md +2 -2
- package/docs/components/icon/use-cases.md +1 -1
- package/docs/components/input/overview.md +1 -1
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-amount-dropdown/api-table.md +1 -1
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/api-table.md +21 -4
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-email/overview.md +2 -2
- package/docs/components/input-file/overview.md +1 -1
- package/docs/components/input-iban/overview.md +2 -2
- package/docs/components/input-range/overview.md +2 -2
- package/docs/components/input-stepper/overview.md +1 -1
- package/docs/components/input-tel/overview.md +1 -1
- package/docs/components/input-tel/use-cases.md +6 -6
- package/docs/components/input-tel-dropdown/overview.md +1 -1
- package/docs/components/listbox/use-cases.md +1 -1
- package/docs/components/menu/api-table.md +460 -0
- package/docs/components/menu/applyMenuDemoStyles.js +173 -0
- package/docs/components/menu/extensions.md +262 -0
- package/docs/components/menu/index.md +13 -0
- package/docs/components/menu/overview.md +422 -0
- package/docs/components/menu/use-cases.md +77 -0
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.md +1 -1
- package/docs/components/select-rich/api-table.md +21 -5
- package/docs/components/select-rich/use-cases.md +2 -2
- package/docs/components/tabs/examples.md +1 -1
- package/docs/components/tooltip/api-table.md +36 -11
- package/docs/components/tooltip/use-cases.md +22 -0
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
- package/docs/fundamentals/rationales/accessibility.md +1 -1
- package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
- package/docs/fundamentals/systems/core/overview.md +1 -1
- package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
- package/docs/fundamentals/systems/form/model-value.md +1 -1
- package/docs/fundamentals/systems/form/overview.md +28 -28
- package/docs/fundamentals/systems/form/validate.md +2 -2
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/api-table.md +36 -34
- package/docs/fundamentals/systems/overlays/configuration.md +2 -2
- package/docs/fundamentals/systems/overlays/overview.md +5 -5
- package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
- package/docs/fundamentals/tools/helpers/overview.md +1 -1
- package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
- package/docs/guides/how-to/create-a-custom-field.md +5 -5
- package/docs/guides/how-to/create-a-form.md +4 -4
- package/docs/guides/how-to/extend-a-native-input.md +2 -2
- package/docs/guides/how-to/index.md +1 -1
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/styling.md +1 -1
- package/exports/collapsible.js +1 -0
- package/exports/define/lion-item.js +3 -0
- package/exports/define/lion-menu-overlay.js +3 -0
- package/exports/define/lion-menu.js +3 -0
- package/exports/define/lion-navigation-bar.js +3 -0
- package/exports/define/lion-toolbar.js +3 -0
- package/exports/define/lion-tree.js +3 -0
- package/exports/menu-test-suites.js +4 -0
- package/exports/menu.js +7 -0
- package/exports/navigation-bar.js +1 -0
- package/exports/overlays.js +6 -0
- package/menu-test-suites.js +4 -0
- package/menu.js +7 -0
- package/navigation-bar.js +1 -0
- package/overlays.js +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { expect, html, fixture as _fixture, unsafeStatic, defineCE } from '@open-wc/testing';
|
|
3
|
+
import { InteractiveListMixin } from '../src/InteractiveListMixin.js';
|
|
4
|
+
import { mimicKeyPress } from '../test-helpers/mimicKeyPress.js';
|
|
5
|
+
|
|
6
|
+
class InteractiveListClass extends InteractiveListMixin(LitElement) {}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {import('../types/InteractiveListMixinTypes.js').InteractiveListItemRole} InteractiveListItemRole
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** @type {InteractiveListItemRole[]} */
|
|
13
|
+
const supportedRoles = [
|
|
14
|
+
'menuitem',
|
|
15
|
+
'menuitemcheckbox',
|
|
16
|
+
'menuitemradio',
|
|
17
|
+
'option',
|
|
18
|
+
'treeitem',
|
|
19
|
+
'radio',
|
|
20
|
+
'checkbox',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {import('../src/LionMenu.js').LionMenu} LionMenu
|
|
25
|
+
* @typedef {import('lit').TemplateResult} TemplateResult
|
|
26
|
+
*
|
|
27
|
+
* * @typedef {Object} TestConfig
|
|
28
|
+
* @property {string} tagString
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const fixture = /** @type {(arg: TemplateResult) => Promise<LionMenu>} */ (_fixture);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {TestConfig} [customConfig]
|
|
35
|
+
*/
|
|
36
|
+
export function runInteractiveListMixinSuite(customConfig) {
|
|
37
|
+
const cfg = {
|
|
38
|
+
tagString: customConfig?.tagString || defineCE(InteractiveListClass),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const { tagString } = cfg;
|
|
42
|
+
const tag = unsafeStatic(tagString);
|
|
43
|
+
|
|
44
|
+
describe('InteractiveListMixin', () => {
|
|
45
|
+
it(`supports items with role="${supportedRoles.join('|')}"`, async () => {
|
|
46
|
+
const el = await fixture(html`
|
|
47
|
+
<${tag} name="foo">
|
|
48
|
+
${supportedRoles.map(role => html` <div role="${role}"></div> `)}
|
|
49
|
+
</${tag}>
|
|
50
|
+
`);
|
|
51
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
52
|
+
expect(el.listItems.length).to.equal(supportedRoles.length);
|
|
53
|
+
supportedRoles.forEach((role, i) => {
|
|
54
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
55
|
+
expect(el.listItems[i].getAttribute('role')).to.equal(role);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('moves elements to a private [slot=list] for optimal DX and a11y', async () => {
|
|
60
|
+
const el = await fixture(html`
|
|
61
|
+
<${tag} name="foo">
|
|
62
|
+
<div role="menuitem" id="item1">Item 1</div>
|
|
63
|
+
<div role="menuitem" id="item2">Item 2</div>
|
|
64
|
+
</${tag}>
|
|
65
|
+
`);
|
|
66
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
67
|
+
const listSlotNode = Array.from(el.children).find(c => c.slot === 'list');
|
|
68
|
+
// @ts-ignore - accessing children property
|
|
69
|
+
const listItemEls = Array.from(listSlotNode.children);
|
|
70
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
71
|
+
expect(listItemEls.includes(el.listItems[0])).to.be.true;
|
|
72
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
73
|
+
expect(listItemEls.includes(el.listItems[1])).to.be.true;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('inherits from DisclosureMixin', async () => {});
|
|
77
|
+
|
|
78
|
+
describe('Active mode', async () => {
|
|
79
|
+
it('supports "activedescendant" pattern', async () => {
|
|
80
|
+
const el = await fixture(html`
|
|
81
|
+
<${tag} name="foo" ._activeMode="${'activedescendant'}">
|
|
82
|
+
<div role="menuitem" id="item1">Item 1</div>
|
|
83
|
+
<div role="menuitem" id="item2">Item 2</div>
|
|
84
|
+
</${tag}>
|
|
85
|
+
`);
|
|
86
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
87
|
+
el.checkedIndex = 0;
|
|
88
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
89
|
+
const listSlotNode = Array.from(el.children).find(c => c.slot === 'list');
|
|
90
|
+
|
|
91
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
92
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
93
|
+
expect(el.listItems[0].hasAttribute('id')).to.be.true;
|
|
94
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
95
|
+
expect(el.listItems[1].hasAttribute('id')).to.be.true;
|
|
96
|
+
expect(listSlotNode?.hasAttribute('aria-activedescendant')).to.be.false;
|
|
97
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
98
|
+
el.activeIndex = 1;
|
|
99
|
+
expect(listSlotNode?.hasAttribute('aria-activedescendant')).to.be.true;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('supports "roving-tabindex" pattern', async () => {
|
|
103
|
+
const el = await fixture(html`
|
|
104
|
+
<${tag} name="foo" ._activeMode="${'roving-tabindex'}">
|
|
105
|
+
<div role="menuitem" id="item1">Item 1</div>
|
|
106
|
+
<div role="menuitem" id="item2">Item 2</div>
|
|
107
|
+
</${tag}>
|
|
108
|
+
`);
|
|
109
|
+
|
|
110
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
111
|
+
el.activeIndex = 0;
|
|
112
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
113
|
+
expect(el.listItems[0].getAttribute('tabindex')).to.equal('0');
|
|
114
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
115
|
+
expect(el.listItems[1].getAttribute('tabindex')).to.equal('-1');
|
|
116
|
+
|
|
117
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
118
|
+
el.activeIndex = 1;
|
|
119
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
120
|
+
expect(el.listItems[0].getAttribute('tabindex')).to.equal('-1');
|
|
121
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
122
|
+
expect(el.listItems[1].getAttribute('tabindex')).to.equal('0');
|
|
123
|
+
|
|
124
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
125
|
+
el.activeIndex = 1;
|
|
126
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
127
|
+
expect(document.activeElement).to.equal(el.listItems[1]);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('preselect', () => {
|
|
132
|
+
it('sets the checkedIndex to 0 by default when noPreselect is false', async () => {
|
|
133
|
+
const el = await fixture(html`
|
|
134
|
+
<${tag}>
|
|
135
|
+
<div role="menuitem" id="item1">Item 1</div>
|
|
136
|
+
</${tag}>
|
|
137
|
+
`);
|
|
138
|
+
if (!el.noPreselect) {
|
|
139
|
+
expect(el.checkedIndex).to.equal(0);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('sets the checkedIndex to -1 when noPreselect is true', async () => {
|
|
144
|
+
const el = await fixture(html`
|
|
145
|
+
<${tag} no-preselect>
|
|
146
|
+
<div role="menuitem" id="item1">Item 1</div>
|
|
147
|
+
</${tag}>
|
|
148
|
+
`);
|
|
149
|
+
expect(el.checkedIndex).to.equal(-1);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('Programmatic interaction', () => {
|
|
154
|
+
// If we have the item line directly in the fixture the linting rule lit-a11y/role-has-required-aria-attrs
|
|
155
|
+
// will fail. Inside our code we set the required aria attributes, but the linter doesn't know that.
|
|
156
|
+
const item = /** @param {number} i, @param {string} role */ (i, role) => html`
|
|
157
|
+
<div role="${role}" id="item${i}">Item ${i}</div>
|
|
158
|
+
`;
|
|
159
|
+
|
|
160
|
+
it('set checked state sets aria-current attribute with role="listitem"', async () => {
|
|
161
|
+
const el = await fixture(html`
|
|
162
|
+
<${tag}>
|
|
163
|
+
${item(1, 'listitem')}
|
|
164
|
+
${item(2, 'listitem')}
|
|
165
|
+
</${tag}>
|
|
166
|
+
`);
|
|
167
|
+
el.setCheckedIndex(1);
|
|
168
|
+
const item1 = el.listItems[1];
|
|
169
|
+
expect(item1.getAttribute('aria-current')).to.equal('true');
|
|
170
|
+
el.setCheckedIndex(0);
|
|
171
|
+
expect(item1.getAttribute('aria-current')).to.equal('false');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('set checked state sets aria-selected attribute with role="option"', async () => {
|
|
175
|
+
const el = await fixture(html`
|
|
176
|
+
<${tag}>
|
|
177
|
+
${item(1, 'option')}
|
|
178
|
+
${item(2, 'option')}
|
|
179
|
+
</${tag}>
|
|
180
|
+
`);
|
|
181
|
+
const item1 = el.listItems[1];
|
|
182
|
+
expect(item1.getAttribute('aria-selected')).to.equal('false');
|
|
183
|
+
|
|
184
|
+
el.setCheckedIndex(1);
|
|
185
|
+
expect(item1.getAttribute('aria-selected')).to.equal('true');
|
|
186
|
+
|
|
187
|
+
el.setCheckedIndex(0);
|
|
188
|
+
expect(item1.getAttribute('aria-selected')).to.equal('false');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('set checked state sets aria-selected attribute with role="treeitem"', async () => {
|
|
192
|
+
const el = await fixture(html`
|
|
193
|
+
<${tag}>
|
|
194
|
+
${item(1, 'treeitem')}
|
|
195
|
+
${item(2, 'treeitem')}
|
|
196
|
+
</${tag}>
|
|
197
|
+
`);
|
|
198
|
+
el.setCheckedIndex(1);
|
|
199
|
+
// @ts-ignore - test element with InteractiveListMixin properties
|
|
200
|
+
const item1 = el.listItems[1];
|
|
201
|
+
expect(item1.getAttribute('aria-selected')).to.equal('true');
|
|
202
|
+
el.setCheckedIndex(0);
|
|
203
|
+
expect(item1.getAttribute('aria-selected')).to.equal('false');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('set checked state sets aria-current attribute with role="menuitem"', async () => {
|
|
207
|
+
const el = await fixture(html`
|
|
208
|
+
<${tag}>
|
|
209
|
+
${item(1, 'menuitem')}
|
|
210
|
+
${item(2, 'menuitem')}
|
|
211
|
+
</${tag}>
|
|
212
|
+
`);
|
|
213
|
+
el.setCheckedIndex(1);
|
|
214
|
+
const item1 = el.listItems[1];
|
|
215
|
+
expect(item1.getAttribute('aria-current')).to.equal('true');
|
|
216
|
+
el.setCheckedIndex(0);
|
|
217
|
+
expect(item1.getAttribute('aria-current')).to.equal('false');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('set checked state sets aria-checked attribute with role="menuitemradio"', async () => {
|
|
221
|
+
const el = await fixture(html`
|
|
222
|
+
<${tag}>
|
|
223
|
+
${item(1, 'menuitemradio')}
|
|
224
|
+
${item(2, 'menuitemradio')}
|
|
225
|
+
</${tag}>
|
|
226
|
+
`);
|
|
227
|
+
el.setCheckedIndex(1);
|
|
228
|
+
const item1 = el.listItems[1];
|
|
229
|
+
expect(item1.getAttribute('aria-checked')).to.equal('true');
|
|
230
|
+
el.setCheckedIndex(0);
|
|
231
|
+
expect(item1.getAttribute('aria-checked')).to.equal('false');
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('set checked state sets aria-checked attribute with role="menuitemcheckbox"', async () => {
|
|
235
|
+
const el = await fixture(html`
|
|
236
|
+
<${tag} multiple-choice>
|
|
237
|
+
${item(1, 'menuitemcheckbox')}
|
|
238
|
+
${item(2, 'menuitemcheckbox')}
|
|
239
|
+
</${tag}>
|
|
240
|
+
`);
|
|
241
|
+
el.setCheckedIndex(1);
|
|
242
|
+
const item1 = el.listItems[1];
|
|
243
|
+
expect(item1.getAttribute('aria-checked')).to.equal('true');
|
|
244
|
+
el.setCheckedIndex(0);
|
|
245
|
+
// As this is multiple choice it doesn't unset the checked state
|
|
246
|
+
expect(item1.getAttribute('aria-checked')).to.equal('true');
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('can set checked state to "page" for role="listitem"', async () => {
|
|
250
|
+
const el = await fixture(html`
|
|
251
|
+
<${tag}>
|
|
252
|
+
<a role="listitem" id="item1" href="#">Item 1</a>
|
|
253
|
+
<a role="listitem" id="item2" href="#">Item 2</a>
|
|
254
|
+
</${tag}>
|
|
255
|
+
`);
|
|
256
|
+
el.setCheckedIndex(1);
|
|
257
|
+
const item1 = el.listItems[1];
|
|
258
|
+
expect(item1.getAttribute('aria-current')).to.equal('page');
|
|
259
|
+
el.setCheckedIndex(0);
|
|
260
|
+
expect(item1.getAttribute('aria-current')).to.equal('false');
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('can set checked state to "mixed" for role="menuitemcheckbox"', async () => {
|
|
264
|
+
const el = await fixture(html`
|
|
265
|
+
<${tag} multiple-choice>
|
|
266
|
+
${item(1, 'menuitemcheckbox')}
|
|
267
|
+
${item(2, 'menuitemcheckbox')}
|
|
268
|
+
</${tag}>
|
|
269
|
+
`);
|
|
270
|
+
const item1 = el.listItems[1];
|
|
271
|
+
// @ts-ignore - not yet supported property
|
|
272
|
+
item1.mixedState = true;
|
|
273
|
+
el.setCheckedIndex(1);
|
|
274
|
+
expect(item1.getAttribute('aria-checked')).to.equal('mixed');
|
|
275
|
+
el.setCheckedIndex(0);
|
|
276
|
+
expect(item1.getAttribute('aria-checked')).to.equal('mixed');
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('does not allow to set checkedIndex or activeIndex to be out of bound', async () => {
|
|
280
|
+
const el = await fixture(html`
|
|
281
|
+
<${tag} no-preselect>
|
|
282
|
+
<div role="menuitem" id="item1">Item 1</div>
|
|
283
|
+
</${tag}>
|
|
284
|
+
`);
|
|
285
|
+
expect(() => {
|
|
286
|
+
el.checkedIndex = -1;
|
|
287
|
+
el.checkedIndex = 1;
|
|
288
|
+
}).to.not.throw();
|
|
289
|
+
expect(el.checkedIndex).to.equal(-1);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('unsets checked on other options when option becomes checked', async () => {
|
|
293
|
+
const el = await fixture(html`
|
|
294
|
+
<${tag}>
|
|
295
|
+
<div role="menuitem" id="item1">Item 1</div>
|
|
296
|
+
<div role="menuitem" id="item2">Item 2</div>
|
|
297
|
+
</${tag}>
|
|
298
|
+
`);
|
|
299
|
+
const { listItems } = el;
|
|
300
|
+
el.setCheckedIndex(0);
|
|
301
|
+
expect(listItems[0].hasAttribute('checked')).to.be.true;
|
|
302
|
+
expect(listItems[1].hasAttribute('checked')).to.be.false;
|
|
303
|
+
el.setCheckedIndex(1);
|
|
304
|
+
expect(listItems[0].hasAttribute('checked')).to.be.false;
|
|
305
|
+
expect(listItems[1].hasAttribute('checked')).to.be.true;
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('sets aria-current="page" when the location href matches the item href', async () => {
|
|
310
|
+
const el = await fixture(html`
|
|
311
|
+
<${tag}>
|
|
312
|
+
<div role="menuitem" id="item0">
|
|
313
|
+
<a href="${window.location.href}">Item 0</a>
|
|
314
|
+
</div>
|
|
315
|
+
<div role="menuitem" id="item1">
|
|
316
|
+
<a href="#bar">Item 1</a>
|
|
317
|
+
</div>
|
|
318
|
+
</${tag}>
|
|
319
|
+
`);
|
|
320
|
+
const item0 = el.listItems[0];
|
|
321
|
+
expect(item0.getAttribute('aria-current')).to.equal('page');
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Copy tests from ListboxMixin. Later, make this mixin a fundament of the ListboxMixin
|
|
325
|
+
|
|
326
|
+
// orientation
|
|
327
|
+
// multipleChoice
|
|
328
|
+
// selectionFollowsFocus
|
|
329
|
+
// rotateKeyboardNavigation
|
|
330
|
+
// _scrollTargetNode
|
|
331
|
+
|
|
332
|
+
describe('Interactions', () => {
|
|
333
|
+
describe('Keyboard navigation', () => {
|
|
334
|
+
it('navigates between items on [ArrowDown] [ArrowUp] keys', async () => {
|
|
335
|
+
const el = await fixture(html`
|
|
336
|
+
<${tag}>
|
|
337
|
+
<div role="listitem" id="item-0">
|
|
338
|
+
<button data-invoker>Item 0</button>
|
|
339
|
+
</div>
|
|
340
|
+
<div role="listitem" id="item-1">
|
|
341
|
+
<a href="#baz">Item 1</a>
|
|
342
|
+
</div>
|
|
343
|
+
<div role="listitem" id="item-2">
|
|
344
|
+
<a href="#foobar">Item 2</a>
|
|
345
|
+
</div>
|
|
346
|
+
</${tag}>
|
|
347
|
+
`);
|
|
348
|
+
|
|
349
|
+
const { _listNode } = el;
|
|
350
|
+
|
|
351
|
+
// Normalize
|
|
352
|
+
el.activeIndex = 0;
|
|
353
|
+
|
|
354
|
+
mimicKeyPress(_listNode, 'ArrowDown');
|
|
355
|
+
expect(el.activeIndex).to.be.equal(1);
|
|
356
|
+
mimicKeyPress(_listNode, 'ArrowDown');
|
|
357
|
+
expect(el.activeIndex).to.be.equal(2);
|
|
358
|
+
mimicKeyPress(_listNode, 'ArrowUp');
|
|
359
|
+
expect(el.activeIndex).to.be.equal(1);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('navigates between items on [ArrowRight] [ArrowLeft] keys when orientation is "horizontal" and _activeMode="tabbable-disclosure"', async () => {
|
|
363
|
+
const el = await fixture(html`
|
|
364
|
+
<${tag} orientation="horizontal">
|
|
365
|
+
<div role="listitem" id="item-0">
|
|
366
|
+
<button data-invoker>Item 0</button>
|
|
367
|
+
</div>
|
|
368
|
+
<div role="listitem" id="item-1">
|
|
369
|
+
<a href="#baz">Item 1</a>
|
|
370
|
+
</div>
|
|
371
|
+
<div role="listitem" id="item-2">
|
|
372
|
+
<a href="#foobar">Item 2</a>
|
|
373
|
+
</div>
|
|
374
|
+
</${tag}>
|
|
375
|
+
`);
|
|
376
|
+
el._activeMode = 'tabbable-disclosure';
|
|
377
|
+
const { _listNode } = el;
|
|
378
|
+
|
|
379
|
+
// Normalize
|
|
380
|
+
el.activeIndex = 0;
|
|
381
|
+
|
|
382
|
+
mimicKeyPress(_listNode, 'ArrowRight');
|
|
383
|
+
expect(el.activeIndex).to.be.equal(1);
|
|
384
|
+
mimicKeyPress(_listNode, 'ArrowRight');
|
|
385
|
+
expect(el.activeIndex).to.be.equal(2);
|
|
386
|
+
mimicKeyPress(_listNode, 'ArrowLeft');
|
|
387
|
+
expect(el.activeIndex).to.be.equal(1);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('stops navigation by default at end of option list', async () => {
|
|
391
|
+
const el = await fixture(html`
|
|
392
|
+
<${tag}>
|
|
393
|
+
<div role="listitem" id="item-0">
|
|
394
|
+
<button data-invoker>Item 0</button>
|
|
395
|
+
</div>
|
|
396
|
+
<div role="listitem" id="item-1">
|
|
397
|
+
<a href="#baz">Item 1</a>
|
|
398
|
+
</div>
|
|
399
|
+
<div role="listitem" id="item-2">
|
|
400
|
+
<a href="#foobar">Item 2</a>
|
|
401
|
+
</div>
|
|
402
|
+
</${tag}>
|
|
403
|
+
`);
|
|
404
|
+
|
|
405
|
+
const { _listNode } = el;
|
|
406
|
+
|
|
407
|
+
// Normalize
|
|
408
|
+
el.activeIndex = 0;
|
|
409
|
+
|
|
410
|
+
mimicKeyPress(_listNode, 'ArrowUp');
|
|
411
|
+
expect(el.activeIndex).to.be.equal(0);
|
|
412
|
+
|
|
413
|
+
el.activeIndex = 2;
|
|
414
|
+
mimicKeyPress(_listNode, 'ArrowDown');
|
|
415
|
+
expect(el.activeIndex).to.be.equal(2);
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it('navigates to first and last option with [Home] and [End] keys', async () => {
|
|
419
|
+
const el = await fixture(html`
|
|
420
|
+
<${tag} orientation="horizontal">
|
|
421
|
+
<div role="listitem" id="item-0">
|
|
422
|
+
<button data-invoker>Item 0</button>
|
|
423
|
+
</div>
|
|
424
|
+
<div role="listitem" id="item-1">
|
|
425
|
+
<a href="#baz">Item 1</a>
|
|
426
|
+
</div>
|
|
427
|
+
<div role="listitem" id="item-2">
|
|
428
|
+
<a href="#foobar">Item 2</a>
|
|
429
|
+
</div>
|
|
430
|
+
</${tag}>
|
|
431
|
+
`);
|
|
432
|
+
|
|
433
|
+
const { _listNode } = el;
|
|
434
|
+
|
|
435
|
+
// Normalize
|
|
436
|
+
el.activeIndex = 2;
|
|
437
|
+
|
|
438
|
+
mimicKeyPress(_listNode, 'Home');
|
|
439
|
+
expect(el.activeIndex).to.equal(0);
|
|
440
|
+
mimicKeyPress(_listNode, 'End');
|
|
441
|
+
expect(el.activeIndex).to.equal(2);
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
describe('Widget extensions', () => {
|
|
447
|
+
it('can be extended to [role=listbox]', async () => {});
|
|
448
|
+
it('can be extended to [role=menu]', async () => {});
|
|
449
|
+
it('can be extended to [role=menubar]', async () => {});
|
|
450
|
+
it('can be extended to [role=toolbar]', async () => {});
|
|
451
|
+
it('can be extended to [role=tree]', async () => {});
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/* eslint-disable lit-a11y/click-events-have-key-events */
|
|
2
|
+
import { defineCE, expect, fixture as _fixture, html, unsafeStatic } from '@open-wc/testing';
|
|
3
|
+
import { LionMenu } from '../src/LionMenu.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {import('lit').TemplateResult} TemplateResult
|
|
7
|
+
*
|
|
8
|
+
* @typedef {Object} TestConfig
|
|
9
|
+
* @property {string} tagString
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fixture = /** @type {(arg: TemplateResult) => Promise<LionMenu>} */ (_fixture);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {TestConfig} [customConfig]
|
|
16
|
+
*/
|
|
17
|
+
export function runLionMenuSuite(customConfig) {
|
|
18
|
+
const cfg = {
|
|
19
|
+
tagString: customConfig?.tagString || defineCE(LionMenu),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const { tagString } = cfg;
|
|
23
|
+
const tag = unsafeStatic(tagString);
|
|
24
|
+
|
|
25
|
+
describe('LionMenu', () => {
|
|
26
|
+
it('sets the correct role to the listNode', async () => {
|
|
27
|
+
const el = await fixture(html`
|
|
28
|
+
<${tag}>
|
|
29
|
+
<div role="listitem" id="item-0">
|
|
30
|
+
<a href="#foo">Item 0</a>
|
|
31
|
+
</div>
|
|
32
|
+
<div role="listitem" id="item-1">
|
|
33
|
+
<a href="#bar">Item 1</a>
|
|
34
|
+
</div>
|
|
35
|
+
</${tag}>
|
|
36
|
+
`);
|
|
37
|
+
|
|
38
|
+
const listNode = el.querySelector('[slot="list"]');
|
|
39
|
+
expect(listNode?.getAttribute('role')).to.equal('menu');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('sets the correct role to the listNode when activeMode is tabbable-disclosure', async () => {
|
|
43
|
+
const el = await fixture(html`
|
|
44
|
+
<${tag} ._activeMode=${'tabbable-disclosure'}>
|
|
45
|
+
<div role="listitem" id="item-0">
|
|
46
|
+
<a href="#foo">Item 0</a>
|
|
47
|
+
</div>
|
|
48
|
+
<div role="listitem" id="item-1">
|
|
49
|
+
<a href="#bar">Item 1</a>
|
|
50
|
+
</div>
|
|
51
|
+
</${tag}>
|
|
52
|
+
`);
|
|
53
|
+
const listNode = el.querySelector('[slot="list"]');
|
|
54
|
+
expect(listNode?.getAttribute('role')).to.equal('list');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('sets the correct roles when it is a bar', async () => {
|
|
58
|
+
const el = await fixture(html`
|
|
59
|
+
<${tag}>
|
|
60
|
+
<div role="listitem" id="item-0">
|
|
61
|
+
<a href="#foo">Item 0</a>
|
|
62
|
+
</div>
|
|
63
|
+
<div role="listitem" id="item-1">
|
|
64
|
+
<a href="#bar">Item 1</a>
|
|
65
|
+
</div>
|
|
66
|
+
</${tag}>
|
|
67
|
+
`);
|
|
68
|
+
|
|
69
|
+
el._listRole = 'menu';
|
|
70
|
+
expect(el._listRole).to.equal('menu');
|
|
71
|
+
expect(el.orientation).to.equal('vertical');
|
|
72
|
+
el.bar = true;
|
|
73
|
+
await el.updateComplete;
|
|
74
|
+
expect(el._listRole).to.equal('menubar');
|
|
75
|
+
expect(el.orientation).to.equal('horizontal');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('Programmatic interaction', () => {
|
|
79
|
+
it('allows groups within one menu level', async () => {
|
|
80
|
+
const el = await fixture(html`
|
|
81
|
+
<${tag}>
|
|
82
|
+
<div role="menuitemcheckbox" aria-checked="false">Bold</div>
|
|
83
|
+
<div role="menuitemcheckbox" aria-checked="false">Italic</div>
|
|
84
|
+
<div role="separator"></div>
|
|
85
|
+
<div role="group" aria-label="Text Color">
|
|
86
|
+
<div role="menuitemradio" aria-checked="false">Blue</div>
|
|
87
|
+
<div role="menuitemradio" aria-checked="false">Red</div>
|
|
88
|
+
<div role="menuitemradio" aria-checked="false">Green</div>
|
|
89
|
+
</div>
|
|
90
|
+
</${tag}>
|
|
91
|
+
`);
|
|
92
|
+
el.setCheckedIndex(1);
|
|
93
|
+
const item1 = el.listItems[1];
|
|
94
|
+
const item3 = el.listItems[3];
|
|
95
|
+
expect(item1.getAttribute('aria-checked')).to.equal('true');
|
|
96
|
+
|
|
97
|
+
// change within checkbox group doesn't trigger a change on checkbox
|
|
98
|
+
el.setCheckedIndex(0);
|
|
99
|
+
expect(item1.getAttribute('aria-checked')).to.equal('true');
|
|
100
|
+
|
|
101
|
+
// update outside checkbox group doesn't trigger a change on checkbox
|
|
102
|
+
el.setCheckedIndex(3);
|
|
103
|
+
expect(item1.getAttribute('aria-checked')).to.equal('true');
|
|
104
|
+
expect(item3.getAttribute('aria-checked')).to.equal('true');
|
|
105
|
+
|
|
106
|
+
// change within radio group triggers a change on radio button and not on checkbox
|
|
107
|
+
el.setCheckedIndex(4);
|
|
108
|
+
expect(item1.getAttribute('aria-checked')).to.equal('true');
|
|
109
|
+
expect(item3.getAttribute('aria-checked')).to.equal('false');
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|