-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
split out dropdown options into a dedicated element
- Loading branch information
1 parent
25c8151
commit 23f2566
Showing
4 changed files
with
170 additions
and
125 deletions.
There are no files selected for viewing
126 changes: 126 additions & 0 deletions
126
packages/vira/src/elements/dropdown/vira-dropdown-options.element.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import {nav, navSelector} from 'device-navigation'; | ||
import { | ||
classMap, | ||
css, | ||
defineElementEvent, | ||
html, | ||
ifDefined, | ||
listen, | ||
nothing, | ||
testId, | ||
} from 'element-vir'; | ||
import {viraDisabledStyles} from '../../styles'; | ||
import {viraBorders} from '../../styles/border'; | ||
import {viraFormCssVars} from '../../styles/form-themes'; | ||
import {viraShadows} from '../../styles/shadows'; | ||
import {defineViraElement} from '../define-vira-element'; | ||
import {ViraDropdownItem, ViraDropdownOption} from './vira-dropdown-item.element'; | ||
|
||
export const viraDropdownOptionsTestIds = { | ||
option: 'dropdown-option', | ||
}; | ||
|
||
export const ViraDropdownOptions = defineViraElement< | ||
Readonly<{ | ||
/** All dropdown options to show to the user. */ | ||
options: ReadonlyArray<Readonly<ViraDropdownOption>>; | ||
/** | ||
* The currently selected dropdown options. Note that this must be a reference subset of the | ||
* options input. Meaning, entries in this array must be the exact same objects (by | ||
* reference) as entries in the `options` input array for them to be marked as selected. | ||
*/ | ||
selectedOptions: ReadonlyArray<Readonly<ViraDropdownOption>>; | ||
}> | ||
>()({ | ||
tagName: 'vira-dropdown-options', | ||
events: { | ||
selectionChange: defineElementEvent<Readonly<ViraDropdownOption>>(), | ||
}, | ||
styles: css` | ||
:host { | ||
display: flex; | ||
flex-direction: column; | ||
pointer-events: auto; | ||
width: 100%; | ||
max-height: 100%; | ||
overflow-y: auto; | ||
z-index: 99; | ||
border-radius: ${viraBorders['vira-form-input-radius'].value}; | ||
border-top-left-radius: 0; | ||
border-top-right-radius: 0; | ||
background-color: ${viraFormCssVars['vira-form-background-color'].value}; | ||
border: 1px solid ${viraFormCssVars['vira-form-border-color'].value}; | ||
color: ${viraFormCssVars['vira-form-foreground-color'].value}; | ||
${viraShadows.menuShadow} | ||
} | ||
.dropdown-item { | ||
background-color: white; | ||
outline: none; | ||
} | ||
${navSelector.css.selected('.dropdown-item:not(.disabled)')} { | ||
background-color: ${viraFormCssVars['vira-form-selection-hover-background-color'] | ||
.value}; | ||
outline: none; | ||
} | ||
${ViraDropdownItem} { | ||
pointer-events: none; | ||
} | ||
.dropdown-item.disabled { | ||
${viraDisabledStyles}; | ||
pointer-events: auto; | ||
} | ||
`, | ||
renderCallback({inputs, dispatch, events}) { | ||
const optionTemplates = inputs.options.map((option) => { | ||
const innerTemplate = | ||
option.template || | ||
html` | ||
<${ViraDropdownItem.assign({ | ||
label: option.label, | ||
selected: inputs.selectedOptions.includes(option), | ||
})}></${ViraDropdownItem}> | ||
`; | ||
|
||
return html` | ||
<div | ||
class="dropdown-item ${classMap({ | ||
disabled: !!option.disabled, | ||
})}" | ||
${testId(viraDropdownOptionsTestIds.option)} | ||
title=${ifDefined(option.hoverText || undefined)} | ||
role="option" | ||
${option.disabled ? nothing : nav()} | ||
${listen('mousedown', (event) => { | ||
/** | ||
* Prevent this mousedown event from propagating to the window, which would | ||
* then trigger the dropdown to close. | ||
*/ | ||
event.stopPropagation(); | ||
})} | ||
${listen('mouseup', (event) => { | ||
/** | ||
* Prevent this event from propagating to the window, which would then | ||
* trigger the dropdown to close. | ||
*/ | ||
event.stopPropagation(); | ||
if (!option.disabled) { | ||
dispatch(new events.selectionChange(option)); | ||
} | ||
})} | ||
> | ||
${innerTemplate} | ||
</div> | ||
`; | ||
}); | ||
|
||
return html` | ||
<slot>${optionTemplates}</slot> | ||
`; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.