From 2844a2bd71dcf1eb17a53992c10129b7496332e0 Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Tue, 31 Oct 2023 17:41:43 +0100
Subject: feat(components): add an Overlay component

* add useScrollbarWidth hook
* add useScrollLock hook
* add a new component to lock scroll with an overlay (it can be useful
especially on small screens to prevent background contents to be
scrolled)
---
 src/components/atoms/overlay/overlay.tsx | 47 ++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 src/components/atoms/overlay/overlay.tsx

(limited to 'src/components/atoms/overlay/overlay.tsx')

diff --git a/src/components/atoms/overlay/overlay.tsx b/src/components/atoms/overlay/overlay.tsx
new file mode 100644
index 0000000..7dd7446
--- /dev/null
+++ b/src/components/atoms/overlay/overlay.tsx
@@ -0,0 +1,47 @@
+import {
+  forwardRef,
+  type ForwardRefRenderFunction,
+  type HTMLAttributes,
+  type ReactNode,
+} from 'react';
+import { useScrollLock } from '../../../utils/hooks';
+import styles from './overlay.module.scss';
+
+export type OverlayProps = HTMLAttributes<HTMLDivElement> & {
+  /**
+   * The elements to display in front of the overlay.
+   */
+  children: ReactNode;
+  /**
+   * Should the overlay be visible?
+   *
+   * Use it if you want an animated overlay instead of mounting/demounting it.
+   *
+   * @default true
+   */
+  isVisible?: boolean;
+};
+
+const OverlayWithRef: ForwardRefRenderFunction<HTMLDivElement, OverlayProps> = (
+  { children, className = '', isVisible = true, ...props },
+  ref
+) => {
+  const overlayClass = [
+    styles.overlay,
+    styles[isVisible ? 'overlay--visible' : 'overlay--hidden'],
+    className,
+  ].join(' ');
+
+  useScrollLock(isVisible);
+
+  return (
+    <div {...props} className={overlayClass} ref={ref}>
+      {children}
+    </div>
+  );
+};
+
+/**
+ * Overlay component.
+ */
+export const Overlay = forwardRef(OverlayWithRef);
-- 
cgit v1.2.3

