Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions core/src/components/AppMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ const PROFILE_ID = 'profile'
// Entry of the app management page, the target of the "More apps" tile.
const APP_MANAGEMENT_ID = 'appstore'

// Hover delays, same values as github.com's header navigation.
const HOVER_OPEN_DELAY = 90
// Pause before hover opens the menu: the trigger sits in the corner, which
// cursors cross on the way elsewhere.
const HOVER_OPEN_DELAY = 300
const HOVER_CLOSE_DELAY = 180
// Ignore a trigger click this long after a hover-open, so it does not close again.
const HOVER_CLICK_GRACE = 500
Expand Down
22 changes: 13 additions & 9 deletions core/src/tests/components/AppMenu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,13 @@ describe('core: AppMenu', () => {
const wrapper = mount(AppMenu, { attachTo: document.body })
await wrapper.get('.app-menu__trigger').trigger('mouseenter')

// The intent-pause means it must not open on the same tick.
// The intent-pause means it must not open on the same tick, and it
// has to outlast a cursor merely passing over the corner.
expect(wrapper.vm.opened).toBe(false)
vi.advanceTimersByTime(90)
vi.advanceTimersByTime(200)
expect(wrapper.vm.opened).toBe(false)

vi.advanceTimersByTime(100)
expect(wrapper.vm.opened).toBe(true)
})

Expand All @@ -345,7 +349,7 @@ describe('core: AppMenu', () => {
it('stays open when the cursor moves from the trigger into the popover', async () => {
const wrapper = mount(AppMenu, { attachTo: document.body })
await wrapper.get('.app-menu__trigger').trigger('mouseenter')
vi.advanceTimersByTime(90)
vi.advanceTimersByTime(300)
expect(wrapper.vm.opened).toBe(true)

// Leaving the trigger schedules a close; entering the popover within the
Expand All @@ -360,7 +364,7 @@ describe('core: AppMenu', () => {
it('closes shortly after the cursor leaves the popover', async () => {
const wrapper = mount(AppMenu, { attachTo: document.body })
await wrapper.get('.app-menu__trigger').trigger('mouseenter')
vi.advanceTimersByTime(90)
vi.advanceTimersByTime(300)
wrapper.vm.onPopoverPointerEnter()
expect(wrapper.vm.opened).toBe(true)

Expand All @@ -381,7 +385,7 @@ describe('core: AppMenu', () => {
it('opens on hover without the focus trap, so focus is not stolen', async () => {
const wrapper = mount(AppMenu, { attachTo: document.body })
await wrapper.get('.app-menu__trigger').trigger('mouseenter')
vi.advanceTimersByTime(90)
vi.advanceTimersByTime(300)

// Hovering must not pull focus out of e.g. the search field.
expect(wrapper.vm.hoverOpen).toBe(true)
Expand All @@ -398,7 +402,7 @@ describe('core: AppMenu', () => {
it('restores the focus trap when a click follows a hover-open', async () => {
const wrapper = mount(AppMenu, { attachTo: document.body })
await wrapper.get('.app-menu__trigger').trigger('mouseenter')
vi.advanceTimersByTime(90)
vi.advanceTimersByTime(300)
vi.advanceTimersByTime(500) // click grace over
await wrapper.get('.app-menu__waffle').trigger('click')

Expand All @@ -415,7 +419,7 @@ describe('core: AppMenu', () => {
it('ignores a trigger click right after a hover-open (habitual click-to-open)', async () => {
const wrapper = mount(AppMenu, { attachTo: document.body })
await wrapper.get('.app-menu__trigger').trigger('mouseenter')
vi.advanceTimersByTime(90)
vi.advanceTimersByTime(300)
expect(wrapper.vm.opened).toBe(true)

// A click within the grace window must not toggle the menu shut.
Expand All @@ -426,7 +430,7 @@ describe('core: AppMenu', () => {
it('allows closing by click once the grace window elapses', async () => {
const wrapper = mount(AppMenu, { attachTo: document.body })
await wrapper.get('.app-menu__trigger').trigger('mouseenter')
vi.advanceTimersByTime(90)
vi.advanceTimersByTime(300)
vi.advanceTimersByTime(500) // grace window elapses

await wrapper.get('.app-menu__waffle').trigger('click')
Expand All @@ -436,7 +440,7 @@ describe('core: AppMenu', () => {
it('blocks the popover auto-hide during the grace window, allows it after', async () => {
const wrapper = mount(AppMenu, { attachTo: document.body })
await wrapper.get('.app-menu__trigger').trigger('mouseenter')
vi.advanceTimersByTime(90)
vi.advanceTimersByTime(300)

// autoHideCheck() feeds floating-ui: false = don't close on outside
// click (e.g. a habitual click on the trigger) during the grace window.
Expand Down
4 changes: 2 additions & 2 deletions dist/core-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/core-main.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/settings-vue-settings-language-locale.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/settings-vue-settings-language-locale.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/settings-vue-settings-profile-contact.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/settings-vue-settings-profile-contact.js.map

Large diffs are not rendered by default.

Loading