Skip to content
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
2 changes: 1 addition & 1 deletion packages/patternfly-4/react-charts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@
"glob": "^7.1.2",
"npmlog": "^4.1.2"
}
}
}
2 changes: 1 addition & 1 deletion packages/patternfly-4/react-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@
"glob": "^7.1.2",
"npmlog": "^4.1.2"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { SFC, HTMLProps, ReactNode } from 'react';
import { OneOf } from '@patternfly/react-core/src/typeUtils';

export interface PopoverProps extends HTMLProps<HTMLDivElement> {
position: OneOf<typeof PopoverPosition, keyof typeof PopoverPosition>;
children: ReactNode;
header: string;
onClose?(event: React.SyntheticEvent<HTMLButtonElement>): void
}

declare const Popover: SFC<PopoverProps>;

export default Popover;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
PopoverPosition,
PopoverDialog,
PopoverArrow,
PopoverContent,
PopoverCloseButton,
PopoverHeader,
PopoverBody
} from '@patternfly/react-core';
import SimplePopover from './examples/SimplePopover';
import HeadlessPopover from './examples/HeadlessPopover';

export default {
title: 'Popover',
components: {
PopoverDialog,
PopoverArrow,
PopoverContent,
PopoverCloseButton,
PopoverHeader,
PopoverBody
},
enumValues: {
'Object.values(PopoverPosition)': Object.values(PopoverPosition)
},
examples: [
{ component: SimplePopover, title: 'Closable Popover Position' },
{ component: HeadlessPopover, title: 'Headless Popover' }
]
};
40 changes: 40 additions & 0 deletions packages/patternfly-4/react-core/src/components/Popover/Popover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from '@patternfly/patternfly-next/components/Popover/popover.css';
import { css, getModifier } from '@patternfly/react-styles';
import PopoverDialog, { PopoverPosition } from './PopoverDialog';
import PopoverArrow from './PopoverArrow';
import PopoverContent from './PopoverContent';
import PopoverHeader from './PopoverHeader';
import PopoverBody from './PopoverBody';
import PopoverCloseButton from './PopoverCloseButton';

const Popover = ({ position, header, onClose, children, className }) => (
<PopoverDialog position={position}>
<PopoverArrow />
<PopoverContent>
<PopoverCloseButton onClose={onClose} />
<PopoverHeader id={`popover-${position}-header`}>{header}</PopoverHeader>
<PopoverBody id={`popover-${position}-body`}>{children}</PopoverBody>
</PopoverContent>
</PopoverDialog>
);

const propTypes = {
/** Popover position */
position: PropTypes.oneOf(Object.values(PopoverPosition)),
/** Popover header text */
header: PropTypes.string.isRequired,
/** Popover body text */
children: PropTypes.string.isRequired,
/** Popover onClose function */
onClose: PropTypes.func
};

Popover.propTypes = propTypes;
Popover.defaultProps = {
onClose: () => {},
position: 'top'
};

export default Popover;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { mount } from 'enzyme';
import { Popover } from './index';
import { Button } from '@patternfly/react-core';

test('popover renders close-button, header and body', () => {
const view = mount(<Popover header="popover header">popover body</Popover>);
expect(view).toMatchSnapshot();
});

test('popover is calling onClose when clicking the close button', () => {
const onClose = jest.fn();
const view = mount(
<Popover header="popover header" onClose={onClose}>
popover body
</Popover>
);
expect(onClose.mock.calls).toHaveLength(0);
view.find(Button).simulate('click');
expect(onClose.mock.calls).toHaveLength(1);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SFC, HTMLProps } from 'react';

export interface PopoverArrowProps extends HTMLProps<HTMLDivElement> {
}

declare const PopoverArrow: SFC<PopoverArrowProps>;

export default PopoverArrow;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from '@patternfly/patternfly-next/components/Popover/popover.css';
import { css } from '@patternfly/react-styles';

const PopoverArrow = ({ className, ...props }) => <div className={css(styles.popoverArrow, className)} {...props} />;

PopoverArrow.propTypes = {
/** Popover arrow additional className */
className: PropTypes.string
};

PopoverArrow.defaultProps = {
className: null
};

export default PopoverArrow;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SFC, ReactNode } from 'react';

