Skip to content

Commit

Permalink
Revert "Remove unused components from ui/ (#54573)"
Browse files Browse the repository at this point in the history
This reverts commit 06608b2.
  • Loading branch information
mikachan committed Jan 5, 2024
1 parent fdd2fc9 commit a5e5d98
Show file tree
Hide file tree
Showing 20 changed files with 635 additions and 9 deletions.
4 changes: 0 additions & 4 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@
- `SlotFill`: Migrate to TypeScript and Convert to Functional Component `<Slot bubblesVirtually />`. ([#51350](https://github.com/WordPress/gutenberg/pull/51350)).


### Internal

- `Tooltip`, `Shortcut`: Remove unused `ui/` components from the codebase ([#54573](https://github.com/WordPress/gutenberg/pull/54573))

## 25.8.0 (2023-09-20)

### Enhancements
Expand Down
14 changes: 9 additions & 5 deletions packages/components/src/color-picker/color-copy-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { __ } from '@wordpress/i18n';
* Internal dependencies
*/
import { CopyButton } from './styles';
import Tooltip from '../tooltip';
import { Text } from '../text';
import { Tooltip } from '../ui/tooltip';

import type { ColorCopyButtonProps } from './types';

Expand Down Expand Up @@ -55,11 +56,14 @@ export const ColorCopyButton = ( props: ColorCopyButtonProps ) => {

return (
<Tooltip
delay={ 0 }
hideOnClick={ false }
text={
copiedColor === color.toHex() ? __( 'Copied!' ) : __( 'Copy' )
content={
<Text color="white">
{ copiedColor === color.toHex()
? __( 'Copied!' )
: __( 'Copy' ) }
</Text>
}
placement="bottom"
>
<CopyButton
isSmall
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/tooltip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ function Tooltip( props: TooltipProps ) {
return (
<>
<Ariakit.TooltipAnchor
onBlur={ tooltipStore.hide }
onClick={ hideOnClick ? tooltipStore.hide : undefined }
store={ tooltipStore }
render={ isOnlyChild ? children : undefined }
Expand Down
62 changes: 62 additions & 0 deletions packages/components/src/ui/shortcut/component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* External dependencies
*/
import type { ForwardedRef } from 'react';

/**
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
import { useContextSystem, contextConnect } from '../context';
import { View } from '../../view';

export interface ShortcutDescription {
display: string;
ariaLabel: string;
}

export interface Props {
shortcut?: ShortcutDescription | string;
className?: string;
}

function Shortcut(
props: WordPressComponentProps< Props, 'span' >,
forwardedRef: ForwardedRef< any >
): JSX.Element | null {
const {
as: asProp = 'span',
shortcut,
className,
...otherProps
} = useContextSystem( props, 'Shortcut' );
if ( ! shortcut ) {
return null;
}

let displayText: string;
let ariaLabel: string | undefined;

if ( typeof shortcut === 'string' ) {
displayText = shortcut;
} else {
displayText = shortcut.display;
ariaLabel = shortcut.ariaLabel;
}

return (
<View
as={ asProp }
className={ className }
aria-label={ ariaLabel }
ref={ forwardedRef }
{ ...otherProps }
>
{ displayText }
</View>
);
}

const ConnectedShortcut = contextConnect( Shortcut, 'Shortcut' );

export default ConnectedShortcut;
2 changes: 2 additions & 0 deletions packages/components/src/ui/shortcut/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as Shortcut } from './component';
export type { Props as ShortcutProps, ShortcutDescription } from './component';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Shortcut should render a span with the shortcut text 1`] = `
<span
class="components-shortcut emotion-0 emotion-1"
data-wp-c16t="true"
data-wp-component="Shortcut"
>
meta + P
</span>
`;

exports[`Shortcut should render null when no shortcut is provided 1`] = `<div />`;
36 changes: 36 additions & 0 deletions packages/components/src/ui/shortcut/test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* External dependencies
*/
import { render, screen } from '@testing-library/react';

/**
* Internal dependencies
*/
import { Shortcut } from '..';

describe( 'Shortcut', () => {
it( 'should render null when no shortcut is provided', () => {
const { container } = render( <Shortcut /> );
expect( container ).toMatchSnapshot();
} );

it( 'should render a span with the shortcut text', () => {
const shortcutText = 'meta + P';
render( <Shortcut shortcut={ shortcutText } /> );
const shortcut = screen.getByText( shortcutText );
expect( shortcut ).toMatchSnapshot();
} );

it( 'should render a span with aria label', () => {
const shortcutObject = {
display: 'meta + P',
ariaLabel: 'print',
};
render( <Shortcut shortcut={ shortcutObject } /> );
const shortcut = screen.getByText( shortcutObject.display );
expect( shortcut ).toHaveAttribute(
'aria-label',
shortcutObject.ariaLabel
);
} );
} );
21 changes: 21 additions & 0 deletions packages/components/src/ui/tooltip/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Tooltip

<div class="callout callout-alert">
This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
</div>

`Tooltip` is a component to render floating help text relative to a node when it receives focus or when the user places the mouse cursor atop it.

## Usage

```jsx
import { Tooltip, Text } from '@wordpress/components/ui';

function Example() {
return (
<Tooltip content="Code is Poetry">
<Text>WordPress.org</Text>
</Tooltip>
);
}
```
102 changes: 102 additions & 0 deletions packages/components/src/ui/tooltip/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* External dependencies
*/
// eslint-disable-next-line no-restricted-imports
import { TooltipReference, useTooltipState } from 'reakit';

/**
* WordPress dependencies
*/
import { useMemo, cloneElement } from '@wordpress/element';

/**
* Internal dependencies
*/
import { contextConnect, useContextSystem } from '../context';
import { TooltipContext } from './context';
import TooltipContent from './content';
import { TooltipShortcut } from './styles';

/**
* @param {import('../context').WordPressComponentProps<import('./types').Props, 'div'>} props
* @param {import('react').ForwardedRef<any>} forwardedRef
*/
function Tooltip( props, forwardedRef ) {
const {
animated = true,
animationDuration = 160,
baseId,
children,
content,
focusable = true,
gutter = 4,
id,
modal = true,
placement,
visible = false,
shortcut,
...otherProps
} = useContextSystem( props, 'Tooltip' );

const tooltip = useTooltipState( {
animated: animated ? animationDuration : undefined,
baseId: baseId || id,
gutter,
placement,
visible,
...otherProps,
} );

const contextProps = useMemo(
() => ( {
tooltip,
} ),
[ tooltip ]
);

return (
<TooltipContext.Provider value={ contextProps }>
{ content && (
<TooltipContent unstable_portal={ modal } ref={ forwardedRef }>
{ content }
{ shortcut && <TooltipShortcut shortcut={ shortcut } /> }
</TooltipContent>
) }
{ children && (
<TooltipReference
{ ...tooltip }
{ ...children.props }
// @ts-ignore If ref doesn't exist that's fine with us, it'll just be undefined, but it can exist on ReactElement and there's no reason to try to scope this (it'll just overcomplicate things)
ref={ children?.ref }
>
{ ( referenceProps ) => {
if ( ! focusable ) {
referenceProps.tabIndex = undefined;
}
return cloneElement( children, referenceProps );
} }
</TooltipReference>
) }
</TooltipContext.Provider>
);
}

/**
* `Tooltip` is a component that provides context for a user interface element.
*
* @example
* ```jsx
* import { Tooltip, Text } from `@wordpress/components/ui`;
*
* function Example() {
* return (
* <Tooltip content="Code is Poetry">
* <Text>WordPress.org</Text>
* </Tooltip>
* )
* }
* ```
*/
const ConnectedTooltip = contextConnect( Tooltip, 'Tooltip' );

export default ConnectedTooltip;
45 changes: 45 additions & 0 deletions packages/components/src/ui/tooltip/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* External dependencies
*/
// eslint-disable-next-line no-restricted-imports
import { Tooltip as ReakitTooltip } from 'reakit';

/**
* Internal dependencies
*/
import { contextConnect, useContextSystem } from '../context';
import { View } from '../../view';
import { useTooltipContext } from './context';
import * as styles from './styles';
import { useCx } from '../../utils/hooks/use-cx';

const { TooltipPopoverView } = styles;

/**
*
* @param {import('../context').WordPressComponentProps<import('./types').ContentProps, 'div'>} props
* @param {import('react').ForwardedRef<any>} forwardedRef
*/
function TooltipContent( props, forwardedRef ) {
const { children, className, ...otherProps } = useContextSystem(
props,
'TooltipContent'
);
const { tooltip } = useTooltipContext();
const cx = useCx();
const classes = cx( styles.TooltipContent, className );

return (
<ReakitTooltip
as={ View }
{ ...otherProps }
{ ...tooltip }
className={ classes }
ref={ forwardedRef }
>
<TooltipPopoverView>{ children }</TooltipPopoverView>
</ReakitTooltip>
);
}

export default contextConnect( TooltipContent, 'TooltipContent' );
10 changes: 10 additions & 0 deletions packages/components/src/ui/tooltip/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* WordPress dependencies
*/
import { createContext, useContext } from '@wordpress/element';

/**
* @type {import('react').Context<{ tooltip?: import('reakit').TooltipState }>}
*/
export const TooltipContext = createContext( {} );
export const useTooltipContext = () => useContext( TooltipContext );
2 changes: 2 additions & 0 deletions packages/components/src/ui/tooltip/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as Tooltip } from './component';
export * from './context';
26 changes: 26 additions & 0 deletions packages/components/src/ui/tooltip/stories/index.story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Internal dependencies
*/
import { Text } from '../../../text';
import { Tooltip } from '../index';

export default {
component: Tooltip,
title: 'Components (Experimental)/Tooltip',
};

export const _default = () => {
return (
<Tooltip
content="Tooltip"
visible
gutter={ 10 }
shortcut={ {
display: 'meta + 1',
ariaLabel: 'shortcut-aria-label',
} }
>
<Text>Hello</Text>
</Tooltip>
);
};
Loading

0 comments on commit a5e5d98

Please sign in to comment.