From f3227da47c36002742c452b450fa75c7f0569d41 Mon Sep 17 00:00:00 2001 From: shadowusr <58862284+shadowusr@users.noreply.github.com> Date: Wed, 18 Sep 2024 02:03:31 +0300 Subject: [PATCH] feat(new-ui): implement drag to hide hint card (#602) * chore(new-ui): implement drag to hide hint card * chore(new-ui): expand right side to full height * chore(new-ui): add transitions to section width changes and animate gutter handle * chore(new-ui): fix attempt picker margins --- .../Card/KeepDraggingToHideCard.module.css | 55 ++++++++++++++++ .../Card/KeepDraggingToHideCard.tsx | 12 ++++ .../new-ui/components/Card/index.module.css | 11 +++- lib/static/new-ui/components/Card/index.tsx | 6 +- .../components/SplitViewLayout.module.css | 62 ++++++++++++++++--- .../new-ui/components/SplitViewLayout.tsx | 56 +++++++++++++++-- .../components/SuitesPage/index.module.css | 13 ++-- .../suites/components/SuitesPage/index.tsx | 46 +++++++------- lib/static/styles.css | 4 +- 9 files changed, 217 insertions(+), 48 deletions(-) create mode 100644 lib/static/new-ui/components/Card/KeepDraggingToHideCard.module.css create mode 100644 lib/static/new-ui/components/Card/KeepDraggingToHideCard.tsx diff --git a/lib/static/new-ui/components/Card/KeepDraggingToHideCard.module.css b/lib/static/new-ui/components/Card/KeepDraggingToHideCard.module.css new file mode 100644 index 000000000..4be02a50b --- /dev/null +++ b/lib/static/new-ui/components/Card/KeepDraggingToHideCard.module.css @@ -0,0 +1,55 @@ + +@keyframes appear { + 0% { opacity: 0; visibility: hidden; } + 100% { opacity: 1; visibility: visible; } +} + +.overlay-container { + align-items: center; + background: #9176ffa9; + box-shadow: inset 0 0 0 4px #9176ff; + display: flex; + height: 100%; + justify-content: center; + opacity: 0; + overflow: hidden; + position: absolute; + top: 0; + transition: opacity .5s ease, visibility .5s ease; + width: 100%; + visibility: hidden; + z-index: 999; +} + +@keyframes overlay-pulse { + 0% { box-shadow: inset 0 0 0 0 #9176ff; } + 95% { box-shadow: inset 0 0 0 30px #9176ff; } + 100% { opacity: 0; } +} + +.pulsing { + animation: overlay-pulse 2s ease infinite; + position: absolute; + width: 100%; + height: 100%; +} + +@container (max-width: 400px) { + :global(.is-resizing) .overlay-container { + visibility: visible; + opacity: 1; + } +} + +:global(.is-collapsed) .hint { + opacity: 0 +} + +.hint { + font-size: 18px; + color: white; + font-weight: 500; + opacity: 1; + white-space: nowrap; + transition: opacity .1s ease; +} diff --git a/lib/static/new-ui/components/Card/KeepDraggingToHideCard.tsx b/lib/static/new-ui/components/Card/KeepDraggingToHideCard.tsx new file mode 100644 index 000000000..7ef5aec01 --- /dev/null +++ b/lib/static/new-ui/components/Card/KeepDraggingToHideCard.tsx @@ -0,0 +1,12 @@ +import classNames from 'classnames'; +import React, {ReactNode} from 'react'; + +import cardStyles from './index.module.css'; +import styles from './KeepDraggingToHideCard.module.css'; + +export function KeepDraggingToHideCard(): ReactNode { + return
+
+ Keep dragging to hide +
; +} diff --git a/lib/static/new-ui/components/Card/index.module.css b/lib/static/new-ui/components/Card/index.module.css index d3a1bb8ee..87848e2f7 100644 --- a/lib/static/new-ui/components/Card/index.module.css +++ b/lib/static/new-ui/components/Card/index.module.css @@ -1,3 +1,12 @@ +.common-card { + border-radius: 10px; + position: relative; +} + .card { - box-shadow: rgb(255, 255, 255) 0px 0px 0px 0px, rgba(9, 9, 11, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.05) 0px 1px 2px 0px; + box-shadow: rgb(255, 255, 255) 0 0 0 0, rgba(9, 9, 11, 0.05) 0 0 0 1px, rgba(0, 0, 0, 0.05) 0 1px 2px 0; +} + +.wrapper { + overflow: hidden; } diff --git a/lib/static/new-ui/components/Card/index.tsx b/lib/static/new-ui/components/Card/index.tsx index b752b4063..fecc3b7fa 100644 --- a/lib/static/new-ui/components/Card/index.tsx +++ b/lib/static/new-ui/components/Card/index.tsx @@ -9,5 +9,9 @@ interface CardProps { } export function Card(props: CardProps): React.ReactNode { - return
{props.children}
; + return
+
+ {props.children} +
+
; } diff --git a/lib/static/new-ui/components/SplitViewLayout.module.css b/lib/static/new-ui/components/SplitViewLayout.module.css index 01e7b0a9c..fb05f806b 100644 --- a/lib/static/new-ui/components/SplitViewLayout.module.css +++ b/lib/static/new-ui/components/SplitViewLayout.module.css @@ -2,19 +2,67 @@ display: flex; flex-direction: row; height: 100vh; + padding: 0 10px; } - .split > div { - overflow-y: scroll; - } - .split :global(.gutter) { background-color: #eee; background-repeat: no-repeat; background-position: 50%; } - .split :global(.gutter.gutter-horizontal) { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg=='); - cursor: col-resize; +.gutter { + cursor: col-resize; + min-width: 16px; + display: flex; + align-items: center; + justify-content: center; +} + +.gutter-handle { + background: var(--g-color-private-black-200); + height: 40px; + border-radius: 10px; + width: 8px; +} + +@keyframes gutter-activate { + 100% { + transform: scale(1.1); + background: var(--g-color-private-black-400); + } +} + +:global(.is-resizing) .gutter-handle { + animation: gutter-activate 0.3s forwards ease-in; +} + +@keyframes gutter-deactivate { + 0% { + transform: scale(1.1); + background: var(--g-color-private-black-400); + } + + 50% { transform: scale(0.9); } + + 100% { + transform: scale(1); + background: var(--g-color-private-black-200); } +} + +:global(.is-idle) .gutter-handle { + animation: gutter-deactivate 0.4s forwards ease-in; +} + +.container { + min-width: 400px; + container-type: size; + margin: 10px 0; + position: relative; + transition: min-width .2s ease; +} + +.container-collapsed { + min-width: 0; +} diff --git a/lib/static/new-ui/components/SplitViewLayout.tsx b/lib/static/new-ui/components/SplitViewLayout.tsx index 24da06db4..71faf8bb4 100644 --- a/lib/static/new-ui/components/SplitViewLayout.tsx +++ b/lib/static/new-ui/components/SplitViewLayout.tsx @@ -1,13 +1,59 @@ -import React from 'react'; +import classNames from 'classnames'; +import React, {ReactNode} from 'react'; import Split from 'react-split'; import styles from './SplitViewLayout.module.css'; +import {KeepDraggingToHideCard} from '@/static/new-ui/components/Card/KeepDraggingToHideCard'; interface SplitViewLayoutProps { - children?: React.ReactNode; + sections: React.ReactNode[]; } -export function SplitViewLayout(props: SplitViewLayoutProps): JSX.Element { - return - {props.children} +export function SplitViewLayout(props: SplitViewLayoutProps): ReactNode { + const snapOffset = 200; + const [wasDragged, setWasDragged] = React.useState(false); + const [isDragging, setIsDragging] = React.useState(false); + const [isHiddenByIndex, setIsHiddenByIndex] = React.useState([]); + + const onDragHandler = (sizes: number[]): void => { + setIsHiddenByIndex(sizes.map(size => size < 1)); + }; + + const onDragStartHandler = (): void => { + setWasDragged(true); + setIsDragging(true); + }; + + const onDragEndHandler = (): void => { + setIsDragging(false); + }; + + const createGutter = (): HTMLDivElement => { + const handle = document.createElement('div'); + handle.classList.add(styles.gutterHandle); + + const gutter = document.createElement('div'); + gutter.appendChild(handle); + gutter.classList.add(styles.gutter); + + return gutter; + }; + + return + {props.sections.map((section, index) => +
+ + {section} +
)}
; } diff --git a/lib/static/new-ui/features/suites/components/SuitesPage/index.module.css b/lib/static/new-ui/features/suites/components/SuitesPage/index.module.css index ff7fd0109..c05519eb9 100644 --- a/lib/static/new-ui/features/suites/components/SuitesPage/index.module.css +++ b/lib/static/new-ui/features/suites/components/SuitesPage/index.module.css @@ -19,25 +19,22 @@ background-color: #fff; display: flex; flex-direction: column; - margin: 10px; - border-radius: 10px; - border: 20px solid white; - border-top: 15px solid white; + padding: 0 20px 20px 20px; + overflow: hidden; + position: relative; + height: calc(100vh - 20px); } .card__title { margin-bottom: 8px !important; + padding-top: 15px; } .tree-view-card { - height: calc(100vh - 20px); - margin-right: 2px; gap: 8px; } .test-view-card { - margin-left: 2px; - max-height: calc(100vh - 20px); gap: 12px; overflow: scroll; } diff --git a/lib/static/new-ui/features/suites/components/SuitesPage/index.tsx b/lib/static/new-ui/features/suites/components/SuitesPage/index.tsx index c59518a09..8e8544039 100644 --- a/lib/static/new-ui/features/suites/components/SuitesPage/index.tsx +++ b/lib/static/new-ui/features/suites/components/SuitesPage/index.tsx @@ -26,31 +26,27 @@ interface SuitesPageProps { } function SuitesPageInternal(props: SuitesPageProps): ReactNode { - return -
- -

Suites

- - - - - - -
-
-
- -
- - props.actions.changeTestRetry({browserId, retryIndex})} /> -
- - -
} id={'overview'}/> - - - -
; + return +

Suites

+ + + + + + + , + +
+ + props.actions.changeTestRetry({browserId, retryIndex})} /> +
+ + + } id={'overview'}/> + +
+ ]} />; } export const SuitesPage = connect( diff --git a/lib/static/styles.css b/lib/static/styles.css index 75a6652c6..c39757817 100644 --- a/lib/static/styles.css +++ b/lib/static/styles.css @@ -608,8 +608,10 @@ a:active { } .tab-switcher { - display: inline-block; + display: inline-flex; margin-bottom: 5px; + gap: 2px; + flex-wrap: wrap; } .tab-switcher:before {