Skip to content

Commit

Permalink
feat(RisAutoComplete): implement clear button (#82)
Browse files Browse the repository at this point in the history
* chore(RisAutoComplete): add placeholder in story

* feat(RisAutoComplete): add clear button, change styles

* chore: fix formatting
  • Loading branch information
MasterCarl authored Dec 2, 2024
1 parent b39ce85 commit b1e9ad3
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 19 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"@digitalservice4germany/style-dictionary": "~2.0.0",
"@eslint/compat": "~1.2.2",
"@eslint/js": "~9.14.0",
"@iconify-json/ic": "^1.2.1",
"@iconify-json/material-symbols": "~1.2.6",
"@iconify-json/mdi": "~1.2.1",
"@iconify/vue": "~4.1.2",
Expand Down
1 change: 1 addition & 0 deletions src/components/RisAutoComplete/RisAutoComplete.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const meta: Meta<typeof RisAutoComplete> = {
dropdown: true,
dropdownMode: "current",
ariaLabel: "",
placeholder: "Type something",
ariaLabelledby: "",
delay: 300,
completeOnFocus: false,
Expand Down
41 changes: 26 additions & 15 deletions src/components/RisAutoComplete/RisAutoComplete.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script lang="ts" setup>
import IconChevron from "~icons/mdi/chevron-down";
import IcOutlineClear from "~icons/ic/outline-clear?height=16";
import AutoComplete, { type AutoCompleteProps } from "primevue/autocomplete";
import RisGhostButton from "@/components/RisGhostButton/RisGhostButton.vue";
import ProgressSpinner from "primevue/progressspinner";
import { ref } from "vue";
Expand Down Expand Up @@ -74,6 +76,8 @@ const onUpdateInnerValue = (
}
};
const onClear = () => onUpdateInnerValue("");
const autoCompleteRef = ref<typeof AutoComplete | null>(null);
defineExpose({ autoCompleteRef });
</script>
Expand All @@ -84,40 +88,47 @@ defineExpose({ autoCompleteRef });
v-bind="$attrs"
:suggestions="props.suggestions"
:model-value="innerValue"
@update:model-value="onUpdateInnerValue"
@option-select="(e) => (model = e.value.id)"
:dropdown="props.dropdown"
:dropdownMode="props.dropdownMode"
:dropdown-mode="props.dropdownMode"
:disabled="props.disabled"
:forceSelection="props.forceSelection"
:force-selection="props.forceSelection"
:placeholder="props.placeholder"
:ariaLabel="props.ariaLabel"
:ariaLabelledby="props.ariaLabelledby"
:aria-label="props.ariaLabel"
:aria-labelledby="props.ariaLabelledby"
:delay="props.delay"
:completeOnFocus="props.completeOnFocus"
:complete-on-focus="props.completeOnFocus"
:typeahead="props.typeahead"
:scrollHeight="props.scrollHeight"
:scroll-height="props.scrollHeight"
:loading="props.loading"
:invalid="props.invalid"
:autoOptionFocus="props.autoOptionFocus"
:selectOnFocus="props.selectOnFocus"
:auto-option-focus="props.autoOptionFocus"
:select-on-focus="props.selectOnFocus"
:fluid="true"
:optionDisabled="props.optionDisabled"
:option-disabled="props.optionDisabled"
option-label="label"
data-key="value"
@update:model-value="onUpdateInnerValue"
@option-select="(e) => (model = e.value.id)"
>
<template #loader>
<ProgressSpinner class="absolute inset-y-0 right-12 my-auto mr-2" />
<ProgressSpinner class="absolute inset-y-0 right-8 my-auto mr-1" />
</template>
<template #dropdownicon>
<IconChevron />
<template #dropdown="slotProps">
<RisGhostButton v-if="innerValue" aria-label="Entfernen" @click="onClear">
<IcOutlineClear />
</RisGhostButton>
<RisGhostButton @click="slotProps.toggleCallback">
<IconChevron />
</RisGhostButton>
</template>
<template #option="slotProps: { option: AutoCompleteSuggestion }">
<div
:data-variant="isActiveOption(slotProps.option) && 'active'"
class="flex min-h-48 flex-col justify-center gap-2 border-l-4 border-transparent px-12 py-10 data-[variant=active]:border-blue-800 data-[variant=active]:bg-blue-200"
>
<div class="ris-label1-regular">{{ slotProps.option.label }}</div>
<div class="ris-label1-regular">
{{ slotProps.option.label }}
</div>
<div
v-if="slotProps.option.secondaryLabel"
class="ris-label2-regular text-gray-900"
Expand Down
9 changes: 9 additions & 0 deletions src/components/RisGhostButton/RisGhostButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script setup lang="ts"></script>

<template>
<button
class="p-8 hover:bg-blue-100 hover:text-blue-800 focus-visible:bg-blue-800 focus-visible:text-white focus-visible:outline-none"
>
<slot />
</button>
</template>
9 changes: 5 additions & 4 deletions src/primevue/autocomplete/autocomplete.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import { AutoCompletePassThroughOptions } from "primevue/autocomplete";
import { tw } from "@/lib/tags.ts";
import { base, small } from "../inputText/inputText";

const fluid = tw`w-full`;

const autocomplete: AutoCompletePassThroughOptions = {
root: ({ props }) => {
const base = tw`relative`;
const base = tw`flex border-2 border-blue-800 bg-white outline-4 -outline-offset-4 outline-blue-800 placeholder:text-gray-800 focus-within:outline hover:outline disabled:border-blue-500 disabled:bg-white disabled:text-blue-500 disabled:outline-none`;
const small = tw`ris-body2-regular h-48 py-4 pl-16 pr-4`;

return {
class: {
[base]: true,
[small]: true,
[fluid]: !!props.fluid,
},
};
},
pcInput: {
root: ({ props }) => {
const focus = tw`focus-visible:outline-none`;
return {
class: {
[base]: true,
[small]: true,
[focus]: true,
[fluid]: !!props.fluid,
},
};
Expand Down

0 comments on commit b1e9ad3

Please sign in to comment.