Skip to content

Commit

Permalink
feat(createMenuButton): Add trigger prop on createMenuButton composab…
Browse files Browse the repository at this point in the history
…le (#2318)

<!-- Is your PR related to an issue? Then please link it via the
"Relates to #" below. Else, remove it. -->

Relates to #2293 

<!-- Briefly describe the changes of this PR. -->

## Checklist

- [x] The added / edited code has been documented with
[JSDoc](https://jsdoc.app/about-getting-started)
- [x] A changeset is added with `npx changeset add` if your changes
should be released as npm package (because they affect the library
usage)
  • Loading branch information
MajaZarkova authored Dec 16, 2024
1 parent 1be4024 commit b76647b
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/tricky-adults-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sit-onyx/headless": minor
---

feat(createMenuButton): add new trigger property that enables the flyout to be expanded on click, not on hover. The default behavior is on hover
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { ref } from "vue";
import { ref, type Ref } from "vue";
import { createMenuButton } from "./createMenuButton";
const items = Array.from({ length: 10 }, (_, index) => {
Expand All @@ -10,10 +10,11 @@ const items = Array.from({ length: 10 }, (_, index) => {
const activeItem = ref<string>();
const isExpanded = ref(false);
const onToggle = () => (isExpanded.value = !isExpanded.value);
const trigger: Readonly<Ref<"click" | "hover">> = ref("hover");
const {
elements: { root, button, menu, menuItem, listItem },
} = createMenuButton({ isExpanded, onToggle });
} = createMenuButton({ isExpanded, onToggle, trigger });
</script>

<template>
Expand Down
17 changes: 15 additions & 2 deletions packages/headless/src/composables/menuButton/createMenuButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useGlobalEventListener } from "../helpers/useGlobalListener";

type CreateMenuButtonOptions = {
isExpanded: Readonly<Ref<boolean>>;
trigger: Readonly<Ref<"hover" | "click">>;
onToggle: () => void;
};

Expand Down Expand Up @@ -105,13 +106,25 @@ export const createMenuButton = createBuilder((options: CreateMenuButtonOptions)
}
};

const triggerEvents = () => {
if (options.trigger.value === "click") {
return {
onClick: () => setExpanded(true),
};
} else {
return {
onMouseenter: () => setExpanded(true),
onMouseleave: () => setExpanded(false, true),
};
}
};

return {
elements: {
root: {
id: rootId,
onKeydown: handleKeydown,
onMouseenter: () => setExpanded(true),
onMouseleave: () => setExpanded(false, true),
...triggerEvents(),
onFocusout: (event) => {
// if focus receiving element is not part of the menu button, then close
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export const useDataGridFeatures = <
OnyxFlyoutMenu,
{
label: t.value("navigation.moreActionsFlyout", { column: column as string }),
trigger: "click",
},
{
button: ({ trigger }) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,30 @@ test("check custom interactivity", async ({ page, mount }) => {
await expect(item).toBeEnabled();
}
});

test("should open on click", async ({ page, mount }) => {
// ARRANGE
const component = await mount(TestWrapperCt, {
props: { label: "Choose application language", trigger: "click" },
});
const menu = page.locator("ul");
const menuItems = page.getByRole("menuitem");

// ASSERT
await expect(menu).toBeHidden();

// ACT
await component.hover();

// ASSERT
await expect(menu).toBeHidden();

// ACT
await component.click();

// ASSERT
await expect(menu).toBeVisible();
for (const item of await menuItems.all()) {
await expect(item).toBeEnabled();
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { MANAGED_SYMBOL, useManagedState } from "../../../../composables/useMana
import type { SelectOptionValue } from "../../../../types";
import type { OnyxFlyoutMenuProps } from "./types";
const props = withDefaults(defineProps<OnyxFlyoutMenuProps>(), { open: MANAGED_SYMBOL });
const props = withDefaults(defineProps<OnyxFlyoutMenuProps>(), {
open: MANAGED_SYMBOL,
trigger: "hover",
});
const emit = defineEmits<{
"update:open": [isOpen: boolean];
Expand Down Expand Up @@ -46,6 +49,7 @@ const {
} = createMenuButton({
isExpanded: computed(() => !!isExpanded.value),
onToggle: () => (isExpanded.value = !isExpanded.value),
trigger: computed(() => props.trigger),
});
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ export type OnyxFlyoutMenuProps = {
* If `undefined`, the state will be managed internally.
*/
open?: ManagedProp<boolean>;
/**
* If the flyout is expanded on click or hover.
* The default value is 'hover' which will expand the flyout on hover.
*/
trigger?: "hover" | "click";
/**
* Aria label for the flyout.
*/
Expand Down

0 comments on commit b76647b

Please sign in to comment.