diff --git a/web-admin/src/features/organizations/user-management/table/dropdownAlignment.ts b/web-admin/src/features/organizations/user-management/table/dropdownAlignment.ts
new file mode 100644
index 00000000000..a4e544f9e06
--- /dev/null
+++ b/web-admin/src/features/organizations/user-management/table/dropdownAlignment.ts
@@ -0,0 +1,31 @@
+const DEFAULT_VIEWPORT_MARGIN_PX = 16;
+const DEFAULT_MENU_WIDTH_PX = 240;
+
+export function determineDropdownAlign({
+ triggerRect,
+ menuWidth,
+ viewportWidth,
+ boundaryRight,
+ margin = DEFAULT_VIEWPORT_MARGIN_PX,
+}: {
+ triggerRect: DOMRect | null;
+ menuWidth?: number;
+ viewportWidth: number;
+ boundaryRight?: number | null;
+ margin?: number;
+}): "start" | "end" {
+ if (!triggerRect) return "start";
+
+ const width =
+ typeof menuWidth === "number" ? menuWidth : DEFAULT_MENU_WIDTH_PX;
+ const comparisonRight =
+ typeof boundaryRight === "number"
+ ? Math.min(boundaryRight, viewportWidth)
+ : viewportWidth;
+ const projectedRightEdge = triggerRect.left + width;
+ const safeRightEdge = comparisonRight - margin;
+
+ return projectedRightEdge > safeRightEdge ? "end" : "start";
+}
+
+export const DROPDOWN_DEFAULT_MARGIN = DEFAULT_VIEWPORT_MARGIN_PX;
diff --git a/web-admin/src/features/organizations/user-management/table/users/UserActionsCell.svelte b/web-admin/src/features/organizations/user-management/table/users/UserActionsCell.svelte
index 42d1979893b..c81461cb8db 100644
--- a/web-admin/src/features/organizations/user-management/table/users/UserActionsCell.svelte
+++ b/web-admin/src/features/organizations/user-management/table/users/UserActionsCell.svelte
@@ -81,7 +81,7 @@
-
+
{#if role === OrgUserRoles.Guest}
import { getUserGroupsForUsersInOrg } from "@rilldata/web-admin/features/organizations/user-management/selectors.ts";
+ import { determineDropdownAlign } from "@rilldata/web-admin/features/organizations/user-management/table/dropdownAlignment.ts";
import * as Dropdown from "@rilldata/web-common/components/dropdown-menu";
import CaretDownIcon from "@rilldata/web-common/components/icons/CaretDownIcon.svelte";
import CaretUpIcon from "@rilldata/web-common/components/icons/CaretUpIcon.svelte";
import { writable } from "svelte/store";
+ import { browser } from "$app/environment";
+ import { onDestroy, onMount, tick } from "svelte";
export let organization: string;
export let userId: string;
@@ -13,6 +16,9 @@
let isDropdownOpen = false;
const userGroupsEnabledStore = writable(false);
$: userGroupsEnabledStore.set(isDropdownOpen);
+ let dropdownAlign: "start" | "end" = "start";
+ let dropdownTriggerEl: HTMLElement | null = null;
+ let dropdownContentEl: HTMLElement | null = null;
const userGroupsQuery = getUserGroupsForUsersInOrg(
organization,
@@ -21,11 +27,56 @@
);
$: ({ data: userGroups, isPending, error } = $userGroupsQuery);
$: hasGroups = groupCount > 0;
+
+ async function updateDropdownAlignment() {
+ if (!browser || !isDropdownOpen || !dropdownTriggerEl) return;
+ await tick();
+
+ const menuWidth =
+ dropdownContentEl?.offsetWidth ?? dropdownTriggerEl?.offsetWidth ?? 200;
+ const scrollContainerRight =
+ dropdownTriggerEl?.closest(".scroll-container")?.getBoundingClientRect()
+ .right ?? null;
+
+ dropdownAlign = determineDropdownAlign({
+ triggerRect: dropdownTriggerEl.getBoundingClientRect(),
+ menuWidth,
+ viewportWidth: window.innerWidth,
+ boundaryRight: scrollContainerRight,
+ });
+ }
+
+ function handleWindowResize() {
+ void updateDropdownAlignment();
+ }
+
+ onMount(() => {
+ if (!browser) return;
+ window.addEventListener("resize", handleWindowResize);
+ });
+
+ onDestroy(() => {
+ if (!browser) return;
+ window.removeEventListener("resize", handleWindowResize);
+ });
+
+ $: if (isDropdownOpen) {
+ void updateDropdownAlignment();
+ }
+
+ $: if (isDropdownOpen && dropdownContentEl) {
+ void updateDropdownAlignment();
+ }
+
+ $: if (isDropdownOpen && userGroups?.length !== undefined) {
+ void updateDropdownAlignment();
+ }
{#if hasGroups}
{/if}
-
+
{#if isPending}
Loading...
{:else if error}
diff --git a/web-admin/src/features/organizations/user-management/table/users/UserProjectsCell.svelte b/web-admin/src/features/organizations/user-management/table/users/UserProjectsCell.svelte
index dabcfd5f150..4d10c8488b4 100644
--- a/web-admin/src/features/organizations/user-management/table/users/UserProjectsCell.svelte
+++ b/web-admin/src/features/organizations/user-management/table/users/UserProjectsCell.svelte
@@ -1,11 +1,14 @@