Skip to content

Commit 6682968

Browse files
[TASK] New UI for Alias and Tags (#433)
#433 * used use-gesture for all interactions with sidebar toggle; Signed-off-by: Sahil Shubham <[email protected]> * added button animation behind drag toggle; Signed-off-by: Sahil Shubham <[email protected]> * Added shortener component to the floating buttons; Signed-off-by: Sahil Shubham <[email protected]> * delayed animation end till done with shortening; Signed-off-by: Sahil Shubham <[email protected]> * fixed icon hover color; Signed-off-by: Sahil Shubham <[email protected]> * added vertical bounds; Fixed horizontal animation on other displays; Signed-off-by: Sahil Shubham <[email protected]> * Added tooltip to shortener component; Signed-off-by: Sahil Shubham <[email protected]> * added patch changeset --------- Signed-off-by: Sahil Shubham <[email protected]>
1 parent 2b588e9 commit 6682968

File tree

9 files changed

+244
-253
lines changed

9 files changed

+244
-253
lines changed

.changeset/metal-oranges-talk.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'mexit': patch
3+
---
4+
5+
Moved url shortener away from sidebar to a floating button

apps/extension/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@sentry/react": "^6.17.4",
2222
"@tippyjs/react": "^4.2.6",
2323
"@udecode/plate": "^16.4.1",
24+
"@use-gesture/react": "^10.2.27",
2425
"@webcomponents/custom-elements": "1.5.0",
2526
"@workduck-io/dwindle": "^0.1.7",
2627
"@workduck-io/mex-components": "^0.0.25",
@@ -47,7 +48,6 @@
4748
"react-hot-toast": "^2.2.0",
4849
"react-image-crop": "^10.0.9",
4950
"react-spring": "^9.4.3",
50-
"react-use-hoverintent": "^1.2.9",
5151
"react-virtual": "^2.10.4",
5252
"sanitize-html": "^2.6.1",
5353
"slate": "^0.78.0",
@@ -99,4 +99,4 @@
9999
"last 1 safari version"
100100
]
101101
}
102-
}
102+
}

apps/extension/src/Components/Sidebar/ContextInfoBar.tsx

