Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core] Add position prop to Drawer component, deprecate vertical prop #3386

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/core/src/common/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { Alignment } from "./alignment";
import { Elevation } from "./elevation";
import { Intent } from "./intent";
import { Position } from "./position";

const NS = process.env.BLUEPRINT_NAMESPACE || "bp3";

Expand All @@ -28,6 +29,10 @@ export const MULTILINE = `${NS}-multiline`;
export const ROUND = `${NS}-round`;
export const SMALL = `${NS}-small`;
export const VERTICAL = `${NS}-vertical`;
export const POSITION_TOP = positionClass(Position.TOP);
export const POSITION_BOTTOM = positionClass(Position.BOTTOM);
export const POSITION_LEFT = positionClass(Position.LEFT);
export const POSITION_RIGHT = positionClass(Position.RIGHT);

export const ELEVATION_0 = elevationClass(Elevation.ZERO);
export const ELEVATION_1 = elevationClass(Elevation.ONE);
Expand Down Expand Up @@ -304,3 +309,10 @@ export function intentClass(intent?: Intent) {
}
return `${NS}-intent-${intent.toLowerCase()}`;
}

export function positionClass(position: Position) {
if (position == null) {
return undefined;
}
return `${NS}-position-${position}`;
}
4 changes: 4 additions & 0 deletions packages/core/src/common/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,7 @@ export const TOASTER_WARN_INLINE = ns + ` Toaster.create() ignores inline prop a
export const DIALOG_WARN_NO_HEADER_ICON = ns + ` <Dialog> iconName is ignored if title is omitted.`;
export const DIALOG_WARN_NO_HEADER_CLOSE_BUTTON =
ns + ` <Dialog> isCloseButtonShown prop is ignored if title is omitted.`;

export const DRAWER_VERTICAL_IS_IGNORED = ns + ` <Drawer> vertical is ignored if position is defined`;
export const DRAWER_ANGLE_POSITIONS_ARE_CASTED =
ns + ` <Drawer> all angle positions are casted into pure position (TOP, BOTTOM, LEFT or RIGHT)`;
24 changes: 24 additions & 0 deletions packages/core/src/common/position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,27 @@ export function isPositionVertical(position: Position) {
position === Position.RIGHT_BOTTOM
);
}

export function getPositionIgnoreAngles(position: Position) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice 👍

if (
position === Position.TOP ||
position === Position.TOP_LEFT ||
position === Position.TOP_RIGHT
) {
return Position.TOP;
} else if (
position === Position.BOTTOM ||
position === Position.BOTTOM_LEFT ||
position === Position.BOTTOM_RIGHT
) {
return Position.BOTTOM;
} else if (
position === Position.LEFT ||
position === Position.LEFT_TOP ||
position === Position.LEFT_BOTTOM
) {
return Position.LEFT;
} else {
return Position.RIGHT;
}
}
107 changes: 101 additions & 6 deletions packages/core/src/components/drawer/_drawer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,30 @@ $drawer-default-size: 50%;
outline: 0;
}

&:not(.#{$ns}-vertical) {
&.#{$ns}-position-top {
@include react-transition-phase(
"#{$ns}-overlay",
"enter",
(transform: (translateX(100%), translateX(0))),
(transform: (translateY(-100%), translateY(0))),
$pt-transition-duration * 2,
$pt-transition-ease,
$before: "&"
);
@include react-transition-phase(
"#{$ns}-overlay",
"exit",
(transform: (translateX(100%), translateX(0))),
(transform: (translateY(-100%), translateY(0))),
$pt-transition-duration,
$before: "&"
);

top: 0;
right: 0;
bottom: 0;
width: $drawer-default-size;
left: 0;
height: $drawer-default-size;
}

&.#{$ns}-vertical {
&.#{$ns}-position-bottom {
@include react-transition-phase(
"#{$ns}-overlay",
"enter",
Expand All @@ -69,6 +69,101 @@ $drawer-default-size: 50%;
height: $drawer-default-size;
}

&.#{$ns}-position-left {
@include react-transition-phase(
"#{$ns}-overlay",
"enter",
(transform: (translateX(-100%), translateX(0))),
$pt-transition-duration * 2,
$pt-transition-ease,
$before: "&"
);
@include react-transition-phase(
"#{$ns}-overlay",
"exit",
(transform: (translateX(-100%), translateX(0))),
$pt-transition-duration,
$before: "&"
);

top: 0;
bottom: 0;
left: 0;
width: $drawer-default-size;
}

&.#{$ns}-position-right {
@include react-transition-phase(
"#{$ns}-overlay",
"enter",
(transform: (translateX(100%), translateX(0))),
$pt-transition-duration * 2,
$pt-transition-ease,
$before: "&"
);
@include react-transition-phase(
"#{$ns}-overlay",
"exit",
(transform: (translateX(100%), translateX(0))),
$pt-transition-duration,
$before: "&"
);

top: 0;
right: 0;
bottom: 0;
width: $drawer-default-size;
}

&:not(.#{$ns}-position-top):not(.#{$ns}-position-bottom):not(.#{$ns}-position-left):not(
.#{$ns}-position-right) {
&:not(.#{$ns}-vertical) {
@include react-transition-phase(
"#{$ns}-overlay",
"enter",
(transform: (translateX(100%), translateX(0))),
$pt-transition-duration * 2,
$pt-transition-ease,
$before: "&"
);
@include react-transition-phase(
"#{$ns}-overlay",
"exit",
(transform: (translateX(100%), translateX(0))),
$pt-transition-duration,
$before: "&"
);

top: 0;
right: 0;
bottom: 0;
width: $drawer-default-size;
}

&.#{$ns}-vertical {
@include react-transition-phase(
"#{$ns}-overlay",
"enter",
(transform: (translateY(100%), translateY(0))),
$pt-transition-duration * 2,
$pt-transition-ease,
$before: "&"
);
@include react-transition-phase(
"#{$ns}-overlay",
"exit",
(transform: (translateY(100%), translateY(0))),
$pt-transition-duration,
$before: "&"
);

right: 0;
bottom: 0;
left: 0;
height: $drawer-default-size;
}
}

&.#{$ns}-dark,
.#{$ns}-dark & {
box-shadow: $pt-dark-dialog-box-shadow;
Expand Down
41 changes: 38 additions & 3 deletions packages/core/src/components/drawer/drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as React from "react";
import { AbstractPureComponent } from "../../common/abstractPureComponent";
import * as Classes from "../../common/classes";
import * as Errors from "../../common/errors";
import { getPositionIgnoreAngles, isPositionHorizontal, Position } from "../../common/position";
import { DISPLAYNAME_PREFIX, IProps, MaybeElement } from "../../common/props";
import { Button } from "../button/buttons";
import { H4 } from "../html/html";
Expand Down Expand Up @@ -37,6 +38,13 @@ export interface IDrawerProps extends IOverlayableProps, IBackdropProps, IProps
*/
isOpen: boolean;

/**
* Position of a drawer. All angled positions will be casted into pure positions
* (TOP, BOTTOM, LEFT or RIGHT).
* @default Position.RIGHT
*/
position?: Position;

/**
* CSS size of the drawer. This sets `width` if `vertical={false}` (default)
* and `height` otherwise.
Expand Down Expand Up @@ -70,7 +78,9 @@ export interface IDrawerProps extends IOverlayableProps, IBackdropProps, IProps

/**
* Whether the drawer should appear with vertical styling.
* It will be ignored if `position` prop is set
* @default false
* @deprecated use `position` instead
*/
vertical?: boolean;
}
Expand All @@ -80,6 +90,7 @@ export class Drawer extends AbstractPureComponent<IDrawerProps, {}> {
public static defaultProps: IDrawerProps = {
canOutsideClickClose: true,
isOpen: false,
position: null,
style: {},
vertical: false,
};
Expand All @@ -89,9 +100,25 @@ export class Drawer extends AbstractPureComponent<IDrawerProps, {}> {
public static readonly SIZE_LARGE = "90%";

public render() {
const { size, style, vertical } = this.props;
const classes = classNames(Classes.DRAWER, { [Classes.VERTICAL]: vertical }, this.props.className);
const styleProp = size == null ? style : { ...style, [vertical ? "height" : "width"]: size };
const { size, style, position, vertical } = this.props;
const realPosition = position ? getPositionIgnoreAngles(position) : null;

const classes = classNames(
Classes.DRAWER,
{
[Classes.VERTICAL]: !realPosition && vertical,
[realPosition ? Classes.positionClass(realPosition) : ""]: true,
},
this.props.className,
);

const styleProp =
size == null
? style
: {
...style,
[(realPosition ? isPositionHorizontal(realPosition) : vertical) ? "height" : "width"]: size,
};
return (
<Overlay {...this.props} className={Classes.OVERLAY_CONTAINER}>
<div className={classes} style={styleProp}>
Expand All @@ -111,6 +138,14 @@ export class Drawer extends AbstractPureComponent<IDrawerProps, {}> {
console.warn(Errors.DIALOG_WARN_NO_HEADER_CLOSE_BUTTON);
}
}
if (props.position != null) {
if (props.vertical) {
console.warn(Errors.DRAWER_VERTICAL_IS_IGNORED);
}
if (props.position !== getPositionIgnoreAngles(props.position)) {
console.warn(Errors.DRAWER_ANGLE_POSITIONS_ARE_CASTED);
}
}
}

private maybeRenderCloseButton() {
Expand Down
Loading