Listbox: checkmark, highlightOnSelect properties added

pull/5756/head
tugcekucukoglu 2024-05-09 13:02:54 +03:00
parent 438440072f
commit 6295928c7a
9 changed files with 137 additions and 3 deletions

View File

@ -62,6 +62,14 @@ export default {
type: Boolean, type: Boolean,
default: true default: true
}, },
highlightOnSelect: {
type: Boolean,
default: true
},
checkmark: {
type: Boolean,
default: false
},
filterMessage: { filterMessage: {
type: String, type: String,
default: null default: null

View File

@ -164,6 +164,14 @@ export interface ListboxPassThroughOptions<T = any> {
* Used to pass attributes to the option's DOM element. * Used to pass attributes to the option's DOM element.
*/ */
option?: ListboxPassThroughOptionType<T>; option?: ListboxPassThroughOptionType<T>;
/**
* Used to pass attributes to the option check icon's DOM element.
*/
optionCheckIcon?: ListboxPassThroughOptionType<T>;
/**
* Used to pass attributes to the option blank icon's DOM element.
*/
optionBlankIcon?: ListboxPassThroughOptionType<T>;
/** /**
* Used to pass attributes to the emptyMessage's DOM element. * Used to pass attributes to the emptyMessage's DOM element.
*/ */
@ -351,6 +359,16 @@ export interface ListboxProps {
* @defaultValue true * @defaultValue true
*/ */
focusOnHover?: boolean | undefined; focusOnHover?: boolean | undefined;
/**
* Whether the selected option will be add highlight class.
* @defaultValue true
*/
highlightOnSelect?: boolean | undefined;
/**
* Whether the selected option will be shown with a check mark.
* @defaultValue false
*/
checkmark?: boolean | undefined;
/** /**
* Text to be displayed in hidden accessible field when filtering returns any results. Defaults to value from PrimeVue locale configuration. * Text to be displayed in hidden accessible field when filtering returns any results. Defaults to value from PrimeVue locale configuration.
* @defaultValue '{0} results are available' * @defaultValue '{0} results are available'

View File

@ -91,6 +91,10 @@
:data-p-focused="focusedOptionIndex === getOptionIndex(i, getItemOptions)" :data-p-focused="focusedOptionIndex === getOptionIndex(i, getItemOptions)"
:data-p-disabled="isOptionDisabled(option)" :data-p-disabled="isOptionDisabled(option)"
> >
<template v-if="checkmark">
<CheckIcon v-if="isSelected(option)" :class="cx('optionCheckIcon')" v-bind="ptm('optionCheckIcon')" />
<BlankIcon v-else :class="cx('optionBlankIcon')" v-bind="ptm('optionBlankIcon')" />
</template>
<slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{ getOptionLabel(option) }}</slot> <slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{ getOptionLabel(option) }}</slot>
</li> </li>
</template> </template>
@ -131,6 +135,8 @@
<script> <script>
import { FilterService } from 'primevue/api'; import { FilterService } from 'primevue/api';
import IconField from 'primevue/iconfield'; import IconField from 'primevue/iconfield';
import BlankIcon from 'primevue/icons/blank';
import CheckIcon from 'primevue/icons/check';
import SearchIcon from 'primevue/icons/search'; import SearchIcon from 'primevue/icons/search';
import InputIcon from 'primevue/inputicon'; import InputIcon from 'primevue/inputicon';
import InputText from 'primevue/inputtext'; import InputText from 'primevue/inputtext';
@ -754,7 +760,9 @@ export default {
VirtualScroller, VirtualScroller,
InputIcon, InputIcon,
IconField, IconField,
SearchIcon SearchIcon,
CheckIcon,
BlankIcon
} }
}; };
</script> </script>

View File

@ -17,6 +17,8 @@ export enum ListboxClasses {
list = 'p-listbox-list', list = 'p-listbox-list',
optionGroup = 'p-listbox-option-group', optionGroup = 'p-listbox-option-group',
option = 'p-listbox-option', option = 'p-listbox-option',
optionCheckIcon = 'p-listbox-option-check-icon',
optionBlankIcon = 'p-listbox-option-blank-icon',
emptyMessage = 'p-listbox-empty-message' emptyMessage = 'p-listbox-empty-message'
} }

View File

@ -55,6 +55,8 @@ const theme = ({ dt }) => `
} }
.p-listbox-option { .p-listbox-option {
display: flex;
align-items: center;
cursor: pointer; cursor: pointer;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
@ -85,6 +87,13 @@ const theme = ({ dt }) => `
color: ${dt('listbox.option.focus.color')}; color: ${dt('listbox.option.focus.color')};
} }
.p-listbox-option-check-icon {
position: relative;
margin-left: -0.375rem;
margin-right: 0.375rem;
color: ${dt('listbox.checkmark.color')};
}
.p-listbox-option-group { .p-listbox-option-group {
margin: 0; margin: 0;
padding: ${dt('listbox.option.group.padding')}; padding: ${dt('listbox.option.group.padding')};
@ -112,14 +121,16 @@ const classes = {
listContainer: 'p-listbox-list-container', listContainer: 'p-listbox-list-container',
list: 'p-listbox-list', list: 'p-listbox-list',
optionGroup: 'p-listbox-option-group', optionGroup: 'p-listbox-option-group',
option: ({ instance, option, index, getItemOptions }) => [ option: ({ instance, props, option, index, getItemOptions }) => [
'p-listbox-option', 'p-listbox-option',
{ {
'p-listbox-option-selected': instance.isSelected(option), 'p-listbox-option-selected': instance.isSelected(option) && props.highlightOnSelect,
'p-focus': instance.focusedOptionIndex === instance.getOptionIndex(index, getItemOptions), 'p-focus': instance.focusedOptionIndex === instance.getOptionIndex(index, getItemOptions),
'p-disabled': instance.isOptionDisabled(option) 'p-disabled': instance.isOptionDisabled(option)
} }
], ],
optionCheckIcon: 'p-listbox-option-check-icon',
optionBlankIcon: 'p-listbox-option-blank-icon',
emptyMessage: 'p-listbox-empty-message' emptyMessage: 'p-listbox-empty-message'
}; };

View File

@ -42,6 +42,9 @@ export default {
fontWeight: '{list.option.group.font.weight}', fontWeight: '{list.option.group.font.weight}',
padding: '{list.option.group.padding}' padding: '{list.option.group.padding}'
}, },
checkmark: {
color: '{list.option.color}'
},
emptyMessage: { emptyMessage: {
padding: '{list.option.padding}' padding: '{list.option.padding}'
} }

View File

@ -42,6 +42,9 @@ export default {
fontWeight: '{list.option.group.font.weight}', fontWeight: '{list.option.group.font.weight}',
padding: '{list.option.group.padding}' padding: '{list.option.group.padding}'
}, },
checkmark: {
color: '{list.option.color}'
},
emptyMessage: { emptyMessage: {
padding: '{list.option.padding}' padding: '{list.option.padding}'
} }

View File

@ -0,0 +1,75 @@
<template>
<DocSectionText v-bind="$attrs">
<p>An alternative way to highlight the selected option is displaying a checkmark instead.</p>
</DocSectionText>
<div class="card flex justify-content-center">
<Listbox v-model="selectedCity" :options="cities" optionLabel="name" checkmark :highlightOnSelect="false" class="w-full md:w-14rem" />
</div>
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
selectedCity: null,
cities: [
{ name: 'New York', code: 'NY' },
{ name: 'Rome', code: 'RM' },
{ name: 'London', code: 'LDN' },
{ name: 'Istanbul', code: 'IST' },
{ name: 'Paris', code: 'PRS' }
],
code: {
basic: `
<Listbox v-model="selectedCity" :options="cities" optionLabel="name" checkmark :highlightOnSelect="false" class="w-full md:w-14rem" />
`,
options: `
<template>
<div class="card flex justify-content-center">
<Listbox v-model="selectedCity" :options="cities" optionLabel="name" checkmark :highlightOnSelect="false" class="w-full md:w-14rem" />
</div>
</template>
<script>
export default {
data() {
return {
selectedCity: null,
cities: [
{ name: 'New York', code: 'NY' },
{ name: 'Rome', code: 'RM' },
{ name: 'London', code: 'LDN' },
{ name: 'Istanbul', code: 'IST' },
{ name: 'Paris', code: 'PRS' }
]
};
}
};
<\/script>
`,
composition: `
<template>
<div class="card flex justify-content-center">
<Listbox v-model="selectedCity" :options="cities" optionLabel="name" checkmark :highlightOnSelect="false" class="w-full md:w-14rem" />
</div>
</template>
<script setup>
import { ref } from "vue";
const selectedCity = ref();
const cities = ref([
{ name: 'New York', code: 'NY' },
{ name: 'Rome', code: 'RM' },
{ name: 'London', code: 'LDN' },
{ name: 'Istanbul', code: 'IST' },
{ name: 'Paris', code: 'PRS' }
]);
<\/script>
`
}
};
}
};
</script>

View File

@ -5,6 +5,7 @@
<script> <script>
import AccessibilityDoc from '@/doc/listbox/AccessibilityDoc.vue'; import AccessibilityDoc from '@/doc/listbox/AccessibilityDoc.vue';
import BasicDoc from '@/doc/listbox/BasicDoc.vue'; import BasicDoc from '@/doc/listbox/BasicDoc.vue';
import CheckmarkDoc from '@/doc/listbox/CheckmarkDoc.vue';
import DisabledDoc from '@/doc/listbox/DisabledDoc.vue'; import DisabledDoc from '@/doc/listbox/DisabledDoc.vue';
import FilterDoc from '@/doc/listbox/FilterDoc.vue'; import FilterDoc from '@/doc/listbox/FilterDoc.vue';
import GroupDoc from '@/doc/listbox/GroupDoc.vue'; import GroupDoc from '@/doc/listbox/GroupDoc.vue';
@ -30,6 +31,11 @@ export default {
label: 'Basic', label: 'Basic',
component: BasicDoc component: BasicDoc
}, },
{
id: 'checkmark',
label: 'Checkmark',
component: CheckmarkDoc
},
{ {
id: 'multiple', id: 'multiple',
label: 'Multiple', label: 'Multiple',