diff --git a/packages/react-core/src/components/Hint/Hint.tsx b/packages/react-core/src/components/Hint/Hint.tsx new file mode 100644 index 00000000000..f773832c0a6 --- /dev/null +++ b/packages/react-core/src/components/Hint/Hint.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import styles from '@patternfly/react-styles/css/components/Hint/hint'; +import { css } from '@patternfly/react-styles'; + +export interface HintProps { + /** Content rendered inside the hint. */ + children?: React.ReactNode; + /** Additional classes applied to the hint. */ + className?: string; + /** Actions of the hint. */ + actions?: React.ReactNode; +} + +export const Hint: React.FunctionComponent = ({ children, className, actions, ...props }: HintProps) => ( +
+
{actions}
+ {children} +
+); +Hint.displayName = 'Hint'; diff --git a/packages/react-core/src/components/Hint/HintBody.tsx b/packages/react-core/src/components/Hint/HintBody.tsx new file mode 100644 index 00000000000..0bd1b7e843e --- /dev/null +++ b/packages/react-core/src/components/Hint/HintBody.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import styles from '@patternfly/react-styles/css/components/Hint/hint'; +import { css } from '@patternfly/react-styles'; + +export interface HintBodyProps { + /** Content rendered inside the hint body. */ + children?: React.ReactNode; + /** Additional classes applied to the hint body. */ + className?: string; +} + +export const HintBody: React.FunctionComponent = ({ children, className, ...props }: HintBodyProps) => ( +
+ {children} +
+); +HintBody.displayName = 'HintBody'; diff --git a/packages/react-core/src/components/Hint/HintFooter.tsx b/packages/react-core/src/components/Hint/HintFooter.tsx new file mode 100644 index 00000000000..e019157cae5 --- /dev/null +++ b/packages/react-core/src/components/Hint/HintFooter.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import styles from '@patternfly/react-styles/css/components/Hint/hint'; +import { css } from '@patternfly/react-styles'; + +export interface HintFooterProps { + /** Content rendered inside the hint footer. */ + children?: React.ReactNode; + /** Additional classes applied to the hint footer. */ + className?: string; +} + +export const HintFooter: React.FunctionComponent = ({ + children, + className, + ...props +}: HintFooterProps) => ( +
+ {children} +
+); +HintFooter.displayName = 'HintFooter'; diff --git a/packages/react-core/src/components/Hint/HintTitle.tsx b/packages/react-core/src/components/Hint/HintTitle.tsx new file mode 100644 index 00000000000..93f9a1a52e5 --- /dev/null +++ b/packages/react-core/src/components/Hint/HintTitle.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import styles from '@patternfly/react-styles/css/components/Hint/hint'; +import { css } from '@patternfly/react-styles'; + +export interface HintTitleProps { + /** Content rendered inside the hint title. */ + children?: React.ReactNode; + /** Additional classes applied to the hint title. */ + className?: string; +} + +export const HintTitle: React.FunctionComponent = ({ + children, + className, + ...props +}: HintTitleProps) => ( +
+ {children} +
+); +HintTitle.displayName = 'HintTitle'; diff --git a/packages/react-core/src/components/Hint/__tests__/Hint.test.tsx b/packages/react-core/src/components/Hint/__tests__/Hint.test.tsx new file mode 100644 index 00000000000..179263f5474 --- /dev/null +++ b/packages/react-core/src/components/Hint/__tests__/Hint.test.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { shallow } from 'enzyme'; +import { Hint } from '../Hint'; +import { HintBody } from '../HintBody'; +import { HintTitle } from '../HintTitle'; +import { HintFooter } from '../HintFooter'; + +test('simple hint', () => { + const view = shallow( + + Title + Body + Footer + + ); + expect(view).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Hint/__tests__/__snapshots__/Hint.test.tsx.snap b/packages/react-core/src/components/Hint/__tests__/__snapshots__/Hint.test.tsx.snap new file mode 100644 index 00000000000..25989100dd3 --- /dev/null +++ b/packages/react-core/src/components/Hint/__tests__/__snapshots__/Hint.test.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`simple hint 1`] = ` +
+
+ + Title + + + Body + + + Footer + +
+`; diff --git a/packages/react-core/src/components/Hint/examples/Hint.md b/packages/react-core/src/components/Hint/examples/Hint.md new file mode 100644 index 00000000000..347bb6b1f48 --- /dev/null +++ b/packages/react-core/src/components/Hint/examples/Hint.md @@ -0,0 +1,184 @@ +--- +id: Hint +section: components +cssPrefix: null +propComponents: ['Hint', 'HintTitle', 'HintBody', 'HintFooter'] +beta: true +--- + +## Examples + +### Basic with title + +```js +import React from 'react'; +import { + Hint, + HintTitle, + HintBody, + HintFooter, + Button, + Dropdown, + DropdownToggle, + DropdownItem, + DropdownSeparator, + DropdownPosition, + DropdownDirection, + KebabToggle +} from '@patternfly/react-core'; + +class BasicHint extends React.Component { + constructor(props) { + super(props); + this.state = { + isOpen: false + }; + this.onToggle = isOpen => { + this.setState({ + isOpen + }); + }; + this.onSelect = event => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + } + + render() { + const { isOpen } = this.state; + const dropdownItems = [ + Link, + + Action + , + + Disabled Link + , + + Disabled Action + , + , + Separated Link, + + Separated Action + + ]; + const actions = ( + } + isOpen={isOpen} + dropdownItems={dropdownItems} + position="right" + isPlain + /> + ); + return ( + + Do more with Find it Fix it capabilities + + Upgrade to Red Hat Smart Management to remediate all your systems across regions and geographies. + + + + + + ); + } +} +``` + +### Basic without title + +```js +import React from 'react'; +import { + Hint, + HintBody, + HintFooter, + Button, + Dropdown, + DropdownToggle, + DropdownItem, + DropdownSeparator, + DropdownPosition, + DropdownDirection, + KebabToggle +} from '@patternfly/react-core'; + +class BasicHint extends React.Component { + constructor(props) { + super(props); + this.state = { + isOpen: false + }; + this.onToggle = isOpen => { + this.setState({ + isOpen + }); + }; + this.onSelect = event => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + } + + render() { + const { isOpen } = this.state; + const dropdownItems = [ + Link, + + Action + , + + Disabled Link + , + + Disabled Action + , + , + Separated Link, + + Separated Action + + ]; + const actions = ( + } + isOpen={isOpen} + dropdownItems={dropdownItems} + position="right" + isPlain + /> + ); + return ( + + + + Welcome to the new documentation experience. + + + +
+ + + Upgrade to Red Hat Smart Management to remediate all your systems across regions and geographies. + + + + + +
+ ); + } +} +``` diff --git a/packages/react-core/src/components/Hint/index.ts b/packages/react-core/src/components/Hint/index.ts new file mode 100644 index 00000000000..b8cf0689675 --- /dev/null +++ b/packages/react-core/src/components/Hint/index.ts @@ -0,0 +1,4 @@ +export * from './Hint'; +export * from './HintBody'; +export * from './HintFooter'; +export * from './HintTitle'; diff --git a/packages/react-core/src/components/index.ts b/packages/react-core/src/components/index.ts index bc83888fafc..7936c2b1e6b 100644 --- a/packages/react-core/src/components/index.ts +++ b/packages/react-core/src/components/index.ts @@ -26,6 +26,7 @@ export * from './ExpandableSection'; export * from './FileUpload'; export * from './Form'; export * from './FormSelect'; +export * from './Hint'; export * from './InputGroup'; export * from './Label'; export * from './List'; diff --git a/packages/react-integration/cypress/integration/hint.spec.ts b/packages/react-integration/cypress/integration/hint.spec.ts new file mode 100644 index 00000000000..a11a45fa35e --- /dev/null +++ b/packages/react-integration/cypress/integration/hint.spec.ts @@ -0,0 +1,12 @@ +describe('Hint Demo Test', () => { + it('Navigate to demo section', () => { + cy.visit('http://localhost:3000/'); + cy.get('#hint-demo-nav-item-link').click(); + cy.url().should('eq', 'http://localhost:3000/hint-demo-nav-link'); + }); + + it('Verify banner', () => { + cy.get('.pf-c-hint').should('exist'); + cy.get('.pf-c-hint__title').should('exist'); + }); +}); diff --git a/packages/react-integration/demo-app-ts/src/Demos.ts b/packages/react-integration/demo-app-ts/src/Demos.ts index cb1223ad6c9..1ffdddd28a0 100644 --- a/packages/react-integration/demo-app-ts/src/Demos.ts +++ b/packages/react-integration/demo-app-ts/src/Demos.ts @@ -346,6 +346,11 @@ export const Demos: DemoInterface[] = [ name: 'Grid Demo', componentType: Examples.GridDemo }, + { + id: 'hint-demo', + name: 'Hint Demo', + componentType: Examples.HintDemo + }, { id: 'input-group-demo', name: 'Input Group Demo', diff --git a/packages/react-integration/demo-app-ts/src/components/demos/HintDemo/HintDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/HintDemo/HintDemo.tsx new file mode 100644 index 00000000000..f7b18d137f6 --- /dev/null +++ b/packages/react-integration/demo-app-ts/src/components/demos/HintDemo/HintDemo.tsx @@ -0,0 +1,88 @@ +import React from 'react'; +import { + Hint, + HintBody, + HintTitle, + HintFooter, + Dropdown, + DropdownItem, + DropdownSeparator, + KebabToggle, + Button +} from '@patternfly/react-core'; + +export class HintDemo extends React.Component { + static displayName = 'HintDemo'; + componentDidMount() { + window.scrollTo(0, 0); + } + + state = { + isOpen: false + }; + onToggle = (isOpen: boolean) => { + this.setState({ + isOpen + }); + }; + onSelect = () => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + + render() { + const { isOpen } = this.state; + const dropdownItems = [ + Link, + + Action + , + + Disabled Link + , + + Disabled Action + , + , + Separated Link, + + Separated Action + + ]; + const actions = ( + } + isOpen={isOpen} + dropdownItems={dropdownItems} + position="right" + isPlain + /> + ); + return ( + + + Do more with Find it Fix it capabilities + + Welcome to the new documentation experience. + + + +
+ + + Upgrade to Red Hat Smart Management to remediate all your systems across regions and geographies. + + + + + +
+ ); + } +} diff --git a/packages/react-integration/demo-app-ts/src/components/demos/index.ts b/packages/react-integration/demo-app-ts/src/components/demos/index.ts index 06d45546041..4c151bdacfa 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/index.ts +++ b/packages/react-integration/demo-app-ts/src/components/demos/index.ts @@ -66,6 +66,7 @@ export * from './FormDemo/FormDemo'; export * from './FormSelectDemo/FormSelectDemo'; export * from './GalleryDemo/GalleryDemo'; export * from './GridDemo/GridDemo'; +export * from './HintDemo/HintDemo'; export * from './InputGroupDemo/InputGroupDemo'; export * from './LabelDemo/LabelDemo'; export * from './LevelDemo/LevelDemo';