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

[WIP] chore(packaging): use explicit tippy.js imports and tooltip updates #2395

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@
"minimist": "^1.2.0",
"mutation-observer": "^1.0.3",
"node-sass": "^4.8.3",
"patch-package": "^6.1.2",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these new dependencies for?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It automatically applies any patch files in the new "patches" directory at the root https://github.com/patternfly/patternfly-react/pull/2395/files#diff-1a027bc721cd1ce512f626ff77e9f5b3 - does it in a safe and predictable manner. It's basically a better alternative than using hand crafted scripts like https://github.com/patternfly/patternfly-react/pull/2395/files#diff-c5a66feeb31fe3511a6e4d157ef2bfb8 to apply changes to modules after they've landed in node_modules

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, and the whole yarn remove thing not working as expected for regular postinstall scripts https://github.com/ds300/patch-package#why-use-postinstall-postinstall-with-yarn

"plop": "^2.0.0",
"postinstall-postinstall": "^2.0.0",
"prettier": "^1.16.1",
"prettier-eslint": "^8.8.1",
"react": "~16.8.4",
Expand Down Expand Up @@ -105,6 +107,7 @@
"lint:style": "lerna run stylelint",
"lint:ts": "lerna run lint:ts --parallel",
"lint:versions": "lerna run lint:versions",
"postinstall": "patch-package",
"prettier": "prettier --write 'storybook/**/*.js' 'packages/**/*.js' 'scripts/**/*.js'",
"start": "yarn start:pf3",
"start:cypress": "lerna run cypress:open",
Expand Down
10 changes: 9 additions & 1 deletion packages/patternfly-4/react-core/scripts/copyStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const { parse: parseCSS, stringify: stringifyCSS } = require('css');

const baseCSSFilename = 'patternfly-base.css';
const stylesDir = resolve(__dirname, '../dist/styles');
const baseTippyStylesPath = resolve(__dirname, '../../../../node_modules/tippy.js/index.css');
const tippyOverridesPath = resolve(__dirname, '../src/styles/tippyOverrides.css');
const pfDir = dirname(require.resolve(`@patternfly/patternfly/${baseCSSFilename}`));

const css = readFileSync(join(pfDir, baseCSSFilename), 'utf8');
Expand Down Expand Up @@ -33,11 +35,17 @@ ast.stylesheet.rules = ast.stylesheet.rules.filter(rule => {
}
});

copySync(baseTippyStylesPath, join(stylesDir, 'tippy.css'));
copySync(tippyOverridesPath, join(stylesDir, 'tippyOverrides.css'));
copySync(join(pfDir, 'assets/images'), join(stylesDir, 'assets/images'));
copySync(join(pfDir, 'assets/pficon'), join(stylesDir, 'assets/pficon'));
copySync(join(pfDir, 'assets/fonts'), join(stylesDir, 'assets/fonts'), {
filter(src) {
return !ununsedFontFilesRegExt.test(src);
}
});
writeFileSync(join(stylesDir, 'base.css'), stringifyCSS(ast));
writeFileSync(join(stylesDir, 'base.css'), `
${stringifyCSS(ast)}
\n@import "./tippy.css";
\n@import "./tippyOverrides.css";
`);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { readFileSync, writeFileSync } = require('fs');
const { resolve } = require('path');
const tippyPath = resolve(__dirname, '../../../../node_modules/tippy.js/index.css');
writeFileSync(tippyPath,
readFileSync(tippyPath, 'utf8')
.replace(
"import tippy from 'tippy.js'",
"import tippy from 'tippy.js/esm'"
).replace(
"export { default as tippy } from 'tippy.js';",
"export { default as tippy } from 'tippy.js/esm';"
)
);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

exports[`copy button render 1`] = `
<Tooltip
animation="scale"
appendTo={[Function]}
aria="describedby"
className=""
content={
<div>
Expand All @@ -13,9 +15,11 @@ exports[`copy button render 1`] = `
enableFlip={true}
entryDelay={2000}
exitDelay={1000}
hideOnClick={true}
isAppLauncher={false}
maxWidth="500px"
position="right"
showOnInit={false}
trigger="mouseenter focus click"
zIndex={9999}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import Tippy from '@tippy.js/react';
import Tippy, { TippyProps } from '@tippy.js/react';
import { Instance as TippyInstance } from 'tippy.js';
import { KEY_CODES } from '../../helpers/constants';
import styles from '@patternfly/react-styles/css/components/Popover/popover';
Expand All @@ -12,13 +12,11 @@ import { PopoverFooter } from './PopoverFooter';
import { PopoverCloseButton } from './PopoverCloseButton';
import GenerateId from '../../helpers/GenerateId/GenerateId';
import { c_popover_MaxWidth as popoverMaxWidth } from '@patternfly/react-tokens';
import { tippyStyles } from '../Tooltip/styles';
import { ReactElement } from 'react';
// Can't use ES6 imports :(
// The types for it are also wrong, we should probably ditch this dependency.
// tslint:disable-next-line
const FocusTrap: any = require('focus-trap-react');
tippyStyles();

