Repository: opengovsg/plumber
Pull request #1009: [SIDE-DRAWER-27]: Improve side drawer sliding motion
Author: login: kevinkim-ogp
Created: 2025-05-21T08:46:19Z | Merged: 2025-05-26T07:23:02Z

## TL;DR
This PR focuses on improving the sliding motion of the side drawer to make it more 'drawer' like.
Previous implementation had the right drawer elements opening from the centre of the right drawer, which made it look like there were a lot of layout changes.

**Additional changes**
* replace the side drawer left box shadow with a divider instead

## How to test
- [ ] Drawer opens / closes as intended
- [ ] Drawer motion is smooth when opening and closing

## Screenshots

[Screen Recording 2025-05-21 at 4.50.30 PM.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/Wrwhm8Mmhv1Z2GwlSb7V/3a5f999e-1d40-4efd-8754-fb4715692a7b.mov" />](https://app.graphite.dev/media/video/Wrwhm8Mmhv1Z2GwlSb7V/3a5f999e-1d40-4efd-8754-fb4715692a7b.mov)

[Screen Recording 2025-05-21 at 4.50.50 PM.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/Wrwhm8Mmhv1Z2GwlSb7V/a17e15e8-4f7a-400f-958f-de384362c2fc.mov" />](https://app.graphite.dev/media/video/Wrwhm8Mmhv1Z2GwlSb7V/a17e15e8-4f7a-400f-958f-de384362c2fc.mov)

**replace box shadow with border**
![Screenshot 2025-05-22 at 7.06.36 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/Wrwhm8Mmhv1Z2GwlSb7V/853ce64d-8377-4639-a690-0eeaea910251.png)




Diff:
diff --git a/packages/frontend/src/components/Editor/index.tsx b/packages/frontend/src/components/Editor/index.tsx
index fba71742d1..86bcc24282 100644
--- a/packages/frontend/src/components/Editor/index.tsx
+++ b/packages/frontend/src/components/Editor/index.tsx
@@ -151,21 +151,19 @@ export default function Editor(props: EditorProps): React.ReactElement {
     )
   }
 
-  const getStepPadding = () => {
-    if (isDrawerOpen) {
-      if (isMobile) {
-        return 0
-      }
-      return '5rem'
-    }
-    return 0
-  }
+  const leftStepPadding = isDrawerOpen ? (isMobile ? 0 : '5rem') : 0
+  const rightDrawerTransform = isDrawerOpen
+    ? 'translateX(0)'
+    : 'translateX(100%)'
+  const rightDrawerWidth = isDrawerOpen
+    ? isMobile
+      ? '100vw'
+      : EDITOR_RIGHT_DRAWER_WIDTH
+    : '0'
 
   return (
     <Flex
-      w="full"
-      justifyContent="center"
-      overflowX="hidden"
+      {...editorStyles.editorWrapper}
       sx={{
         backgroundImage: 'radial-gradient(#f5f5f5 2px, transparent 2px)',
         backgroundSize: '30px 30px',
@@ -173,9 +171,9 @@ export default function Editor(props: EditorProps): React.ReactElement {
     >
       <StepExecutionsToIncludeProvider value={stepExecutionsToInclude}>
         <Flex
-          {...editorStyles.container}
+          {...editorStyles.stepHeaderContainer}
           flex={isDrawerOpen ? (isMobile ? 0 : 1) : undefined}
-          px={getStepPadding()}
+          px={leftStepPadding}
           maxWidth={`calc(100% - ${
             isDrawerOpen ? EDITOR_RIGHT_DRAWER_WIDTH : '0px'
           })`}
@@ -211,19 +209,18 @@ export default function Editor(props: EditorProps): React.ReactElement {
             />
           )}
         </Flex>
-
+        {/** HACKFIX (kevinkim-ogp): to ensure that the transitions are smooth */}
+        <Flex
+          {...editorStyles.dummyRightContainer}
+          w={rightDrawerWidth}
+          transform={rightDrawerTransform}
+        />
         <Flex
           {...editorStyles.rightDrawerContainer}
-          w={
-            isDrawerOpen
-              ? isMobile
-                ? '100vw'
-                : EDITOR_RIGHT_DRAWER_WIDTH
-              : '0'
-          }
+          w={rightDrawerWidth}
           visibility={isDrawerOpen ? 'visible' : 'hidden'}
           opacity={isDrawerOpen ? 1 : 0}
-          transform={isDrawerOpen ? 'translateX(0)' : 'translateX(100%)'}
+          transform={rightDrawerTransform}
         >
           <EditorRightDrawer
             flowStepGroupIconUrl={flowStepGroupIconUrl}
diff --git a/packages/frontend/src/components/Editor/styles.ts b/packages/frontend/src/components/Editor/styles.ts
index 7b7f2a6a8c..eb31558120 100644
--- a/packages/frontend/src/components/Editor/styles.ts
+++ b/packages/frontend/src/components/Editor/styles.ts
@@ -1,9 +1,15 @@
 import { FlexProps } from '@chakra-ui/react'
 
-import { EDITOR_MAX_HEIGHT } from './constants'
+import { EDITOR_MAX_HEIGHT, EDITOR_RIGHT_DRAWER_WIDTH } from './constants'
 
 export const editorStyles = {
-  container: {
+  editorWrapper: {
+    w: 'full',
+    overflowX: 'hidden' as FlexProps['overflowX'],
+    justifyContent: 'center',
+    pos: 'relative' as FlexProps['pos'],
+  },
+  stepHeaderContainer: {
     display: 'block',
     flexDir: 'column' as FlexProps['flexDir'],
     alignItems: 'center',
@@ -16,18 +22,27 @@ export const editorStyles = {
     transition: 'transform 0.4s cubic-bezier(0.3, 0, 0.2, 1)',
     w: '100%',
   },
+  dummyRightContainer: {
+    pos: 'relative' as FlexProps['pos'],
+    maxHeight: EDITOR_MAX_HEIGHT,
+    h: EDITOR_MAX_HEIGHT,
+    overflow: 'hidden' as FlexProps['overflow'],
+    transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
+    border: 'none',
+  },
   rightDrawerContainer: {
     flexDir: 'column' as FlexProps['flexDir'],
-    position: 'relative' as FlexProps['position'],
+    position: 'absolute' as FlexProps['position'],
     bg: 'white',
     borderRadius: 'none',
-    borderLeft: '1px',
-    borderColor: 'base.divider.medium',
-    boxShadow: 'lg',
+    borderLeftWidth: '1px',
+    borderLeftColor: 'base.divider.medium',
     opacity: 0,
+    right: 0,
+    minWidth: EDITOR_RIGHT_DRAWER_WIDTH,
     maxHeight: EDITOR_MAX_HEIGHT,
     h: EDITOR_MAX_HEIGHT,
     overflowY: 'auto' as FlexProps['overflowY'],
-    transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
+    transition: 'transform 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
   },
 }


Reviews:
user: login: m0nggh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T02:22:57Z
user: login: kevinkim-ogp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T03:38:25Z
user: login: m0nggh
body: okok thks, think its good to go, tested that the animation is working, lgtm
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T04:53:47Z

Review comments:
diff_hunk: @@ -211,19 +209,19 @@ export default function Editor(props: EditorProps): React.ReactElement {
             />
           )}
         </Flex>
-
+        {/** HACKFIX (kevinkim-ogp): to ensure that the transitions are smooth */}
+        <Flex
+          {...editorStyles.dummyRightContainer}
+          w={rightDrawerWidth}
+          transform={rightDrawerTransform}
+        />
         <Flex
           {...editorStyles.rightDrawerContainer}
-          w={
-            isDrawerOpen
-              ? isMobile
-                ? '100vw'
-                : EDITOR_RIGHT_DRAWER_WIDTH
-              : '0'
-          }
+          w={rightDrawerWidth}
           visibility={isDrawerOpen ? 'visible' : 'hidden'}
           opacity={isDrawerOpen ? 1 : 0}
-          transform={isDrawerOpen ? 'translateX(0)' : 'translateX(100%)'}
+          transform={rightDrawerTransform}
+          borderLeft={isDrawerOpen ? '1px solid base.divider.medium' : 'none'}
path: packages/frontend/src/components/Editor/index.tsx
user: login: m0nggh
body: is this necessary actually? was trying to trace the code and it seems like the borderLeft is taken from the styles instead hmm ps just a little confused how this works
created_at: 2025-05-26T02:22:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -211,19 +209,19 @@ export default function Editor(props: EditorProps): React.ReactElement {
             />
           )}
         </Flex>
-
+        {/** HACKFIX (kevinkim-ogp): to ensure that the transitions are smooth */}
+        <Flex
+          {...editorStyles.dummyRightContainer}
+          w={rightDrawerWidth}
+          transform={rightDrawerTransform}
+        />
         <Flex
           {...editorStyles.rightDrawerContainer}
-          w={
-            isDrawerOpen
-              ? isMobile
-                ? '100vw'
-                : EDITOR_RIGHT_DRAWER_WIDTH
-              : '0'
-          }
+          w={rightDrawerWidth}
           visibility={isDrawerOpen ? 'visible' : 'hidden'}
           opacity={isDrawerOpen ? 1 : 0}
-          transform={isDrawerOpen ? 'translateX(0)' : 'translateX(100%)'}
+          transform={rightDrawerTransform}
+          borderLeft={isDrawerOpen ? '1px solid base.divider.medium' : 'none'}
path: packages/frontend/src/components/Editor/index.tsx
user: login: kevinkim-ogp
body: thanks for catching this sir 👍  
this is indeed unnecessary, only the one in the styles is required
created_at: 2025-05-26T03:38:24Z
author_association: CONTRIBUTOR

PR comments:
user: login: kevinkim-ogp
created_at: 2025-05-21T08:47:13Z
body: * **#1010** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/1010?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#1009** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/1009?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a> 👈 <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/1009?utm_source=stack-comment-view-in-graphite" target="_blank">(View in Graphite)</a>
* **#1007** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/1007?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#1003** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/1003?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#1002** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/1002?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#1001** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/1001?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#1000** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/1000?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#999** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/999?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#996** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/996?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#995** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/995?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#994** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/994?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#993** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/993?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#989** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/989?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#988** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/988?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#984** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/984?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#983** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/983?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#981** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/981?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#980** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/980?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#979** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/979?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#978** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/978?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#970** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/970?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#963** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/963?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#955** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/955?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#950** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/950?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#935** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/935?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#924** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/924?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#911** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/911?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#910** <a href="https://app.graphite.dev/github/pr/opengovsg/plumber/910?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* `trunk/ui-revamp`


<h2></h2>

This stack of pull requests is managed by <a href="https://graphite.dev?utm-source=stack-comment"><b>Graphite</b></a>. Learn more about <a href="https://stacking.dev/?utm_source=stack-comment">stacking</a>.
<!-- Current dependencies on/for this PR: -->
author_association: CONTRIBUTOR
user: login: datadog-opengovsg[bot]
created_at: 2025-05-21T08:51:35Z
body: 
## Datadog Report

Branch report: [`chore/ui-revamp/improve-drawer-motion`](https://ogp.datadoghq.com/ci/test-branch/github.com%2Fopengovsg%2Fplumber/plumber/chore%2Fui-revamp%2Fimprove-drawer-motion?env=ci&index=citest&_user_click_origin_=github)
Commit report: [`a7e46c4`](https://ogp.datadoghq.com/ci/test-commit/github.com%2Fopengovsg%2Fplumber/plumber/chore%2Fui-revamp%2Fimprove-drawer-motion/a7e46c476ab477d1ed05d6468ea8f3679bf75de7?env=ci&index=citest&_user_click_origin_=github)
Test service: `plumber`

:white_check_mark: 0 Failed, 790 Passed, 0 Skipped, 2m 31.46s Total Time
:small_red_triangle_down: Test Sessions change in coverage: 1 decreased (-0.78%)



### :small_red_triangle_down: Code Coverage Decreases vs Default Branch (1)

* `vitest ` 31.76% (-0.78%) - [Details](https://ogp.datadoghq.com/ci/test/AwAAAZcLT51pAZSqfQAAABhBWmNMVDUxNkFBQVFCMHpkQlRUd0JsWjYAAAAkMDE5NzBiNGYtOWQ2OS00ZDNkLWEyNWYtMjU2NTU4MDliNjM0AAAAAg?currentTab=coverage)
author_association: NONE