-6
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,6 @@ const Highlights = () => {
226226
export function ContextInfoBar() {
227227
return (
228228
<SnippetCards fullHeight>
229-
{/* <SidebarSection label="Shorten URL" icon={getMIcon('ICON', 'ri:link-m')}>
230-
<ShortenerComponent />
231-
</SidebarSection>
232-
<SidebarSection label="Tags" icon={DefaultMIcons.TAG}>
233-
<AddTags />
234-
</SidebarSection> */}
235229
<UpcomingEvents />
236230
<Highlights />
237231
</SnippetCards>
Original file line numberDiff line numberDiff line change
@@ -1,174 +1,117 @@
1-
import React, { useEffect, useRef, useState } from 'react'
2-
import { useHoverIntent } from 'react-use-hoverintent'
1+
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'
2+
import { useSpring, useSprings } from 'react-spring'
33

4-
import { Icon } from '@iconify/react'
54
import Tippy from '@tippyjs/react'
6-
import styled, { css } from 'styled-components'
5+
import { useGesture } from '@use-gesture/react'
76

87
import { TitleWithShortcut } from '@workduck-io/mex-components'
98

109
import { useLayoutStore } from '@mexit/core'
1110
import { WDLogo } from '@mexit/shared'
1211

13-
import { useSidebarTransition } from '../../Hooks/useSidebarTransition'
1412
import { getElementById } from '../../Utils/cs-utils'
1513

16-
const DragIcon = styled(Icon)<{ $show: boolean }>`
17-
margin-right: -18px;
18-
opacity: 0;
19-
pointer-events: none;
20-
transition: margin-right 0.2s ease-in-out, opacity 0.2s ease-in-out;
21-
${(props) =>
22-
props.$show &&
23-
css`
24-
margin-right: 0;
25-
opacity: 1;
26-
pointer-events: all;
27-
`}
28-
`
29-
30-
const ToggleWrapper = styled.div<{ $endColumnWidth?: string; $expanded?: boolean; $top: number }>`
31-
position: fixed;
32-
display: flex;
33-
align-items: center;
34-
width: max-content;
35-
36-
${({ $expanded, $top, $endColumnWidth, theme }) =>
37-
$expanded
38-
? css`
39-
top: ${$top}px;
40-
right: calc(${($endColumnWidth ?? '400px') + ' + ' + (theme.additional.hasBlocks ? 0 : -15)}px);
41-
`
42-
: css`
43-
top: ${$top}px;
44-
right: 0;
45-
`}
46-
47-
z-index: 9999999999;
48-
padding: 8px;
49-
border-radius: ${({ theme }) => theme.borderRadius.small};
50-
background: ${({ theme }) => theme.tokens.surfaces.sidebar};
51-
color: ${({ theme }) => theme.tokens.text.fade};
52-
transition: right 0.2s ease-in-out, background 0.2s ease-in-out, width 0.2s ease-in-out;
53-
54-
svg {
55-
height: 16px;
56-
width: 16px;
57-
}
58-
59-
&:hover {
60-
cursor: pointer;
61-
box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.25);
62-
background: ${({ theme }) => theme.tokens.colors.primary.default};
63-
color: ${({ theme }) => theme.tokens.colors.primary.text};
64-
65-
svg {
66-
path {
67-
fill: ${({ theme }) => theme.tokens.surfaces.sidebar};
68-
}
69-
}
70-
}
71-
72-
${DragIcon} {
73-
cursor: ns-resize;
74-
}
75-
76-
&:active {
77-
transition: background 0.1s ease;
78-
background-color: ${({ theme }) => theme.tokens.colors.primary.default};
79-
color: ${({ theme }) => theme.tokens.colors.primary.text};
80-
}
81-
`
82-
83-
const Wrapper = styled.div`
84-
display: flex;
85-
align-items: center;
86-
justify-content: center;
87-
position: relative;
88-
89-
/* ::before {
90-
content: '';
91-
position: absolute;
92-
bottom: 20px;
93-
height: 20px;
94-
width: 20px;
95-
border-bottom-right-radius: ${({ theme }) => theme.borderRadius.large};
96-
background: ${({ theme }) => theme.tokens.surfaces.sidebar};
97-
color: ${({ theme }) => theme.tokens.text.fade};
98-
} */
99-
`
14+
import { ShortenerComponent } from './ShortenerComponent'
15+
import { ButtonWrapper, DragIcon, ToggleWrapper, Wrapper } from './styled'
16+
17+
// Change this if more buttons have to be added
18+
const FLOATING_BUTTONS = 1
10019

10120
export const DraggableToggle = () => {
102-
const [isHovering, intentRef, setIsHovering] = useHoverIntent({ timeout: 500 })
103-
const [tracking, setTracking] = useState(false)
21+
const [isHovering, setIsHovering] = useState(false)
22+
const [editable, setEditable] = useState(false)
10423
const { rhSidebar, toggleRHSidebar, toggleTop, setToggleTop } = useLayoutStore()
105-
const { endColumnWidth } = useSidebarTransition()
106-
107-
const handleRef = useRef<any>(null)
108-
109-
useEffect(() => {
110-
const handleMouseDown = (event: MouseEvent) => {
111-
event.preventDefault()
112-
event.stopPropagation()
113-
setTracking(true)
114-
}
11524

116-
if (handleRef?.current) {
117-
handleRef.current.addEventListener('mousedown', handleMouseDown)
118-
}
119-
120-
return () => {
121-
handleRef?.current?.removeEventListener('mousedown', handleMouseDown)
25+
const avatarRefs = useRef<HTMLDivElement[]>([])
26+
const avatarRefInitialPositions = useRef<number[]>([])
27+
const toggleRef = useRef<HTMLDivElement>(null)
28+
const avatarTimeoutRef = useRef<ReturnType<typeof setTimeout>>()
29+
30+
const [{ x, y }, api] = useSpring(() => ({ x: `${window.innerWidth - 40}px`, y: toggleTop }), [])
31+
const [buttonSprings, buttonApi] = useSprings(FLOATING_BUTTONS, (i) => ({ y: 0 }), [])
32+
33+
const bind = useGesture(
34+
{
35+
onDrag: ({ offset: [, y] }) => {
36+
api.start({ y })
37+
},
38+
onDragEnd: () => {
39+
setToggleTop(y.get())
40+
},
41+
onHover: ({ hovering }) => {
42+
setIsHovering(hovering)
43+
}
44+
},
45+
{
46+
drag: {
47+
from: () => [0, y.get()],
48+
axis: 'y',
49+
// filters click events when dragging
50+
filterTaps: true,
51+
pointer: {
52+
keys: false
53+
},
54+
// Hard coding lower bound for now but would have to change if more buttons are added
55+
bounds: {
56+
top: -window.innerHeight,
57+
bottom: -100
58+
}
59+
}
12260
}
123-
}, [handleRef?.current])
61+
)
12462

125-
useEffect(() => {
126-
const handleMouseMove = (event: MouseEvent) => {
127-
event.stopPropagation()
63+
useLayoutEffect(() => {
64+
if (avatarRefInitialPositions.current.length === 0) {
65+
const { y: buttonY } = toggleRef.current.getBoundingClientRect()
12866

129-
if (tracking) {
130-
const newHeight = event.clientY
131-
setToggleTop(newHeight)
132-
}
67+
avatarRefInitialPositions.current = avatarRefs.current.map((node) => buttonY - node.getBoundingClientRect().y)
13368
}
13469

135-
window.addEventListener('mousemove', handleMouseMove)
70+
buttonApi.start((i) => ({
71+
y: avatarRefInitialPositions.current[i],
72+
immediate: true
73+
}))
74+
}, [])
13675

137-
return () => {
138-
window.removeEventListener('mousemove', handleMouseMove)
139-
}
140-
}, [tracking])
76+
useEffect(() => {
77+
api.start({ x: `${window.innerWidth - (rhSidebar.expanded ? 433 : 40)}px` })
78+
}, [rhSidebar.expanded])
14179

14280
useEffect(() => {
143-
const handleMouseUp = (event) => {
144-
if (tracking) setTracking(false)
145-
}
146-
window.addEventListener('mouseup', handleMouseUp)
81+
if (isHovering || editable) {
82+
if (avatarTimeoutRef.current) {
83+
clearTimeout(avatarTimeoutRef.current)
84+
}
14785

148-
return () => {
149-
window.removeEventListener('mouseup', handleMouseUp)
86+
buttonApi.start({
87+
y: 0
88+
})
89+
} else {
90+
avatarTimeoutRef.current = setTimeout(() => {
91+
buttonApi.start((i) => ({
92+
y: avatarRefInitialPositions.current[i]
93+
}))
94+
}, 1500)
15095
}
151-
}, [tracking])
96+
}, [isHovering, editable])
15297

15398
return (
154-
<Tippy
155-
theme="mex-bright"
156-
placement="left"
157-
appendTo={() => getElementById('ext-side-nav')}
158-
content={<TitleWithShortcut title={rhSidebar.expanded ? 'Collapse Sidebar' : 'Expand Sidebar'} />}
159-
>
160-
<ToggleWrapper
161-
$endColumnWidth={endColumnWidth}
162-
ref={intentRef as any}
163-
$top={toggleTop}
164-
$expanded={rhSidebar.expanded}
165-
onClick={toggleRHSidebar}
99+
<ToggleWrapper ref={toggleRef} {...bind()} style={{ x, y }}>
100+
<Tippy
101+
theme="mex-bright"
102+
placement="left"
103+
appendTo={() => getElementById('ext-side-nav')}
104+
content={<TitleWithShortcut title={rhSidebar.expanded ? 'Collapse Sidebar' : 'Expand Sidebar'} />}
166105
>
167-
<Wrapper>
106+
<Wrapper onClick={() => toggleRHSidebar()}>
168107
<WDLogo />
169-
<DragIcon ref={handleRef} $show={isHovering} icon="ic:outline-drag-indicator" />
108+
<DragIcon $show={isHovering} icon="ic:outline-drag-indicator" />
170109
</Wrapper>
171-
</ToggleWrapper>
172-
</Tippy>
110+
</Tippy>
111+
112+
<ButtonWrapper ref={(ref) => (avatarRefs.current[0] = ref!)} style={buttonSprings[0]}>
113+
<ShortenerComponent editable={editable} setEditable={setEditable} />
114+
</ButtonWrapper>
115+
</ToggleWrapper>
173116
)
174117
}

0 commit comments

Comments
 (0)