export enum PopoverPosition {
top = 'top',
Expand All @@ -27,7 +25,9 @@ export enum PopoverPosition {
right = 'right'
};

export interface PopoverProps {
export interface PopoverProps extends TippyProps {
/** The type of transition animation */
animation?: 'fade' | 'scale' | 'shift-toward' | 'perspective' | 'shift-away';
/** Popover position */
position?: 'top' | 'bottom' | 'left' | 'right';
/** If true, tries to keep the popover in view by flipping it if necessary */
Expand All @@ -46,7 +46,7 @@ export interface PopoverProps {
/**
* True to show the popover programmatically. Used in conjunction with the shouldClose prop.
* By default, the popover child element handles click events automatically. If you want to control this programmatically,
* the popover will not auto-close if the Close button is clicked, ESC key is used, or if a click occurs outside the popover.
* the popover will not auto-close if the Close button is clicked, or if a click occurs outside the popover.
* Instead, the consumer is responsible for closing the popover themselves by adding a callback listener for the shouldClose prop.
*/
isVisible?: boolean | null;
Expand Down Expand Up @@ -84,6 +84,7 @@ export interface PopoverState {
export class Popover extends React.Component<PopoverProps, PopoverState> {
private tip: TippyInstance;
static defaultProps = {
animation: 'scale',
position: 'top',
enableFlip: true,
className: '',
Expand Down Expand Up @@ -178,6 +179,7 @@ export class Popover extends React.Component<PopoverProps, PopoverState> {

render() {
const {
animation,
position,
enableFlip,
children,
Expand Down Expand Up @@ -246,7 +248,7 @@ export class Popover extends React.Component<PopoverProps, PopoverState> {
return (
<Tippy
a11y={false}
animation="scale"
animation={animation}
animateFill={false}
appendTo={appendTo}
boundary="window"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`popover can specify position as object value 1`] = `
.pf-tippy {
display: block;
}

<ForwardRef(TippyWrapper)
a11y={false}
animateFill={false}
Expand Down Expand Up @@ -60,10 +56,6 @@ exports[`popover can specify position as object value 1`] = `
`;

exports[`popover renders close-button, header and body 1`] = `
.pf-tippy {
display: block;
}

<ForwardRef(TippyWrapper)
a11y={false}
animateFill={false}
Expand Down
93 changes: 85 additions & 8 deletions packages/patternfly-4/react-core/src/components/Tooltip/Tooltip.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ typescript: true
propComponents: ['Tooltip']
---

import { Tooltip, TooltipPosition, Checkbox } from '@patternfly/react-core';
import { Button, Checkbox, Tooltip, TooltipPosition } from '@patternfly/react-core';

## Simple tooltip
```js
Expand Down Expand Up @@ -88,12 +88,89 @@ class TooltipPositions extends React.Component {
import React from 'react';
import { Tooltip } from '@patternfly/react-core';

<Tooltip
position="right"
content={
<div>Pancetta hamburger alcatra andouille shank frankfurter cow beef meatloaf shankle pork chop capicola tenderloin shoulder.</div>
class TooltipOverLink extends React.Component {
render() {
return (
<Tooltip
position="right"
content={
<div>PatternFly 4 is an open source design system built to drive consistency and unify teams.</div>
}
>
<a tabIndex={-1} onClick={e => e.preventDefault()} href="https://www.patternfly.org/v4/">Patternfly 4 Website</a>
</Tooltip>
);
}
>
<a href="">I'm a link with a tooltip!</a>
</Tooltip>
}
```

## Tooltip shown on init
```js
import React from 'react';
import { Button, Tooltip } from '@patternfly/react-core';

class OpenedTooltip extends React.Component {
render() {
return (
<Tooltip
position="right"
showOnInit
aria="labelledby"
trigger="manual"
hideOnClick={false}
content={
<div role="info">Pressing esc key will always close opened tooltips.</div>
}
>
<Button tabIndex={-1}>Tooltip shown on init</Button>
</Tooltip>
);
}
}
```

## Tooltip using aria-labelledby announcement strategy
```js
import React from 'react';
import { Tooltip } from '@patternfly/react-core';

class LabelledbyTooltip extends React.Component {
render() {
return (
<>
<Tooltip
aria="labelledby"
position="top"
content={
<div role="status">This link uses aria-labelledby.</div>
}
>
<label style={{marginRight: '6px'}} htmlFor="tooltip-input-1">This element is related to the Tooltip via aria-labelledby</label>
</Tooltip>
<input id="tooltip-input-1" type="text" placeholder="Example Input" />
</>
);
}
}
```

## Tooltip that announces its content immediately via `alert` role
```js
import React from 'react';
import { Tooltip } from '@patternfly/react-core';

class TooltipAlertRole extends React.Component {
render() {
return (
<Tooltip
position="top"
content={
<div role="alert">This is a really important tooltip!</div>
}
>
<span>Span With an Alert Tooltip</span>
</Tooltip>
);
}
}
```
36 changes: 26 additions & 10 deletions packages/patternfly-4/react-core/src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import * as React from 'react';
import Tippy from '@tippy.js/react';
import Tippy, { TippyProps } from '@tippy.js/react';
import { Instance as TippyInstance } from 'tippy.js';
import styles from '@patternfly/react-styles/css/components/Tooltip/tooltip';
import { css, getModifier } from '@patternfly/react-styles';
import { TooltipArrow } from './TooltipArrow';
import { TooltipContent } from './TooltipContent';
import { KEY_CODES } from '../../helpers/constants';
import { Omit } from '../../helpers/typeUtils';
import { c_tooltip_MaxWidth as tooltipMaxWidth } from '@patternfly/react-tokens';
import { tippyStyles } from './styles';
import { ReactElement } from 'react';

tippyStyles();

export enum TooltipPosition {
top = 'top',
Expand All @@ -19,7 +16,11 @@ export enum TooltipPosition {
right = 'right'
};

export interface TooltipProps {
export interface TooltipProps extends Omit<TippyProps, 'content'> {
/** The type of transition animation */
animation?: 'fade' | 'scale' | 'shift-toward' | 'perspective' | 'shift-away';
/** The aria-* attribute applied to the reference element. */
aria?: 'describedby' | 'labelledby' | null
/** Tooltip position */
position?: 'top' | 'bottom' | 'left' | 'right';
/** Tooltip trigger: click, mouseenter, focus */
Expand All @@ -31,7 +32,7 @@ export interface TooltipProps {
/** Tooltip content */
content: React.ReactNode;
/** The reference element to which the tooltip is relatively placed to */
children: ReactElement<any>;
children: React.ReactElement<any>;
/** Delay in ms before the tooltip appears */
entryDelay?: number;
/** Delay in ms before the tooltip disappears */
Expand All @@ -46,11 +47,17 @@ export interface TooltipProps {
isAppLauncher?: boolean;
/** Distance of the tooltip to its target, defaults to 15 */
distance?: number;
/** If the tooltip should display automatically on init */
showOnInit?: boolean;
/** Determines if the tooltip should hide if a click event is fired outside of it */
hideOnClick?: boolean;
};

export class Tooltip extends React.Component<TooltipProps> {
private tip: TippyInstance;
static defaultProps = {
animation: 'scale',
aria: 'describedby',
position: 'top',
trigger: 'mouseenter focus',
enableFlip: true,
Expand All @@ -61,7 +68,9 @@ export class Tooltip extends React.Component<TooltipProps> {
zIndex: 9999,
maxWidth: tooltipMaxWidth && tooltipMaxWidth.value,
isAppLauncher: false,
distance: 15
distance: 15,
showOnInit: false,
hideOnClick: true
};

storeTippyInstance = (tip:TippyInstance) => {
Expand Down Expand Up @@ -90,6 +99,8 @@ export class Tooltip extends React.Component<TooltipProps> {

render() {
const {
animation,
aria,
position,
trigger,
enableFlip,
Expand All @@ -103,6 +114,8 @@ export class Tooltip extends React.Component<TooltipProps> {
maxWidth,
isAppLauncher,
distance,
showOnInit,
hideOnClick,
...rest
} = this.props;
const content = (
Expand All @@ -117,7 +130,8 @@ export class Tooltip extends React.Component<TooltipProps> {
);
return (
<Tippy
animation="scale"
aria={aria}
animation={animation}
animateFill={false}
appendTo={appendTo}
boundary="window"
Expand All @@ -126,8 +140,9 @@ export class Tooltip extends React.Component<TooltipProps> {
delay={[entryDelay, exitDelay]}
distance={distance}
flip={enableFlip}
interactive
hideOnClick={hideOnClick}
ignoreAttributes
interactive
lazy
maxWidth={maxWidth}
onCreate={this.storeTippyInstance}
Expand All @@ -142,6 +157,7 @@ export class Tooltip extends React.Component<TooltipProps> {
}
}
}}
showOnInit={showOnInit}
trigger={trigger}
zIndex={zIndex}
>
Expand Down
Loading