Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add TooltipContext to set global timeout values #846

Merged
merged 3 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Reactist follows [semantic versioning](https://semver.org/) and doesn't introduce breaking changes (API-wise) in minor or patch releases. However, the appearance of a component might change in a minor or patch release so keep an eye on redesigns and make sure your app still looks and feels like you expect it.

# 26.2.0

- [Feat] Add `TooltipContext` to allow `showTimeout` and `hideTimeout` to be set globally

# v26.1.0

- [Feat] Expose `showTimeout` and `hideTimeout` props for `Tooltip`
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"email": "[email protected]",
"url": "http://doist.com"
},
"version": "26.1.0",
"version": "26.2.0",
"license": "MIT",
"homepage": "https://github.com/Doist/reactist#readme",
"repository": {
Expand Down
67 changes: 54 additions & 13 deletions src/tooltip/tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react'
import { createPortal } from 'react-dom'

import { Tooltip, TooltipProps } from './tooltip'
import { Tooltip, TooltipContext, TooltipProps } from './tooltip'
import { Button } from '../button'
import { Stack } from '../stack'
import { TextField } from '../text-field'
Expand Down Expand Up @@ -66,14 +66,14 @@ function StoryTemplate(props: Omit<TooltipProps, 'children'>) {
}

//
// Playground story
// Playground
//

export function TooltipPlaygroundStory(args: Omit<TooltipProps, 'children'>) {
export function TooltipPlayground(args: Omit<TooltipProps, 'children'>) {
return <StoryTemplate {...args} />
}

TooltipPlaygroundStory.args = {
TooltipPlayground.args = {
content: 'You did it!',
position: 'top',
gapSize: 5,
Expand All @@ -82,17 +82,17 @@ TooltipPlaygroundStory.args = {
hideTimeout: 100,
}

TooltipPlaygroundStory.argTypes = {
TooltipPlayground.argTypes = {
position: {
control: { type: 'select', options: positions },
},
}

//
// Rich content story
// Rich content
//

export function TooltipRichContentStory({
export function TooltipRichContent({
position,
gapSize,
withArrow,
Expand Down Expand Up @@ -124,24 +124,25 @@ export function TooltipRichContentStory({
)
}

TooltipRichContentStory.args = {
TooltipRichContent.args = {
position: 'bottom',
gapSize: 10,
withArrow: true,
showTimeout: 500,
hideTimeout: 100,
}

TooltipRichContentStory.argTypes = {
TooltipRichContent.argTypes = {
position: {
control: { type: 'select', options: positions },
},
}

// This story sets a new z-index for the tooltip, but it will leak into other stories
// when viewed from the Docs page, since all stories live in a single iframe.
// Only in the Canvas page will stories be isolated from each other
export function TooltipCustomZIndexStory() {
//
// Custom Z Index
//

export function TooltipCustomZIndex() {
return (
<>
<PortalToHead>
Expand Down Expand Up @@ -176,3 +177,43 @@ export function TooltipCustomZIndexStory() {
function PortalToHead({ children }: React.PropsWithChildren<unknown>) {
return createPortal(children, document.head)
}

//
// Tooltip Global Context
//

export function TooltipGlobalContext({
showTimeout,
hideTimeout,
}: Required<Pick<TooltipProps, 'showTimeout' | 'hideTimeout'>>) {
const contextValue = React.useMemo(() => ({ showTimeout, hideTimeout }), [
showTimeout,
hideTimeout,
])

return (
<Stack space="medium">
<Text>
<code>{'<TooltipContext>'}</code> can be used to provide global settings to all
tooltips:
</Text>

<TooltipContext.Provider value={contextValue}>
<Box padding="large" display="flex" gap="medium">
<Tooltip content="Click here to begin your journey">
<Button variant="primary">Got it</Button>
</Tooltip>

<Tooltip content="Click here to return">
<Button variant="secondary">Cancel</Button>
</Tooltip>
</Box>
</TooltipContext.Provider>
</Stack>
)
}

TooltipGlobalContext.args = {
showTimeout: 1000,
hideTimeout: 2000,
}
27 changes: 23 additions & 4 deletions src/tooltip/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ import type { TooltipStoreState } from '@ariakit/react'
import styles from './tooltip.module.css'
import type { ObfuscatedClassName } from '../utils/common-types'

type TooltipContextState = {
showTimeout: number
hideTimeout: number
}

const TooltipContext = React.createContext<TooltipContextState>({
showTimeout: 500,
hideTimeout: 100,
})

interface TooltipProps extends ObfuscatedClassName {
/**
* The element that triggers the tooltip. Generally a button or link.
Expand Down Expand Up @@ -69,12 +79,14 @@ interface TooltipProps extends ObfuscatedClassName {

/**
* The amount of time in milliseconds to wait before showing the tooltip
* Use `<TooltipContext.Provider>` to set a global value for all tooltips
* @default 500
*/
showTimeout?: number

/**
* The amount of time in milliseconds to wait before hiding the tooltip
* Use `<TooltipContext.Provider>` to set a global value for all tooltips
* @default 100
*/
hideTimeout?: number
Expand All @@ -86,11 +98,18 @@ function Tooltip({
position = 'top',
gapSize = 3,
withArrow = false,
showTimeout = 500,
hideTimeout = 100,
showTimeout,
hideTimeout,
exceptionallySetClassName,
}: TooltipProps) {
const tooltip = useTooltipStore({ placement: position, showTimeout, hideTimeout })
const { showTimeout: globalShowTimeout, hideTimeout: globalHideTimeout } = React.useContext(
TooltipContext,
)
const tooltip = useTooltipStore({
placement: position,
showTimeout: showTimeout ?? globalShowTimeout,
hideTimeout: hideTimeout ?? globalHideTimeout,
})
const isOpen = tooltip.useState('open')

const child = React.Children.only(
Expand Down Expand Up @@ -135,4 +154,4 @@ function Tooltip({
}

export type { TooltipProps }
export { Tooltip }
export { Tooltip, TooltipContext }
Loading