From e2198afcf71e9bef79e43bf7a1b2a2f19a8a42a8 Mon Sep 17 00:00:00 2001 From: Kirill Zyusko Date: Fri, 13 Sep 2024 15:27:17 +0200 Subject: [PATCH] docs: hoverable keyboard (interactive animation) (#583) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📜 Description Added new animation - you can interact with it! ## 💡 Motivation and Context To make docs apges slightly more interactive and attractive. ## 📢 Changelog ### Docs - added `HoverableKeyboard` component; - started to use this component on `useFocusedInputHandler` page. ## 🤔 How Has This Been Tested? Tested via preview. ## 📸 Screenshots (if appropriate): image ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed --- .eslintrc.cjs | 2 +- cspell.json | 4 +- .../hooks/input/use-focused-input-handler.mdx | 6 + .../HoverableKeyboardSVG.tsx | 575 ++++++++++++++++++ .../components/HoverableKeyboard/index.tsx | 56 ++ docs/src/css/custom.css | 74 +++ .../hooks/input/use-focused-input-handler.mdx | 6 + .../hooks/input/use-focused-input-handler.mdx | 6 + 8 files changed, 727 insertions(+), 2 deletions(-) create mode 100644 docs/src/components/HoverableKeyboard/HoverableKeyboardSVG.tsx create mode 100644 docs/src/components/HoverableKeyboard/index.tsx diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 803865a18..99cce64b2 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -168,5 +168,5 @@ module.exports = { "react-native/react-native": true, "jest/globals": true, }, - ignorePatterns: ["node_modules/**", "lib/**", "scripts/**"], + ignorePatterns: ["node_modules/**", "lib/**", "scripts/**", "docs/build/**"], }; diff --git a/cspell.json b/cspell.json index b0fc29eca..3edf36f60 100644 --- a/cspell.json +++ b/cspell.json @@ -119,7 +119,9 @@ "swmansion", "rnscreens", "setinputmode", - "useanimatedkeyboard" + "useanimatedkeyboard", + "Hoverable", + "zxcvbnmasdfghjklqwertyuiop" ], "ignorePaths": [ "node_modules", diff --git a/docs/docs/api/hooks/input/use-focused-input-handler.mdx b/docs/docs/api/hooks/input/use-focused-input-handler.mdx index 222704e87..719acb8c3 100644 --- a/docs/docs/api/hooks/input/use-focused-input-handler.mdx +++ b/docs/docs/api/hooks/input/use-focused-input-handler.mdx @@ -16,6 +16,12 @@ keywords: # useFocusedInputHandler +import HoverableKeyboard from "@site/src/components/HoverableKeyboard"; + +
+ +
+ `useFocusedInputHandler` is a hook that allows to intercept events from a focused `TextInput`. ## Example diff --git a/docs/src/components/HoverableKeyboard/HoverableKeyboardSVG.tsx b/docs/src/components/HoverableKeyboard/HoverableKeyboardSVG.tsx new file mode 100644 index 000000000..0c4a9fe51 --- /dev/null +++ b/docs/src/components/HoverableKeyboard/HoverableKeyboardSVG.tsx @@ -0,0 +1,575 @@ +type Props = { + onHoverFocus: () => void; + onHoverBlur: () => void; +}; + +export default function FrameSVG({ onHoverFocus, onHoverBlur }: Props) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/docs/src/components/HoverableKeyboard/index.tsx b/docs/src/components/HoverableKeyboard/index.tsx new file mode 100644 index 000000000..8a87313de --- /dev/null +++ b/docs/src/components/HoverableKeyboard/index.tsx @@ -0,0 +1,56 @@ +import React, { useCallback, useEffect, useRef } from "react"; + +import HoverableKeyboardSVG from "./HoverableKeyboardSVG"; + +const alphabet = "zxcvbnmasdfghjklqwertyuiop_"; +const storyToTell = "Hello, World!".toLowerCase().replace(/ /g, "_"); + +function HoverableKeyboard() { + const timerRef = useRef(null); + const currentLetterRef = useRef(""); + + const cleanCurrentlyAnimatedLetter = useCallback(() => { + document + .getElementById(currentLetterRef.current) + ?.classList.remove("hover"); + }, []); + const onStopAnimation = useCallback(() => { + clearInterval(timerRef.current); + cleanCurrentlyAnimatedLetter(); + }, [cleanCurrentlyAnimatedLetter]); + const onStartAnimation = useCallback(() => { + let i = 0; + + timerRef.current = setInterval(() => { + if (i >= storyToTell.length) { + i = 0; + + return; + } + + setTimeout(cleanCurrentlyAnimatedLetter, 200); + currentLetterRef.current = storyToTell[i++]; + + if (!alphabet.includes(currentLetterRef.current)) { + return; + } + + document.getElementById(currentLetterRef.current)?.classList.add("hover"); + }, 350); + }, [cleanCurrentlyAnimatedLetter]); + + useEffect(() => { + onStartAnimation(); + + return onStopAnimation; + }, [onStartAnimation, onStopAnimation]); + + return ( + + ); +} + +export default HoverableKeyboard; diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 82d60b323..a797bcfd6 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -234,3 +234,77 @@ h3 .label { width: 100%; height: 100%; } + +.keyboard-button { + transition: all 0.25s ease-in-out; +} + +.keyboard-button-primary { + transition: all 0.25s ease-in-out; +} + +.keyboard-button-secondary { + transition: all 0.25s ease-in-out; +} + +.keyboard-button-secondary-2 { + transition: all 0.25s ease-in-out; +} + +.keyboard-button-group:hover .keyboard-button { + fill: rgb(160, 160, 160); +} + +.keyboard-button-group:hover .keyboard-button-primary { + fill: rgb(46, 157, 255); +} + +.keyboard-button-group:hover .keyboard-button-secondary { + fill: rgb(123, 123, 123); +} + +.keyboard-button-group:hover .keyboard-button-secondary-2 { + fill: rgb(255, 255, 255); +} + +.hover { + fill: rgb(50, 50, 50); +} + +@keyframes typing { + 0% { + transform: translateY(0px); + } + 25% { + transform: translateY(0px); + } + 50% { + transform: translateY(-5px); + } + 100% { + transform: translateY(0px); + } +} + +.dot { + animation-iteration-count: infinite; + animation-name: typing; + animation-duration: 1s; +} + +.dot-1 { + animation-delay: 0s; +} + +.dot-2 { + animation-delay: 0.2s; +} + +.dot-3 { + animation-delay: 0.4s; +} + +.interactive-animation { + height: 400px; + margin-bottom: 24px; +} diff --git a/docs/versioned_docs/version-1.12.0/api/hooks/input/use-focused-input-handler.mdx b/docs/versioned_docs/version-1.12.0/api/hooks/input/use-focused-input-handler.mdx index 222704e87..719acb8c3 100644 --- a/docs/versioned_docs/version-1.12.0/api/hooks/input/use-focused-input-handler.mdx +++ b/docs/versioned_docs/version-1.12.0/api/hooks/input/use-focused-input-handler.mdx @@ -16,6 +16,12 @@ keywords: # useFocusedInputHandler +import HoverableKeyboard from "@site/src/components/HoverableKeyboard"; + +
+ +
+ `useFocusedInputHandler` is a hook that allows to intercept events from a focused `TextInput`. ## Example diff --git a/docs/versioned_docs/version-1.13.0/api/hooks/input/use-focused-input-handler.mdx b/docs/versioned_docs/version-1.13.0/api/hooks/input/use-focused-input-handler.mdx index 222704e87..719acb8c3 100644 --- a/docs/versioned_docs/version-1.13.0/api/hooks/input/use-focused-input-handler.mdx +++ b/docs/versioned_docs/version-1.13.0/api/hooks/input/use-focused-input-handler.mdx @@ -16,6 +16,12 @@ keywords: # useFocusedInputHandler +import HoverableKeyboard from "@site/src/components/HoverableKeyboard"; + +
+ +
+ `useFocusedInputHandler` is a hook that allows to intercept events from a focused `TextInput`. ## Example