From d75b9a1e150ab211c1052fb49bede9bd16320aca Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Sat, 7 Oct 2023 18:44:14 +0200
Subject: feat(components): add a generic Flip component

The flipping animation is used at several places so it makes sense to
use a single component to handle the animation. It will avoid styles
duplication.
---
 .../forms/flipping-label/flipping-label.tsx        | 45 +++++++++++++++-------
 1 file changed, 31 insertions(+), 14 deletions(-)

(limited to 'src/components/molecules/forms/flipping-label/flipping-label.tsx')

diff --git a/src/components/molecules/forms/flipping-label/flipping-label.tsx b/src/components/molecules/forms/flipping-label/flipping-label.tsx
index e9d6a10..586301f 100644
--- a/src/components/molecules/forms/flipping-label/flipping-label.tsx
+++ b/src/components/molecules/forms/flipping-label/flipping-label.tsx
@@ -1,37 +1,54 @@
-import type { FC } from 'react';
-import { Icon, Label, type LabelProps } from '../../../atoms';
+import type { FC, ReactNode } from 'react';
+import {
+  Icon,
+  Label,
+  VisuallyHidden,
+  type LabelProps,
+  Flip,
+  FlipSide,
+} from '../../../atoms';
 import styles from './flipping-label.module.scss';
 
-export type FlippingLabelProps = Pick<
+export type FlippingLabelProps = Omit<
   LabelProps,
-  'aria-label' | 'className' | 'htmlFor'
+  'children' | 'isHidden' | 'isRequired'
 > & {
   /**
    * The front icon.
    */
-  children: JSX.Element;
+  icon: ReactNode;
   /**
    * Which side of the label should be displayed? True for the close icon.
    */
   isActive: boolean;
+  /**
+   * An accessible name for the label.
+   */
+  label: string;
 };
 
 export const FlippingLabel: FC<FlippingLabelProps> = ({
-  children,
   className = '',
+  icon,
   isActive,
+  label,
   ...props
 }) => {
-  const wrapperModifier = isActive ? 'wrapper--active' : 'wrapper--inactive';
+  const wrapperClass = `${styles.wrapper} ${className}`;
 
   return (
-    <Label {...props} className={`${styles.label} ${className}`}>
-      <span className={`${styles.wrapper} ${styles[wrapperModifier]}`}>
-        <span className={styles.front}>{children}</span>
-        <span className={styles.back}>
-          <Icon aria-hidden={true} shape="cross" />
-        </span>
-      </span>
+    <Label {...props} className={wrapperClass}>
+      <VisuallyHidden>{label}</VisuallyHidden>
+      <Flip
+        aria-hidden
+        // eslint-disable-next-line react/jsx-no-literals -- Shape allowed
+        showBack={isActive}
+      >
+        <FlipSide className={styles.front}>{icon}</FlipSide>
+        <FlipSide className={styles.back} isBack>
+          <Icon aria-hidden shape="cross" />
+        </FlipSide>
+      </Flip>
     </Label>
   );
 };
-- 
cgit v1.2.3