export interface PopoverBodyProps {
id: string
children: ReactNode;
}

declare const PopoverBody: SFC<PopoverBodyProps>;

export default PopoverBody;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from '@patternfly/patternfly-next/components/Popover/popover.css';
import { css } from '@patternfly/react-styles';

const PopoverBody = ({ children, id }) => (
<div className={css(styles.popoverBody)} id={id}>
{children}
</div>
);

PopoverBody.propTypes = {
/** PopoverBody id */
id: PropTypes.string.isRequired,
/** PopoverBody content */
children: PropTypes.node.isRequired
};

export default PopoverBody;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SFC } from 'react';

export interface PopoverCloseButtonProps {
onClose(event: React.SyntheticEvent<HTMLButtonElement>): void
}

declare const PopoverCloseButton : SFC<PopoverCloseButtonProps>;

export default PopoverCloseButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from '@patternfly/patternfly-next/components/Popover/popover.css';
import { css } from '@patternfly/react-styles';
import { Button } from '@patternfly/react-core';
import { TimesIcon } from '@patternfly/react-icons';

const PopoverCloseButton = ({ onClose }) => (
<div className={css(styles.popoverClose)}>
<Button onClick={onClose} variant="plain" aria-label="Action">
<TimesIcon />
</Button>
</div>
);

PopoverCloseButton.propTypes = {
/** PopoverCloseButton onClose function */
onClose: PropTypes.func.isRequired
};

export default PopoverCloseButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SFC, HTMLProps } from 'react';

export interface PopoverContentProps extends HTMLProps<HTMLDivElement> {
}

declare const PopoverContent: SFC<PopoverContentProps>;

export default PopoverContent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from '@patternfly/patternfly-next/components/Popover/popover.css';
import { css } from '@patternfly/react-styles';

const PopoverContent = ({ className, children, ...props }) => (
<div className={css(styles.popoverContent, className)} {...props}>
{children}
</div>
);

PopoverContent.propTypes = {
/** PopoverContent additional class */
className: PropTypes.string,
/** PopoverContent content */
children: PropTypes.node.isRequired,
};

PopoverContent.defaultProps = {
className: null
};

export default PopoverContent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { SFC, HTMLProps, ReactNode } from 'react';
import { OneOf, Omit } from '../../typeUtils';

export const PopoverPosition: {
top: 'top';
bottom: 'bottom';
left: 'left';
right: 'right';
};

export interface PopoverDialogProps extends Omit<HTMLProps<HTMLDivElement>, 'children'> {
children: ReactNode
position: OneOf<typeof PopoverPosition, keyof typeof PopoverPosition>;
}

declare const PopoverDialog: SFC<PopoverDialogProps>;

export default PopoverDialog;

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from '@patternfly/patternfly-next/components/Popover/popover.css';
import { css, getModifier } from '@patternfly/react-styles';

export const PopoverPosition = {
top: 'top',
bottom: 'bottom',
left: 'left',
right: 'right'
};

const PopoverDialog = ({ position, children, className, ...props }) => (
<div
className={css(styles.popover, getModifier(styles, position, styles.modifiers.top), className)}
role="dialog"
aria-modal="true"
{...props}
>
{children}
</div>
);

PopoverDialog.propTypes = {
/** PopoverDialog position */
position: PropTypes.oneOf(Object.values(PopoverPosition)),
/** PopoverDialog additional class */
className: PropTypes.string,
/** PopoverDialog body */
children: PropTypes.node.isRequired
};

PopoverDialog.defaultProps = {
position: 'top',
className: null
};

export default PopoverDialog;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SFC, ReactNode } from 'react';

export interface PopoverHeaderProps {
id: string
children: ReactNode;
}

declare const PopoverHeader: SFC<PopoverHeaderProps>;

export default PopoverHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from '@patternfly/patternfly-next/components/Popover/popover.css';
import { css } from '@patternfly/react-styles';

const PopoverHeader = ({ children, id }) => (
<header className={css(styles.popoverHeader)}>
<h1 className={css(styles.popoverHeaderTitle)} id={id}>
{children}
</h1>
</header>
);

PopoverHeader.propTypes = {
/** popover id */
id: PropTypes.string.isRequired,
/** header node */
children: PropTypes.node.isRequired
};

export default PopoverHeader;
Loading