diff --git a/content/components/dropdowns.md b/content/components/dropdowns.md index 5fdd465d..3696607f 100644 --- a/content/components/dropdowns.md +++ b/content/components/dropdowns.md @@ -45,7 +45,9 @@ The `dropdownId` is the id of the dropdown menu element. ## Dropdown hover -Use the `data-dropdown-trigger="{hover|click}"` data attribute options to set whether the dropdown should be shown when hovering or clicking on the trigger element (ie. button). +Use the `data-dropdown-trigger="{hover|click}"` data attribute options to set whether the dropdown should be shown when hovering or clicking on the trigger element (ie. button). + +There's a 300ms default delay when showing or hiding the dropdown due to UI/UX reasons and how it may affect the interaction with other components on the page. Generally, we recommend using the `click` method. {{< example id="dropdown-hover-example" class="flex justify-center" github="components/dropdowns.md" show_dark=true iframeHeight="240" >}} @@ -68,6 +70,31 @@ Use the `data-dropdown-trigger="{hover|click}"` data attribute options to set wh {{< /example >}} +### Delay duration + +You can use the `data-dropdown-delay={miliseconds}` data attribute to set they delay on when to show or hide the dropdown menu when using hover. You may want to use this depending on how the users interact with your interface. In this example we add 500 miliseconds instead of the default 300. + +{{< example id="dropdown-delay-example" class="flex justify-center" github="components/dropdowns.md" show_dark=true iframeHeight="240" >}} + + + +{{< /example >}} + ## Dropdown divider You can use the `divide-y divide-gray-100` classes to add separate elements inside the dropdown menu. @@ -1179,6 +1206,17 @@ Use the following options as the third parameter for the Dropdown class to set t Set the position of the dropdown menu relative to the trigger element choosing from top|right|bottom|left. + + + triggerType + + + String + + + The possible options are click, hover, or none and these will set based on which event the dropdown will be shown. + + offsetDistance @@ -1201,6 +1239,17 @@ Use the following options as the third parameter for the Dropdown class to set t Set the number of pixels the dropdown menu should be offset relative to the trigger element on the Y horizontal axis. + + + delay + + + Number + + + Set the miliseconds for which the showing or hiding of the dropdown will be delayed for when using the hover trigger type. + + onHide @@ -1282,8 +1331,10 @@ const $triggerEl = document.getElementById('dropdownButton'); // options with default values const options = { placement: 'bottom', + triggerType: 'click', offsetSkidding: 0, offsetDistance: 10, + delay: 300, onHide: () => { console.log('dropdown has been hidden'); }, @@ -1318,7 +1369,7 @@ dropdown.hide(); Use the following HTML code for the JavaScript example above. -```html + -``` + ### TypeScript diff --git a/src/components/dropdown/index.ts b/src/components/dropdown/index.ts index ae27de10..eca6d9f5 100644 --- a/src/components/dropdown/index.ts +++ b/src/components/dropdown/index.ts @@ -12,6 +12,7 @@ const Default: DropdownOptions = { triggerType: 'click', offsetSkidding: 0, offsetDistance: 10, + delay: 300, onShow: () => {}, onHide: () => {}, }; @@ -39,48 +40,54 @@ class Dropdown implements DropdownInterface { _init() { if (this._triggerEl) { - const triggerEvents = this._getTriggerEvents(); + this._setupEventListeners(); + } + } - // click event handling for trigger element - if (this._options.triggerType === 'click') { - triggerEvents.showEvents.forEach((ev) => { - this._triggerEl.addEventListener(ev, () => { - this.toggle(); - }); + _setupEventListeners() { + const triggerEvents = this._getTriggerEvents(); + + // click event handling for trigger element + if (this._options.triggerType === 'click') { + triggerEvents.showEvents.forEach((ev) => { + this._triggerEl.addEventListener(ev, () => { + this.toggle(); }); - } + }); + } - // hover event handling for trigger element - if (this._options.triggerType === 'hover') { - triggerEvents.showEvents.forEach((ev) => { - this._triggerEl.addEventListener(ev, () => { - if (ev === 'click') { - this.toggle(); - } else { + // hover event handling for trigger element + if (this._options.triggerType === 'hover') { + triggerEvents.showEvents.forEach((ev) => { + this._triggerEl.addEventListener(ev, () => { + if (ev === 'click') { + this.toggle(); + } else { + setTimeout(() => { this.show(); + }, this._options.delay); + } + }); + this._targetEl.addEventListener(ev, () => { + this.show(); + }); + }); + triggerEvents.hideEvents.forEach((ev) => { + this._triggerEl.addEventListener(ev, () => { + setTimeout(() => { + if (!this._targetEl.matches(':hover')) { + this.hide(); } - }); - this._targetEl.addEventListener(ev, () => { - this.show(); - }); + }, this._options.delay); }); - triggerEvents.hideEvents.forEach((ev) => { - this._triggerEl.addEventListener(ev, () => { - setTimeout(() => { - if (!this._targetEl.matches(':hover')) { - this.hide(); - } - }, 100); - }); - this._targetEl.addEventListener(ev, () => { - setTimeout(() => { - if (!this._triggerEl.matches(':hover')) { - this.hide(); - } - }, 100); - }); + this._targetEl.addEventListener(ev, () => { + setTimeout(() => { + if (!this._triggerEl.matches(':hover')) { + this.hide(); + } + }, this._options.delay); }); - } + }); } } @@ -144,6 +151,11 @@ class Dropdown implements DropdownInterface { showEvents: ['click'], hideEvents: [], }; + case 'none': + return { + showEvents: [], + hideEvents: [], + }; default: return { showEvents: ['click'], @@ -229,6 +241,7 @@ export function initDropdowns() { const triggerType = $triggerEl.getAttribute( 'data-dropdown-trigger' ); + const delay = $triggerEl.getAttribute('data-dropdown-delay'); new Dropdown( $dropdownEl as HTMLElement, @@ -244,6 +257,7 @@ export function initDropdowns() { offsetDistance: offsetDistance ? parseInt(offsetDistance) : Default.offsetDistance, + delay: delay ? parseInt(delay) : Default.delay, } as DropdownOptions ); } else { diff --git a/src/components/dropdown/types.ts b/src/components/dropdown/types.ts index da239468..65c34199 100644 --- a/src/components/dropdown/types.ts +++ b/src/components/dropdown/types.ts @@ -1,11 +1,11 @@ import { DropdownInterface } from './interface'; import type { Placement } from '@popperjs/core'; -export declare type TriggerType = 'click' | 'hover'; +export declare type TriggerType = 'click' | 'hover' | 'none'; export declare type TriggerEventTypes = { - show: string[]; - hide: string[]; + showEvents: string[]; + hideEvents: string[]; }; export declare type DropdownOptions = { @@ -13,6 +13,7 @@ export declare type DropdownOptions = { triggerType?: TriggerType; offsetSkidding?: number; offsetDistance?: number; + delay?: number; onShow?: (tooltip: DropdownInterface) => void; onHide?: (tooltip: DropdownInterface) => void; };