Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(frontend): add vertical resizer in timeline view (#3670)
- Loading branch information
Showing
13 changed files
with
372 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 19 additions & 11 deletions
30
web/src/components/Visualization/components/Timeline/Header.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,30 @@ | ||
import {toPercent} from 'utils/Common'; | ||
import Ticks from './Ticks/Ticks'; | ||
import * as S from './Timeline.styled'; | ||
import VerticalResizer from './VerticalResizer/VerticalResizer'; | ||
import {useVerticalResizer} from './VerticalResizer.provider'; | ||
|
||
const NUM_TICKS = 5; | ||
|
||
interface IProps { | ||
duration: number; | ||
} | ||
|
||
const Header = ({duration}: IProps) => ( | ||
<S.HeaderRow> | ||
<S.Col> | ||
<S.HeaderContent> | ||
<S.HeaderTitle level={3}>Span</S.HeaderTitle> | ||
</S.HeaderContent> | ||
<S.Separator /> | ||
</S.Col> | ||
<Ticks numTicks={NUM_TICKS} startTime={0} endTime={duration} /> | ||
</S.HeaderRow> | ||
); | ||
const Header = ({duration}: IProps) => { | ||
const {columnWidth} = useVerticalResizer(); | ||
|
||
return ( | ||
<S.HeaderRow style={{gridTemplateColumns: `${toPercent(columnWidth)} 1fr`}}> | ||
<S.Col> | ||
<S.HeaderContent> | ||
<S.HeaderTitle level={3}>Span</S.HeaderTitle> | ||
</S.HeaderContent> | ||
</S.Col> | ||
<Ticks numTicks={NUM_TICKS} startTime={0} endTime={duration} /> | ||
|
||
<VerticalResizer /> | ||
</S.HeaderRow> | ||
); | ||
}; | ||
|
||
export default Header; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
web/src/components/Visualization/components/Timeline/VerticalResizer.provider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import {INITIAL_NAME_COLUMN_WIDTH, MAX_NAME_COLUMN_WIDTH, MIN_NAME_COLUMN_WIDTH} from 'constants/Timeline.constants'; | ||
import {createContext, useCallback, useContext, useMemo, useState} from 'react'; | ||
import DraggableManager from 'utils/DragabbleManager'; | ||
|
||
interface IContext { | ||
columnWidth: number; | ||
highlightPosition: number | null; | ||
initResizer({rootRef}: {rootRef: React.RefObject<HTMLDivElement>}): ReturnType<typeof DraggableManager>; | ||
} | ||
|
||
export const Context = createContext<IContext>({ | ||
columnWidth: 0, | ||
highlightPosition: null, | ||
initResizer: () => DraggableManager({onGetBounds: () => ({clientXLeft: 0, width: 0})}), | ||
}); | ||
|
||
interface IProps { | ||
children: React.ReactNode; | ||
} | ||
|
||
export const useVerticalResizer = () => useContext(Context); | ||
|
||
const VerticalResizerProvider = ({children}: IProps) => { | ||
const [columnWidth, setColumnWidth] = useState(INITIAL_NAME_COLUMN_WIDTH); | ||
const [highlightPosition, setHighlightPosition] = useState<number | null>(null); | ||
|
||
const initResizer = useCallback(({rootRef}: {rootRef: React.RefObject<HTMLDivElement>}) => { | ||
const draggableManager = DraggableManager({ | ||
onGetBounds: () => { | ||
if (!rootRef.current) { | ||
return {clientXLeft: 0, width: 0, maxValue: 0, minValue: 0}; | ||
} | ||
|
||
const {left: clientXLeft, width} = rootRef.current.getBoundingClientRect(); | ||
return { | ||
clientXLeft, | ||
width, | ||
maxValue: MAX_NAME_COLUMN_WIDTH, | ||
minValue: MIN_NAME_COLUMN_WIDTH, | ||
}; | ||
}, | ||
onDragEnd: ({value, resetBounds}) => { | ||
resetBounds(); | ||
setHighlightPosition(null); | ||
setColumnWidth(value); | ||
}, | ||
onDragMove: ({value}) => { | ||
setHighlightPosition(value); | ||
}, | ||
}); | ||
|
||
return draggableManager; | ||
}, []); | ||
|
||
const value = useMemo<IContext>( | ||
() => ({ | ||
columnWidth, | ||
highlightPosition, | ||
initResizer, | ||
}), | ||
[columnWidth, highlightPosition, initResizer] | ||
); | ||
|
||
return <Context.Provider value={value}>{children}</Context.Provider>; | ||
}; | ||
|
||
export default VerticalResizerProvider; |
53 changes: 53 additions & 0 deletions
53
...rc/components/Visualization/components/Timeline/VerticalResizer/VerticalResizer.styled.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const VerticalResizer = styled.div` | ||
left: 0; | ||
position: absolute; | ||
right: 0; | ||
top: 0; | ||
`; | ||
|
||
export const VerticalResizerDragger = styled.div` | ||
border-left: 1px solid rgb(222, 227, 236); | ||
cursor: ew-resize; | ||
height: calc(100vh - 50px); | ||
margin-left: -1px; | ||
position: absolute; | ||
top: 0; | ||
width: 1px; | ||
z-index: 2; | ||
::before { | ||
position: absolute; | ||
top: 0; | ||
bottom: 0; | ||
left: -8px; | ||
right: 0; | ||
content: ' '; | ||
} | ||
:hover { | ||
border-left: 2px solid ${({theme}) => theme.color.border}; | ||
} | ||
&.right-dragging, | ||
&.left-dragging { | ||
background: rgba(136, 0, 136, 0.05); | ||
width: unset; | ||
::before { | ||
left: -2000px; | ||
right: -2000px; | ||
} | ||
} | ||
&.left-dragging { | ||
border-left: 2px solid ${({theme}) => theme.color.primaryLight}; | ||
border-right: 1px solid ${({theme}) => theme.color.border}; | ||
} | ||
&.right-dragging { | ||
border-left: 1px solid ${({theme}) => theme.color.border}; | ||
border-right: 2px solid ${({theme}) => theme.color.primaryLight}; | ||
} | ||
`; |
44 changes: 44 additions & 0 deletions
44
web/src/components/Visualization/components/Timeline/VerticalResizer/VerticalResizer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import {useEffect, useRef} from 'react'; | ||
import {toPercent} from 'utils/Common'; | ||
import * as S from './VerticalResizer.styled'; | ||
import {useVerticalResizer} from '../VerticalResizer.provider'; | ||
|
||
const VerticalResizer = () => { | ||
const {columnWidth, highlightPosition, initResizer} = useVerticalResizer(); | ||
const rootRef = useRef<HTMLDivElement>(null); | ||
const draggerRef = useRef<HTMLDivElement>(null); | ||
|
||
useEffect(() => { | ||
const resizer = initResizer({rootRef}); | ||
const handleMouseDown = resizer.initEventHandler(); | ||
draggerRef.current?.addEventListener('mousedown', handleMouseDown); | ||
|
||
return () => { | ||
resizer.cleanup(); | ||
draggerRef.current?.removeEventListener('mousedown', handleMouseDown); | ||
Check warning on line 18 in web/src/components/Visualization/components/Timeline/VerticalResizer/VerticalResizer.tsx GitHub Actions / WebUI unit tests
|
||
}; | ||
}, [initResizer]); | ||
|
||
let draggerClass = ''; | ||
let draggerStyle; | ||
|
||
if (highlightPosition !== null) { | ||
draggerClass = `${highlightPosition > columnWidth ? 'right' : 'left'}-dragging`; | ||
// Draw a highlight from the current dragged position to the original position | ||
const draggerLeft = toPercent(Math.min(columnWidth, highlightPosition)); | ||
// Subtract 1px for draggerRight to deal with the right border being off | ||
// by 1px when dragging left | ||
const draggerRight = `calc(${toPercent(1 - Math.max(columnWidth, highlightPosition))} - 1px)`; | ||
draggerStyle = {left: draggerLeft, right: draggerRight}; | ||
} else { | ||
draggerStyle = {left: toPercent(columnWidth)}; | ||
} | ||
|
||
return ( | ||
<S.VerticalResizer ref={rootRef}> | ||
<S.VerticalResizerDragger className={draggerClass} style={draggerStyle} ref={draggerRef} /> | ||
</S.VerticalResizer> | ||
); | ||
}; | ||
|
||
export default VerticalResizer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.