-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
606 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
import React from 'react'; | ||
import TitleAndDescription from '@/component/TitleAndDescription'; | ||
import { LayoutCourse } from '@/component/LayoutCourse'; | ||
import { lessonList } from '@/util/lessonList'; | ||
import { CodeSandbox } from '@/component/CodeSandbox'; | ||
import Link from 'next/link'; | ||
import { Badge } from '@/component/UI/badge'; | ||
import { ExerciseAccordion } from '@/component/ExerciseAccordion'; | ||
import { | ||
Exercise, | ||
ExerciseDoubleSandbox, | ||
} from '@/component/ExerciseDoubleSandbox'; | ||
import { Caption } from '@/component/UI/Caption'; | ||
import { Sidenote } from '@/component/SideNote'; | ||
import { ScatterplotBasicDemo } from '@/viz/ScatterplotBasic/ScatterplotBasicDemo'; | ||
import { ScatterplotClimateCrisisDemo } from '@/viz/ScatterplotClimateCrisis/ScatterplotClimateCrisisDemo'; | ||
import { ChartOrSandbox } from '@/component/ChartOrSandbox'; | ||
import { TakeHome } from '@/component/TakeHome'; | ||
import { CodeBlock } from '@/component/UI/CodeBlock'; | ||
import { Graph2 } from '@/viz/exercise/TooltipFirstSolution/Graph'; | ||
import { Graph8 } from '@/viz/exercise/TooltipAddContentSolution/Graph'; | ||
|
||
const previousURL = '/course/tooltip/introduction'; | ||
const currentURL = '/course/tooltip/tooltip-component'; | ||
const nextURL = '/course/tooltip/display-on-hover'; | ||
const seoDescription = ''; | ||
|
||
export default function Home() { | ||
const currentLesson = lessonList.find((l) => l.link === currentURL); | ||
|
||
if (!currentLesson) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<LayoutCourse | ||
title={currentLesson.name} | ||
seoDescription={seoDescription} | ||
nextTocItem={lessonList.find((l) => l.link === nextURL)} | ||
previousTocItem={lessonList.find((l) => l.link === previousURL)} | ||
> | ||
<TitleAndDescription | ||
title={currentLesson.name} | ||
lessonStatus={currentLesson.status} | ||
readTime={currentLesson.readTime} | ||
selectedLesson={currentLesson} | ||
description={ | ||
<> | ||
<p> | ||
Let's see how to create a <code>Tooltip</code> component that can | ||
be re-used in your codebase when a tooltip is required. | ||
</p> | ||
</> | ||
} | ||
/> | ||
<h2>Minimal tooltip example</h2> | ||
<h3> | ||
💾 <code>InteractionData</code>: where the tooltip info is stored. | ||
</h3> | ||
<p> | ||
Our tooltip component is going to expect one property only: an object of | ||
type InteractionData. | ||
</p> | ||
<p> | ||
This object stores everything we need to build a tooltip. At the very | ||
least we need some positions (xPos and yPos) and a title to display | ||
(name here) | ||
</p> | ||
<CodeBlock | ||
code={` | ||
type InteractionData = { | ||
xPos: number; | ||
yPos: number; | ||
name: string; | ||
} | ||
type TooltipProps = { | ||
interactionData: InteractionData | undefined; | ||
}; | ||
`.trim()} | ||
/> | ||
<p> | ||
But we could put many other things! A color for the border, some values | ||
to display, a link to an image.. Anything really. | ||
</p> | ||
<h3>🦴 Tooltip component skeleton</h3> | ||
<p> | ||
The Tooltip component uses some props of type TooltipProps, which is | ||
basically just an interactionData object. | ||
</p> | ||
<p> | ||
If this object is undefined (user is not hovering anything), then we do | ||
not return anything; | ||
</p> | ||
<CodeBlock | ||
code={` | ||
// Tooltip.tsx | ||
export const Tooltip = ({ interactionData }: TooltipProps) => { | ||
if (!interactionData) { | ||
return null; | ||
} | ||
... Do something with interactionData otherwise | ||
}; | ||
`.trim()} | ||
/> | ||
<h3>🍔 The meat</h3> | ||
<p> | ||
Now, we just need to return something based on the{' '} | ||
<code>interactionData</code> information. | ||
</p> | ||
<p> | ||
Do not forget to use <code>xPos</code> and <code>yPos</code> to put the | ||
tooltip at the right position! | ||
</p> | ||
<CodeBlock | ||
code={` | ||
const { xPos, yPos, name } = interactionData; | ||
return ( | ||
<div | ||
style={{ | ||
left: xPos, | ||
top: yPos, | ||
}} | ||
> | ||
<b>{name}</b> | ||
</div> | ||
); | ||
`.trim()} | ||
/> | ||
|
||
{/* - | ||
- | ||
- | ||
- | ||
- | ||
- | ||
- | ||
- | ||
*/} | ||
<p> | ||
<br /> | ||
</p> | ||
<h2>Exercises</h2> | ||
<ExerciseAccordion | ||
localStorageId={currentLesson.link} | ||
exercises={[ | ||
{ | ||
title: <span>Your first tooltip!</span>, | ||
content: <ExerciseDoubleSandbox exercise={exercices[0]} />, | ||
}, | ||
{ | ||
title: <span>Pass more information</span>, | ||
content: <ExerciseDoubleSandbox exercise={exercices[1]} />, | ||
}, | ||
]} | ||
/> | ||
</LayoutCourse> | ||
); | ||
} | ||
|
||
const exercices: Exercise[] = [ | ||
{ | ||
whyItMatters: ( | ||
<> | ||
<p> | ||
Let's start with a very simple tooltip. We'll see how to improve it | ||
later on. | ||
</p> | ||
</> | ||
), | ||
toDo: ( | ||
<ul> | ||
<li>The Sandbox has a circle rendered in SVG.</li> | ||
<li>Create an absolute positionned div on top of the SVG area</li> | ||
<li> | ||
Create a <code>Tooltip</code> component in a <code>Tooltip.tsx</code>{' '} | ||
file. | ||
</li> | ||
<li> | ||
In this div, render a small div exactly where the circle is with one | ||
word in it: <code>hello</code> | ||
</li> | ||
</ul> | ||
), | ||
practiceSandbox: 'exercise/TooltipFirstPractice', | ||
solutionSandbox: 'exercise/TooltipFirstSolution', | ||
}, | ||
{ | ||
whyItMatters: ( | ||
<> | ||
<p> | ||
Keep in mind that you can pass absolutely any information to the | ||
tooltip component to display it. | ||
</p> | ||
<p> | ||
Passing styling information like the marker color to make the tooltip | ||
fit the style is a very good practice. | ||
</p> | ||
</> | ||
), | ||
toDo: ( | ||
<ul> | ||
<li> | ||
Pass 3 more information to the <code>Tooltip</code> component:{' '} | ||
<code>xValue</code>, <code>yValue</code> and color (use{' '} | ||
<code>green</code>) | ||
</li> | ||
<li> | ||
Use the <code>color</code> to change the tooltip border color | ||
</li> | ||
<li> | ||
Display <code>xValue</code> and <code>yValue</code> in the tooltip | ||
body. | ||
</li> | ||
</ul> | ||
), | ||
practiceSandbox: 'exercise/TooltipAddContentPractice', | ||
solutionSandbox: 'exercise/TooltipAddContentSolution', | ||
}, | ||
]; |
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,31 @@ | ||
import { Tooltip } from './Tooltip'; | ||
|
||
const width = 500; | ||
const height = 300; | ||
|
||
export const Graph = () => { | ||
return ( | ||
<div style={{ position: 'relative' }}> | ||
{/* SVG layer */} | ||
<svg width={width} height={height}> | ||
<circle cx={width / 2} cy={height / 2} r={30} fill="red" /> | ||
</svg> | ||
|
||
{/* Tooltip Layer */} | ||
<div | ||
style={{ | ||
position: 'absolute', | ||
width, | ||
height, | ||
top: 0, | ||
left: 0, | ||
pointerEvents: 'none', | ||
}} | ||
> | ||
<Tooltip | ||
interactionData={{ xPos: width / 2, yPos: height / 2, name: 'hello' }} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
}; |
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,31 @@ | ||
import styles from './tooltip.module.css'; | ||
|
||
type InteractionData = { | ||
xPos: number; | ||
yPos: number; | ||
name: string; | ||
}; | ||
|
||
type TooltipProps = { | ||
interactionData: InteractionData | undefined; | ||
}; | ||
|
||
export const Tooltip = ({ interactionData }: TooltipProps) => { | ||
if (!interactionData) { | ||
return null; | ||
} | ||
|
||
const { xPos, yPos, name } = interactionData; | ||
|
||
return ( | ||
<div | ||
className={styles.tooltip} | ||
style={{ | ||
left: xPos, | ||
top: yPos, | ||
}} | ||
> | ||
<b className={styles.title}>{name}</b> | ||
</div> | ||
); | ||
}; |
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,6 @@ | ||
// File used to render something in codesandbox only | ||
import ReactDOM from 'react-dom'; | ||
import { Graph } from './Graph'; | ||
|
||
const rootElement = document.getElementById('root'); | ||
ReactDOM.render(<Graph />, rootElement); |
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,28 @@ | ||
{ | ||
"name": "pie-chart-basic", | ||
"version": "1.0.0", | ||
"description": "", | ||
"keywords": [], | ||
"main": "index.js", | ||
"dependencies": { | ||
"react": "17.0.2", | ||
"react-dom": "17.0.2", | ||
"react-scripts": "4.0.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/runtime": "7.13.8", | ||
"typescript": "4.1.3" | ||
}, | ||
"scripts": { | ||
"start": "react-scripts start", | ||
"build": "react-scripts build", | ||
"test": "react-scripts test --env=jsdom", | ||
"eject": "react-scripts eject" | ||
}, | ||
"browserslist": [ | ||
">0.2%", | ||
"not dead", | ||
"not ie <= 11", | ||
"not op_mini all" | ||
] | ||
} |
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,9 @@ | ||
.tooltip { | ||
position: absolute; | ||
background-color: black; | ||
color: white; | ||
border-radius: 4px; | ||
padding: 4px; | ||
max-width: 100px; | ||
font-size: 14px; | ||
} |
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,38 @@ | ||
import { Tooltip } from './Tooltip'; | ||
|
||
const width = 500; | ||
const height = 300; | ||
|
||
export const Graph8 = () => { | ||
return ( | ||
<div style={{ position: 'relative' }}> | ||
{/* SVG layer */} | ||
<svg width={width} height={height}> | ||
<circle cx={width / 2} cy={height / 2} r={30} fill="red" /> | ||
</svg> | ||
|
||
{/* Tooltip Layer */} | ||
<div | ||
style={{ | ||
position: 'absolute', | ||
width, | ||
height, | ||
top: 0, | ||
left: 0, | ||
pointerEvents: 'none', | ||
}} | ||
> | ||
<Tooltip | ||
interactionData={{ | ||
xPos: width / 2, | ||
yPos: height / 2, | ||
name: 'hello', | ||
xValue: width / 2, | ||
yValue: height / 2, | ||
color: 'green', | ||
}} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
}; |
Oops, something went wrong.