Skip to content

Commit

Permalink
feat: always highlight first item in home view iff no filter
Browse files Browse the repository at this point in the history
  • Loading branch information
d-rita committed Feb 21, 2025
1 parent 91465a2 commit acecd23
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,5 +152,8 @@ describe('Command Palette - List View - Browse Apps View', () => {
// first app item - highlighted
expect(backActionListItem).not.toHaveClass('highlighted')
expect(listItems[1]).toHaveClass('highlighted')
expect(listItems[1].querySelector('span')).toHaveTextContent(
'Test App 1'
)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,111 @@ describe('Command Palette - List View - Search Results', () => {
expect(listItems[0]).toHaveTextContent('Logout')
expect(listItems[0]).toHaveClass('highlighted')
})

it('handles navigation of muliple app search results in the HOME View', async () => {
const user = userEvent.setup()
const {
getByPlaceholderText,
queryAllByTestId,
container,
getByTestId,
queryByTestId,
} = render(
<CommandPalette apps={testApps} shortcuts={[]} commands={[]} />
)
// open modal
fireEvent.keyDown(container, { key: 'k', metaKey: true })

// Search field
const searchField = await getByPlaceholderText(
'Search apps, shortcuts, commands'
)
expect(searchField).toHaveValue('')

const searchTerm = 'app'

await user.type(searchField, searchTerm)
expect(queryByTestId('headerbar-top-apps-list')).not.toBeInTheDocument()

const resultsListItems = queryAllByTestId('headerbar-list-item')
expect(resultsListItems.length).toBe(9)

const firstResult = resultsListItems[0]
const fifthResult = resultsListItems[4]

expect(firstResult).toHaveTextContent('Test App 1')
expect(firstResult).toHaveClass('highlighted')

// scroll down to fifth result
for (let keyPress = 1; keyPress < 5; keyPress++) {
await user.keyboard('{ArrowDown}')
}

expect(fifthResult).toHaveTextContent('Test App 5')
expect(fifthResult).toHaveClass('highlighted')

// clear search field
for (let keyPress = 0; keyPress < searchTerm.length; keyPress++) {
await user.keyboard('{Backspace}')
}

expect(searchField).toHaveValue('')

const appsGrid = getByTestId('headerbar-top-apps-list')
const firstGridApp = appsGrid.querySelectorAll('a')[0]

expect(firstGridApp).toHaveClass('highlighted')
expect(firstGridApp.querySelector('span')).toHaveTextContent(
'Test App 1'
)
})

it('highlights first action in "no grid home view" when search is cleared', async () => {
const user = userEvent.setup()
const {
getByPlaceholderText,
queryAllByTestId,
container,
queryByTestId,
} = render(
<CommandPalette
apps={[]}
shortcuts={testShortcuts}
commands={testCommands}
/>
)
// open modal
fireEvent.keyDown(container, { key: 'k', metaKey: true })

const appsGrid = queryByTestId('headerbar-top-apps-list')
const browseAppsAction = queryByTestId('headerbar-browse-apps')
const browseCommandsAction = queryByTestId('headerbar-browse-commands')

// since there are no apps
expect(appsGrid).not.toBeInTheDocument()
// since apps < MIN_APPS_NUM(8)
expect(browseAppsAction).not.toBeInTheDocument()
// since commands > 1
expect(browseCommandsAction).toBeInTheDocument()
expect(browseCommandsAction).toHaveClass('highlighted')

// Search field
const searchField = await getByPlaceholderText(
'Search apps, shortcuts, commands'
)
const searchTerm = 'test'
await user.type(searchField, searchTerm)

const resultsListItems = queryAllByTestId('headerbar-list-item')
expect(resultsListItems.length).toBe(2)
expect(resultsListItems[0]).toHaveClass('highlighted')

// clear search field
for (let keyPress = 0; keyPress < searchTerm.length; keyPress++) {
await user.keyboard('{Backspace}')
}

expect(searchField).toHaveValue('')
expect(browseCommandsAction).toHaveClass('highlighted')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,24 @@ export const CommandPaletteContextProvider = ({ children }) => {
const [activeSection, setActiveSection] = useState(null)
const [showGrid, setShowGrid] = useState(null)

const goToDefaultView = useCallback(() => {
const goToDefaultSection = useCallback(() => {
const defaultSection = showGrid ? GRID_SECTION : ACTIONS_SECTION

setFilter('')
setCurrentView(HOME_VIEW)
setActiveSection(defaultSection)
setHighlightedIndex(0)
}, [
showGrid,
setCurrentView,
setFilter,
setActiveSection,
setHighlightedIndex,
])
}, [showGrid, setActiveSection, setHighlightedIndex])

const goToDefaultView = useCallback(() => {
setFilter('')
setCurrentView(HOME_VIEW)
goToDefaultSection()
}, [setCurrentView, setFilter, goToDefaultSection])

const contextValue = useMemo(
() => ({
filter,
setFilter,
goToDefaultSection,
goToDefaultView,
highlightedIndex,
setHighlightedIndex,
Expand All @@ -49,6 +48,7 @@ export const CommandPaletteContextProvider = ({ children }) => {
}),
[
filter,
goToDefaultSection,
goToDefaultView,
highlightedIndex,
currentView,
Expand Down
11 changes: 9 additions & 2 deletions components/header-bar/src/command-palette/views/home-view.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { spacers } from '@dhis2/ui-constants'
import PropTypes from 'prop-types'
import React from 'react'
import React, { useEffect } from 'react'
import i18n from '../../locales/index.js'
import { useCommandPaletteContext } from '../context/command-palette-context.js'
import AppItem from '../sections/app-item.js'
Expand All @@ -14,9 +14,16 @@ import {
import ListView from './list-view.js'

function HomeView({ apps, filteredItems, actions }) {
const { filter, highlightedIndex, activeSection } =
const { filter, highlightedIndex, activeSection, goToDefaultSection } =
useCommandPaletteContext()
const topApps = apps?.slice(0, MIN_APPS_NUM)

useEffect(() => {
if (!filter) {
goToDefaultSection()
}
}, [filter, goToDefaultSection])

return (
<>
{filter.length > 0 ? (
Expand Down

0 comments on commit acecd23

Please sign in to comment.