Skip to content

Commit

Permalink
Own tooltips implementation based on Floating UI
Browse files Browse the repository at this point in the history
  • Loading branch information
grubersjoe committed Nov 14, 2024
1 parent 8604135 commit e7c1abc
Show file tree
Hide file tree
Showing 17 changed files with 216 additions and 159 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
node_modules/
build/
coverage/
dist/
bundle.html

.env.*
Expand Down
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
build/
dist/
docs/
examples/
pnpm-lock.yaml
3 changes: 2 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export default typescript.config(
...typescript.configs.strictTypeChecked,
{
ignores: [
'build/',
'coverage/',
'dist/',
'docs/',
'examples/',
'eslint.config.mjs',
Expand All @@ -22,6 +22,7 @@ export default typescript.config(
},
{
rules: {
'@typescript-eslint/no-confusing-void-expression': ['error', { ignoreArrowShorthand: true }],
'@typescript-eslint/restrict-template-expressions': 'off',
'no-console': 'error',
},
Expand Down
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
"type": "git",
"url": "git+https://github.com/grubersjoe/react-activity-calendar.git"
},
"main": "build/index.js",
"types": "build/index.d.ts",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"build"
"dist"
],
"scripts": {
"build": "rollup -c",
Expand All @@ -22,13 +22,14 @@
"dev": "storybook dev -p 9000",
"format": "prettier --write .",
"lint": "eslint .",
"postbuild": "dts-bundle-generator src/index.tsx -o build/index.d.ts --no-check --no-banner --external-imports react date-fns",
"postbuild": "dts-bundle-generator src/index.tsx -o dist/index.d.ts --no-check --no-banner --external-imports react date-fns @floating-ui/react",
"prepublishOnly": "pnpm check && pnpm build",
"start": "rollup -c -w",
"test": "jest",
"prepare": "husky"
},
"dependencies": {
"@floating-ui/react-dom": "^2.1.2",
"date-fns": "^4.1.0"
},
"devDependencies": {
Expand Down
25 changes: 20 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const useExternal = process.env.EXTERNAL_DEPS?.toLowerCase() !== 'false';
export default {
input: 'src/index.tsx',
output: {
file: 'build/index.js',
file: 'dist/index.js',
format: 'cjs',
sourcemap: true,
exports: 'named',
Expand All @@ -29,6 +29,7 @@ export default {
},
plugins: [
replace({
preventAssignment: true,
'process.env.NODE_ENV': JSON.stringify('production'),
}),
...(useExternal ? [externalDeps({ includeDependencies: true })] : [commonjs()]),
Expand All @@ -41,7 +42,10 @@ export default {
extensions,
}),
copy({
targets: [{ src: 'src/*.d.ts', dest: 'build/' }],
targets: [
{ src: 'src/*.d.ts', dest: 'dist/' },
{ src: 'src/styles/tooltips.css', dest: 'dist/' },
],
}),
filesize(),
visualizer({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import {
cloneElement,
useEffect,
useMemo,
useRef,
type ForwardedRef,
type ReactElement,
} from 'react';
import { Tooltip as MuiTooltip } from '@mui/material';
import LinkTo from '@storybook/addon-links/react';
import type { Meta, StoryObj } from '@storybook/react';
import { Highlight, themes as prismThemes } from 'prism-react-renderer';
import { Tooltip as ReactTooltip } from 'react-tooltip';
import 'react-tooltip/dist/react-tooltip.css';
import { useEffect, useMemo, useRef, type ForwardedRef, type ReactElement } from 'react';
import { useDarkMode } from 'storybook-dark-mode';
import Container from '../../.storybook/components/Container';
import exampleCustomization from '../../examples/customization?raw';
Expand All @@ -22,11 +13,11 @@ import exampleLabels from '../../examples/labels?raw';
import exampleRef from '../../examples/ref?raw';
import exampleThemeExplicit from '../../examples/themes-explicit?raw';
import exampleTheme from '../../examples/themes?raw';
import exampleTooltipsMui from '../../examples/tooltips-mui?raw';
import exampleTooltipsReact from '../../examples/tooltips-react?raw';
import { generateTestData } from '../lib/calendar';
import type { Theme } from '../types';
import { ActivityCalendar, type Props } from './ActivityCalendar';
import '../styles/tooltips.css';

type Story = StoryObj<Props>;

Expand Down Expand Up @@ -394,78 +385,24 @@ export const EventHandlers: Story = {
};

export const Tooltips: Story = {
args: defaultProps,
args: {
...defaultProps,
tooltips: {
block: activity => `${activity.level} activities on ${activity.date}`,
colorLegend: level => `Activity level ${level + 1}`,
},
},
render: args => {
const data = useMemo(() => generateTestData({ maxLevel: args.maxLevel }), [args.maxLevel]);
return <ActivityCalendar {...args} data={data} />;
},
parameters: {
docs: {
source: {
code: exampleTooltipsReact,
},
},
},
render: args => {
const data = useMemo(() => generateTestData({ maxLevel: args.maxLevel }), [args.maxLevel]);

return (
<Container>
<h1>Tooltips</h1>
<p>
To add a 3rd party tooltip component to the calendar you can use the{' '}
<code>renderBlock</code> prop.
</p>
<p>
<i>
Caveat: unfortunately not all tooltip components can be supported, currently. In the
future, the idea is to render{' '}
<a href="https://martinfowler.com/articles/headless-component.html">headless</a>{' '}
tooltips and let the users decide how to style them.
</i>
</p>

<h2>
<a href="https://mui.com/material-ui/react-tooltip/">Material UI</a>
</h2>
<p>
In the simplest case, each block only needs to be wrapped with a{' '}
<code>&lt;Tooltip/&gt;</code> component, as shown in the following for Material UI.
Additionally, you can add tooltips to the color legend below the calendar using the{' '}
<code>renderColorLegend</code> prop:
</p>
<Source code={exampleTooltipsMui} isDarkMode={useDarkMode()} />
<ActivityCalendar
{...args}
data={data}
renderBlock={(block, activity) => (
<MuiTooltip title={`${activity.count} activities on ${activity.date}`}>
{block}
</MuiTooltip>
)}
renderColorLegend={(block, level) => (
<MuiTooltip title={`Level ${level}`}>{block}</MuiTooltip>
)}
/>
<h2>
<a href="https://github.com/ReactTooltip/react-tooltip">react-tooltip</a>
</h2>
<p>
Some libraries, like <code>react-tooltip</code>, require that additional props are passed
to the block elements. You can achieve this using the <code>React.cloneElement</code>{' '}
function:
</p>
<Source code={exampleTooltipsReact} isDarkMode={useDarkMode()} />
<ActivityCalendar
{...args}
data={data}
renderBlock={(block, activity) =>
cloneElement(block, {
'data-tooltip-id': 'react-tooltip',
'data-tooltip-html': `${activity.count} activities on ${activity.date}`,
})
}
/>
<ReactTooltip id="react-tooltip" />
</Container>
);
},
};

export const WithoutLabels: Story = {
Expand Down
Loading

0 comments on commit e7c1abc

Please sign in to comment.