Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 23 additions & 35 deletions src/AgentConnectButton.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,45 @@
"use client";
import React, { forwardRef, memo, useState, type CSSProperties } from "react";
import React, { forwardRef, memo, type CSSProperties } from "react";
import { symToStr } from "tsafe/symToStr";
import { createComponentI18nApi } from "./i18n";
import { fr } from "./fr";
import { assert, type Equals } from "tsafe/assert";
import agentconnectBtnPrincipalSvgUrl from "./assets/agentconnect-btn-principal.svg";
import agentconnectBtnPrincipalHoverSvgUrl from "./assets/agentconnect-btn-principal-hover.svg";
import agentconnectBtnAlternatifSvgUrl from "./assets/agentconnect-btn-alternatif.svg";
import agentconnectBtnAlternatifHoverSvgUrl from "./assets/agentconnect-btn-alternatif-hover.svg";
import "./assets/agentconnect.css";
import { useIsDark } from "./useIsDark";
import { getAssetUrl } from "./tools/getAssetUrl";
import { cx } from "./tools/cx";

export type AgentConnectButtonProps = {
className?: string;
url: string;
style?: CSSProperties;
};
export type AgentConnectButtonProps = AgentConnectButtonProps.Common &
(AgentConnectButtonProps.WithUrl | AgentConnectButtonProps.WithOnClick);

export namespace AgentConnectButtonProps {
export type Common = {
className?: string;
style?: CSSProperties;
};
export type WithUrl = {
url: string;
onClick?: never;
};
export type WithOnClick = {
url?: never;
onClick: React.MouseEventHandler<HTMLButtonElement>;
};
}

