From e133c29b2c1f67e6cd0ce90b217d774be12dbd21 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 9 Nov 2024 18:46:31 +0000 Subject: [PATCH 1/6] feat: widget bounciness --- .../src/components/DocsGPTWidget.tsx | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/extensions/react-widget/src/components/DocsGPTWidget.tsx b/extensions/react-widget/src/components/DocsGPTWidget.tsx index 699803598..6588ccc5c 100644 --- a/extensions/react-widget/src/components/DocsGPTWidget.tsx +++ b/extensions/react-widget/src/components/DocsGPTWidget.tsx @@ -99,7 +99,7 @@ const WidgetContainer = styled.div<{ modal?: boolean, isOpen?: boolean }>` transform: scale(1.02); } 100% { - transform: scale(0); + transform: scale(0.45); } } `; @@ -127,7 +127,7 @@ const StyledContainer = styled.div` overflow: auto; } `; -const FloatingButton = styled.div<{ bgcolor: string, hidden: boolean }>` +const FloatingButton = styled.div<{ bgcolor: string, hidden: boolean, isAnimatingButton: boolean }>` position: fixed; display: ${props => props.hidden ? "none" : "flex"}; z-index: 500; @@ -144,9 +144,22 @@ const FloatingButton = styled.div<{ bgcolor: string, hidden: boolean }>` background: ${props => props.bgcolor}; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); cursor: pointer; + animation: ${props => props.isAnimatingButton ? 'scaleAnimation 200ms forwards' : 'none'}; &:hover { - transform: scale(1.1); - transition: transform 0.2s ease-in-out; + transform: scale(1.1); + transition: transform 0.2s ease-in-out; + } + &:not(:hover) { + transition: transform 0.2s ease-in-out; + } + + @keyframes scaleAnimation { + from { + transform: scale(1.2); + } + to { + transform: scale(1); + } } `; const CancelButton = styled.button` @@ -433,6 +446,8 @@ export const DocsGPTWidget = ({ const [conversationId, setConversationId] = React.useState(null) const [open, setOpen] = React.useState(deafultOpen) const [eventInterrupt, setEventInterrupt] = React.useState(false); //click or scroll by user while autoScrolling + const [isAnimatingButton, setIsAnimatingButton] = React.useState(false); + const [isFloatingButtonVisible, setIsFloatingButtonVisible] = React.useState(true); const isBubbleHovered = useRef(false) const widgetRef = useRef(null) const endMessageRef = React.useRef(null); @@ -549,14 +564,17 @@ export const DocsGPTWidget = ({ const handleClose = () => { setOpen(false); size !== "large" ? setTimeout(() => { - if (widgetRef.current) - widgetRef.current.style.display = "none" + if (widgetRef.current) widgetRef.current.style.display = "none"; + setIsFloatingButtonVisible(true); + setIsAnimatingButton(true); + setTimeout(() => setIsAnimatingButton(false), 200); }, 250) : widgetRef.current && (widgetRef.current.style.display = "none") }; const handleOpen = () => { setOpen(true); + setIsFloatingButtonVisible(false); if (widgetRef.current) widgetRef.current.style.display = 'block' } @@ -570,7 +588,7 @@ export const DocsGPTWidget = ({ {open && size === 'large' && } - - { + {
From ba1c0ab6fb93658b2575388b1b76fe90bcba19c1 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 10 Nov 2024 16:36:14 +0000 Subject: [PATCH 3/6] fix: large closing --- extensions/react-widget/src/components/DocsGPTWidget.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/react-widget/src/components/DocsGPTWidget.tsx b/extensions/react-widget/src/components/DocsGPTWidget.tsx index e3cf72245..c74d658f6 100644 --- a/extensions/react-widget/src/components/DocsGPTWidget.tsx +++ b/extensions/react-widget/src/components/DocsGPTWidget.tsx @@ -577,7 +577,7 @@ export const DocsGPTWidget = ({ setTimeout(() => setIsAnimatingButton(false), 200); }, 250) : - widgetRef.current && (widgetRef.current.style.display = "none") + widgetRef.current && (widgetRef.current.style.display = "none") && setIsFloatingButtonVisible(true); }; const handleOpen = () => { setOpen(true); From dfc3cdd5d471edcf1312eccfe8fdfea0fb7864ce Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 10 Nov 2024 21:53:10 +0000 Subject: [PATCH 4/6] fix: open cooler morph --- .../src/components/DocsGPTWidget.tsx | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/extensions/react-widget/src/components/DocsGPTWidget.tsx b/extensions/react-widget/src/components/DocsGPTWidget.tsx index c74d658f6..9a4845275 100644 --- a/extensions/react-widget/src/components/DocsGPTWidget.tsx +++ b/extensions/react-widget/src/components/DocsGPTWidget.tsx @@ -81,7 +81,7 @@ const WidgetContainer = styled.div<{ modal?: boolean, isOpen?: boolean }>` text-align: left; @keyframes createBox { 0% { - transform: scale(0.5); + transform: scale(0.6); } 90% { transform: scale(1.02); @@ -107,31 +107,47 @@ const StyledContainer = styled.div<{ isOpen: boolean }>` all: initial; max-height: ${(props) => props.theme.dimensions.maxHeight}; max-width: ${(props) => props.theme.dimensions.maxWidth}; - height: ${(props) => props.theme.dimensions.height}; - width: ${(props) => props.theme.dimensions.width}; - ${({ isOpen }) => - !isOpen && - ` - width: 200px; - height: 100px; - border-radius: 50%; - `} - display: flex; position: relative; flex-direction: column; justify-content: space-between; bottom: 0; left: 0; - border-radius: 12px; background-color: ${props => props.theme.primary.bg}; font-family: sans-serif; + display: flex; + border-radius: 12px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 2px 4px rgba(0, 0, 0, 0.1); - transition: all 0.3s ease-in-out; - padding: 26px 26px 0px 26px ; + padding: 26px 26px 0px 26px; + animation: ${({ isOpen }) => + isOpen + ? 'openContainer 150ms ease-in forwards' + : 'closeContainer 250ms ease-in forwards'}; + @keyframes openContainer { + 0% { + width: 200px; + height: 100px; + } + 100% { + width: ${(props) => props.theme.dimensions.width}; + height: ${(props) => props.theme.dimensions.height}; + border-radius: 12px; + } + } + @keyframes closeContainer { + 0% { + width: ${(props) => props.theme.dimensions.width}; + height: ${(props) => props.theme.dimensions.height}; + border-radius: 12px; + } + 100% { + width: 200px; + height: 100px; + } + } @media only screen and (max-width: 768px) { - max-height: 100vh ; - max-width: 80vw; - overflow: auto; + max-height: 100vh; + max-width: 80vw; + overflow: auto; } `; const FloatingButton = styled.div<{ bgcolor: string, hidden: boolean, isAnimatingButton: boolean }>` From e475a4cc7c1f49d3e662cc144e1f1260a1d6700e Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 10 Nov 2024 22:11:20 +0000 Subject: [PATCH 5/6] fix: large size animation --- .../src/components/DocsGPTWidget.tsx | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/extensions/react-widget/src/components/DocsGPTWidget.tsx b/extensions/react-widget/src/components/DocsGPTWidget.tsx index 9a4845275..c9afebf60 100644 --- a/extensions/react-widget/src/components/DocsGPTWidget.tsx +++ b/extensions/react-widget/src/components/DocsGPTWidget.tsx @@ -112,16 +112,20 @@ const StyledContainer = styled.div<{ isOpen: boolean }>` justify-content: space-between; bottom: 0; left: 0; - background-color: ${props => props.theme.primary.bg}; + background-color: ${(props) => props.theme.primary.bg}; font-family: sans-serif; display: flex; border-radius: 12px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 2px 4px rgba(0, 0, 0, 0.1); padding: 26px 26px 0px 26px; - animation: ${({ isOpen }) => - isOpen - ? 'openContainer 150ms ease-in forwards' - : 'closeContainer 250ms ease-in forwards'}; + animation: ${({ isOpen, theme }) => + theme.dimensions.size === 'large' + ? isOpen + ? 'fadeIn 150ms ease-in forwards' + : 'fadeOut 150ms ease-in forwards' + : isOpen + ? 'openContainer 150ms ease-in forwards' + : 'closeContainer 250ms ease-in forwards'}; @keyframes openContainer { 0% { width: 200px; @@ -144,6 +148,28 @@ const StyledContainer = styled.div<{ isOpen: boolean }>` height: 100px; } } + @keyframes fadeIn { + from { + opacity: 0; + width: ${(props) => props.theme.dimensions.width}; + height: ${(props) => props.theme.dimensions.height}; + transform: scale(0.9); + } + to { + opacity: 1; + transform: scale(1); + width: ${(props) => props.theme.dimensions.width}; + height: ${(props) => props.theme.dimensions.height}; + } + } + @keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } + } @media only screen and (max-width: 768px) { max-height: 100vh; max-width: 80vw; From c6dc1675d89f74ddec6f230b24c6883b54965ea5 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 10 Nov 2024 22:13:48 +0000 Subject: [PATCH 6/6] fix: smoother animation on large modal close --- extensions/react-widget/src/components/DocsGPTWidget.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/extensions/react-widget/src/components/DocsGPTWidget.tsx b/extensions/react-widget/src/components/DocsGPTWidget.tsx index c9afebf60..d01e1635f 100644 --- a/extensions/react-widget/src/components/DocsGPTWidget.tsx +++ b/extensions/react-widget/src/components/DocsGPTWidget.tsx @@ -165,9 +165,14 @@ const StyledContainer = styled.div<{ isOpen: boolean }>` @keyframes fadeOut { from { opacity: 1; + width: ${(props) => props.theme.dimensions.width}; + height: ${(props) => props.theme.dimensions.height}; } to { opacity: 0; + transform: scale(0.9); + width: ${(props) => props.theme.dimensions.width}; + height: ${(props) => props.theme.dimensions.height}; } } @media only screen and (max-width: 768px) { @@ -612,14 +617,12 @@ export const DocsGPTWidget = ({ }; const handleClose = () => { setOpen(false); - size !== "large" ? setTimeout(() => { + setTimeout(() => { if (widgetRef.current) widgetRef.current.style.display = "none"; setIsFloatingButtonVisible(true); setIsAnimatingButton(true); setTimeout(() => setIsAnimatingButton(false), 200); }, 250) - : - widgetRef.current && (widgetRef.current.style.display = "none") && setIsFloatingButtonVisible(true); }; const handleOpen = () => { setOpen(true);