Skip to content

Commit

Permalink
feat(UI): Dropdowns now automatically open either above or below (#706)
Browse files Browse the repository at this point in the history
Depending on where there is more space.
Fixes #692
  • Loading branch information
rouk1 authored Nov 12, 2024
1 parent c979293 commit 96a9618
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 24 deletions.
35 changes: 16 additions & 19 deletions skore-ui/src/components/DropdownButton.vue
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
<script lang="ts">
export interface DropdownProps {
label?: string;
icon?: string;
isPrimary?: boolean;
align?: "left" | "right";
isInline?: boolean;
}
</script>

<script setup lang="ts">
import { autoUpdate, useFloating } from "@floating-ui/vue";
import { autoPlacement, autoUpdate, useFloating, type Placement } from "@floating-ui/vue";
import { computed, onBeforeUnmount, onMounted, ref } from "vue";
import SimpleButton from "@/components/SimpleButton.vue";
import SimpleButton, { type ButtonProps } from "@/components/SimpleButton.vue";
const { label, icon, isPrimary = false, align = "left", isInline } = defineProps<DropdownProps>();
interface DropdownProps extends ButtonProps {
allowedPlacements?: Placement[];
}
const props = withDefaults(defineProps<DropdownProps>(), {
isPrimary: false,
allowedPlacements: () => ["top-end", "bottom-end", "top-start", "bottom-start"],
});
const isOpen = ref(false);
const el = ref<HTMLDivElement>();
const reference = ref<HTMLElement>();
const floating = ref<HTMLDivElement>();
const { floatingStyles } = useFloating(reference, floating, {
placement: align === "right" ? "bottom-end" : "bottom-start",
strategy: "fixed",
middleware: [autoPlacement({ allowedPlacements: props.allowedPlacements as Placement[] })],
whileElementsMounted: autoUpdate,
});
Expand Down Expand Up @@ -87,12 +84,12 @@ onBeforeUnmount(() => {
</script>

<template>
<div class="dropdown" ref="el" :class="{ 'align-right': align === 'right' }">
<div class="dropdown" ref="el">
<SimpleButton
:is-primary="isPrimary"
:label="label"
:icon="icon"
:is-inline="isInline"
:is-primary="props.isPrimary"
:label="props.label"
:icon="props.icon"
:is-inline="props.isInline"
@click="isOpen = !isOpen"
ref="reference"
/>
Expand Down
1 change: 1 addition & 0 deletions skore-ui/src/components/DropdownButtonItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const props = withDefaults(defineProps<DropdownItemProps>(), { iconPosition: "le
<style scoped>
.dropdown-item {
display: inline-block;
width: 100%;
box-sizing: border-box;
padding: var(--spacing-6);
border: 0;
Expand Down
12 changes: 7 additions & 5 deletions skore-ui/src/components/SimpleButton.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<script setup lang="ts">
import { generateRandomMultiple } from "@/services/utils";
import { onBeforeMount, ref } from "vue";
interface ButtonProps {
<script lang="ts">
export interface ButtonProps {
label?: string;
icon?: string;
isPrimary?: boolean;
isInline?: boolean;
}
</script>

<script setup lang="ts">
import { generateRandomMultiple } from "@/services/utils";
import { onBeforeMount, ref } from "vue";
const props = withDefaults(defineProps<ButtonProps>(), { isPrimary: false });
const randomBackgroundOffsetX = ref(0);
Expand Down

0 comments on commit 96a9618

Please sign in to comment.