Skip to content

Commit 33f83f6

Browse files
committed
git config core.ignorecase false
1 parent 9895a39 commit 33f83f6

File tree

13 files changed

+756
-0
lines changed

13 files changed

+756
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const HEADER_HEIGHT = 48;
2+
export const MOBILE_BREAKPOINT = 390;
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
import { css, cx, keyframes } from '@leafygreen-ui/emotion';
2+
import { createUniqueClassName, type Theme } from '@leafygreen-ui/lib';
3+
import {
4+
addOverflowShadow,
5+
color,
6+
Side,
7+
spacing,
8+
transitionDuration,
9+
} from '@leafygreen-ui/tokens';
10+
11+
import { PANEL_WIDTH } from '../constants';
12+
13+
import { HEADER_HEIGHT, MOBILE_BREAKPOINT } from './drawer.constants';
14+
import { DisplayMode } from './drawer.types';
15+
16+
export const drawerTransitionDuration = transitionDuration.slower;
17+
18+
export const drawerClassName = createUniqueClassName('lg-drawer');
19+
20+
// Because of .show() and .close() in the drawer component, transitioning from 0px to (x)px does not transition correctly. Having the drawer start at the open position while hidden, moving to the closed position, and then animating to the open position is a workaround to get the animation to work.
21+
// These styles are used for a standalone drawer in overlay mode since it is not part of a grid layout.
22+
const drawerIn = keyframes`
23+
0% {
24+
transform: translate3d(0%, 0, 0);
25+
opacity: 0;
26+
visibility: hidden;
27+
}
28+
1% {
29+
transform: translate3d(100%, 0, 0);
30+
opacity: 1;
31+
visibility: visible;
32+
}
33+
100% {
34+
transform: translate3d(0%, 0, 0);
35+
}
36+
`;
37+
38+
// Keep the drawer opacity at 1 until the end of the animation. The inner container opacity is transitioned separately.
39+
const drawerOut = keyframes`
40+
0% {
41+
transform: translate3d(0%, 0, 0);
42+
}
43+
99% {
44+
transform: translate3d(100%, 0, 0);
45+
opacity: 1;
46+
}
47+
100% {
48+
opacity: 0;
49+
visibility: hidden;
50+
}
51+
`;
52+
53+
const getBaseStyles = ({ theme }: { theme: Theme }) => css`
54+
all: unset;
55+
background-color: ${color[theme].background.primary.default};
56+
border: 1px solid ${color[theme].border.secondary.default};
57+
width: 100%;
58+
max-width: ${PANEL_WIDTH}px;
59+
height: 100%;
60+
overflow: hidden;
61+
box-sizing: border-box;
62+
63+
@media only screen and (max-width: ${MOBILE_BREAKPOINT}px) {
64+
max-width: 100%;
65+
height: 50vh;
66+
}
67+
`;
68+
69+
const overlayOpenStyles = css`
70+
opacity: 1;
71+
animation-name: ${drawerIn};
72+
73+
// On mobile, the drawer should be positioned at the bottom of the screen when closed, and slide up to the top when opened.
74+
@media only screen and (max-width: ${MOBILE_BREAKPOINT}px) {
75+
transform: none;
76+
}
77+
`;
78+
79+
const overlayClosedStyles = css`
80+
pointer-events: none;
81+
animation-name: ${drawerOut};
82+
83+
// On mobile, the drawer should be positioned at the bottom of the screen when closed, and slide up to the top when opened.
84+
@media only screen and (max-width: ${MOBILE_BREAKPOINT}px) {
85+
transform: translate3d(0, 100%, 0);
86+
opacity: 0;
87+
}
88+
`;
89+
90+
const getOverlayStyles = ({
91+
open,
92+
shouldAnimate,
93+
zIndex,
94+
}: {
95+
open: boolean;
96+
shouldAnimate: boolean;
97+
zIndex: number;
98+
}) =>
99+
cx(
100+
css`
101+
position: absolute;
102+
z-index: ${zIndex};
103+
top: 0;
104+
bottom: 0;
105+
right: 0;
106+
overflow: visible;
107+
108+
// By default, the drawer is positioned off-screen to the right.
109+
transform: translate3d(100%, 0, 0);
110+
animation-timing-function: ease-in-out;
111+
animation-duration: ${drawerTransitionDuration}ms;
112+
animation-fill-mode: forwards;
113+
114+
@media only screen and (max-width: ${MOBILE_BREAKPOINT}px) {
115+
top: unset;
116+
left: 0;
117+
// Since the drawer has position: fixed, we can use normal transitions
118+
animation: none;
119+
position: fixed;
120+
transform: translate3d(0, 100%, 0);
121+
transition: transform ${drawerTransitionDuration}ms ease-in-out,
122+
opacity ${drawerTransitionDuration}ms ease-in-out
123+
${open ? '0ms' : `${drawerTransitionDuration}ms`};
124+
}
125+
`,
126+
{
127+
[overlayOpenStyles]: open,
128+
[overlayClosedStyles]: !open && shouldAnimate, // This ensures that the drawer does not animate closed on initial render
129+
}
130+
);
131+
132+
const getDisplayModeStyles = ({
133+
displayMode,
134+
open,
135+
shouldAnimate,
136+
zIndex,
137+
}: {
138+
displayMode: DisplayMode;
139+
open: boolean;
140+
shouldAnimate: boolean;
141+
zIndex: number;
142+
}) =>
143+
cx({
144+
[getOverlayStyles({ open, shouldAnimate, zIndex })]:
145+
displayMode === DisplayMode.Overlay,
146+
});
147+
148+
export const getDrawerStyles = ({
149+
className,
150+
displayMode,
151+
open,
152+
shouldAnimate,
153+
theme,
154+
zIndex,
155+
}: {
156+
className?: string;
157+
displayMode: DisplayMode;
158+
open: boolean;
159+
shouldAnimate: boolean;
160+
theme: Theme;
161+
zIndex: number;
162+
}) =>
163+
cx(
164+
getBaseStyles({ theme }),
165+
getDisplayModeStyles({ displayMode, open, shouldAnimate, zIndex }),
166+
className,
167+
drawerClassName
168+
);
169+
170+
export const getDrawerShadowStyles = ({
171+
theme,
172+
displayMode,
173+
}: {
174+
theme: Theme;
175+
displayMode: DisplayMode;
176+
}) =>
177+
cx(
178+
css`
179+
height: 100%;
180+
background-color: ${color[theme].background.primary.default};
181+
`,
182+
{
183+
[css`
184+
${addOverflowShadow({ isInside: false, side: Side.Left, theme })};
185+
186+
@media only screen and (max-width: ${MOBILE_BREAKPOINT}px) {
187+
${addOverflowShadow({ isInside: false, side: Side.Top, theme })};
188+
}
189+
`]: displayMode === DisplayMode.Overlay,
190+
}
191+
);
192+
193+
const getBaseInnerContainerStyles = ({ theme }: { theme: Theme }) => css`
194+
width: 100%;
195+
height: 100%;
196+
display: flex;
197+
flex-direction: column;
198+
background-color: ${color[theme].background.primary.default};
199+
opacity: 0;
200+
transition-property: opacity;
201+
transition-duration: ${transitionDuration.faster}ms;
202+
transition-timing-function: linear;
203+
`;
204+
205+
const getInnerOpenContainerStyles = css`
206+
transition-property: opacity;
207+
transition-duration: ${transitionDuration.slowest}ms;
208+
transition-timing-function: linear;
209+
opacity: 1;
210+
`;
211+
212+
export const getInnerContainerStyles = ({
213+
theme,
214+
open,
215+
}: {
216+
theme: Theme;
217+
open: boolean;
218+
}) =>
219+
cx(getBaseInnerContainerStyles({ theme }), {
220+
[getInnerOpenContainerStyles]: open,
221+
});
222+
223+
export const getHeaderStyles = ({ theme }: { theme: Theme }) => css`
224+
height: ${HEADER_HEIGHT}px;
225+
padding: ${spacing[400]}px;
226+
display: flex;
227+
justify-content: space-between;
228+
align-items: center;
229+
border-bottom: 1px solid ${color[theme].border.secondary.default};
230+
transition-property: box-shadow;
231+
transition-duration: ${transitionDuration.faster}ms;
232+
transition-timing-function: ease-in-out;
233+
`;
234+
235+
const baseChildrenContainerStyles = css`
236+
height: 100%;
237+
overflow: hidden;
238+
`;
239+
240+
export const getChildrenContainerStyles = ({
241+
hasShadowTop,
242+
theme,
243+
}: {
244+
hasShadowTop: boolean;
245+
theme: Theme;
246+
}) =>
247+
cx(baseChildrenContainerStyles, {
248+
[addOverflowShadow({ isInside: true, side: Side.Top, theme })]:
249+
hasShadowTop,
250+
});
251+
252+
const baseInnerChildrenContainerStyles = css`
253+
height: 100%;
254+
`;
255+
256+
const scrollContainerStyles = css`
257+
padding: ${spacing[400]}px;
258+
overflow-y: auto;
259+
overscroll-behavior: contain;
260+
`;
261+
262+
export const innerChildrenContainerStyles = cx(
263+
baseInnerChildrenContainerStyles,
264+
scrollContainerStyles
265+
);

0 commit comments

Comments
 (0)