diff --git a/frontend/playwright/ui/specs/tokens.spec.js b/frontend/playwright/ui/specs/tokens.spec.js index 88221356b..d6422060b 100644 --- a/frontend/playwright/ui/specs/tokens.spec.js +++ b/frontend/playwright/ui/specs/tokens.spec.js @@ -252,7 +252,10 @@ test.describe("Tokens: Tokens Tab", () => { const themeSelect = tokenThemesSetsSidebar.getByRole("combobox"); await themeSelect.click(); - await themeSelect.getByRole("option", { name: "Changed" }).click(); + await page + .getByTestId("theme-select-dropdown") + .getByRole("option", { name: "Changed" }) + .click(); const sidebarLightSet = tokenThemesSetsSidebar.getByRole("button", { name: "light", diff --git a/frontend/src/app/main/ui/workspace/tokens/theme_select.cljs b/frontend/src/app/main/ui/workspace/tokens/theme_select.cljs index f62ebadfa..cd8bae9bc 100644 --- a/frontend/src/app/main/ui/workspace/tokens/theme_select.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/theme_select.cljs @@ -89,10 +89,12 @@ ;; State state* (mf/use-state - {:id (uuid/next) - :is-open? false}) + #(do {:id (uuid/next) + :is-open? false + :rect nil})) state (deref state*) is-open? (:is-open? state) + rect (:rect state) ;; Dropdown on-close-dropdown (mf/use-fn #(swap! state* assoc :is-open? false)) @@ -100,9 +102,13 @@ on-open-dropdown (mf/use-fn (mf/deps can-edit?) - (fn [] + (fn [event] (when can-edit? - (swap! state* assoc :is-open? true))))] + (when-let [node (dom/get-current-target event)] + (let [rect (dom/get-bounding-rect node)] + (swap! state* assoc + :is-open? true + :rect rect))))))] ;; TODO: This element should be accessible by keyboard [:div {:on-click on-open-dropdown @@ -116,8 +122,19 @@ [:> text* {:as "span" :typography "body-small" :class (stl/css :current-label)} current-label] [:> icon* {:icon-id i/arrow-down :class (stl/css :dropdown-button) :aria-hidden true}] - [:& dropdown {:show is-open? - :on-close on-close-dropdown} - [:& theme-options {:active-theme-paths active-theme-paths - :themes themes - :on-close on-close-dropdown}]]])) + + (when is-open? + (mf/portal + (mf/html + [:div {:class (stl/css :dropdown-portal) + :data-testid "theme-select-dropdown" + :style {:top (:top rect) + :left (:left rect) + :width (:width rect)}} + + [:& dropdown {:show is-open? + :on-close on-close-dropdown} + [:& theme-options {:active-theme-paths active-theme-paths + :themes themes + :on-close on-close-dropdown}]]]) + (.-body js/document)))])) diff --git a/frontend/src/app/main/ui/workspace/tokens/theme_select.scss b/frontend/src/app/main/ui/workspace/tokens/theme_select.scss index 297b95f1f..087347aa6 100644 --- a/frontend/src/app/main/ui/workspace/tokens/theme_select.scss +++ b/frontend/src/app/main/ui/workspace/tokens/theme_select.scss @@ -122,3 +122,7 @@ .current-label { @include textEllipsis; } + +.dropdown-portal { + position: absolute; +}