Skip to content

Commit

Permalink
feat(Dialog): add fullHeight & fix stlyes on large heights
Browse files Browse the repository at this point in the history
  • Loading branch information
zettca committed Jan 9, 2025
1 parent fa2704a commit 11ec84d
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 77 deletions.
3 changes: 2 additions & 1 deletion apps/docs/src/pages/components/dialog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ export default function Demo() {
<pre>{JSON.stringify(postData, null, 2)}</pre>
<HvDialog
disableBackdropClick
fullHeight
open={open}
onClose={() => setOpen(false)}
aria-describedby={descId}
Expand All @@ -337,7 +338,7 @@ export default function Demo() {
<DialogForm />
</form>
</HvDialogContent>
<HvDialogActions>
<HvDialogActions className="sticky bottom-0">
<HvButton type="submit" form="create-post">
Create
</HvButton>
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/Dialog/Actions/Actions.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { theme } from "@hitachivantara/uikit-styles";

export const { staticClasses, useClasses } = createClasses("HvDialog-Action", {
root: {
margin: "0",
margin: 0,
padding: theme.space.sm,
backgroundColor: "inherit",
borderTop: `3px solid ${theme.colors.atmo2}`,
height: 65,
maxHeight: 65,
flex: 1,
},
fullscreen: { position: "fixed", width: "100%", bottom: 0, left: 0 },
spacing: {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/Dialog/Actions/Actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ export const HvDialogActions = (props: HvDialogActionsProps) => {
...others
} = useDefaultProps("HvDialogActions", props);
const context = useDialogContext();
const fullscreen = fullScreenProp ?? context.fullscreen;
const fullScreen = fullScreenProp ?? context.fullScreen;

const { classes, cx } = useClasses(classesProp);

return (
<MuiDialogActions
className={className}
classes={{
root: cx(classes.root, { [classes.fullscreen]: fullscreen }),
root: cx(classes.root, { [classes.fullscreen]: fullScreen }),
spacing: classes.spacing,
}}
{...others}
Expand Down
4 changes: 1 addition & 3 deletions packages/core/src/Dialog/Content/Content.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import { theme } from "@hitachivantara/uikit-styles";

export const { staticClasses, useClasses } = createClasses("HvDialog-Content", {
root: {
padding: `0 ${theme.space.sm} ${theme.space.sm} ${theme.space.sm}`,
flex: "none",
padding: theme.spacing(0, "sm", "sm"),
},
textContent: {
marginLeft: "42px",
paddingRight: "62px",
flex: 1,
overflowY: "auto",
},
});
16 changes: 8 additions & 8 deletions packages/core/src/Dialog/Dialog.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,6 @@ export const Main: StoryObj<HvDialogProps> = {
docs: {
source: { code: MainStoryRaw },
},
...setupChromatic(["DS3 dawn", "DS5 dawn", "Pentaho+ dawn"]),
},
// For visual testing and a11y
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = canvas.getByRole("button", { name: /open dialog/i });
await userEvent.click(button);
await expect(canvas.getByRole("dialog")).toBeInTheDocument();
},
render: (args) => <MainStory {...args} />,
};
Expand Down Expand Up @@ -105,6 +97,14 @@ export const Form: StoryObj<HvDialogProps> = {
Accessibility-wise, `HvDialogTitle` automatically labels the dialog. A `aria-describedby` can be used to describe the content.",
},
},
...setupChromatic(["DS3 dawn", "DS5 dawn", "Pentaho+ dawn"]),
},
// For visual testing and a11y
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = canvas.getByRole("button", { name: /create a post/i });
await userEvent.click(button);
await expect(canvas.getByRole("dialog")).toBeInTheDocument();
},
decorators: [(Story) => <div style={{ minHeight: 440 }}>{Story()}</div>],
render: () => <FormStory />,
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/Dialog/Dialog.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export const { staticClasses, useClasses } = createClasses("HvDialog", {
borderRadius: theme.radii.round,
},
fullscreen: {},
fullHeight: {
height: "100%",
},
closeButton: {
padding: 0,
minWidth: "auto",
Expand Down
40 changes: 18 additions & 22 deletions packages/core/src/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export interface HvDialogProps
maxWidth?: MuiDialogProps["maxWidth"];
/** @inheritdoc */
fullWidth?: MuiDialogProps["fullWidth"];
/** If true, the dialog stretches vertically, limited by the margins. @default false */
fullHeight?: boolean;
/**
* Element id that should be focus when the Dialog opens.
* Auto-focusing elements can cause usability issues, so this should be avoided.
Expand Down Expand Up @@ -63,12 +65,13 @@ export const HvDialog = (props: HvDialogProps) => {
onClose,
firstFocusable,
buttonTitle = "Close",
fullscreen = false,
fullHeight,
fullscreen: fullScreen = false, // TODO: rename to `fullScreen` in v6
disableBackdropClick = false,
...others
} = useDefaultProps("HvDialog", props);

const { classes, css, cx } = useClasses(classesProp);
const { classes, cx } = useClasses(classesProp);
const { rootId } = useTheme();

const measuredRef = useCallback(() => {
Expand All @@ -78,17 +81,24 @@ export const HvDialog = (props: HvDialogProps) => {
element?.focus();
}, [firstFocusable]);

const contextValue = useMemo(() => ({ fullscreen }), [fullscreen]);
const contextValue = useMemo(() => ({ fullScreen }), [fullScreen]);

return (
<MuiDialog
container={getElementById(rootId)}
className={cx(classes.root, className)}
classes={{ container: css({ position: "relative" }) }}
className={className}
classes={{
root: classes.root,
paper: cx(classes.paper, classes[variant!], {
[classes.fullHeight]: fullHeight,
[classes.statusBar]: !!variant,
[classes.fullscreen]: fullScreen,
}),
}}
id={id}
ref={measuredRef}
open={open}
fullScreen={fullscreen}
fullScreen={fullScreen}
onClose={(event, reason) => {
// `disableBackdropClick` property was removed in MUI5
// and we want to maintain that functionality
Expand All @@ -103,27 +113,13 @@ export const HvDialog = (props: HvDialogProps) => {
},
},
}}
PaperProps={{
classes: {
root: cx(
css({ position: "absolute" }),
classes.paper,
variant && cx(classes.statusBar, classes[variant]),
{
[classes.fullscreen]: fullscreen,
},
),
},
}}
{...others}
>
<HvIconButton
<HvIconButton<"button">
title={buttonTitle}
id={setId(id, "close")}
className={classes.closeButton}
onClick={(event: React.MouseEvent<HTMLButtonElement>) =>
onClose?.(event, undefined)
}
onClick={(event) => onClose?.(event, undefined)}
>
<Close />
</HvIconButton>
Expand Down
23 changes: 10 additions & 13 deletions packages/core/src/Dialog/Title/Title.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@ import { theme } from "@hitachivantara/uikit-styles";

export const { staticClasses, useClasses } = createClasses("HvDialog-Title", {
root: {
fontFamily: theme.fontFamily.body, // override MUI font
padding: theme.space.sm,
margin: 0,
},
fullscreen: {},
messageContainer: {
marginRight: 32, // close icon padding
flex: "0 0 auto",
display: "flex",
alignItems: "center",
gap: theme.space.xs,
},
textWithIcon: {
marginLeft: theme.space.xs,
// 32px is the icon width
marginRight: `calc(32px + ${theme.space.xs})`,
},
titleText: {
...theme.typography.title4,
},
fullscreen: {},
/** @deprecated use `classes.root` instead */
messageContainer: {},
// TODO: consider deprecating
textWithIcon: {},
/** @deprecated use `classes.root` instead */
titleText: {},
});
39 changes: 15 additions & 24 deletions packages/core/src/Dialog/Title/Title.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import MuiDialogTitle, {
DialogTitleProps as MuiDialogTitleProps,
} from "@mui/material/DialogTitle";
import {
useDefaultProps,
type ExtractNames,
} from "@hitachivantara/uikit-react-utils";

import { HvTypography, HvTypographyProps } from "../../Typography";
import { iconVariant } from "../../utils/iconVariant";
import { useDialogContext } from "../context";
import { staticClasses, useClasses } from "./Title.styles";
Expand All @@ -22,7 +20,7 @@ export type HvDialogTitleVariant =
| "default";

export interface HvDialogTitleProps
extends Omit<MuiDialogTitleProps, "variant" | "classes"> {
extends Omit<HvTypographyProps, "variant" | "classes"> {
/** Variant of the dialog title. */
variant?: HvDialogTitleVariant;
/** Controls if the associated icon to the variant should be shown. */
Expand All @@ -40,40 +38,33 @@ export const HvDialogTitle = (props: HvDialogTitleProps) => {
children,
variant = "default",
showIcon = true,
customIcon = null,
customIcon,
...others
} = useDefaultProps("HvDialogTitle", props);

const { classes, css, cx } = useClasses(classesProp);
const { fullscreen } = useDialogContext();

const isString = typeof children === "string";
const { classes, cx } = useClasses(classesProp);
const { fullScreen } = useDialogContext();

const icon = customIcon || (showIcon && iconVariant(variant));

return (
<MuiDialogTitle
<HvTypography
component="h2"
variant="title4"
className={cx(
!fullscreen && css({ flex: 1 }),
classes.root,
classes.messageContainer,
{
[classes.fullscreen]: fullscreen,
[classes.fullscreen]: fullScreen,
[classes.textWithIcon]: icon,
[classes.titleText]: typeof children === "string",
},
className,
)}
{...others}
>
<div className={classes.messageContainer}>
{icon}
<div
className={cx({
[classes.textWithIcon]: !!icon,
[classes.titleText]: isString,
})}
>
{children}
</div>
</div>
</MuiDialogTitle>
{icon}
{children}
</HvTypography>
);
};
2 changes: 1 addition & 1 deletion packages/core/src/Dialog/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createContext, useContext } from "react";

export const DialogContext = createContext({ fullscreen: false });
export const DialogContext = createContext({ fullScreen: false });

export const useDialogContext = () => useContext(DialogContext);
6 changes: 5 additions & 1 deletion packages/core/src/Dialog/stories/FormStory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const FormStory = () => {
<pre>{JSON.stringify(postData, null, 2)}</pre>
<HvDialog
disableBackdropClick
fullHeight
open={open}
onClose={() => setOpen(false)}
aria-describedby={descId}
Expand All @@ -60,7 +61,10 @@ export const FormStory = () => {
<DialogForm />
</form>
</HvDialogContent>
<HvDialogActions>
<HvDialogActions
// submit/cancel always visible
style={{ position: "sticky", bottom: 0 }}
>
<HvButton type="submit" form="create-post">
Create
</HvButton>
Expand Down

0 comments on commit 11ec84d

Please sign in to comment.