From 07cf8efa065d77b307d9e0842ec8eea4b7065894 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Wed, 22 Nov 2023 17:05:46 -0800 Subject: [PATCH 01/19] feature(comp): adds modal --- .../src/registry-index.ts | 15 ++++ packages/wethegit-components/package.json | 4 + .../src/components/index.tsx | 1 + .../src/components/modal/index.tsx | 2 + .../src/components/modal/modal.module.scss | 30 +++++++ .../src/components/modal/modal.stories.tsx | 27 ++++++ .../src/components/modal/modal.tsx | 89 +++++++++++++++++++ .../src/components/modal/readme.stories.mdx | 35 ++++++++ .../types/wethegit-react-hooks.d.ts | 1 + yarn.lock | 15 ++++ 10 files changed, 219 insertions(+) create mode 100644 packages/wethegit-components/src/components/modal/index.tsx create mode 100644 packages/wethegit-components/src/components/modal/modal.module.scss create mode 100644 packages/wethegit-components/src/components/modal/modal.stories.tsx create mode 100644 packages/wethegit-components/src/components/modal/modal.tsx create mode 100644 packages/wethegit-components/src/components/modal/readme.stories.mdx create mode 100644 packages/wethegit-components/types/wethegit-react-hooks.d.ts diff --git a/packages/wethegit-components-cli/src/registry-index.ts b/packages/wethegit-components-cli/src/registry-index.ts index c3c6d0de..5f166609 100644 --- a/packages/wethegit-components-cli/src/registry-index.ts +++ b/packages/wethegit-components-cli/src/registry-index.ts @@ -92,6 +92,19 @@ const NAVIGATION: Registry = { localDependencies: [FLEX, CLASSNAMES, VISUALLY_HIDDEN, FIXED_FORWARD_REF], } +const ICON: Registry = { + name: "icon", + category: "component", + localDependencies: [CLASSNAMES], +} + +const MODAL: Registry = { + name: "modal", + category: "component", + localDependencies: [CLASSNAMES], + dependencies: ["@wethegit/react-modal@beta-2", "@wethegit/react-hooks"], +} + /* INDEX */ export const REGISTRY_INDEX: RegistryIndex = { [FLEX.name]: FLEX, @@ -101,5 +114,7 @@ export const REGISTRY_INDEX: RegistryIndex = { [TEXT.name]: TEXT, [VISUALLY_HIDDEN.name]: VISUALLY_HIDDEN, [NAVIGATION.name]: NAVIGATION, + [ICON.name]: ICON, + [MODAL.name]: MODAL, } /* END REGISTRY INDEX */ diff --git a/packages/wethegit-components/package.json b/packages/wethegit-components/package.json index c7ad2aa4..496fab88 100644 --- a/packages/wethegit-components/package.json +++ b/packages/wethegit-components/package.json @@ -27,6 +27,8 @@ "typecheck": "tsc --noEmit" }, "peerDependencies": { + "@wethegit/react-hooks": "^1.0.3", + "@wethegit/react-modal": "^2.0.0-beta.2", "react": "^17.0.2", "react-dom": "^17.0.2", "typescript": "5.1.6" @@ -45,6 +47,8 @@ "@types/react": "^17.0.39", "@types/react-dom": "^17.0.11", "@vitejs/plugin-react": "^1.3.2", + "@wethegit/react-hooks": "^1.0.3", + "@wethegit/react-modal": "^2.0.0-beta.2", "eslint": "^8.15.0", "eslint-config-custom": "*", "eslint-plugin-storybook": "^0.6.15", diff --git a/packages/wethegit-components/src/components/index.tsx b/packages/wethegit-components/src/components/index.tsx index e7f25840..5dd9ea5d 100644 --- a/packages/wethegit-components/src/components/index.tsx +++ b/packages/wethegit-components/src/components/index.tsx @@ -2,6 +2,7 @@ export * from "./flex" export * from "./grid-layout" export * from "./icon" export * from "./image-group" +export * from "./modal" export * from "./navigation" export * from "./tag" export * from "./text" diff --git a/packages/wethegit-components/src/components/modal/index.tsx b/packages/wethegit-components/src/components/modal/index.tsx new file mode 100644 index 00000000..ad3a16e3 --- /dev/null +++ b/packages/wethegit-components/src/components/modal/index.tsx @@ -0,0 +1,2 @@ +export { Modal } from "./modal" +export type { ModalProps } from "./modal" diff --git a/packages/wethegit-components/src/components/modal/modal.module.scss b/packages/wethegit-components/src/components/modal/modal.module.scss new file mode 100644 index 00000000..ca902e4b --- /dev/null +++ b/packages/wethegit-components/src/components/modal/modal.module.scss @@ -0,0 +1,30 @@ +.modalBackdrop { + background-color: rgb(0 0 0 / 70%); +} + +.modalCloseButton { + background-color: black; + border: none; + border-radius: 0.25rem; + color: white; + cursor: pointer; + font-size: 1rem; + padding: 0.5em 1em; +} + +.modalContent { + background-color: white; + border-radius: 1rem; + box-shadow: 0 0 5px 0 rgb(0 0 0 / 20%); + font-family: sans-serif; + max-width: 70%; + padding: 2rem; + transform: scale(var(--scale, 0)); + transition: transform var(--transition-duration) + var(--ease, cubic-bezier(0.75, -0.46, 0.4, 1)); +} + +.modalContentOpen { + --ease: cubic-bezier(0.77, 0, 0.1, 1.39); + --scale: 1; +} diff --git a/packages/wethegit-components/src/components/modal/modal.stories.tsx b/packages/wethegit-components/src/components/modal/modal.stories.tsx new file mode 100644 index 00000000..c2ad6824 --- /dev/null +++ b/packages/wethegit-components/src/components/modal/modal.stories.tsx @@ -0,0 +1,27 @@ +import type { Meta, StoryObj } from "@storybook/react" + +import { Modal } from "./modal" + +const meta = { + title: "components/modal", + component: Modal, + args: { + trigger: (toggle) => , + appendToBody: false, + }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +} satisfies Meta + +export default meta + +type Story = StoryObj + +export const Default: Story = { + render: (args) => , +} diff --git a/packages/wethegit-components/src/components/modal/modal.tsx b/packages/wethegit-components/src/components/modal/modal.tsx new file mode 100644 index 00000000..5c7a9985 --- /dev/null +++ b/packages/wethegit-components/src/components/modal/modal.tsx @@ -0,0 +1,89 @@ +"use client" + +import { useRef } from "react" +import { + Modal as WTCModal, + ModalContent, + ModalBackdrop, + useModal, + ModalStates, +} from "@wethegit/react-modal" +import "@wethegit/react-modal/style.css" +import { useUserPrefs } from "@wethegit/react-hooks" + +import { classnames } from "@local/utilities" + +import styles from "./modal.module.scss" + +export interface ModalProps { + /** + * If true the modal will be appended to the body instead of the parent element. + * @defaultValue true + */ + appendToBody?: boolean + /** + * The duration of the modal transition in milliseconds. + */ + transitionDuration?: number + /** + * If provided, the modal state will be controlled by the hash in the URL. + */ + slug?: string + /** + * A function that returns the trigger element for the modal. + */ + trigger: (toggleModal: () => void) => React.ReactNode + /** + * The modal content. + */ + children?: React.ReactNode +} + +/** + * Wrapper around the `@wethegit/react-modal` component that adds a trigger and takes care of reducing motion. + * For more information, see the [modal documentation](https://github.com/wethegit/react-modal). + */ +export function Modal({ + transitionDuration = 800, + slug, + children, + appendToBody = true, + trigger, +}: ModalProps) { + const triggerButton = useRef(null) + const { prefersReducedMotion } = useUserPrefs() + const transition = prefersReducedMotion ? 0 : transitionDuration + const { isOpen, state, toggle } = useModal({ + triggerRef: triggerButton, + transitionDuration: transition, + slug, + }) + + const stylesVars = { + "--transition-duration": `${transition}ms`, + } as React.CSSProperties + + return ( + <> + {trigger && trigger(toggle)} + + {isOpen && ( + + + + + {children} + + + )} + + ) +} diff --git a/packages/wethegit-components/src/components/modal/readme.stories.mdx b/packages/wethegit-components/src/components/modal/readme.stories.mdx new file mode 100644 index 00000000..5cc5e902 --- /dev/null +++ b/packages/wethegit-components/src/components/modal/readme.stories.mdx @@ -0,0 +1,35 @@ +import { Meta } from "@storybook/blocks" + + + +# modal + +The `` component is a wrapper around [@wethegit/react-modal](https://github.com/wethegit/react-modal) with some default styles and added functionality to handle reduce motion. + +### Install + +```bash +npx @wethegit/components-cli add modal +``` + +### Usage + +Most of the time all you need is a button that toggles a modal. The `` component takes a `trigger` prop that is a function which receives a `toggle` function as its only argument and returns the element that will trigger the modal. + +```tsx +import { Modal } from "@local/components" + +function Page() { + return ( +
+ }> +

Modal Content

+

+ Pariatur occaecat quis aliquip excepteur adipisicing minim ipsum qui proident + qui voluptate ut sunt. +

