|
1 | | -<script lang="ts"> |
2 | | -export interface DropdownProps { |
3 | | - label?: string; |
4 | | - icon?: string; |
5 | | - isPrimary?: boolean; |
6 | | - align?: "left" | "right"; |
7 | | - isInline?: boolean; |
8 | | -} |
9 | | -</script> |
10 | | - |
11 | 1 | <script setup lang="ts"> |
12 | | -import { autoUpdate, useFloating } from "@floating-ui/vue"; |
| 2 | +import { autoPlacement, autoUpdate, useFloating, type Placement } from "@floating-ui/vue"; |
13 | 3 | import { computed, onBeforeUnmount, onMounted, ref } from "vue"; |
14 | 4 |
|
15 | | -import SimpleButton from "@/components/SimpleButton.vue"; |
| 5 | +import SimpleButton, { type ButtonProps } from "@/components/SimpleButton.vue"; |
16 | 6 |
|
17 | | -const { label, icon, isPrimary = false, align = "left", isInline } = defineProps<DropdownProps>(); |
| 7 | +interface DropdownProps extends ButtonProps { |
| 8 | + allowedPlacements?: Placement[]; |
| 9 | +} |
| 10 | +
|
| 11 | +const props = withDefaults(defineProps<DropdownProps>(), { |
| 12 | + isPrimary: false, |
| 13 | + allowedPlacements: () => ["top-end", "bottom-end", "top-start", "bottom-start"], |
| 14 | +}); |
18 | 15 |
|
19 | 16 | const isOpen = ref(false); |
20 | 17 | const el = ref<HTMLDivElement>(); |
21 | 18 | const reference = ref<HTMLElement>(); |
22 | 19 | const floating = ref<HTMLDivElement>(); |
23 | 20 | const { floatingStyles } = useFloating(reference, floating, { |
24 | | - placement: align === "right" ? "bottom-end" : "bottom-start", |
25 | 21 | strategy: "fixed", |
| 22 | + middleware: [autoPlacement({ allowedPlacements: props.allowedPlacements as Placement[] })], |
26 | 23 | whileElementsMounted: autoUpdate, |
27 | 24 | }); |
28 | 25 |
|
@@ -87,12 +84,12 @@ onBeforeUnmount(() => { |
87 | 84 | </script> |
88 | 85 |
|
89 | 86 | <template> |
90 | | - <div class="dropdown" ref="el" :class="{ 'align-right': align === 'right' }"> |
| 87 | + <div class="dropdown" ref="el"> |
91 | 88 | <SimpleButton |
92 | | - :is-primary="isPrimary" |
93 | | - :label="label" |
94 | | - :icon="icon" |
95 | | - :is-inline="isInline" |
| 89 | + :is-primary="props.isPrimary" |
| 90 | + :label="props.label" |
| 91 | + :icon="props.icon" |
| 92 | + :is-inline="props.isInline" |
96 | 93 | @click="isOpen = !isOpen" |
97 | 94 | ref="reference" |
98 | 95 | /> |
|
0 commit comments