Skip to content

Commit

Permalink
feat(KtField*Select*): implement scroll-to behavior on keyboard navig…
Browse files Browse the repository at this point in the history
…ation

..scroll to the option as you use keyboard (arrow down/up)

fix: show separator between options/no-data & actions
..even if options.length ===0 since no-data is still an item

fix: scrollbar for chrome
  • Loading branch information
carsoli authored and FlorianWendelborn committed May 31, 2022
1 parent b9fffa4 commit 513f981
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
23 changes: 18 additions & 5 deletions packages/kotti-ui/source/kotti-field-select/components/Options.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="kt-field-select__options">
<div ref="optionsRef" class="kt-field-select__options">
<div v-if="isLoading" class="kt-field-select__options__loading">
<div class="loading" />
</div>
Expand All @@ -9,6 +9,7 @@
isDisabled
:label="translations.noDataText"
type="option"
@scrollTo="scrollTo"
/>
<FieldSelectOptionsItem
v-for="(option, index) in modifiedOptions"
Expand All @@ -20,23 +21,22 @@
:label="option.label"
type="option"
@click="() => selectOption(option)"
@scrollTo="scrollTo"
>
<slot
v-bind="{ index, option, select: () => selectOption(option) }"
name="option"
/>
</FieldSelectOptionsItem>
<div
v-if="modifiedOptions.length && actions.length"
class="kt-field-select__options__separator"
/>
<div v-if="actions.length" class="kt-field-select__options__separator" />
<FieldSelectOptionsItem
v-for="(action, index) in actions"
:key="`action-${index}`"
:isHovered="isHovered('action', index)"
:label="action.label"
type="action"
@click="() => onAction(action)"
@scrollTo="scrollTo"
/>
</div>
</template>
Expand Down Expand Up @@ -88,6 +88,8 @@ export default defineComponent<z.output<typeof propsSchema>>({
setup(props, { emit }) {
const translations = useTranslationNamespace('KtFieldSelects')
const optionsRef = ref<HTMLDivElement | null>(null)
const modifiedOptions = computed(() => {
const modifiedOptions: ModifiedOption[] = props.options.map((option) => ({
...option,
Expand Down Expand Up @@ -191,6 +193,13 @@ export default defineComponent<z.output<typeof propsSchema>>({
},
modifiedOptions,
onAction,
optionsRef,
scrollTo: (optionDistanceToOptionsTop: number) => {
if (optionsRef.value === null)
throw new Error('Unexpected Unbound optionsRef: null')
optionsRef.value.scrollTo({ top: optionDistanceToOptionsTop })
},
selectOption,
translations,
}
Expand All @@ -199,9 +208,13 @@ export default defineComponent<z.output<typeof propsSchema>>({
</script>

<style lang="scss" scoped>
@import '../../kotti-field/mixins.scss';
.kt-field-select__options {
position: relative;
@include prettify-scrollbar;
max-height: 40vh;
/*
undo padding from theme,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<div
ref="optionRef"
:class="classes"
:data-test="dataTest"
@click.stop="(e) => $emit('click', e)"
Expand All @@ -11,7 +12,7 @@
</template>

<script lang="ts">
import { computed, defineComponent } from '@vue/composition-api'
import { computed, defineComponent, ref, watch } from '@vue/composition-api'
import { z } from 'zod'
import { makeProps } from '../../make-props'
Expand All @@ -28,7 +29,23 @@ const propsSchema = z.object({
export default defineComponent<z.output<typeof propsSchema>>({
name: 'FieldSelectOptionsItem',
props: makeProps(propsSchema),
setup(props) {
setup(props, { emit }) {
const optionRef = ref<HTMLDivElement | null>(null)
watch(
() => props.isHovered,
(isHovered, wasHovered) => {
if (optionRef.value === null)
throw new Error('Unexpected Unbound option ref: null')
if (isHovered && !wasHovered) {
const distanceFromParentTop = optionRef.value.offsetTop
emit('scrollTo', distanceFromParentTop)
}
},
)
return {
classes: computed(() => ({
'kt-field-select-options-item': true,
Expand All @@ -37,6 +54,7 @@ export default defineComponent<z.output<typeof propsSchema>>({
'kt-field-select-options-item--is-selected': props.isSelected,
[`kt-field-select-options-item--is-type-${props.type}`]: true,
})),
optionRef,
}
},
})
Expand Down

0 comments on commit 513f981

Please sign in to comment.