/** @see <https://react-dsfr-components.etalab.studio/?path=/docs/components-franceconnectbutton> */
export const AgentConnectButton = memo(
forwardRef<HTMLDivElement, AgentConnectButtonProps>((props, ref) => {
const { className, url, style, ...rest } = props;
const { className, url: href, style, onClick, ...rest } = props;

assert<Equals<keyof typeof rest, never>>();

const { t } = useTranslation();

const [isMouseHover, setIsMouseHover] = useState(false);

const { isDark } = useIsDark();
const Inner = onClick !== undefined ? "button" : "a";
const innerProps = (onClick !== undefined ? { onClick } : { href }) as any;

return (
<div className={className} style={style} ref={ref}>
<a
className="agentconnect-button__link"
href={url}
onMouseEnter={() => setIsMouseHover(true)}
onMouseLeave={() => setIsMouseHover(false)}
>
<img
src={getAssetUrl(
isDark
? isMouseHover
? agentconnectBtnAlternatifHoverSvgUrl
: agentconnectBtnAlternatifSvgUrl
: isMouseHover
? agentconnectBtnPrincipalHoverSvgUrl
: agentconnectBtnPrincipalSvgUrl
)}
/>
</a>
<span className="agentconnect-button__preload-hover" />
<Inner className="agentconnect-button__link" {...innerProps} />
<p>
<a
className={cx(
Expand Down
2 changes: 1 addition & 1 deletion src/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export const Button = memo(
prop_className
);

return linkProps ? (
return linkProps !== undefined ? (
<Link
{...linkProps}
title={title ?? linkProps.title}
Expand Down
37 changes: 26 additions & 11 deletions src/FranceConnectButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,53 @@ import { fr } from "./fr";
import { assert, type Equals } from "tsafe/assert";
import { cx } from "./tools/cx";

export type FranceConnectButtonProps = {
className?: string;
url: string;
/** Default: false */
plus?: boolean;
classes?: Partial<Record<"root" | "login" | "brand", string>>;
style?: CSSProperties;
};
export type FranceConnectButtonProps = FranceConnectButtonProps.Common &
(FranceConnectButtonProps.WithUrl | FranceConnectButtonProps.WithOnClick);

export namespace FranceConnectButtonProps {
export type Common = {
className?: string;
/** Default: false */
plus?: boolean;
classes?: Partial<Record<"root" | "login" | "brand", string>>;
style?: CSSProperties;
};
export type WithUrl = {
url: string;
onClick?: never;
};
export type WithOnClick = {
url?: never;
onClick: React.MouseEventHandler<HTMLButtonElement>;
};
}

/** @see <https://react-dsfr-components.etalab.studio/?path=/docs/components-franceconnectbutton> */
export const FranceConnectButton = memo(
forwardRef<HTMLDivElement, FranceConnectButtonProps>((props, ref) => {
const { classes = {}, className, url, plus = false, style, ...rest } = props;
const { classes = {}, className, url: href, plus = false, style, onClick, ...rest } = props;

assert<Equals<keyof typeof rest, never>>();

const { t } = useTranslation();

const Inner = onClick !== undefined ? "button" : "a";
const innerProps = (onClick !== undefined ? { onClick } : { href }) as any;

return (
<div
className={cx(fr.cx("fr-connect-group"), classes.root, className)}
style={style}
ref={ref}
>
<a className={fr.cx("fr-btn", "fr-connect")} href={url}>
<Inner className={fr.cx("fr-btn", "fr-connect")} {...innerProps}>
<span className={cx(fr.cx("fr-connect__login"), classes.login)}>
S’identifier avec
</span>
<span className={cx(fr.cx("fr-connect__brand"), classes.brand)}>
FranceConnect{plus ? "+" : ""}
</span>
</a>
</Inner>
<p>
<a
href={
Expand Down
36 changes: 27 additions & 9 deletions src/MonCompteProButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,54 @@ import { assert, type Equals } from "tsafe/assert";
import { cx } from "./tools/cx";
import "./assets/moncomptepro.css";

export type FranceConnectButtonProps = {
className?: string;
url: string;
classes?: Partial<Record<"root" | "login" | "brand", string>>;
style?: CSSProperties;
};
export type FranceConnectButtonProps = FranceConnectButtonProps.Common &
(FranceConnectButtonProps.WithUrl | FranceConnectButtonProps.WithOnClick);

export namespace FranceConnectButtonProps {
export type Common = {
className?: string;
classes?: Partial<Record<"root" | "login" | "brand", string>>;
style?: CSSProperties;
};
export type WithUrl = {
url: string;
onClick?: never;
};
export type WithOnClick = {
url?: never;
onClick: React.MouseEventHandler<HTMLButtonElement>;
};
}

/** @see <https://react-dsfr-components.etalab.studio/?path=/docs/components-franceconnectbutton> */
export const MonCompteProButton = memo(
forwardRef<HTMLDivElement, FranceConnectButtonProps>((props, ref) => {
const { classes = {}, className, url, style, ...rest } = props;
const { classes = {}, className, url: href, style, onClick, ...rest } = props;

assert<Equals<keyof typeof rest, never>>();

const { t } = useTranslation();

const Inner = onClick !== undefined ? "button" : "a";
const innerProps = (onClick !== undefined ? { onClick } : { href }) as any;

return (
<div
className={cx(fr.cx("fr-connect-group"), classes.root, className)}
style={style}
ref={ref}
>
<a className={cx(fr.cx("fr-btn", "fr-connect"), "moncomptepro-button")} href={url}>
<Inner
className={cx(fr.cx("fr-btn", "fr-connect"), "moncomptepro-button")}
{...innerProps}
>
<span className={cx(fr.cx("fr-connect__login"), classes.login)}>
S’identifier avec
</span>
<span className={cx(fr.cx("fr-connect__brand"), classes.brand)}>
MonComptePro
</span>
</a>
</Inner>
<p>
<a
href="https://moncomptepro.beta.gouv.fr/"
Expand Down
26 changes: 24 additions & 2 deletions src/assets/agentconnect.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@

.agentconnect-button__link {
display: block;
background-image: unset;
width: 206px;
height: 60px;
display: inline-block;
background-image: url("./agentconnect-btn-principal.svg");
--active-tint: unset;
background-color: transparent;
background-position: 0 0;
background-repeat: no-repeat;
background-size: contain;
}

.agentconnect-button__preload-hover {
display: none;
}
.agentconnect-button__link:hover, .agentconnect-button__preload-hover {
background-image: url("./agentconnect-btn-principal-hover.svg");
}

:root[data-fr-theme=dark] .agentconnect-button__link {
background-image: url("./agentconnect-btn-alternatif.svg");
}

:root[data-fr-theme=dark] .agentconnect-button__link:hover,
:root[data-fr-theme=dark] .agentconnect-button__preload-hover {
background-image: url("./agentconnect-btn-alternatif-hover.svg");
}

.agentconnect-button__hint {
Expand Down
6 changes: 5 additions & 1 deletion stories/AgentConnectButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AgentConnectButton } from "../dist/AgentConnectButton";
import { sectionName } from "./sectionName";
import { getStoryFactory } from "./getStory";
import { getStoryFactory, logCallbacks } from "./getStory";

const { meta, getStory } = getStoryFactory({
sectionName,
Expand All @@ -22,3 +22,7 @@ export const Centered = getStory({
},
"url": "https://example.com"
});

export const WithOnClick = getStory({
...logCallbacks(["onClick"])
});
6 changes: 5 additions & 1 deletion stories/FranceConnectButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FranceConnectButton } from "../dist/FranceConnectButton";
import { sectionName } from "./sectionName";
import { getStoryFactory } from "./getStory";
import { getStoryFactory, logCallbacks } from "./getStory";

const { meta, getStory } = getStoryFactory({
sectionName,
Expand All @@ -27,3 +27,7 @@ export const Centered = getStory({
},
"url": "https://example.com"
});

export const WithOnClick = getStory({
...logCallbacks(["onClick"])
});
6 changes: 5 additions & 1 deletion stories/MonComptePro.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MonCompteProButton } from "../dist/MonCompteProButton";
import { sectionName } from "./sectionName";
import { getStoryFactory } from "./getStory";
import { getStoryFactory, logCallbacks } from "./getStory";

const { meta, getStory } = getStoryFactory({
sectionName,
Expand All @@ -22,3 +22,7 @@ export const Centered = getStory({
},
"url": "https://example.com"
});

export const WithOnClick = getStory({
...logCallbacks(["onClick"])
});