From 7810621046f39e1e32bb722b6ee0372e22ae16e1 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 19 Jul 2020 18:05:11 -0700 Subject: [PATCH 1/4] scroll to top on new level Signed-off-by: shmck --- web-app/src/containers/Tutorial/components/Level.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index a7ef0415..f0f1189b 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -39,23 +39,22 @@ type Props = { } const Level = ({ level }: Props) => { - const pageBottomRef = React.useRef(null) - const scrollToBottom = () => { + const pageTopRef = React.useRef(null) + const scrollToTop = () => { // @ts-ignore - pageBottomRef.current.scrollIntoView({ behavior: 'smooth' }) + pageTopRef.current.scrollIntoView({ behavior: 'smooth' }) } - React.useEffect(scrollToBottom, [level.id]) + React.useEffect(scrollToTop, [level.id]) return (
+
{level.content.length && level.steps.length ?
: null} - -
) From aa2a750d51f50ea8dd8a1f9ceeaa0042513c6c34 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 19 Jul 2020 18:13:50 -0700 Subject: [PATCH 2/4] refactor scroll content Signed-off-by: shmck --- .../containers/Tutorial/components/Level.tsx | 8 ------ .../Tutorial/components/ScrollContent.tsx | 28 +++++++++++++++++++ web-app/src/containers/Tutorial/index.tsx | 7 ++++- 3 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 web-app/src/containers/Tutorial/components/ScrollContent.tsx diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index f0f1189b..a4839d06 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -39,16 +39,8 @@ type Props = { } const Level = ({ level }: Props) => { - const pageTopRef = React.useRef(null) - const scrollToTop = () => { - // @ts-ignore - pageTopRef.current.scrollIntoView({ behavior: 'smooth' }) - } - React.useEffect(scrollToTop, [level.id]) - return (
-
diff --git a/web-app/src/containers/Tutorial/components/ScrollContent.tsx b/web-app/src/containers/Tutorial/components/ScrollContent.tsx new file mode 100644 index 00000000..b1b83902 --- /dev/null +++ b/web-app/src/containers/Tutorial/components/ScrollContent.tsx @@ -0,0 +1,28 @@ +import * as React from 'react' + +type Props = { + item: string + children: React.ReactElement +} + +const ScrollContent = ({ item, children }: Props) => { + const pageTopRef: React.RefObject = React.useRef(null) + + const pageBottomRef: React.RefObject = React.useRef(null) + + const scrollToTop = () => { + pageTopRef.current.scrollIntoView({ behavior: 'smooth' }) + } + + React.useEffect(scrollToTop, [item]) + + return ( + <> +
+ {children} +
+ + ) +} + +export default ScrollContent diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 3e784fa2..83525726 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -13,6 +13,7 @@ import { DISPLAY_RUN_TEST_BUTTON } from '../../environment' import formatLevels from './formatLevels' import Reset from './components/Reset' import Continue from './components/Continue' +import ScrollContent from './components/ScrollContent' const styles = { header: { @@ -120,7 +121,11 @@ const TutorialPage = (props: PageProps) => { {tutorial.summary.title}
- {page === 'level' && } + {page === 'level' && ( + + + + )} {page === 'review' && } {/* {page === 'settings' && } */}
From 96ef687f2aa363c6755a6fbdfee344923eb7f399 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 19 Jul 2020 18:44:05 -0700 Subject: [PATCH 3/4] detect page bottom Signed-off-by: shmck --- .../containers/Tutorial/components/Level.tsx | 1 - .../Tutorial/components/ScrollContent.tsx | 48 ++++++++++++++++++- web-app/src/containers/Tutorial/index.tsx | 5 +- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index a4839d06..452001c3 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -15,7 +15,6 @@ const styles = { display: 'flex' as 'flex', flexDirection: 'column' as 'column', padding: 0, - paddingBottom: '5rem', }, text: { diff --git a/web-app/src/containers/Tutorial/components/ScrollContent.tsx b/web-app/src/containers/Tutorial/components/ScrollContent.tsx index b1b83902..fe391118 100644 --- a/web-app/src/containers/Tutorial/components/ScrollContent.tsx +++ b/web-app/src/containers/Tutorial/components/ScrollContent.tsx @@ -1,26 +1,70 @@ import * as React from 'react' +const styles = { + scrollIndicator: { + position: 'fixed' as 'fixed', + bottom: '2rem', + }, +} + type Props = { item: string children: React.ReactElement } const ScrollContent = ({ item, children }: Props) => { + const [showScrollIndicator, setShowScrollIndicator] = React.useState(false) const pageTopRef: React.RefObject = React.useRef(null) - const pageBottomRef: React.RefObject = React.useRef(null) const scrollToTop = () => { pageTopRef.current.scrollIntoView({ behavior: 'smooth' }) + let hideTimeout: any + + // API to detect if an HTML element is in the viewport + // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API + const observer = new IntersectionObserver( + ([entry]) => { + // show a scroll indicator to let the user know + // they can scroll down for more + const isVisible = !entry.isIntersecting + setShowScrollIndicator(isVisible) + if (!isVisible) { + hideTimeout = setTimeout(() => { + setShowScrollIndicator(false) + }, 3000) + } + }, + { + rootMargin: '0px', + }, + ) + + const showTimeout = setTimeout(() => { + // detect if bottom of page is visible + + if (pageBottomRef.current) { + observer.observe(pageBottomRef.current) + } + }, 300) + return () => { + // cleanup timeouts & subs + observer.unobserve(pageBottomRef.current) + clearTimeout(showTimeout) + clearTimeout(hideTimeout) + } } React.useEffect(scrollToTop, [item]) + console.log(`showScrollIndicator = ${showScrollIndicator}`) + return ( <>
{children} -
+ {showScrollIndicator ?
MORE
: null} +
BOTTOM
) } diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 83525726..857b96c4 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -16,6 +16,9 @@ import Continue from './components/Continue' import ScrollContent from './components/ScrollContent' const styles = { + page: { + paddingBottom: '5rem', + }, header: { display: 'flex' as 'flex', alignItems: 'center', @@ -113,7 +116,7 @@ const TutorialPage = (props: PageProps) => { return (
-
+
setMenuVisible(!menuVisible)}> From 4e6b79cc60e05c7754874e4ecfa103a7b7200ca9 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 19 Jul 2020 19:44:12 -0700 Subject: [PATCH 4/4] add scroll indicator Signed-off-by: shmck --- .../Tutorial/components/ScrollContent.tsx | 45 +++++++++++-------- web-app/src/containers/Tutorial/index.tsx | 1 + web-app/stories/Tutorial.stories.tsx | 7 +-- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/ScrollContent.tsx b/web-app/src/containers/Tutorial/components/ScrollContent.tsx index fe391118..2354d1c9 100644 --- a/web-app/src/containers/Tutorial/components/ScrollContent.tsx +++ b/web-app/src/containers/Tutorial/components/ScrollContent.tsx @@ -1,9 +1,17 @@ import * as React from 'react' +import { Icon } from '@alifd/next' const styles = { scrollIndicator: { position: 'fixed' as 'fixed', - bottom: '2rem', + display: 'flex' as 'flex', + justifyContent: 'center' as 'center', + alignItems: 'center' as 'center', + left: 'calc(50% - 8px)', + borderRadius: '100%', + zIndex: 100, + bottom: '2.2rem', + boxShadow: '0 0 0 5px transparent', }, } @@ -13,7 +21,7 @@ type Props = { } const ScrollContent = ({ item, children }: Props) => { - const [showScrollIndicator, setShowScrollIndicator] = React.useState(false) + const [showScrollIndicator, setShowScrollIndicator] = React.useState<'UNDETERMINED' | 'SHOW' | 'HIDE'>('UNDETERMINED') const pageTopRef: React.RefObject = React.useRef(null) const pageBottomRef: React.RefObject = React.useRef(null) @@ -27,17 +35,16 @@ const ScrollContent = ({ item, children }: Props) => { ([entry]) => { // show a scroll indicator to let the user know // they can scroll down for more - const isVisible = !entry.isIntersecting - setShowScrollIndicator(isVisible) - if (!isVisible) { - hideTimeout = setTimeout(() => { - setShowScrollIndicator(false) - }, 3000) + const isVisible = entry.isIntersecting + if (!isVisible && showScrollIndicator === 'UNDETERMINED') { + setShowScrollIndicator('SHOW') } + hideTimeout = setTimeout(() => { + setShowScrollIndicator('HIDE') + observer.unobserve(pageBottomRef.current) + }, 2000) }, - { - rootMargin: '0px', - }, + { rootMargin: '0px' }, ) const showTimeout = setTimeout(() => { @@ -46,7 +53,7 @@ const ScrollContent = ({ item, children }: Props) => { if (pageBottomRef.current) { observer.observe(pageBottomRef.current) } - }, 300) + }, 600) return () => { // cleanup timeouts & subs observer.unobserve(pageBottomRef.current) @@ -57,15 +64,17 @@ const ScrollContent = ({ item, children }: Props) => { React.useEffect(scrollToTop, [item]) - console.log(`showScrollIndicator = ${showScrollIndicator}`) - return ( - <> +
{children} - {showScrollIndicator ?
MORE
: null} -
BOTTOM
- + {showScrollIndicator === 'SHOW' ? ( +
+ +
+ ) : null} +
+
) } diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 857b96c4..5b884fb8 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -51,6 +51,7 @@ const styles = { left: 0, right: 0, color: 'white', + zIndex: 1000, }, processes: { padding: '0 1rem', diff --git a/web-app/stories/Tutorial.stories.tsx b/web-app/stories/Tutorial.stories.tsx index 044feddc..a44bcbf1 100644 --- a/web-app/stories/Tutorial.stories.tsx +++ b/web-app/stories/Tutorial.stories.tsx @@ -36,7 +36,8 @@ const context: Partial = { id: '1', title: 'First Level', summary: 'A summary of the first level', - content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + content: + 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!\nShould support markdown test\n ```js\nvar a = 1\n```\nwhew it works!\nShould support markdown test\n ```js\nvar a = 1\n```\nwhew it works!\nShould support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', setup: null, status: 'COMPLETE' as 'COMPLETE', steps: [ @@ -147,6 +148,6 @@ storiesOf('Tutorial', module) position: { levelId: '1', stepId: '1.2' }, progress: { levels: {}, steps: {}, complete: false }, } - return + return }) - .add('3 step', () => ) + .add('3 step', () => )