diff --git a/pages/course/tooltip/tooltip-component.tsx b/pages/course/tooltip/tooltip-component.tsx new file mode 100644 index 00000000..1624c271 --- /dev/null +++ b/pages/course/tooltip/tooltip-component.tsx @@ -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 ( + l.link === nextURL)} + previousTocItem={lessonList.find((l) => l.link === previousURL)} + > + +

+ Let's see how to create a Tooltip component that can + be re-used in your codebase when a tooltip is required. +

+ + } + /> +

Minimal tooltip example

+

+ 💾 InteractionData: where the tooltip info is stored. +

+

+ Our tooltip component is going to expect one property only: an object of + type InteractionData. +

+

+ 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) +

+ +

+ But we could put many other things! A color for the border, some values + to display, a link to an image.. Anything really. +

+

🦴 Tooltip component skeleton

+

+ The Tooltip component uses some props of type TooltipProps, which is + basically just an interactionData object. +

+

+ If this object is undefined (user is not hovering anything), then we do + not return anything; +

+ { + + if (!interactionData) { + return null; + } + + ... Do something with interactionData otherwise +}; + + `.trim()} + /> +

🍔 The meat

+

+ Now, we just need to return something based on the{' '} + interactionData information. +

+

+ Do not forget to use xPos and yPos to put the + tooltip at the right position! +

+ + {name} + +); + + `.trim()} + /> + + {/* - + - + - + - + - + - + - + - + */} +

+
+

+

Exercises

