Skip to content

Commit 69dcab6

Browse files
committed
fix: layer mobile widget details above header
1 parent bffefb9 commit 69dcab6

7 files changed

Lines changed: 38 additions & 4 deletions

File tree

apps/nextjs/src/components/layout/header.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { ReactNode } from "react";
22
import { AppShellHeader, Group, UnstyledButton } from "@mantine/core";
33

44
import { Spotlight } from "@homarr/spotlight";
5-
import { Link } from "@homarr/ui";
5+
import { appShellHeaderZIndex, Link } from "@homarr/ui";
66

77
import { ClientBurger } from "./header/burger";
88
import { DesktopSearchInput, MobileSearchButton } from "./header/search";
@@ -31,7 +31,7 @@ export const MainHeader = ({
3131
return (
3232
<AppShellHeader
3333
maw="100vw"
34-
zIndex={201}
34+
zIndex={appShellHeaderZIndex}
3535
style={{
3636
overflowX: "hidden",
3737
paddingTop: withSafeArea ? "env(safe-area-inset-top)" : undefined,

packages/modals/src/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
import type { PropsWithChildren } from "react";
44
import { createContext, useCallback, useContext, useEffect, useReducer, useRef, useState } from "react";
5-
import { getDefaultZIndex, Modal } from "@mantine/core";
5+
import { Modal } from "@mantine/core";
66
import { randomId } from "@mantine/hooks";
77

88
import type { stringOrTranslation } from "@homarr/translation";
99
import { translateIfNecessary } from "@homarr/translation";
1010
import { useI18n } from "@homarr/translation/client";
11+
import { managedModalZIndex } from "@homarr/ui";
1112

1213
import type { ConfirmModalProps } from "./confirm-modal";
1314
import { ConfirmModal } from "./confirm-modal";
@@ -99,7 +100,7 @@ const ActiveModal = ({ modal, state, handleCloseModal }: ActiveModalProps) => {
99100
return (
100101
<Modal
101102
key={modal.id}
102-
zIndex={getDefaultZIndex("modal") + 1}
103+
zIndex={managedModalZIndex}
103104
style={{
104105
userSelect: modal.id === state.current?.id ? undefined : "none",
105106
}}

packages/ui/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { MantineProviderProps } from "@mantine/core";
33
import { theme } from "./theme";
44

55
export { theme } from "./theme";
6+
export { appShellHeaderZIndex, managedModalZIndex, modalZIndex } from "./theme/layers";
67
export { modalSizeForm, modalSizeSelect } from "./theme/modal";
78
export * from "./components";
89

packages/ui/src/theme.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createTheme, rem } from "@mantine/core";
22

3+
import { modalZIndex } from "./theme/layers";
34
import { modalComponent } from "./theme/modal";
45

56
export const theme = createTheme({
@@ -101,6 +102,11 @@ export const theme = createTheme({
101102
overlayProps: { radius: "sm", blur: 2 },
102103
},
103104
},
105+
Drawer: {
106+
defaultProps: {
107+
zIndex: modalZIndex,
108+
},
109+
},
104110
Modal: modalComponent,
105111
},
106112
});

packages/ui/src/theme/layers.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { getDefaultZIndex } from "@mantine/core";
2+
3+
export const appShellHeaderZIndex = getDefaultZIndex("modal") + 1;
4+
export const modalZIndex = appShellHeaderZIndex + 1;
5+
export const managedModalZIndex = modalZIndex + 1;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { getDefaultZIndex } from "@mantine/core";
2+
import { describe, expect, test } from "vitest";
3+
4+
import { theme } from "../theme";
5+
import { appShellHeaderZIndex, managedModalZIndex, modalZIndex } from "./layers";
6+
import { modalComponent } from "./modal";
7+
8+
describe("application layers", () => {
9+
test("keeps dialogs above the fixed header and managed dialogs above regular dialogs", () => {
10+
expect(appShellHeaderZIndex).toBe(getDefaultZIndex("modal") + 1);
11+
expect(modalZIndex).toBe(appShellHeaderZIndex + 1);
12+
expect(managedModalZIndex).toBe(modalZIndex + 1);
13+
expect(modalComponent.defaultProps).toMatchObject({ zIndex: modalZIndex });
14+
expect(theme.components?.Drawer?.defaultProps).toMatchObject({ zIndex: modalZIndex });
15+
});
16+
});

packages/ui/src/theme/modal.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import type { MantineTheme, MantineThemeComponent, ModalProps } from "@mantine/core";
22

3+
import { modalZIndex } from "./layers";
4+
35
export const modalSizeSelect = "xxl";
46
export const modalSizeForm = "lg";
57

@@ -8,6 +10,9 @@ const fixedModalSizes = new Set([modalSizeSelect, modalSizeForm]);
810
const modalWidth = "min(var(--modal-size), calc(100vw - 2 * var(--mantine-spacing-md)))";
911

1012
export const modalComponent: MantineThemeComponent = {
13+
defaultProps: {
14+
zIndex: modalZIndex,
15+
},
1116
vars: (_theme: MantineTheme, props: Partial<ModalProps>) => {
1217
if (props.size === modalSizeSelect) {
1318
return { root: { "--modal-size": "75rem" } };

0 commit comments

Comments
 (0)