Skip to content

Commit

Permalink
fixup! add Tooltip component
Browse files Browse the repository at this point in the history
  • Loading branch information
celineung committed Aug 30, 2023
1 parent 4d3feaa commit 4c3a407
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 71 deletions.
90 changes: 46 additions & 44 deletions src/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,73 +5,75 @@ import { useAnalyticsId } from "./tools/useAnalyticsId";
import { fr } from "./fr";
import { cx } from "./tools/cx";

export type TooltipProps = {
export type UseTooltipParams = {
id?: string;
className?: string;
trigger?: "click" | "hover";
children: string;
};
}

export const createTooltip = (
props?: Omit<TooltipProps, "children">
): {
id: string;
type UseTooltipReturn = {
wrapperProps: {
"aria-describedby": string;
className?: string;
};
TooltipComponent: ({ children }: { children: string }) => JSX.Element;
} => {
TooltipButtonComponent?: JSX.Element;
}

export const useTooltip = (
params?: UseTooltipParams
): UseTooltipReturn => {
const tooltipId = useAnalyticsId({
"defaultIdPrefix": "fr-tooltip",
"explicitlyProvidedId": props?.id
"explicitlyProvidedId": params?.id
});

return {
id: tooltipId,
wrapperProps: {
"aria-describedby": tooltipId,
...(params?.trigger === "click" && {"className": cx(fr.cx("fr-btn--tooltip"), params?.className)})
},
TooltipButtonComponent: params?.trigger === "click" ? <TooltipButton tooltipId={tooltipId} /> : undefined,
TooltipComponent: ({ children }) => (
<Tooltip {...props} id={tooltipId}>
<Tooltip {...params} id={tooltipId}>
{children}
</Tooltip>
)
};
};

const TooltipButton = ({ tooltipId }: { tooltipId: string }) => {
const tooltipButtonId = `${tooltipId}-button`;

return (
<button className={fr.cx("fr-btn--tooltip", "fr-btn")} aria-describedby={tooltipId} id={tooltipButtonId}>
Plus d'information ?
</button>
)
}

export type TooltipProps = {
id?: string;
className?: string;
children: string;
};

/** @see <https://components.react-dsfr.codegouv.studio/?path=/docs/components-tooltip> */
const Tooltip = memo(
forwardRef<HTMLSpanElement, TooltipProps>((props, ref) => {
const { id: id_prop, className, trigger, children, ...rest } = props;
const { id, className, children, ...rest } = props;
assert<Equals<keyof typeof rest, never>>();

const id = useAnalyticsId({
"defaultIdPrefix": "fr-tooltip",
"explicitlyProvidedId": id_prop
});

return (
<>
{props.trigger === "click" ? (
<span ref={ref}>
<button className="fr-btn--tooltip fr-btn" aria-describedby={id}>
Plus d'information ?
</button>
<span
className={cx(fr.cx("fr-tooltip", "fr-placement"), props.className)}
id={id}
role="tooltip"
aria-hidden="true"
>
{props.children}
</span>
</span>
) : (
<span
ref={ref}
className={cx(fr.cx("fr-tooltip", "fr-placement"), props.className)}
id={id}
role="tooltip"
aria-hidden="true"
>
{props.children}
</span>
)}
</>
<span
ref={ref}
className={cx(fr.cx("fr-tooltip", "fr-placement"), props.className)}
id={id}
role="tooltip"
aria-hidden="true"
>
{props.children}
</span>
);
})
);
Expand Down
49 changes: 22 additions & 27 deletions stories/Tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { createTooltip, type TooltipProps } from "../dist/Tooltip";
import React from "react";
import { useTooltip, type UseTooltipParams } from "../dist/Tooltip";
import { sectionName } from "./sectionName";
import { getStoryFactory } from "./getStory";
import { assert, Equals } from "tsafe/assert";
import React from "react";

const Template = args => {
const tooltip = createTooltip(args);
const Template = (args: {
trigger?: "click" | "hover",
children: string,
className?: string;
id?: string;
}) => {
const tooltip = useTooltip(args);

return (
<>
{args.trigger != "click" && (
<a className="fr-link" aria-describedby={tooltip.id} href="#">
<a {...tooltip.wrapperProps} className="fr-link" href="#">
Example with hover
</a>
)}
{args.trigger === "click" && tooltip.TooltipButtonComponent }
<tooltip.TooltipComponent {...args} />
</>
);
Expand All @@ -31,17 +36,6 @@ const { meta, getStory } = getStoryFactory({
"description":
"Optional : tootlip Id, which is also use as aria-describedby for hovered/clicked element"
},
"trigger": {
"control": { "type": "select" },
"options": (() => {
const options = ["hover", "click"] as const;

assert<Equals<typeof options[number] | undefined, TooltipProps["trigger"]>>();

return options;
})(),
"description": "Default: hover"
},
"className": {
"control": { "type": "text" },
"description": "Optional"
Expand All @@ -60,14 +54,14 @@ Default.parameters = {
docs: {
source: {
code: `
import { createTooltip } from "@codegouvfr/react-dsfr/Tooltip";
import { useTooltip } from "@codegouvfr/react-dsfr/Tooltip";
function MyComponent() {
const tooltipOnHover = createTooltip()
const tooltipOnHover = useTooltip()
return (
<>
<a className="fr-link" aria-describedby={tooltipOnHover.id} href="#">
<a {...tooltipOnHover.wrapperProps} className="fr-link" href="#">
Example with hover
</a>
<tooltipOnHover.TooltipComponent>Tooltip content</tooltipOnHover.TooltipComponent>
Expand All @@ -88,14 +82,14 @@ TooltipOnHover.parameters = {
docs: {
source: {
code: `
import { createTooltip } from "@codegouvfr/react-dsfr/Tooltip";
import { useTooltip } from "@codegouvfr/react-dsfr/Tooltip";
function MyComponent() {
const tooltipOnHover = createTooltip({ trigger: "hover"})
const tooltipOnHover = useTooltip({ trigger: "hover"})
return (
<>
<a className="fr-link" aria-describedby={tooltipOnHover.id} href="#">
<a {...tooltipOnHover.wrapperProps} className="fr-link" href="#">
Example with hover
</a>
<tooltipOnHover.TooltipComponent>Tooltip content</tooltipOnHover.TooltipComponent>
Expand All @@ -116,12 +110,13 @@ TooltipOnClick.parameters = {
docs: {
source: {
code: `
import { createTooltip } from "@codegouvfr/react-dsfr/Tooltip";
import { useTooltip } from "@codegouvfr/react-dsfr/Tooltip";
function MyComponent() {
const tooltipOnClick = createTooltip({ trigger: "click"})
const tooltipOnClick = useTooltip({ trigger: "click"})
return (
{tooltipOnClick.TooltipButtonComponent}
<tooltipOnClick.TooltipComponent>Tooltip content</tooltipOnClick.TooltipComponent>
)
}
Expand Down

0 comments on commit 4c3a407

Please sign in to comment.