From 531df1e85eafd4469bf1066205bb97dd3e0b3fec Mon Sep 17 00:00:00 2001 From: Damini Date: Thu, 29 Feb 2024 23:57:36 +0530 Subject: [PATCH 1/4] feat: initial commit --- .../nativewind/Tooltip/index.tsx | 325 ++++++------------ .../src/components/Tooltip/Tooltip.tsx | 54 --- 2 files changed, 101 insertions(+), 278 deletions(-) diff --git a/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx b/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx index a03248443f..6076e0a782 100644 --- a/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx +++ b/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx @@ -1,93 +1,39 @@ +import React, { useEffect } from 'react'; import { createTooltip } from '@gluestack-ui/tooltip'; +import { View, Text, Platform } from 'react-native'; import { - AnimatePresence, - AnimatedView, -} from '@gluestack-style/animation-resolver'; -import { View, Text } from 'react-native'; -import { tva, withStyleContext } from '@gluestack-ui/nativewind-utils'; -import React from 'react'; + tva, + withStyleContext, + withStyleContextAndStates, + VariantProps, +} from '@gluestack-ui/nativewind-utils'; +import Animated, { + Easing, + useSharedValue, + withSpring, + withTiming, +} from 'react-native-reanimated'; export const UITooltip = createTooltip({ - Root: withStyleContext(View), - Content: AnimatedView, + Root: + Platform.OS === 'web' + ? withStyleContext(View) + : withStyleContextAndStates(View), + Content: Animated.View, Text: Text, - //@ts-ignore - AnimatePresence: AnimatePresence, + AnimatePresence: React.Fragment, // TODO: Add support for this }); const tooltipStyle = tva({ base: 'w-full h-full web:pointer-events-none', }); -// const StyledRoot = styled( -// View, -// { -// width: '$full', -// height: '$full', -// _web: { -// pointerEvents: 'none', -// }, -// }, -// {} -// ); - const tooltipContentStyle = tva({ - base: 'py-1 px-3 rounded-sm bg-background-900 web:pointer-events-auto shadow', + base: 'py-1 px-3 rounded-sm bg-background-900 web:pointer-events-auto', }); -// const StyledContent = styled( -// AnimatedView, -// { -// ':initial': { -// opacity: 0, -// scale: 0.5, -// }, - -// ':animate': { -// opacity: 1, -// scale: 1, -// }, - -// ':exit': { -// opacity: 0, -// scale: 0.5, -// }, - -// ':transition': { -// type: 'spring', -// damping: 18, -// stiffness: 250, -// opacity: { -// type: 'timing', -// duration: 250, -// }, -// }, - -// 'py': '$1', -// 'px': '$3', -// 'borderRadius': '$sm', -// 'bg': '$background900', - -// '_text': { -// fontSize: '$xs', -// color: '$text50', -// }, - -// '_web': { -// pointerEvents: 'auto', -// }, - -// 'defaultProps': { -// hardShadow: '2', -// }, -// }, -// { -// descendantStyle: ['_text'], -// } -// ); - const tooltipTextStyle = tva({ - base: 'font-normal tracking-normal text-red-400 web:select-none text-xs text-text-50', + base: 'font-normal tracking-normal text-red-400 web:select-none', variants: { isTruncated: { @@ -95,159 +41,79 @@ const tooltipTextStyle = tva({ props: 'line-clamp-1 truncate', }, }, - }, - bold: { - true: 'font-bold', - }, - underline: { - true: 'underline', - }, - strikeThrough: { - true: 'line-through', - }, - size: { - '2xs': 'text-2xs', - 'xs': 'text-xs', - 'sm': 'text-sm', - 'md': 'text-base', - 'lg': 'text-lg', - 'xl': 'text-xl', - '2xl': 'text-2xl', - '3xl': 'text-3xl', - '4xl': 'text-4xl', - '5xl': 'text-5xl', - '6xl': 'text-6xl', - }, - sub: { - true: 'text-xs', - }, - italic: { - true: 'italic', - }, - highlight: { - true: 'bg-yellow-500', + bold: { + true: 'font-bold', + }, + underline: { + true: 'underline', + }, + strikeThrough: { + true: 'line-through', + }, + size: { + '2xs': 'text-2xs', + 'xs': 'text-xs', + 'sm': 'text-sm', + 'md': 'text-base', + 'lg': 'text-lg', + 'xl': 'text-xl', + '2xl': 'text-2xl', + '3xl': 'text-3xl', + '4xl': 'text-4xl', + '5xl': 'text-5xl', + '6xl': 'text-6xl', + }, + sub: { + true: 'text-xs', + }, + italic: { + true: 'italic', + }, + highlight: { + true: 'bg-yellow-500', + }, }, }); -// const StyledText = styled( -// Text, -// { -// fontWeight: '$normal', -// fontStyle: 'normal', -// letterSpacing: '$md', - -// variants: { -// isTruncated: { -// true: { -// props: { -// // @ts-ignore -// numberOfLines: 1, -// ellipsizeMode: 'tail', -// }, -// }, -// }, -// bold: { -// true: { -// fontWeight: '$bold', -// }, -// }, -// underline: { -// true: { -// textDecorationLine: 'underline', -// }, -// }, -// strikeThrough: { -// true: { -// textDecorationLine: 'line-through', -// }, -// }, -// size: { -// '2xs': { -// fontSize: '$2xs', -// }, -// 'xs': { -// fontSize: '$xs', -// }, - -// 'sm': { -// fontSize: '$sm', -// }, - -// 'md': { -// fontSize: '$md', -// }, - -// 'lg': { -// fontSize: '$lg', -// }, - -// 'xl': { -// fontSize: '$xl', -// }, - -// '2xl': { -// fontSize: '$2xl', -// }, - -// '3xl': { -// fontSize: '$3xl', -// }, - -// '4xl': { -// fontSize: '$4xl', -// }, - -// '5xl': { -// fontSize: '$5xl', -// }, +type ITooltipProps = React.ComponentProps & + VariantProps; +type ITooltipContentProps = React.ComponentProps & + VariantProps; +type ITooltipTextProps = React.ComponentProps & + VariantProps; -// '6xl': { -// fontSize: '$6xl', -// }, -// }, -// sub: { -// true: { -// fontSize: '$xs', -// }, -// }, -// italic: { -// true: { -// fontStyle: 'italic', -// }, -// }, -// highlight: { -// true: { -// bg: '$yellow500', -// }, -// }, -// }, - -// defaultProps: { -// size: 'md', -// }, -// color: '$red400', -// fontFamily: '$body', -// _web: { -// userSelect: 'none', -// }, -// }, -// { -// ancestorStyle: ['_text'], -// } -// ); - -export const Tooltip = React.forwardRef(({ className, ...props }: any, ref) => { - return ( - - ); -}); +export const Tooltip = React.forwardRef( + ({ className, ...props }: { className?: string } & ITooltipProps, ref) => { + return ( + + ); + } +); export const TooltipContent = React.forwardRef( - ({ className, ...props }: any, ref) => { + ( + { className, ...props }: { className?: string } & ITooltipContentProps, + ref + ) => { + const opacity = useSharedValue(0); + const scale = useSharedValue(0.5); + useEffect(() => { + opacity.value = withTiming(1, { + easing: Easing.linear, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect(() => { + scale.value = withSpring(1, { + damping: 18, + stiffness: 250, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return ( ); } ); export const TooltipText = React.forwardRef( - ({ className, size = 'md', ...props }: any, ref) => { + ( + { + className, + size = 'md', + ...props + }: { className?: string } & ITooltipTextProps, + ref + ) => { return ( ); } diff --git a/example/storybook-nativewind/src/components/Tooltip/Tooltip.tsx b/example/storybook-nativewind/src/components/Tooltip/Tooltip.tsx index 7d1b9e6e2d..def29741db 100644 --- a/example/storybook-nativewind/src/components/Tooltip/Tooltip.tsx +++ b/example/storybook-nativewind/src/components/Tooltip/Tooltip.tsx @@ -1,16 +1,4 @@ import React from 'react'; -import { - Center, - Text, - Avatar, - AvatarGroup, - AvatarFallbackText, - Box, - Heading, - VStack, - HStack, - Icon, -} from '@gluestack-ui/themed'; import { Tooltip, TooltipContent, TooltipText } from '@/components/ui/Tooltip'; import { Button, ButtonText } from '@/components/ui/Button'; import { Edit, Command } from 'lucide-react-native'; @@ -42,60 +30,18 @@ const TooltipBasic = ({ ); }; -const FigmaTooltipStory = ({ - showTooltip: _showTooltipProp = true, - _placement = 'bottom', - ...props -}: any) => { - 2; - return ( - { - return ( - - - - ); - }} - > - - Hello world! - - - ); -}; - TooltipBasic.description = 'This is a basic Tooltip component example. A tooltip is a popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.'; export default TooltipBasic; export { - FigmaTooltipStory, TooltipBasic, Tooltip, TooltipContent, TooltipText, - Center, Button, ButtonText, - Text, - Avatar, - AvatarGroup, - AvatarFallbackText, - Box, - Heading, Edit, - VStack, Command, - HStack, - Icon, }; From 9d6fd6b0fca81c7fe9ebef45084b241d82471564 Mon Sep 17 00:00:00 2001 From: Damini Date: Fri, 1 Mar 2024 11:10:13 +0530 Subject: [PATCH 2/4] feat: add tooltip component --- .../src/components-example/nativewind/Tooltip/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx b/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx index 6076e0a782..4f359f5ca5 100644 --- a/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx +++ b/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx @@ -33,7 +33,7 @@ const tooltipContentStyle = tva({ }); const tooltipTextStyle = tva({ - base: 'font-normal tracking-normal text-red-400 web:select-none', + base: 'font-normal tracking-normal text-red-400 web:select-none text-xs text-text-50', variants: { isTruncated: { From 7ff00fe56dd45e549f058474c6c30a41ea0679f8 Mon Sep 17 00:00:00 2001 From: Damini Date: Fri, 1 Mar 2024 11:14:37 +0530 Subject: [PATCH 3/4] fix: text typography color --- .../src/components-example/nativewind/Tooltip/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx b/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx index 4f359f5ca5..3739af78bd 100644 --- a/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx +++ b/example/storybook-nativewind/src/components-example/nativewind/Tooltip/index.tsx @@ -33,7 +33,7 @@ const tooltipContentStyle = tva({ }); const tooltipTextStyle = tva({ - base: 'font-normal tracking-normal text-red-400 web:select-none text-xs text-text-50', + base: 'font-normal tracking-normal text-red-400 web:select-none text-xs text-typography-50', variants: { isTruncated: { From 74c9b0b716777c42cb44002aac93427f376888b6 Mon Sep 17 00:00:00 2001 From: Damini Date: Fri, 8 Mar 2024 11:51:31 +0530 Subject: [PATCH 4/4] feat: add tooltip examples --- .../components/Tooltip/index.nw.stories.mdx | 605 +++++++++++++++++- .../Tooltip/index.themed.stories.mdx | 2 +- .../src/core-components/nativewind/index.ts | 1 + 3 files changed, 602 insertions(+), 6 deletions(-) diff --git a/example/storybook-nativewind/src/components/Tooltip/index.nw.stories.mdx b/example/storybook-nativewind/src/components/Tooltip/index.nw.stories.mdx index 0e225322c9..26b2c35ecb 100644 --- a/example/storybook-nativewind/src/components/Tooltip/index.nw.stories.mdx +++ b/example/storybook-nativewind/src/components/Tooltip/index.nw.stories.mdx @@ -7,15 +7,610 @@ pageTitle: Tooltip pageDescription: Whether you need to provide helpful hints to new users or display extra details for power users, the Tooltip component is a simple and effective way. -showHeader: false - -tag: coming soon +showHeader: true --- import { Meta } from '@storybook/addon-docs'; -# Tooltip +import { + Tooltip, + TooltipContent, + TooltipText, + Button, + ButtonText, + Avatar, + AvatarGroup, + AvatarFallbackText, + HStack, + Box, + Heading, + EditIcon, + Center, + VStack, + Icon +} from '../../core-components/nativewind'; +import { transformedCode } from '../../utils'; +import { + AppProvider, + CodePreview, + Table, + TableContainer, + Text, + InlineCode, + CollapsibleCode +} from '@gluestack/design-system'; +import Wrapper from '../../core-components/nativewind/Wrapper'; +; +import {Command} from 'lucide-react-native'; + +This is an illustration of **Tooltip** component. + +<> + { + return ( + + ); + }} + > + + Tooltip + + + `, + transformCode: (code) => { + return transformedCode(code); + }, + scope: { + Wrapper, + Tooltip, + TooltipContent, + TooltipText, + Center, + Button, + ButtonText, + }, + argsType: { + placement: { + control: 'select', + options: [ + 'top left', + 'top', + 'top right', + 'left top', + 'left', + 'left bottom', + 'bottom left', + 'bottom', + 'bottom right', + 'right top', + 'right', + 'right bottom', + ], + default: 'top', + }, + }, + }} + /> + + +
+ +## Installation + +### Step 1: Install the following dependencies: + +```bash + +npm i @gluestack-ui/tooltip + +``` + +### Step 2: Copy and paste the following code into your project. + + + +```jsx +%%-- File: core-components/nativewind/tooltip/index.tsx --%% +``` + + + +### Step 3: Update the import paths to match your project setup. + +## API Reference + +To use this component in your project, include the following import statement in your file. + +```jsx +import { Tooltip } from '@/components/ui/tooltip'; +``` + +```jsx +export default () => ( + + + + + +); +``` +### Component Props + +This section provides a comprehensive reference list for the component props, detailing descriptions, properties, types, and default behavior for easy project integration. + +#### Tooltip + +It inherits all the properties of React Native's [View](https://reactnative.dev/docs/view) component. + +<> + + + + + + Prop + + + Type + + + Default + + + Description + + + + + + + + isOpen + + + + boolean + + + false + + + {`Whether the tooltip is opened. Useful for controlling the open state.`} + + + + + + isDisabled + + + + boolean + + + false + + + {`Whether the tooltip is disabled.`} + + + + + + defaultIsOpen + + + + boolean + + + false + + + {`If true, the popover will be opened by default.`} + + + + + + onOpen + + + + {'() => void'} + + + true + + + {`This function will be invoked when the tooltip is opened.`} + + + + + + onClose + + + + {'() => void'} + + + - + + + {`This function will be invoked when tooltip is closed. It will also be called when the user attempts to close the tooltip via Escape key or backdrop press.`} + + + + + + openDelay + + + + {'number'} + + + 0 + + + {`Duration in ms to wait till displaying the tooltip.`} + + + + + + closeDelay + + + + {'number'} + + + 0 + + + {`Duration in ms to wait till hiding the tooltip.`} + + + + + + placement + + + + {`"bottom" | "top" | "right" | "left" | "top left" | "top right" | "bottom left" | "bottom right" | "right top" | "right bottom" | "left top" | "left bottom"`} + + + bottom left + + + {`Tooltip placement`} + + + + + + children + + + + any + + + - + + + + The content to display inside the tooltip. + + + + + + + closeOnClick + + + + boolean + + + true + + + + Whether tooltip should be closed on Trigger click. + + + + + + + trigger + + + + {`() => any`} + + + - + + + {`Function that returns a React Element. This element will be used as a Trigger for the tooltip.`} + + + + + + offset + + + + number + + + 10 + + + + Distance between the trigger and the tooltip. + + + + + + + crossOffset + + + + number + + + - + + + + The additional offset applied along the cross axis between the + element and its trigger element. + + + + + + + shouldOverlapWithTrigger + + + + boolean + + + false + + + + Determines whether tooltip content should overlap with the + trigger. + + + + + + + shouldFlip + + + + boolean + + + true + + + + Whether the element should flip its orientation (e.g. top to + bottom or left to right) when there is insufficient room for it to + render completely. + + + + + + + closeOnOverlayClick + + + + boolean + + + true + + + {`Closes tooltip when clicked outside.`} + + + +
+
+ + +#### TooltipText + +Contains all text related layout style props and actions. It inherits all the properties of React Native's Text component. + +#### TooltipContent + +Contains all backdrop related layout style props and actions. It inherits all the properties of React Native's [View](https://reactnative.dev/docs/view) component. + +### Accessibility + +We have outlined the various features that ensure the Tooltip component is accessible to all users, including those with disabilities. These features help ensure that your application is inclusive and meets accessibility standards. It adheres to the [ WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/). + +### Examples + +#### Tooltip with Heading + +A tooltip component with an avatar is a user interface element that displays a small pop-up box of additional information when the user hovers over or interacts with an avatar or an icon. + + + + + { + return ( + + + 3 + + ) + }} + > + + + View all members of this channel +
+ Includes John, Sarah, Mike, Emily + and David +
+
+
+
+ + Sandeep Srivastva + + + Arjun Kapoor + + + Ritik Sharma + +
+ + ); + } + `, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Avatar, + AvatarGroup, + AvatarFallbackText, + Wrapper, + HStack, + Tooltip, + TooltipContent, + TooltipText, + Text, + Box, + Heading, + VStack, + Center, + }, + argsType: {}, + }} + /> +
+ +#### Tooltip with Icon + +A tooltip component with an icon is a user interface element that provides contextual information or explanatory text when the user hovers over or interacts with an icon. + + + + { + return ( + + + + ) + }} + > + + + New message + + + + + + N + + + + + + + ); + } + `, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Avatar, + AvatarFallbackText, + Wrapper, + HStack, + Tooltip, + TooltipContent, + TooltipText, + Text, + Box, + Heading, + EditIcon, + Command, + Icon, + }, + argsType: {}, + }} + /> + + + + + -Coming Soon! \ No newline at end of file diff --git a/example/storybook-nativewind/src/components/Tooltip/index.themed.stories.mdx b/example/storybook-nativewind/src/components/Tooltip/index.themed.stories.mdx index 7c4c831c65..d1bab31bbc 100644 --- a/example/storybook-nativewind/src/components/Tooltip/index.themed.stories.mdx +++ b/example/storybook-nativewind/src/components/Tooltip/index.themed.stories.mdx @@ -627,7 +627,7 @@ A tooltip component with an icon is a user interface element that provides conte New message - + diff --git a/example/storybook-nativewind/src/core-components/nativewind/index.ts b/example/storybook-nativewind/src/core-components/nativewind/index.ts index 9d570d6744..d24c280d57 100644 --- a/example/storybook-nativewind/src/core-components/nativewind/index.ts +++ b/example/storybook-nativewind/src/core-components/nativewind/index.ts @@ -7,6 +7,7 @@ export * from './avatar'; export * from './badge'; export * from './box'; export * from './flat-list'; +export * from './card'; export * from './center'; export * from './checkbox'; export * from './hstack';