+
+
+ ) +} +``` diff --git a/packages/wethegit-components/types/wethegit-react-hooks.d.ts b/packages/wethegit-components/types/wethegit-react-hooks.d.ts new file mode 100644 index 00000000..850361d5 --- /dev/null +++ b/packages/wethegit-components/types/wethegit-react-hooks.d.ts @@ -0,0 +1 @@ +declare module "@wethegit/react-hooks" diff --git a/yarn.lock b/yarn.lock index 6d8f897a..706067f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3485,6 +3485,21 @@ magic-string "^0.27.0" react-refresh "^0.14.0" +"@wethegit/react-hooks@^1.0.0", "@wethegit/react-hooks@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@wethegit/react-hooks/-/react-hooks-1.0.3.tgz#a26473bae7fbe7ad2f6611f860871ad44e4a17d1" + integrity sha512-4QS9kqXKbPbuGRK9/ZtdAl5MnkhQyWSJhdAjcsny0VkfG5SwtV7Bs9zFIpNnPHE1DEYOdj2b4ZDbmzhhKqnEMA== + dependencies: + react "^17.0.2" + react-dom "^17.0.2" + +"@wethegit/react-modal@^2.0.0-beta.2": + version "2.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@wethegit/react-modal/-/react-modal-2.0.0-beta.2.tgz#bab51ca6e931b973c1647f82f39e481a8b3bc878" + integrity sha512-0q2FRGg6s0CSx5F1hhuTkanOfiEsAPOlfGAE6d9e9g8pVk1BhWjb+QRV9n2h4lwxpnH9aG2h2fNKzqi1QYea4Q== + dependencies: + "@wethegit/react-hooks" "^1.0.0" + "@yarnpkg/esbuild-plugin-pnp@^3.0.0-rc.10": version "3.0.0-rc.15" resolved "https://registry.yarnpkg.com/@yarnpkg/esbuild-plugin-pnp/-/esbuild-plugin-pnp-3.0.0-rc.15.tgz#4e40e7d2eb28825c9a35ab9d04c363931d7c0e67" From 282528a5e4ebe33b875a67ec58ff57cd34c2ecd2 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Fri, 24 Nov 2023 12:50:44 -0800 Subject: [PATCH 02/19] feature(comp): adds useAnimatePresence hook --- .../wethegit-components/src/hooks/index.ts | 1 + .../use-animate-presence/readme.stories.mdx | 163 ++++++++++++++++++ .../use-animate-presence.stories.tsx | 130 ++++++++++++++ .../use-animate-presence.ts | 135 +++++++++++++++ .../src/hooks/use-ismounted/index.ts | 1 + .../src/hooks/use-ismounted/use-is-mounted.ts | 0 6 files changed, 430 insertions(+) create mode 100644 packages/wethegit-components/src/hooks/index.ts create mode 100644 packages/wethegit-components/src/hooks/use-animate-presence/readme.stories.mdx create mode 100644 packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.stories.tsx create mode 100644 packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.ts create mode 100644 packages/wethegit-components/src/hooks/use-ismounted/index.ts create mode 100644 packages/wethegit-components/src/hooks/use-ismounted/use-is-mounted.ts diff --git a/packages/wethegit-components/src/hooks/index.ts b/packages/wethegit-components/src/hooks/index.ts new file mode 100644 index 00000000..5392afec --- /dev/null +++ b/packages/wethegit-components/src/hooks/index.ts @@ -0,0 +1 @@ +export * from "./use-ismounted" diff --git a/packages/wethegit-components/src/hooks/use-animate-presence/readme.stories.mdx b/packages/wethegit-components/src/hooks/use-animate-presence/readme.stories.mdx new file mode 100644 index 00000000..dccdf92c --- /dev/null +++ b/packages/wethegit-components/src/hooks/use-animate-presence/readme.stories.mdx @@ -0,0 +1,163 @@ +import { Meta } from "@storybook/blocks" + + + +# useAnimatePresence + +useAnimatePresence is a very simple hook that helps you animate components that are added or removed from the DOM. + +Use it for things like modals, tooltips, dropdowns, etc. + +You are in full control of the animation and the hook only provides you with the current state and the current duration of the animation. + +It also takes care of accessibility by forcing `duration` to `0` if the user has enabled reduced motion. + +- [Install](#install) +- [Usage](#usage) +- [Basic example](#basic-example) +- [Custom animation](#custom-animation) +- [Don't animate on mount](#dont-animate-on-mount) + +## Install + +```bash +npx @wethegit/components-cli add use-animate-presence +``` + +## Usage + +## Basic example + +By default all you need to provide is a boolean that determines whether the element should be visible or not. The hook will return a `shouldRender` boolean that you can use to conditionally render the element. + +It will also return a `reveal` boolean, which is a shorthand that you can use to conditionally apply your animation. + +Finally, it will return a `runningDuration` number that you can use to set the duration of the animation. + +[Story demo](/story/hooks-useanimatepresence--default) + +```jsx +import { useAnimatePresence } from "@local/hooks" +import { classnames } from "@local/utilities" + +function MyComponent() { + const [isVisible, setIsVisible] = useState(false) + + const { shouldRender, reveal, runningDuration } = useAnimatePresence({ + isVisible, + }) + + return ( + <> + + + {shouldRender && ( +
+ Hey! I animate in and out! +
+ )} + + ) +} +``` + +And then in your styles: + +```css +.my-component { + opacity: 0; + transition: opacity var(--transition-duration) ease-out; + + &.is-visible { + opacity: 1; + } +} +``` + +## Custom animation + +[Demo](/story/hooks-useanimatepresence--custom-animation) + +```jsx +import { useAnimatePresence, AnimatePresenceStates } from "@local/hooks" + +function MyComponent() { + // ... shortened for brevity + const { shouldRender, reveal, runningDuration } = useAnimatePresence({ + state, + isVisible, + duration: { + // different durations for enter and exit + enter: 1000, + exit: 500, + }, + }) + + // you can control the animation in every step too + let className + if ( + state === AnimatePresenceStates.ENTERING || + state === AnimatePresenceStates.ENTERED + ) { + className = "is-in" + } else if ( + state === AnimatePresenceStates.EXITED || + state === AnimatePresenceStates.EXITING + ) { + className = "is-out" + } + + return ( + <> + {/* render it the same way, the hook takes care of updating the duration */} + {shouldRender && ( +
+ Hey! I animate in and out! +
+ )} + + ) +} +``` + +And then in your styles: + +```css +.my-component { + transition: all var(--transition-duration) ease-out; + + &.is-in { + opacity: 1; + transform: scale(1); + } + + &.is-out { + opacity: 0; + transform: scale(0) rotate(360deg); + transition-timing-function: ease-in; + } +} +``` + +## Don't animate on mount + +Set `initial` to `true` to have the element start out visible. + +[Story demo](/story/hooks-useanimatepresence--do-not-animate-on-mount) + +```ts +const { shouldRender, reveal, runningDuration } = useAnimatePresence({ + initial: true, + isVisible, +}) +``` diff --git a/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.stories.tsx b/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.stories.tsx new file mode 100644 index 00000000..4112a28d --- /dev/null +++ b/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.stories.tsx @@ -0,0 +1,130 @@ +import type { Meta, StoryObj } from "@storybook/react" + +import { AnimatePresenceProps, useAnimatePresence } from "./use-animate-presence" + +const meta: Meta = { + title: "hooks/useAnimatePresence", + args: { + isVisible: false, + duration: { + enter: 1000, + exit: 300, + }, + }, + argTypes: { + isVisible: { + controls: { + type: "boolean", + }, + description: "Whether the element is visible or not.", + table: { + defaultValue: { summary: "false" }, + }, + }, + duration: { + control: { + type: "object", + }, + table: { + defaultValue: { summary: 300 }, + }, + description: "The duration of the animation. Can be an `object` or a `number`.", + }, + initial: { + control: { + type: "boolean", + }, + description: "Whether the element should be visible on initial render.", + table: { + defaultValue: { summary: "false" }, + }, + }, + }, +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + render: ({ isVisible, duration }) => { + const { shouldRender, reveal, runningDuration } = useAnimatePresence({ + duration, + isVisible, + }) + + if (!shouldRender) return <> + + return ( +
+ Hey! I animate in and out! +
+ ) + }, +} + +export const CustomAnimation: Story = { + render: ({ + isVisible, + duration = { + enter: 1000, + exit: 300, + }, + }) => { + const { shouldRender, reveal, runningDuration } = useAnimatePresence({ + duration, + isVisible, + }) + + if (!shouldRender) return <> + + return ( +
+ I started out visible! +
+ ) + }, +} + +export const DoNotAnimateOnMount: Story = { + render: ({ isVisible, duration }) => { + const { shouldRender, reveal, runningDuration } = useAnimatePresence({ + duration, + isVisible, + initial: true, + }) + + if (!shouldRender) return <> + + return ( +
+ I started out visible! +
+ ) + }, +} diff --git a/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.ts b/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.ts new file mode 100644 index 00000000..96fe9273 --- /dev/null +++ b/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.ts @@ -0,0 +1,135 @@ +import { useEffect, useRef, useState } from "react" +import { useUserPrefs } from "@wethegit/react-hooks" + +export interface AnimatePresenceProps { + /** + * Visibility of the component + */ + isVisible: boolean + /** + * Initial state of the animation + * @defaultValue false + */ + initial?: boolean + /** + * Duration in miliseconds or object with enter and exit duration in miliseconds + * @defaultValue = 300 + */ + duration?: + | number + | { + enter: number + exit: number + } +} + +export interface AnimatePresenceReturn { + /** + * Render your component **only** if `shouldRender` is `true` + */ + shouldRender: boolean + /** + * `reveal` is an shorthand for animating the component in and out + */ + reveal: boolean + /** + * Duration of the current animation + */ + runningDuration: number + /** + * Current state of the animation. Use it for full control of the animation in all states + */ + state: AnimatePresenceState +} + +export enum AnimatePresenceState { + ENTERED = "entered", + EXITED = "exited", + EXITING = "exiting", + ENTERING = "entering", + MOUNTED = "mounted", +} + +/** + * AnimatePresence is a very simple hook that helps you animate components in and out. + * You are in full control of the animation and the hook only provides you with the current state and the current duration of the animation. + * It also takes care of accessibility by forcing duration to `0` if the user has enabled reduced motion. + */ +export function useAnimatePresence({ + initial = false, + duration = 300, + isVisible = false, +}: AnimatePresenceProps): AnimatePresenceReturn { + const { prefersReducedMotion } = useUserPrefs() + const skipMountAnimation = useRef(initial) + const [state, setState] = useState( + skipMountAnimation.current + ? AnimatePresenceState.ENTERED + : AnimatePresenceState.EXITED + ) + const durationEnter = prefersReducedMotion + ? 0 + : typeof duration === "number" + ? duration + : duration.enter + + const durationExit = prefersReducedMotion + ? 0 + : typeof duration === "number" + ? duration + : duration.exit + + const timer = useRef | undefined>(undefined) + + useEffect(() => { + clearTimeout(timer.current) + + console.log({ state }) + + if (state === AnimatePresenceState.MOUNTED) { + timer.current = setTimeout(() => { + setState(AnimatePresenceState.ENTERING) + }, 10) + } else if (state === AnimatePresenceState.ENTERING) { + timer.current = setTimeout(() => { + setState(AnimatePresenceState.ENTERED) + }, durationEnter) + } else if (state === AnimatePresenceState.EXITING) { + timer.current = setTimeout(() => { + setState(AnimatePresenceState.EXITED) + }, durationExit) + } + }, [state]) + + useEffect(() => { + if (skipMountAnimation.current) { + skipMountAnimation.current = false + return + } + + if (isVisible) { + if ( + state === AnimatePresenceState.EXITED || + state === AnimatePresenceState.EXITING + ) { + setState(AnimatePresenceState.MOUNTED) + } + } else { + if ( + state === AnimatePresenceState.ENTERED || + state === AnimatePresenceState.ENTERING + ) { + setState(AnimatePresenceState.EXITING) + } + } + }, [isVisible]) + + return { + shouldRender: state !== AnimatePresenceState.EXITED, + reveal: + state === AnimatePresenceState.ENTERING || state === AnimatePresenceState.ENTERED, + runningDuration: + state === AnimatePresenceState.ENTERING ? durationEnter : durationExit, + state, + } +} diff --git a/packages/wethegit-components/src/hooks/use-ismounted/index.ts b/packages/wethegit-components/src/hooks/use-ismounted/index.ts new file mode 100644 index 00000000..081a8012 --- /dev/null +++ b/packages/wethegit-components/src/hooks/use-ismounted/index.ts @@ -0,0 +1 @@ +export { useIsMounted } from "./use-is-mounted" diff --git a/packages/wethegit-components/src/hooks/use-ismounted/use-is-mounted.ts b/packages/wethegit-components/src/hooks/use-ismounted/use-is-mounted.ts new file mode 100644 index 00000000..e69de29b From 7d6af13156483c90b15a96a5c74d3a529601e8e5 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Fri, 24 Nov 2023 12:54:53 -0800 Subject: [PATCH 03/19] patch(cli): adds hooks to registry --- .../wethegit-components-cli/src/registry-index.ts | 9 ++++++++- .../wethegit-components-cli/src/utils/consts.ts | 4 ++++ .../src/utils/prompt-for-config.ts | 15 ++++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/wethegit-components-cli/src/registry-index.ts b/packages/wethegit-components-cli/src/registry-index.ts index 5f166609..77a1b734 100644 --- a/packages/wethegit-components-cli/src/registry-index.ts +++ b/packages/wethegit-components-cli/src/registry-index.ts @@ -1,4 +1,4 @@ -export type RegistryCategory = "component" | "utility" | "style" | "type" +export type RegistryCategory = "component" | "utility" | "style" | "type" | "hook" export interface Registry { /** Should be the same name as the item's directory */ @@ -105,6 +105,12 @@ const MODAL: Registry = { dependencies: ["@wethegit/react-modal@beta-2", "@wethegit/react-hooks"], } +const USE_ANIMATE_PRESENCE: Registry = { + name: "use-animate-presence", + category: "hook", + dependencies: ["@wethegit/react-hooks"], +} + /* INDEX */ export const REGISTRY_INDEX: RegistryIndex = { [FLEX.name]: FLEX, @@ -116,5 +122,6 @@ export const REGISTRY_INDEX: RegistryIndex = { [NAVIGATION.name]: NAVIGATION, [ICON.name]: ICON, [MODAL.name]: MODAL, + [USE_ANIMATE_PRESENCE.name]: USE_ANIMATE_PRESENCE, } /* END REGISTRY INDEX */ diff --git a/packages/wethegit-components-cli/src/utils/consts.ts b/packages/wethegit-components-cli/src/utils/consts.ts index a026a8d6..73dcc82e 100644 --- a/packages/wethegit-components-cli/src/utils/consts.ts +++ b/packages/wethegit-components-cli/src/utils/consts.ts @@ -9,6 +9,8 @@ export const COMPONENTS_PACKAGE_STYLES_DIR = "src/styles" export const COMPONENTS_PACKAGE_UTILITIES_DIR = "src/utilities" +export const COMPONENTS_PACKAGE_HOOKS_DIR = "src/hooks" + export const COMPONENTS_PACKAGE_TYPES_DIR = "src/types" export const DEFAULT_CONFIG_FILE_NAME = "components.config.json" @@ -18,6 +20,7 @@ export const DEFAULT_CONFIG: Config = { component: "src/components", style: "src/styles", utility: "src/utilities", + hook: "src/hooks", type: "types", }, } @@ -26,5 +29,6 @@ export const REGISTRY_TYPE_TO_ROOT_DIR_MAP: Record = { component: COMPONENTS_PACKAGE_COMPONENTS_DIR, utility: COMPONENTS_PACKAGE_UTILITIES_DIR, style: COMPONENTS_PACKAGE_STYLES_DIR, + hook: COMPONENTS_PACKAGE_HOOKS_DIR, type: COMPONENTS_PACKAGE_TYPES_DIR, } diff --git a/packages/wethegit-components-cli/src/utils/prompt-for-config.ts b/packages/wethegit-components-cli/src/utils/prompt-for-config.ts index 727d3f0e..6ce026a2 100644 --- a/packages/wethegit-components-cli/src/utils/prompt-for-config.ts +++ b/packages/wethegit-components-cli/src/utils/prompt-for-config.ts @@ -52,6 +52,12 @@ export async function promptForConfig(cwd: string, skip: boolean): Promise { @@ -60,7 +66,13 @@ export async function promptForConfig(cwd: string, skip: boolean): Promise Date: Fri, 24 Nov 2023 13:10:42 -0800 Subject: [PATCH 04/19] patch(comp > modal): update with latest api fixes --- packages/wethegit-components/package.json | 4 +-- .../src/components/modal/modal.module.scss | 8 +++-- .../src/components/modal/modal.stories.tsx | 8 ++++- .../src/components/modal/modal.tsx | 36 +++++++------------ .../src/components/modal/readme.stories.mdx | 14 ++++++-- .../wethegit-components/src/hooks/index.ts | 2 +- .../src/hooks/use-animate-presence/index.ts | 6 ++++ .../src/hooks/use-ismounted/index.ts | 1 - .../src/hooks/use-ismounted/use-is-mounted.ts | 0 yarn.lock | 11 +++--- 10 files changed, 51 insertions(+), 39 deletions(-) create mode 100644 packages/wethegit-components/src/hooks/use-animate-presence/index.ts delete mode 100644 packages/wethegit-components/src/hooks/use-ismounted/index.ts delete mode 100644 packages/wethegit-components/src/hooks/use-ismounted/use-is-mounted.ts diff --git a/packages/wethegit-components/package.json b/packages/wethegit-components/package.json index 496fab88..61431014 100644 --- a/packages/wethegit-components/package.json +++ b/packages/wethegit-components/package.json @@ -28,7 +28,7 @@ }, "peerDependencies": { "@wethegit/react-hooks": "^1.0.3", - "@wethegit/react-modal": "^2.0.0-beta.2", + "@wethegit/react-modal": "^2.0.0-beta.4", "react": "^17.0.2", "react-dom": "^17.0.2", "typescript": "5.1.6" @@ -48,7 +48,7 @@ "@types/react-dom": "^17.0.11", "@vitejs/plugin-react": "^1.3.2", "@wethegit/react-hooks": "^1.0.3", - "@wethegit/react-modal": "^2.0.0-beta.2", + "@wethegit/react-modal": "^2.0.0-beta.4", "eslint": "^8.15.0", "eslint-config-custom": "*", "eslint-plugin-storybook": "^0.6.15", diff --git a/packages/wethegit-components/src/components/modal/modal.module.scss b/packages/wethegit-components/src/components/modal/modal.module.scss index ca902e4b..bb0b1c58 100644 --- a/packages/wethegit-components/src/components/modal/modal.module.scss +++ b/packages/wethegit-components/src/components/modal/modal.module.scss @@ -3,13 +3,16 @@ } .modalCloseButton { - background-color: black; + background-color: yellow; border: none; border-radius: 0.25rem; - color: white; + color: black; cursor: pointer; font-size: 1rem; padding: 0.5em 1em; + position: absolute; + right: 1em; + top: -0.5em; } .modalContent { @@ -18,6 +21,7 @@ box-shadow: 0 0 5px 0 rgb(0 0 0 / 20%); font-family: sans-serif; max-width: 70%; + -webkit-overflow-scrolling: touch; padding: 2rem; transform: scale(var(--scale, 0)); transition: transform var(--transition-duration) diff --git a/packages/wethegit-components/src/components/modal/modal.stories.tsx b/packages/wethegit-components/src/components/modal/modal.stories.tsx index c2ad6824..e97229fe 100644 --- a/packages/wethegit-components/src/components/modal/modal.stories.tsx +++ b/packages/wethegit-components/src/components/modal/modal.stories.tsx @@ -23,5 +23,11 @@ export default meta type Story = StoryObj export const Default: Story = { - render: (args) => , + render: (args) => ( + +

+ Excepteur mollit laboris culpa commodo ex. +

+
+ ), } diff --git a/packages/wethegit-components/src/components/modal/modal.tsx b/packages/wethegit-components/src/components/modal/modal.tsx index 5c7a9985..8aa1b1e0 100644 --- a/packages/wethegit-components/src/components/modal/modal.tsx +++ b/packages/wethegit-components/src/components/modal/modal.tsx @@ -6,11 +6,10 @@ import { ModalContent, ModalBackdrop, useModal, - ModalStates, } from "@wethegit/react-modal" import "@wethegit/react-modal/style.css" -import { useUserPrefs } from "@wethegit/react-hooks" +import { useAnimatePresence } from "@local/hooks" import { classnames } from "@local/utilities" import styles from "./modal.module.scss" @@ -21,14 +20,10 @@ export interface ModalProps { * @defaultValue true */ appendToBody?: boolean - /** - * The duration of the modal transition in milliseconds. - */ - transitionDuration?: number /** * If provided, the modal state will be controlled by the hash in the URL. */ - slug?: string + hash?: string /** * A function that returns the trigger element for the modal. */ @@ -43,38 +38,31 @@ export interface ModalProps { * Wrapper around the `@wethegit/react-modal` component that adds a trigger and takes care of reducing motion. * For more information, see the [modal documentation](https://github.com/wethegit/react-modal). */ -export function Modal({ - transitionDuration = 800, - slug, - children, - appendToBody = true, - trigger, -}: ModalProps) { +export function Modal({ hash, children, appendToBody = true, trigger }: ModalProps) { const triggerButton = useRef(null) - const { prefersReducedMotion } = useUserPrefs() - const transition = prefersReducedMotion ? 0 : transitionDuration - const { isOpen, state, toggle } = useModal({ + const { isOpen, toggle } = useModal({ triggerRef: triggerButton, - transitionDuration: transition, - slug, + hash, + }) + const { shouldRender, reveal, runningDuration } = useAnimatePresence({ + isVisible: isOpen, }) const stylesVars = { - "--transition-duration": `${transition}ms`, + "--transition-duration": `${runningDuration}ms`, } as React.CSSProperties return ( <> {trigger && trigger(toggle)} - {isOpen && ( - + {shouldRender && ( + , + [] + ) + return (
- }> +

Modal Content

Pariatur occaecat quis aliquip excepteur adipisicing minim ipsum qui proident diff --git a/packages/wethegit-components/src/hooks/index.ts b/packages/wethegit-components/src/hooks/index.ts index 5392afec..6c889872 100644 --- a/packages/wethegit-components/src/hooks/index.ts +++ b/packages/wethegit-components/src/hooks/index.ts @@ -1 +1 @@ -export * from "./use-ismounted" +export * from "./use-animate-presence" diff --git a/packages/wethegit-components/src/hooks/use-animate-presence/index.ts b/packages/wethegit-components/src/hooks/use-animate-presence/index.ts new file mode 100644 index 00000000..dc6e41b1 --- /dev/null +++ b/packages/wethegit-components/src/hooks/use-animate-presence/index.ts @@ -0,0 +1,6 @@ +export { useAnimatePresence } from "./use-animate-presence" +export type { + AnimatePresenceState, + AnimatePresenceProps, + AnimatePresenceReturn, +} from "./use-animate-presence" diff --git a/packages/wethegit-components/src/hooks/use-ismounted/index.ts b/packages/wethegit-components/src/hooks/use-ismounted/index.ts deleted file mode 100644 index 081a8012..00000000 --- a/packages/wethegit-components/src/hooks/use-ismounted/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useIsMounted } from "./use-is-mounted" diff --git a/packages/wethegit-components/src/hooks/use-ismounted/use-is-mounted.ts b/packages/wethegit-components/src/hooks/use-ismounted/use-is-mounted.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/yarn.lock b/yarn.lock index 706067f5..c6821345 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1129,7 +1129,7 @@ dependencies: "@changesets/types" "^5.2.1" -"@changesets/cli@^2.25.2": +"@changesets/cli@^2.25.2", "@changesets/cli@~2.26.2": version "2.26.2" resolved "https://registry.yarnpkg.com/@changesets/cli/-/cli-2.26.2.tgz#8914dd6ef3ea425a7d5935f6c35a8b7ccde54e45" integrity sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig== @@ -3493,11 +3493,12 @@ react "^17.0.2" react-dom "^17.0.2" -"@wethegit/react-modal@^2.0.0-beta.2": - version "2.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@wethegit/react-modal/-/react-modal-2.0.0-beta.2.tgz#bab51ca6e931b973c1647f82f39e481a8b3bc878" - integrity sha512-0q2FRGg6s0CSx5F1hhuTkanOfiEsAPOlfGAE6d9e9g8pVk1BhWjb+QRV9n2h4lwxpnH9aG2h2fNKzqi1QYea4Q== +"@wethegit/react-modal@^2.0.0-beta.4": + version "2.0.0-beta.4" + resolved "https://registry.yarnpkg.com/@wethegit/react-modal/-/react-modal-2.0.0-beta.4.tgz#ae0f2fe46707f33009c53cf8128653e5f5fb29ab" + integrity sha512-KIVbAzsBqx42LzZVLJMUFnooY/1+FWZqqxfGwufSfdrVvxmsPG0Th4TUTsrcuiP8N2YIzJoti4w7ulw3FmfOpQ== dependencies: + "@changesets/cli" "~2.26.2" "@wethegit/react-hooks" "^1.0.0" "@yarnpkg/esbuild-plugin-pnp@^3.0.0-rc.10": From c7a309d171b6e129d9956f3a3391c47ec6130c80 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Fri, 24 Nov 2023 13:26:49 -0800 Subject: [PATCH 05/19] fix: new changeset release cycle --- .github/workflows/release.yml | 9 +++++---- package.json | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 59fea2c1..f00ed44b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,6 +9,10 @@ concurrency: ${{ github.workflow }}-${{ github.ref }} jobs: release: + permissions: + contents: write # to create release (changesets/action) + issues: write # to post issue comments (changesets/action) + pull-requests: write # to create pull request (changesets/action) name: Release runs-on: ubuntu-latest steps: @@ -34,14 +38,11 @@ jobs: - name: Lint run: yarn lint - - name: Stylelint - run: yarn stylelint - - name: Create Release Pull Request or Publish to npm id: changesets uses: changesets/action@v1 with: - # This expects you to have a script called release which does a build for your packages and calls changeset publish + version: yarn version publish: yarn release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/package.json b/package.json index 0d1b9720..c68c2194 100755 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { "private": true, "scripts": { - "build": "turbo run build", - "changeset": "changeset", "clean": "turbo run clean && rm -rf .turbo node_modules .turbo-cookie", + "build": "turbo run build", "dev": "turbo run dev --no-cache --continue", "format": "prettier --write \"**/*.{ts,tsx,md,mdx}\"", "lint": "turbo run lint stylelint", - "release": "turbo run build && changeset publish", "typecheck": "turbo run typecheck", - "version-packages": "changeset version", + "changeset": "changeset", + "release": "turbo run build && changeset publish", + "version": "changeset version", "prepare": "husky install" }, "devDependencies": { From 5e1fb2f583258f1e5983ee5a135da2bc0d5bd232 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Mon, 27 Nov 2023 10:59:07 -0800 Subject: [PATCH 06/19] patch: changeset --- .changeset/beige-penguins-lay.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/beige-penguins-lay.md diff --git a/.changeset/beige-penguins-lay.md b/.changeset/beige-penguins-lay.md new file mode 100644 index 00000000..f9590255 --- /dev/null +++ b/.changeset/beige-penguins-lay.md @@ -0,0 +1,6 @@ +--- +"@wethegit/components-cli": patch +"@wethegit/components": patch +--- + +Adds Modal component and useAnimatePresence hook From f5c8c69d1849d5fa38f58b49d0ef487ff7183a67 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 14:49:19 -0800 Subject: [PATCH 07/19] fix: updates deps versions --- package.json | 2 +- packages/wethegit-components-cli/package.json | 2 +- .../src/registry-index.ts | 9 +- packages/wethegit-components/package.json | 14 +- .../src/components/modal/modal.tsx | 11 +- .../src/components/modal/readme.stories.mdx | 1 + .../wethegit-components/src/hooks/index.ts | 1 - .../src/hooks/use-animate-presence/index.ts | 6 - .../use-animate-presence/readme.stories.mdx | 163 ------------------ .../use-animate-presence.stories.tsx | 130 -------------- .../use-animate-presence.ts | 135 --------------- .../types/wethegit-react-hooks.d.ts | 1 - turbo.json | 2 +- yarn.lock | 51 ++++-- 14 files changed, 56 insertions(+), 472 deletions(-) delete mode 100644 packages/wethegit-components/src/hooks/index.ts delete mode 100644 packages/wethegit-components/src/hooks/use-animate-presence/index.ts delete mode 100644 packages/wethegit-components/src/hooks/use-animate-presence/readme.stories.mdx delete mode 100644 packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.stories.tsx delete mode 100644 packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.ts delete mode 100644 packages/wethegit-components/types/wethegit-react-hooks.d.ts diff --git a/package.json b/package.json index c68c2194..0e836ab1 100755 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "scripts": { "clean": "turbo run clean && rm -rf .turbo node_modules .turbo-cookie", "build": "turbo run build", - "dev": "turbo run dev --no-cache --continue", + "start": "turbo run start --no-cache --continue", "format": "prettier --write \"**/*.{ts,tsx,md,mdx}\"", "lint": "turbo run lint stylelint", "typecheck": "turbo run typecheck", diff --git a/packages/wethegit-components-cli/package.json b/packages/wethegit-components-cli/package.json index c4646c4c..c26889c4 100644 --- a/packages/wethegit-components-cli/package.json +++ b/packages/wethegit-components-cli/package.json @@ -15,7 +15,7 @@ "scripts": { "build": "tsup", "clean": "rm -rf node_modules dist", - "dev": "tsup --watch", + "start": "tsup --watch", "lint": "eslint src/", "typecheck": "tsc --noEmit" }, diff --git a/packages/wethegit-components-cli/src/registry-index.ts b/packages/wethegit-components-cli/src/registry-index.ts index 77a1b734..ac2a10d9 100644 --- a/packages/wethegit-components-cli/src/registry-index.ts +++ b/packages/wethegit-components-cli/src/registry-index.ts @@ -102,13 +102,7 @@ const MODAL: Registry = { name: "modal", category: "component", localDependencies: [CLASSNAMES], - dependencies: ["@wethegit/react-modal@beta-2", "@wethegit/react-hooks"], -} - -const USE_ANIMATE_PRESENCE: Registry = { - name: "use-animate-presence", - category: "hook", - dependencies: ["@wethegit/react-hooks"], + dependencies: ["@wethegit/react-modal", "@wethegit/react-hooks"], } /* INDEX */ @@ -122,6 +116,5 @@ export const REGISTRY_INDEX: RegistryIndex = { [NAVIGATION.name]: NAVIGATION, [ICON.name]: ICON, [MODAL.name]: MODAL, - [USE_ANIMATE_PRESENCE.name]: USE_ANIMATE_PRESENCE, } /* END REGISTRY INDEX */ diff --git a/packages/wethegit-components/package.json b/packages/wethegit-components/package.json index 61431014..a3a263ae 100644 --- a/packages/wethegit-components/package.json +++ b/packages/wethegit-components/package.json @@ -20,17 +20,17 @@ "scripts": { "build": "storybook build --docs", "clean": "rm -rf .turbo node_modules dist storybook-static", - "dev": "storybook dev -p 6006", + "start": "storybook dev -p 6006", "lint": "eslint src/", "stylelint": "stylelint **/*.{css,scss}", "preview-storybook": "serve storybook-static", "typecheck": "tsc --noEmit" }, "peerDependencies": { - "@wethegit/react-hooks": "^1.0.3", - "@wethegit/react-modal": "^2.0.0-beta.4", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "@wethegit/react-hooks": "^2.0.0", + "@wethegit/react-modal": "^2.0.0", + "react": "17 - 18", + "react-dom": "17 - 18", "typescript": "5.1.6" }, "devDependencies": { @@ -47,8 +47,8 @@ "@types/react": "^17.0.39", "@types/react-dom": "^17.0.11", "@vitejs/plugin-react": "^1.3.2", - "@wethegit/react-hooks": "^1.0.3", - "@wethegit/react-modal": "^2.0.0-beta.4", + "@wethegit/react-hooks": "^2.0.0", + "@wethegit/react-modal": "^2.0.0", "eslint": "^8.15.0", "eslint-config-custom": "*", "eslint-plugin-storybook": "^0.6.15", diff --git a/packages/wethegit-components/src/components/modal/modal.tsx b/packages/wethegit-components/src/components/modal/modal.tsx index 8aa1b1e0..6573444e 100644 --- a/packages/wethegit-components/src/components/modal/modal.tsx +++ b/packages/wethegit-components/src/components/modal/modal.tsx @@ -7,9 +7,10 @@ import { ModalBackdrop, useModal, } from "@wethegit/react-modal" +import { useAnimatePresence } from "@wethegit/react-hooks" + import "@wethegit/react-modal/style.css" -import { useAnimatePresence } from "@local/hooks" import { classnames } from "@local/utilities" import styles from "./modal.module.scss" @@ -44,25 +45,25 @@ export function Modal({ hash, children, appendToBody = true, trigger }: ModalPro triggerRef: triggerButton, hash, }) - const { shouldRender, reveal, runningDuration } = useAnimatePresence({ + const { render, animate, currentDuration } = useAnimatePresence({ isVisible: isOpen, }) const stylesVars = { - "--transition-duration": `${runningDuration}ms`, + "--transition-duration": `${currentDuration}ms`, } as React.CSSProperties return ( <> {trigger && trigger(toggle)} - {shouldRender && ( + {render && ( - - {shouldRender && ( -

- Hey! I animate in and out! -
- )} - - ) -} -``` - -And then in your styles: - -```css -.my-component { - opacity: 0; - transition: opacity var(--transition-duration) ease-out; - - &.is-visible { - opacity: 1; - } -} -``` - -## Custom animation - -[Demo](/story/hooks-useanimatepresence--custom-animation) - -```jsx -import { useAnimatePresence, AnimatePresenceStates } from "@local/hooks" - -function MyComponent() { - // ... shortened for brevity - const { shouldRender, reveal, runningDuration } = useAnimatePresence({ - state, - isVisible, - duration: { - // different durations for enter and exit - enter: 1000, - exit: 500, - }, - }) - - // you can control the animation in every step too - let className - if ( - state === AnimatePresenceStates.ENTERING || - state === AnimatePresenceStates.ENTERED - ) { - className = "is-in" - } else if ( - state === AnimatePresenceStates.EXITED || - state === AnimatePresenceStates.EXITING - ) { - className = "is-out" - } - - return ( - <> - {/* render it the same way, the hook takes care of updating the duration */} - {shouldRender && ( -
- Hey! I animate in and out! -
- )} - - ) -} -``` - -And then in your styles: - -```css -.my-component { - transition: all var(--transition-duration) ease-out; - - &.is-in { - opacity: 1; - transform: scale(1); - } - - &.is-out { - opacity: 0; - transform: scale(0) rotate(360deg); - transition-timing-function: ease-in; - } -} -``` - -## Don't animate on mount - -Set `initial` to `true` to have the element start out visible. - -[Story demo](/story/hooks-useanimatepresence--do-not-animate-on-mount) - -```ts -const { shouldRender, reveal, runningDuration } = useAnimatePresence({ - initial: true, - isVisible, -}) -``` diff --git a/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.stories.tsx b/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.stories.tsx deleted file mode 100644 index 4112a28d..00000000 --- a/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.stories.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react" - -import { AnimatePresenceProps, useAnimatePresence } from "./use-animate-presence" - -const meta: Meta = { - title: "hooks/useAnimatePresence", - args: { - isVisible: false, - duration: { - enter: 1000, - exit: 300, - }, - }, - argTypes: { - isVisible: { - controls: { - type: "boolean", - }, - description: "Whether the element is visible or not.", - table: { - defaultValue: { summary: "false" }, - }, - }, - duration: { - control: { - type: "object", - }, - table: { - defaultValue: { summary: 300 }, - }, - description: "The duration of the animation. Can be an `object` or a `number`.", - }, - initial: { - control: { - type: "boolean", - }, - description: "Whether the element should be visible on initial render.", - table: { - defaultValue: { summary: "false" }, - }, - }, - }, -} - -export default meta - -type Story = StoryObj - -export const Default: Story = { - render: ({ isVisible, duration }) => { - const { shouldRender, reveal, runningDuration } = useAnimatePresence({ - duration, - isVisible, - }) - - if (!shouldRender) return <> - - return ( -
- Hey! I animate in and out! -
- ) - }, -} - -export const CustomAnimation: Story = { - render: ({ - isVisible, - duration = { - enter: 1000, - exit: 300, - }, - }) => { - const { shouldRender, reveal, runningDuration } = useAnimatePresence({ - duration, - isVisible, - }) - - if (!shouldRender) return <> - - return ( -
- I started out visible! -
- ) - }, -} - -export const DoNotAnimateOnMount: Story = { - render: ({ isVisible, duration }) => { - const { shouldRender, reveal, runningDuration } = useAnimatePresence({ - duration, - isVisible, - initial: true, - }) - - if (!shouldRender) return <> - - return ( -
- I started out visible! -
- ) - }, -} diff --git a/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.ts b/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.ts deleted file mode 100644 index 96fe9273..00000000 --- a/packages/wethegit-components/src/hooks/use-animate-presence/use-animate-presence.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { useEffect, useRef, useState } from "react" -import { useUserPrefs } from "@wethegit/react-hooks" - -export interface AnimatePresenceProps { - /** - * Visibility of the component - */ - isVisible: boolean - /** - * Initial state of the animation - * @defaultValue false - */ - initial?: boolean - /** - * Duration in miliseconds or object with enter and exit duration in miliseconds - * @defaultValue = 300 - */ - duration?: - | number - | { - enter: number - exit: number - } -} - -export interface AnimatePresenceReturn { - /** - * Render your component **only** if `shouldRender` is `true` - */ - shouldRender: boolean - /** - * `reveal` is an shorthand for animating the component in and out - */ - reveal: boolean - /** - * Duration of the current animation - */ - runningDuration: number - /** - * Current state of the animation. Use it for full control of the animation in all states - */ - state: AnimatePresenceState -} - -export enum AnimatePresenceState { - ENTERED = "entered", - EXITED = "exited", - EXITING = "exiting", - ENTERING = "entering", - MOUNTED = "mounted", -} - -/** - * AnimatePresence is a very simple hook that helps you animate components in and out. - * You are in full control of the animation and the hook only provides you with the current state and the current duration of the animation. - * It also takes care of accessibility by forcing duration to `0` if the user has enabled reduced motion. - */ -export function useAnimatePresence({ - initial = false, - duration = 300, - isVisible = false, -}: AnimatePresenceProps): AnimatePresenceReturn { - const { prefersReducedMotion } = useUserPrefs() - const skipMountAnimation = useRef(initial) - const [state, setState] = useState( - skipMountAnimation.current - ? AnimatePresenceState.ENTERED - : AnimatePresenceState.EXITED - ) - const durationEnter = prefersReducedMotion - ? 0 - : typeof duration === "number" - ? duration - : duration.enter - - const durationExit = prefersReducedMotion - ? 0 - : typeof duration === "number" - ? duration - : duration.exit - - const timer = useRef | undefined>(undefined) - - useEffect(() => { - clearTimeout(timer.current) - - console.log({ state }) - - if (state === AnimatePresenceState.MOUNTED) { - timer.current = setTimeout(() => { - setState(AnimatePresenceState.ENTERING) - }, 10) - } else if (state === AnimatePresenceState.ENTERING) { - timer.current = setTimeout(() => { - setState(AnimatePresenceState.ENTERED) - }, durationEnter) - } else if (state === AnimatePresenceState.EXITING) { - timer.current = setTimeout(() => { - setState(AnimatePresenceState.EXITED) - }, durationExit) - } - }, [state]) - - useEffect(() => { - if (skipMountAnimation.current) { - skipMountAnimation.current = false - return - } - - if (isVisible) { - if ( - state === AnimatePresenceState.EXITED || - state === AnimatePresenceState.EXITING - ) { - setState(AnimatePresenceState.MOUNTED) - } - } else { - if ( - state === AnimatePresenceState.ENTERED || - state === AnimatePresenceState.ENTERING - ) { - setState(AnimatePresenceState.EXITING) - } - } - }, [isVisible]) - - return { - shouldRender: state !== AnimatePresenceState.EXITED, - reveal: - state === AnimatePresenceState.ENTERING || state === AnimatePresenceState.ENTERED, - runningDuration: - state === AnimatePresenceState.ENTERING ? durationEnter : durationExit, - state, - } -} diff --git a/packages/wethegit-components/types/wethegit-react-hooks.d.ts b/packages/wethegit-components/types/wethegit-react-hooks.d.ts deleted file mode 100644 index 850361d5..00000000 --- a/packages/wethegit-components/types/wethegit-react-hooks.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "@wethegit/react-hooks" diff --git a/turbo.json b/turbo.json index 986b445f..e66d187f 100644 --- a/turbo.json +++ b/turbo.json @@ -7,7 +7,7 @@ }, "lint": {}, "stylelint": {}, - "dev": { + "start": { "cache": false, "persistent": true }, diff --git a/yarn.lock b/yarn.lock index c6821345..3c1e87c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1129,6 +1129,15 @@ dependencies: "@changesets/types" "^5.2.1" +"@changesets/changelog-github@~0.4.8": + version "0.4.8" + resolved "https://registry.yarnpkg.com/@changesets/changelog-github/-/changelog-github-0.4.8.tgz#b7f8ae85d0c0ff08028d924c5e59a1cbd3742634" + integrity sha512-jR1DHibkMAb5v/8ym77E4AMNWZKB5NPzw5a5Wtqm1JepAuIF+hrKp2u04NKM14oBZhHglkCfrla9uq8ORnK/dw== + dependencies: + "@changesets/get-github-info" "^0.5.2" + "@changesets/types" "^5.2.1" + dotenv "^8.1.0" + "@changesets/cli@^2.25.2", "@changesets/cli@~2.26.2": version "2.26.2" resolved "https://registry.yarnpkg.com/@changesets/cli/-/cli-2.26.2.tgz#8914dd6ef3ea425a7d5935f6c35a8b7ccde54e45" @@ -1199,6 +1208,14 @@ fs-extra "^7.0.1" semver "^7.5.3" +"@changesets/get-github-info@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@changesets/get-github-info/-/get-github-info-0.5.2.tgz#0cde2cadba57db85c714dc303c077da919a574e5" + integrity sha512-JppheLu7S114aEs157fOZDjFqUDpm7eHdq5E8SSR0gUBTEK0cNSHsrSR5a66xs0z3RWuo46QvA3vawp8BxDHvg== + dependencies: + dataloader "^1.4.0" + node-fetch "^2.5.0" + "@changesets/get-release-plan@^3.0.17": version "3.0.17" resolved "https://registry.yarnpkg.com/@changesets/get-release-plan/-/get-release-plan-3.0.17.tgz#8aabced2795ffeae864696b60ee3031f8a94c5f3" @@ -3485,21 +3502,19 @@ magic-string "^0.27.0" react-refresh "^0.14.0" -"@wethegit/react-hooks@^1.0.0", "@wethegit/react-hooks@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@wethegit/react-hooks/-/react-hooks-1.0.3.tgz#a26473bae7fbe7ad2f6611f860871ad44e4a17d1" - integrity sha512-4QS9kqXKbPbuGRK9/ZtdAl5MnkhQyWSJhdAjcsny0VkfG5SwtV7Bs9zFIpNnPHE1DEYOdj2b4ZDbmzhhKqnEMA== - dependencies: - react "^17.0.2" - react-dom "^17.0.2" +"@wethegit/react-hooks@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@wethegit/react-hooks/-/react-hooks-2.0.0.tgz#ac4668cdbe860c5fb730fdcb884932c3a4e5b53a" + integrity sha512-6SiARtkVTCMD9vhHrNbJ6yNYLYGWslUyBiAIyChMhJDff48o+G8VXLH9ab2fKC40c0c03YbTRpJ0xGgqI4k9lQ== -"@wethegit/react-modal@^2.0.0-beta.4": - version "2.0.0-beta.4" - resolved "https://registry.yarnpkg.com/@wethegit/react-modal/-/react-modal-2.0.0-beta.4.tgz#ae0f2fe46707f33009c53cf8128653e5f5fb29ab" - integrity sha512-KIVbAzsBqx42LzZVLJMUFnooY/1+FWZqqxfGwufSfdrVvxmsPG0Th4TUTsrcuiP8N2YIzJoti4w7ulw3FmfOpQ== +"@wethegit/react-modal@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@wethegit/react-modal/-/react-modal-2.0.0.tgz#7f9ced1627e12cc12eba5a0b0fe2ab7edc4d6c4a" + integrity sha512-ESkxhqe5rHPC+bw2XD79QbIjFmmJ8AQD4jyg5C30cFV66s4KiF1nBh03axN1DMElvkrY0DK/DD7GmETKLoTXig== dependencies: + "@changesets/changelog-github" "~0.4.8" "@changesets/cli" "~2.26.2" - "@wethegit/react-hooks" "^1.0.0" + "@wethegit/react-hooks" "^2.0.0" "@yarnpkg/esbuild-plugin-pnp@^3.0.0-rc.10": version "3.0.0-rc.15" @@ -4593,6 +4608,11 @@ csv@^5.5.3: csv-stringify "^5.6.5" stream-transform "^2.1.3" +dataloader@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-1.4.0.tgz#bca11d867f5d3f1b9ed9f737bd15970c65dff5c8" + integrity sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw== + debug@2.6.9, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -4807,6 +4827,11 @@ dotenv@^16.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== +dotenv@^8.1.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" + integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== + duplexify@^3.5.0, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -7853,7 +7878,7 @@ node-fetch-native@^1.4.0: resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.4.1.tgz#5a336e55b4e1b1e72b9927da09fecd2b374c9be5" integrity sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w== -node-fetch@^2.0.0: +node-fetch@^2.0.0, node-fetch@^2.5.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== From 32904fe7b16da9bbf94fbc3d505a3b32228811cb Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:02:35 -0800 Subject: [PATCH 08/19] fix: updates modal docs --- .../src/components/modal/modal.module.scss | 18 +++++++++------ .../src/components/modal/modal.stories.tsx | 9 +++++--- .../src/components/modal/modal.tsx | 19 ++++++++-------- .../src/components/modal/readme.stories.mdx | 22 +++++++++++-------- 4 files changed, 40 insertions(+), 28 deletions(-) diff --git a/packages/wethegit-components/src/components/modal/modal.module.scss b/packages/wethegit-components/src/components/modal/modal.module.scss index bb0b1c58..3234600f 100644 --- a/packages/wethegit-components/src/components/modal/modal.module.scss +++ b/packages/wethegit-components/src/components/modal/modal.module.scss @@ -1,3 +1,13 @@ +.modal { + opacity: var(--scale, 0); + transition: opacity var(--duration) ease-in-out; +} + +.modalOpen { + --ease: cubic-bezier(0.77, 0, 0.1, 1.39); + --scale: 1; +} + .modalBackdrop { background-color: rgb(0 0 0 / 70%); } @@ -24,11 +34,5 @@ -webkit-overflow-scrolling: touch; padding: 2rem; transform: scale(var(--scale, 0)); - transition: transform var(--transition-duration) - var(--ease, cubic-bezier(0.75, -0.46, 0.4, 1)); -} - -.modalContentOpen { - --ease: cubic-bezier(0.77, 0, 0.1, 1.39); - --scale: 1; + transition: transform var(--duration) var(--ease, cubic-bezier(0.75, -0.46, 0.4, 1)); } diff --git a/packages/wethegit-components/src/components/modal/modal.stories.tsx b/packages/wethegit-components/src/components/modal/modal.stories.tsx index e97229fe..d120d17d 100644 --- a/packages/wethegit-components/src/components/modal/modal.stories.tsx +++ b/packages/wethegit-components/src/components/modal/modal.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react" +import { UserPreferencesProvider } from "@wethegit/react-hooks" import { Modal } from "./modal" @@ -11,9 +12,11 @@ const meta = { }, decorators: [ (Story) => ( -
- -
+ +
+ +
+
), ], } satisfies Meta diff --git a/packages/wethegit-components/src/components/modal/modal.tsx b/packages/wethegit-components/src/components/modal/modal.tsx index 6573444e..f3674cdd 100644 --- a/packages/wethegit-components/src/components/modal/modal.tsx +++ b/packages/wethegit-components/src/components/modal/modal.tsx @@ -7,7 +7,7 @@ import { ModalBackdrop, useModal, } from "@wethegit/react-modal" -import { useAnimatePresence } from "@wethegit/react-hooks" +import { useAnimatePresence, useUserPrefs } from "@wethegit/react-hooks" import "@wethegit/react-modal/style.css" @@ -45,12 +45,14 @@ export function Modal({ hash, children, appendToBody = true, trigger }: ModalPro triggerRef: triggerButton, hash, }) + const { prefersReducedMotion } = useUserPrefs() const { render, animate, currentDuration } = useAnimatePresence({ isVisible: isOpen, + duration: prefersReducedMotion ? 0 : 500, }) const stylesVars = { - "--transition-duration": `${currentDuration}ms`, + "--duration": `${currentDuration}ms`, } as React.CSSProperties return ( @@ -58,14 +60,13 @@ export function Modal({ hash, children, appendToBody = true, trigger }: ModalPro {trigger && trigger(toggle)} {render && ( - + - + diff --git a/packages/wethegit-components/src/components/modal/readme.stories.mdx b/packages/wethegit-components/src/components/modal/readme.stories.mdx index f5774dc7..40501ff2 100644 --- a/packages/wethegit-components/src/components/modal/readme.stories.mdx +++ b/packages/wethegit-components/src/components/modal/readme.stories.mdx @@ -18,6 +18,8 @@ Most of the time all you need is a button that toggles a modal. The `` component takes a `trigger` prop that is a function which receives a `toggle` function as its only argument and returns the element that will trigger the modal. +It also handles reduced motion by default and because of that you are required to make sure that the modal component renders inside the [UserPreferencesProvider](https://wethegit.github.io/react-hooks/user-preferences-provider). + ```tsx import { useCallback } from "react" @@ -30,15 +32,17 @@ function Page() { ) return ( -
- -

Modal Content

-

- Pariatur occaecat quis aliquip excepteur adipisicing minim ipsum qui proident - qui voluptate ut sunt. -

-
-
+ +
+ +

Modal Content

+

+ Pariatur occaecat quis aliquip excepteur adipisicing minim ipsum qui proident + qui voluptate ut sunt. +

+
+
+
) } ``` From 2326fdd04bfce319f877667d2fdfb4f5f5eedf7c Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:04:02 -0800 Subject: [PATCH 09/19] fix: workflow name --- .github/workflows/lint.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50311707..95cb1558 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,10 +1,6 @@ -name: Release +name: Lint on: - push: - branches: - - main - pull_request: types: [opened, edited, reopened, synchronize] From 86d4314e57c8a41e2132cae9c7db1caaa64e1adc Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:05:41 -0800 Subject: [PATCH 10/19] fix: changelog --- .changeset/beige-penguins-lay.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/beige-penguins-lay.md b/.changeset/beige-penguins-lay.md index f9590255..159fc90b 100644 --- a/.changeset/beige-penguins-lay.md +++ b/.changeset/beige-penguins-lay.md @@ -3,4 +3,4 @@ "@wethegit/components": patch --- -Adds Modal component and useAnimatePresence hook +Adds `` component From eaec309a2cd526f3f2801db127d88256b7bfae18 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:07:57 -0800 Subject: [PATCH 11/19] fix: changeset changelog links --- .changeset/config.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.changeset/config.json b/.changeset/config.json index d4de0c69..e9f6fb3b 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,6 +1,11 @@ { "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", - "changelog": "@changesets/cli/changelog", + "changelog": [ + "@changesets/changelog-github", + { + "repo": "wethegit/component-library" + } + ], "commit": false, "fixed": [], "linked": [], From 66ff6f63f0fe39a07678f3d1e1588b6f613ccbce Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:09:50 -0800 Subject: [PATCH 12/19] fix: locks --- package.json | 4 +++- packages/wethegit-components-cli/package.json | 2 +- packages/wethegit-components/package.json | 2 +- yarn.lock | 22 +++++++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 0e836ab1..b8303661 100755 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ }, "devDependencies": { "@changesets/cli": "^2.25.2", + "@changesets/changelog-github": "^0.5.0", "eslint": "^8.48.0", "eslint-config-custom": "*", "husky": "^8.0.3", @@ -28,5 +29,6 @@ "apps/*", "packages/*" ], - "license": "MIT" + "license": "MIT", + "dependencies": {} } diff --git a/packages/wethegit-components-cli/package.json b/packages/wethegit-components-cli/package.json index c26889c4..4ad1a034 100644 --- a/packages/wethegit-components-cli/package.json +++ b/packages/wethegit-components-cli/package.json @@ -14,7 +14,7 @@ }, "scripts": { "build": "tsup", - "clean": "rm -rf node_modules dist", + "clean": "rm -rf ./node_modules ./dist ./.turbo", "start": "tsup --watch", "lint": "eslint src/", "typecheck": "tsc --noEmit" diff --git a/packages/wethegit-components/package.json b/packages/wethegit-components/package.json index a3a263ae..b1b0d017 100644 --- a/packages/wethegit-components/package.json +++ b/packages/wethegit-components/package.json @@ -19,7 +19,7 @@ }, "scripts": { "build": "storybook build --docs", - "clean": "rm -rf .turbo node_modules dist storybook-static", + "clean": "rm -rf ./.turbo ./node_modules ./dist ./storybook-static", "start": "storybook dev -p 6006", "lint": "eslint src/", "stylelint": "stylelint **/*.{css,scss}", diff --git a/yarn.lock b/yarn.lock index 3c1e87c0..2a4569d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1129,6 +1129,15 @@ dependencies: "@changesets/types" "^5.2.1" +"@changesets/changelog-github@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@changesets/changelog-github/-/changelog-github-0.5.0.tgz#ae96e5029209f7386527b3821d9c988b1ab16662" + integrity sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA== + dependencies: + "@changesets/get-github-info" "^0.6.0" + "@changesets/types" "^6.0.0" + dotenv "^8.1.0" + "@changesets/changelog-github@~0.4.8": version "0.4.8" resolved "https://registry.yarnpkg.com/@changesets/changelog-github/-/changelog-github-0.4.8.tgz#b7f8ae85d0c0ff08028d924c5e59a1cbd3742634" @@ -1216,6 +1225,14 @@ dataloader "^1.4.0" node-fetch "^2.5.0" +"@changesets/get-github-info@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@changesets/get-github-info/-/get-github-info-0.6.0.tgz#faba66a20a3a5a0cbabea28efd43c9ede7429f11" + integrity sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA== + dependencies: + dataloader "^1.4.0" + node-fetch "^2.5.0" + "@changesets/get-release-plan@^3.0.17": version "3.0.17" resolved "https://registry.yarnpkg.com/@changesets/get-release-plan/-/get-release-plan-3.0.17.tgz#8aabced2795ffeae864696b60ee3031f8a94c5f3" @@ -1297,6 +1314,11 @@ resolved "https://registry.yarnpkg.com/@changesets/types/-/types-5.2.1.tgz#a228c48004aa8a93bce4be2d1d31527ef3bf21f6" integrity sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg== +"@changesets/types@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@changesets/types/-/types-6.0.0.tgz#e46abda9890610dd1fbe1617730173d2267544bd" + integrity sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ== + "@changesets/write@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@changesets/write/-/write-0.2.3.tgz#baf6be8ada2a67b9aba608e251bfea4fdc40bc63" From 63f7d9277d0a0bc9d949f60dc6305694cdb9f49a Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:11:53 -0800 Subject: [PATCH 13/19] fix: dev -> start --- README.md | 2 +- packages/wethegit-components-cli/README.md | 2 +- packages/wethegit-components/README.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6975becd..8534d0d2 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Minally styled, accessible, React component primitives that can be copy and past ## Useful Commands - `yarn build` - Build all packages, including the Storybook site -- `yarn dev` - Run all packages locally and preview with Storybook +- `yarn start` - Run all packages locally and preview with Storybook - `yarn lint` - Lint all packages - `yarn changeset` - Generate a changeset - `yarn clean` - Clean up all `node_modules` and `dist` folders (runs each package's clean script) diff --git a/packages/wethegit-components-cli/README.md b/packages/wethegit-components-cli/README.md index 7df02ec8..d0480907 100644 --- a/packages/wethegit-components-cli/README.md +++ b/packages/wethegit-components-cli/README.md @@ -11,7 +11,7 @@ To learn how to contribute, continue reading. Make sure you using the required Node version from [nvmrc](./.nvmrc). 1. Run `yarn install` from the **root of the monorepo**, not from this package's directory. -2. `cd` into this package's directory and run `yarn dev` +2. `cd` into this package's directory and run `yarn start` 3. In another terminal run `npm link` from this package's directory. **Note:** it MUST be `npm link` and not `yarn link` Now that we have a local version of the package available we need a node project to test on. If you have one already, skip to step 3. diff --git a/packages/wethegit-components/README.md b/packages/wethegit-components/README.md index 07da6d23..9ad55892 100644 --- a/packages/wethegit-components/README.md +++ b/packages/wethegit-components/README.md @@ -15,8 +15,8 @@ You will develop and test the components with **Storybook**. From the **root** of the repository, run: ```sh -yarn install -yarn dev +yarn +yarn start ``` This will start Storybook and watch for changes in the components' source files. From 7359b65e4cf7ca00fb20b28e40e81deefa816d9c Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:44:09 -0800 Subject: [PATCH 14/19] fix: redundant prop --- .../src/components/modal/modal.stories.tsx | 7 +++++++ .../wethegit-components/src/components/modal/modal.tsx | 8 ++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/wethegit-components/src/components/modal/modal.stories.tsx b/packages/wethegit-components/src/components/modal/modal.stories.tsx index d120d17d..13ae28f2 100644 --- a/packages/wethegit-components/src/components/modal/modal.stories.tsx +++ b/packages/wethegit-components/src/components/modal/modal.stories.tsx @@ -10,6 +10,13 @@ const meta = { trigger: (toggle) => , appendToBody: false, }, + argTypes: { + appendToBody: { + description: + "If true the modal will be appended to the body instead of the parent element.", + defaultValue: { summary: false }, + }, + }, decorators: [ (Story) => ( diff --git a/packages/wethegit-components/src/components/modal/modal.tsx b/packages/wethegit-components/src/components/modal/modal.tsx index f3674cdd..5603470b 100644 --- a/packages/wethegit-components/src/components/modal/modal.tsx +++ b/packages/wethegit-components/src/components/modal/modal.tsx @@ -7,6 +7,7 @@ import { ModalBackdrop, useModal, } from "@wethegit/react-modal" +import type { ModalProps as WTCModalProps } from "@wethegit/react-modal" import { useAnimatePresence, useUserPrefs } from "@wethegit/react-hooks" import "@wethegit/react-modal/style.css" @@ -15,12 +16,7 @@ import { classnames } from "@local/utilities" import styles from "./modal.module.scss" -export interface ModalProps { - /** - * If true the modal will be appended to the body instead of the parent element. - * @defaultValue true - */ - appendToBody?: boolean +export interface ModalProps extends WTCModalProps { /** * If provided, the modal state will be controlled by the hash in the URL. */ From 4eefd0e06ecddc94f9e3267824d09c8edbf7e8fb Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:48:27 -0800 Subject: [PATCH 15/19] fix: global styles --- packages/wethegit-components/.storybook/preview.ts | 1 + packages/wethegit-components/src/components/modal/modal.tsx | 2 -- .../src/components/modal/readme.stories.mdx | 6 ++++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/wethegit-components/.storybook/preview.ts b/packages/wethegit-components/.storybook/preview.ts index c6cf5a1d..2ba69b5e 100644 --- a/packages/wethegit-components/.storybook/preview.ts +++ b/packages/wethegit-components/.storybook/preview.ts @@ -3,6 +3,7 @@ import { withThemeByClassName } from "@storybook/addon-themes" import { wtcTheme } from "./static/wtc-theme" +import "@wethegit/react-modal/style.css" import "./styles/global-story-styles.scss" const preview: Preview = { diff --git a/packages/wethegit-components/src/components/modal/modal.tsx b/packages/wethegit-components/src/components/modal/modal.tsx index 5603470b..4286b018 100644 --- a/packages/wethegit-components/src/components/modal/modal.tsx +++ b/packages/wethegit-components/src/components/modal/modal.tsx @@ -10,8 +10,6 @@ import { import type { ModalProps as WTCModalProps } from "@wethegit/react-modal" import { useAnimatePresence, useUserPrefs } from "@wethegit/react-hooks" -import "@wethegit/react-modal/style.css" - import { classnames } from "@local/utilities" import styles from "./modal.module.scss" diff --git a/packages/wethegit-components/src/components/modal/readme.stories.mdx b/packages/wethegit-components/src/components/modal/readme.stories.mdx index 40501ff2..dfe3f098 100644 --- a/packages/wethegit-components/src/components/modal/readme.stories.mdx +++ b/packages/wethegit-components/src/components/modal/readme.stories.mdx @@ -14,6 +14,12 @@ npx @wethegit/components-cli add modal ### Usage +First, import the global modal styles from `@wethegit/react-modal` into your global stylesheet or root layout: + +```scss +@import "@wethegit/react-modal/style.css"; +``` + Most of the time all you need is a button that toggles a modal. The `` component takes a `trigger` prop that is a function which receives a `toggle` function as its only argument and returns the element that will trigger the modal. From 84fe8fd47a1601cab3018963305bcebb018f7978 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Tue, 28 Nov 2023 15:52:50 -0800 Subject: [PATCH 16/19] fix: explain props on docs --- packages/wethegit-components/src/components/modal/modal.tsx | 4 ++-- .../src/components/modal/readme.stories.mdx | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/wethegit-components/src/components/modal/modal.tsx b/packages/wethegit-components/src/components/modal/modal.tsx index 4286b018..c5c3085f 100644 --- a/packages/wethegit-components/src/components/modal/modal.tsx +++ b/packages/wethegit-components/src/components/modal/modal.tsx @@ -33,7 +33,7 @@ export interface ModalProps extends WTCModalProps { * Wrapper around the `@wethegit/react-modal` component that adds a trigger and takes care of reducing motion. * For more information, see the [modal documentation](https://github.com/wethegit/react-modal). */ -export function Modal({ hash, children, appendToBody = true, trigger }: ModalProps) { +export function Modal({ hash, children, trigger, ...props }: ModalProps) { const triggerButton = useRef(null) const { isOpen, toggle } = useModal({ triggerRef: triggerButton, @@ -55,9 +55,9 @@ export function Modal({ hash, children, appendToBody = true, trigger }: ModalPro {render && ( diff --git a/packages/wethegit-components/src/components/modal/readme.stories.mdx b/packages/wethegit-components/src/components/modal/readme.stories.mdx index dfe3f098..e87cb7f8 100644 --- a/packages/wethegit-components/src/components/modal/readme.stories.mdx +++ b/packages/wethegit-components/src/components/modal/readme.stories.mdx @@ -20,9 +20,7 @@ First, import the global modal styles from `@wethegit/react-modal` into your glo @import "@wethegit/react-modal/style.css"; ``` -Most of the time all you need is a button that toggles a modal. - -The `` component takes a `trigger` prop that is a function which receives a `toggle` function as its only argument and returns the element that will trigger the modal. +The `` component takes a `trigger` prop that is a function which receives a `toggle` function as its only argument and should return the element that will trigger the modal. It also handles reduced motion by default and because of that you are required to make sure that the modal component renders inside the [UserPreferencesProvider](https://wethegit.github.io/react-hooks/user-preferences-provider). From fd56775a643a9cd6f89aaf0b97fa9b3eca76d7bf Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Wed, 29 Nov 2023 14:15:17 -0800 Subject: [PATCH 17/19] wip: simplifies API for Modal --- .../src/components/modal/modal.stories.tsx | 35 +++++------- .../src/components/modal/modal.tsx | 57 +++++++------------ .../src/components/modal/readme.stories.mdx | 25 ++++---- 3 files changed, 51 insertions(+), 66 deletions(-) diff --git a/packages/wethegit-components/src/components/modal/modal.stories.tsx b/packages/wethegit-components/src/components/modal/modal.stories.tsx index 13ae28f2..cdb49cf1 100644 --- a/packages/wethegit-components/src/components/modal/modal.stories.tsx +++ b/packages/wethegit-components/src/components/modal/modal.stories.tsx @@ -7,23 +7,15 @@ const meta = { title: "components/modal", component: Modal, args: { - trigger: (toggle) => , - appendToBody: false, - }, - argTypes: { - appendToBody: { - description: - "If true the modal will be appended to the body instead of the parent element.", - defaultValue: { summary: false }, - }, + isOpen: true, }, decorators: [ (Story) => ( - -
+
+ -
- + +
), ], } satisfies Meta @@ -33,11 +25,14 @@ export default meta type Story = StoryObj export const Default: Story = { - render: (args) => ( - -

- Excepteur mollit laboris culpa commodo ex. -

-
- ), + render: (args) => { + return ( + +

+ Close button doesn't work becayse inside the story we use the{" "} + isOpen control. +

+
+ ) + }, } diff --git a/packages/wethegit-components/src/components/modal/modal.tsx b/packages/wethegit-components/src/components/modal/modal.tsx index c5c3085f..9425c57f 100644 --- a/packages/wethegit-components/src/components/modal/modal.tsx +++ b/packages/wethegit-components/src/components/modal/modal.tsx @@ -1,12 +1,6 @@ "use client" -import { useRef } from "react" -import { - Modal as WTCModal, - ModalContent, - ModalBackdrop, - useModal, -} from "@wethegit/react-modal" +import { Modal as WTCModal, ModalContent, ModalBackdrop } from "@wethegit/react-modal" import type { ModalProps as WTCModalProps } from "@wethegit/react-modal" import { useAnimatePresence, useUserPrefs } from "@wethegit/react-hooks" @@ -16,13 +10,13 @@ import styles from "./modal.module.scss" export interface ModalProps extends WTCModalProps { /** - * If provided, the modal state will be controlled by the hash in the URL. + * Whether the modal is open or not. */ - hash?: string + isOpen: boolean /** - * A function that returns the trigger element for the modal. + * A function that toggles the modal. */ - trigger: (toggleModal: () => void) => React.ReactNode + toggle: () => void /** * The modal content. */ @@ -33,12 +27,7 @@ export interface ModalProps extends WTCModalProps { * Wrapper around the `@wethegit/react-modal` component that adds a trigger and takes care of reducing motion. * For more information, see the [modal documentation](https://github.com/wethegit/react-modal). */ -export function Modal({ hash, children, trigger, ...props }: ModalProps) { - const triggerButton = useRef(null) - const { isOpen, toggle } = useModal({ - triggerRef: triggerButton, - hash, - }) +export function Modal({ children, isOpen, toggle, ...props }: ModalProps) { const { prefersReducedMotion } = useUserPrefs() const { render, animate, currentDuration } = useAnimatePresence({ isVisible: isOpen, @@ -49,25 +38,21 @@ export function Modal({ hash, children, trigger, ...props }: ModalProps) { "--duration": `${currentDuration}ms`, } as React.CSSProperties - return ( - <> - {trigger && trigger(toggle)} + if (!render) return null - {render && ( - - - - - {children} - - - )} - + return ( + + + + + {children} + + ) } diff --git a/packages/wethegit-components/src/components/modal/readme.stories.mdx b/packages/wethegit-components/src/components/modal/readme.stories.mdx index e87cb7f8..81500f25 100644 --- a/packages/wethegit-components/src/components/modal/readme.stories.mdx +++ b/packages/wethegit-components/src/components/modal/readme.stories.mdx @@ -25,28 +25,33 @@ The `` component takes a `trigger` prop that is a function which receives It also handles reduced motion by default and because of that you are required to make sure that the modal component renders inside the [UserPreferencesProvider](https://wethegit.github.io/react-hooks/user-preferences-provider). ```tsx -import { useCallback } from "react" +import { useRef } from "react" +import { useModal } from "@wethegit/react-modal" +import { UserPreferencesProvider } from "@wethegit/react-hooks" import { Modal } from "@local/components" function Page() { - const trigger = useCallback( - (toggle) => , - [] - ) + const triggerRef = useRef(null) + const props = useModal({ + triggerRef, + }) return ( - -
- + <> + + +

Modal Content

Pariatur occaecat quis aliquip excepteur adipisicing minim ipsum qui proident qui voluptate ut sunt.

-
-
+
+ ) } ``` From 873a6f9a95af2ce7590a67d144b4e6c790647b4a Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Wed, 29 Nov 2023 14:20:00 -0800 Subject: [PATCH 18/19] fix: missing prop --- .../wethegit-components/src/components/modal/readme.stories.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wethegit-components/src/components/modal/readme.stories.mdx b/packages/wethegit-components/src/components/modal/readme.stories.mdx index 81500f25..bd737f24 100644 --- a/packages/wethegit-components/src/components/modal/readme.stories.mdx +++ b/packages/wethegit-components/src/components/modal/readme.stories.mdx @@ -39,7 +39,7 @@ function Page() { return ( <> - From f7a7eb40448cf815b966bc559ee93d60481b6206 Mon Sep 17 00:00:00 2001 From: Marlon Marcello Date: Fri, 1 Dec 2023 17:36:01 -0800 Subject: [PATCH 19/19] patch(comp > modal): adds a new story with a button trigger --- .../src/components/modal/modal.stories.tsx | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/wethegit-components/src/components/modal/modal.stories.tsx b/packages/wethegit-components/src/components/modal/modal.stories.tsx index cdb49cf1..f17c9aae 100644 --- a/packages/wethegit-components/src/components/modal/modal.stories.tsx +++ b/packages/wethegit-components/src/components/modal/modal.stories.tsx @@ -1,5 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react" import { UserPreferencesProvider } from "@wethegit/react-hooks" +import { useModal } from "@wethegit/react-modal" +import { useRef } from "react" import { Modal } from "./modal" @@ -27,7 +29,7 @@ type Story = StoryObj export const Default: Story = { render: (args) => { return ( - +

Close button doesn't work becayse inside the story we use the{" "} isOpen control. @@ -36,3 +38,43 @@ export const Default: Story = { ) }, } + +export const WithButtonTrigger: Story = { + render: () => { + const triggerRef = useRef(null) + const { isOpen, toggle } = useModal({ + triggerRef, + }) + + return ( +

+ + +

+ Close button doesn't work becayse inside the story we use the{" "} + isOpen control. +

+
+
+ ) + }, +}