+ Your first tooltip!, + content: , + }, + { + title: Pass more information, + content: , + }, + ]} + /> +
+ ); +} + +const exercices: Exercise[] = [ + { + whyItMatters: ( + <> +

+ Let's start with a very simple tooltip. We'll see how to improve it + later on. +

+ + ), + toDo: ( + + ), + practiceSandbox: 'exercise/TooltipFirstPractice', + solutionSandbox: 'exercise/TooltipFirstSolution', + }, + { + whyItMatters: ( + <> +

+ Keep in mind that you can pass absolutely any information to the + tooltip component to display it. +

+

+ Passing styling information like the marker color to make the tooltip + fit the style is a very good practice. +

+ + ), + toDo: ( + + ), + practiceSandbox: 'exercise/TooltipAddContentPractice', + solutionSandbox: 'exercise/TooltipAddContentSolution', + }, +]; diff --git a/viz/exercise/TooltipAddContentPractice/Graph.tsx b/viz/exercise/TooltipAddContentPractice/Graph.tsx new file mode 100644 index 00000000..d8e6d0de --- /dev/null +++ b/viz/exercise/TooltipAddContentPractice/Graph.tsx @@ -0,0 +1,31 @@ +import { Tooltip } from './Tooltip'; + +const width = 500; +const height = 300; + +export const Graph = () => { + return ( +
+ {/* SVG layer */} + + + + + {/* Tooltip Layer */} +
+ +
+
+ ); +}; diff --git a/viz/exercise/TooltipAddContentPractice/Tooltip.tsx b/viz/exercise/TooltipAddContentPractice/Tooltip.tsx new file mode 100644 index 00000000..d5f00e02 --- /dev/null +++ b/viz/exercise/TooltipAddContentPractice/Tooltip.tsx @@ -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 ( +
+ {name} +
+ ); +}; diff --git a/viz/exercise/TooltipAddContentPractice/index.js b/viz/exercise/TooltipAddContentPractice/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/TooltipAddContentPractice/index.js @@ -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(, rootElement); diff --git a/viz/exercise/TooltipAddContentPractice/package.json b/viz/exercise/TooltipAddContentPractice/package.json new file mode 100644 index 00000000..ac08117a --- /dev/null +++ b/viz/exercise/TooltipAddContentPractice/package.json @@ -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" + ] +} diff --git a/viz/exercise/TooltipAddContentPractice/tooltip.module.css b/viz/exercise/TooltipAddContentPractice/tooltip.module.css new file mode 100644 index 00000000..76691eeb --- /dev/null +++ b/viz/exercise/TooltipAddContentPractice/tooltip.module.css @@ -0,0 +1,9 @@ +.tooltip { + position: absolute; + background-color: black; + color: white; + border-radius: 4px; + padding: 4px; + max-width: 100px; + font-size: 14px; +} diff --git a/viz/exercise/TooltipAddContentSolution/Graph.tsx b/viz/exercise/TooltipAddContentSolution/Graph.tsx new file mode 100644 index 00000000..04ec3e69 --- /dev/null +++ b/viz/exercise/TooltipAddContentSolution/Graph.tsx @@ -0,0 +1,38 @@ +import { Tooltip } from './Tooltip'; + +const width = 500; +const height = 300; + +export const Graph8 = () => { + return ( +
+ {/* SVG layer */} + + + + + {/* Tooltip Layer */} +
+ +
+
+ ); +}; diff --git a/viz/exercise/TooltipAddContentSolution/Tooltip.tsx b/viz/exercise/TooltipAddContentSolution/Tooltip.tsx new file mode 100644 index 00000000..a170cf3d --- /dev/null +++ b/viz/exercise/TooltipAddContentSolution/Tooltip.tsx @@ -0,0 +1,37 @@ +import styles from './tooltip.module.css'; + +type InteractionData = { + xPos: number; + yPos: number; + name: string; + xValue: number; + yValue: number; + color: string; +}; + +type TooltipProps = { + interactionData: InteractionData | undefined; +}; + +export const Tooltip = ({ interactionData }: TooltipProps) => { + if (!interactionData) { + return null; + } + + const { xPos, yPos, name, xValue, yValue, color } = interactionData; + + return ( +
+ {name} +

{'x: ' + xValue}

+

{'y: ' + yValue}

+
+ ); +}; diff --git a/viz/exercise/TooltipAddContentSolution/index.js b/viz/exercise/TooltipAddContentSolution/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/TooltipAddContentSolution/index.js @@ -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(, rootElement); diff --git a/viz/exercise/TooltipAddContentSolution/package.json b/viz/exercise/TooltipAddContentSolution/package.json new file mode 100644 index 00000000..ac08117a --- /dev/null +++ b/viz/exercise/TooltipAddContentSolution/package.json @@ -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" + ] +} diff --git a/viz/exercise/TooltipAddContentSolution/tooltip.module.css b/viz/exercise/TooltipAddContentSolution/tooltip.module.css new file mode 100644 index 00000000..5dba63cc --- /dev/null +++ b/viz/exercise/TooltipAddContentSolution/tooltip.module.css @@ -0,0 +1,11 @@ +.tooltip { + position: absolute; + background-color: black; + color: white; + border: solid; + border-width: 3px; + border-radius: 4px; + padding: 4px; + max-width: 100px; + font-size: 14px; +} diff --git a/viz/exercise/TooltipFirstPractice/Graph.tsx b/viz/exercise/TooltipFirstPractice/Graph.tsx new file mode 100644 index 00000000..9427d8ac --- /dev/null +++ b/viz/exercise/TooltipFirstPractice/Graph.tsx @@ -0,0 +1,17 @@ +// import { Tooltip } from './Tooltip'; + +const width = 500; +const height = 300; + +export const Graph = () => { + return ( +
+ {/* SVG layer */} + + + + + {/* Tooltip Layer: TODO */} +
+ ); +}; diff --git a/viz/exercise/TooltipFirstPractice/index.js b/viz/exercise/TooltipFirstPractice/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/TooltipFirstPractice/index.js @@ -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(, rootElement); diff --git a/viz/exercise/TooltipFirstPractice/package.json b/viz/exercise/TooltipFirstPractice/package.json new file mode 100644 index 00000000..ac08117a --- /dev/null +++ b/viz/exercise/TooltipFirstPractice/package.json @@ -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" + ] +} diff --git a/viz/exercise/TooltipFirstSolution/Graph.tsx b/viz/exercise/TooltipFirstSolution/Graph.tsx new file mode 100644 index 00000000..d8e6d0de --- /dev/null +++ b/viz/exercise/TooltipFirstSolution/Graph.tsx @@ -0,0 +1,31 @@ +import { Tooltip } from './Tooltip'; + +const width = 500; +const height = 300; + +export const Graph = () => { + return ( +
+ {/* SVG layer */} + + + + + {/* Tooltip Layer */} +
+ +
+
+ ); +}; diff --git a/viz/exercise/TooltipFirstSolution/Tooltip.tsx b/viz/exercise/TooltipFirstSolution/Tooltip.tsx new file mode 100644 index 00000000..d5f00e02 --- /dev/null +++ b/viz/exercise/TooltipFirstSolution/Tooltip.tsx @@ -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 ( +
+ {name} +
+ ); +}; diff --git a/viz/exercise/TooltipFirstSolution/index.js b/viz/exercise/TooltipFirstSolution/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/TooltipFirstSolution/index.js @@ -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(, rootElement); diff --git a/viz/exercise/TooltipFirstSolution/package.json b/viz/exercise/TooltipFirstSolution/package.json new file mode 100644 index 00000000..ac08117a --- /dev/null +++ b/viz/exercise/TooltipFirstSolution/package.json @@ -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" + ] +} diff --git a/viz/exercise/TooltipFirstSolution/tooltip.module.css b/viz/exercise/TooltipFirstSolution/tooltip.module.css new file mode 100644 index 00000000..76691eeb --- /dev/null +++ b/viz/exercise/TooltipFirstSolution/tooltip.module.css @@ -0,0 +1,9 @@ +.tooltip { + position: absolute; + background-color: black; + color: white; + border-radius: 4px; + padding: 4px; + max-width: 100px; + font-size: 14px; +}