-
Notifications
You must be signed in to change notification settings - Fork 358
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(EmptyState): update EmptyState with updates for penta #9947
Changes from all commits
70a3cd5
4645c02
cba4cf0
5869a0f
d8fdee8
dbcc79e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
import * as React from 'react'; | ||
import { css } from '@patternfly/react-styles'; | ||
import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; | ||
import { EmptyStateHeader } from './EmptyStateHeader'; | ||
import { statusIcons } from '../../helpers'; | ||
|
||
export enum EmptyStateVariant { | ||
'xs' = 'xs', | ||
|
@@ -10,37 +12,75 @@ export enum EmptyStateVariant { | |
full = 'full' | ||
} | ||
|
||
export enum EmptyStateStatus { | ||
danger = 'danger', | ||
warning = 'warning', | ||
success = 'success', | ||
info = 'info', | ||
custom = 'custom' | ||
} | ||
|
||
export interface EmptyStateProps extends React.HTMLProps<HTMLDivElement> { | ||
/** Additional classes added to the empty state */ | ||
className?: string; | ||
/** Content rendered inside the empty state */ | ||
children: React.ReactNode; | ||
children?: React.ReactNode; | ||
/** Modifies empty state max-width and sizes of icon, title and body */ | ||
variant?: 'xs' | 'sm' | 'lg' | 'xl' | 'full'; | ||
/** Cause component to consume the available height of its container */ | ||
isFullHeight?: boolean; | ||
/** Status of the empty state, will set a default status icon and color. Icon can be overwritten using the icon prop */ | ||
status?: 'danger' | 'warning' | 'success' | 'info' | 'custom'; | ||
/** Additional class names to apply to the empty state header */ | ||
headerClassName?: string; | ||
/** Additional classes added to the title inside empty state header */ | ||
titleClassName?: string; | ||
/** Text of the title inside empty state header, will be wrapped in headingLevel */ | ||
titleText: React.ReactNode; | ||
/** Empty state icon element to be rendered. Can also be a spinner component */ | ||
icon?: React.ComponentType<any>; | ||
/** The heading level to use, default is h1 */ | ||
headingLevel?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; | ||
} | ||
|
||
export const EmptyState: React.FunctionComponent<EmptyStateProps> = ({ | ||
children, | ||
className, | ||
variant = EmptyStateVariant.full, | ||
isFullHeight, | ||
status, | ||
icon: customIcon, | ||
titleText, | ||
titleClassName, | ||
headerClassName, | ||
headingLevel, | ||
...props | ||
}: EmptyStateProps) => ( | ||
<div | ||
className={css( | ||
styles.emptyState, | ||
variant === 'xs' && styles.modifiers.xs, | ||
variant === 'sm' && styles.modifiers.sm, | ||
variant === 'lg' && styles.modifiers.lg, | ||
variant === 'xl' && styles.modifiers.xl, | ||
isFullHeight && styles.modifiers.fullHeight, | ||
className | ||
)} | ||
{...props} | ||
> | ||
<div className={css(styles.emptyStateContent)}>{children}</div> | ||
</div> | ||
); | ||
}: EmptyStateProps) => { | ||
const statusIcon = status && statusIcons[status]; | ||
const icon = customIcon || statusIcon; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One decision point: if we have the status prop set a default icon should the I think as a consumer I would prefer the former so that I can have the status apply custom colors to my passed icon, so that's what I went with, but I'm not dead set. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. I only have one hesitation with that, but it's something that can be covered in a11y docs (passing an icon that doesn't visually represent the status) |
||
|
||
return ( | ||
<div | ||
className={css( | ||
styles.emptyState, | ||
variant !== 'full' && styles.modifiers[variant], | ||
isFullHeight && styles.modifiers.fullHeight, | ||
status && styles.modifiers[status], | ||
className | ||
)} | ||
{...props} | ||
> | ||
<div className={css(styles.emptyStateContent)}> | ||
<EmptyStateHeader | ||
icon={icon} | ||
titleText={titleText} | ||
titleClassName={titleClassName} | ||
className={headerClassName} | ||
headingLevel={headingLevel} | ||
/> | ||
{children} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
EmptyState.displayName = 'EmptyState'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,44 @@ | ||
import * as React from 'react'; | ||
import { css } from '@patternfly/react-styles'; | ||
import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; | ||
import { EmptyStateIconProps } from './EmptyStateIcon'; | ||
import { EmptyStateIcon } from './EmptyStateIcon'; | ||
|
||
export enum EmptyStateHeadingLevel { | ||
h1 = 'h1', | ||
h2 = 'h2', | ||
h3 = 'h3', | ||
h4 = 'h4', | ||
h5 = 'h5', | ||
h6 = 'h6' | ||
} | ||
|
||
export interface EmptyStateHeaderProps extends React.HTMLProps<HTMLDivElement> { | ||
/** Content rendered inside the empty state header, either in addition to or instead of the titleText prop */ | ||
children?: React.ReactNode; | ||
/** Additional classes added to the empty state header */ | ||
className?: string; | ||
/** Additional classes added to the title inside empty state header */ | ||
titleClassName?: string; | ||
/** Text of the title inside empty state header, will be wrapped in headingLevel */ | ||
titleText?: React.ReactNode; | ||
/** Empty state icon element to be rendered */ | ||
icon?: React.ReactElement<EmptyStateIconProps>; | ||
titleText: React.ReactNode; | ||
/** Empty state icon element to be rendered. Can also be a spinner component */ | ||
icon?: React.ComponentType<any>; | ||
/** The heading level to use, default is h1 */ | ||
headingLevel?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; | ||
} | ||
|
||
export const EmptyStateHeader: React.FunctionComponent<EmptyStateHeaderProps> = ({ | ||
children, | ||
className, | ||
titleClassName, | ||
titleText, | ||
headingLevel: HeadingLevel = 'h1', | ||
icon, | ||
headingLevel: HeadingLevel = EmptyStateHeadingLevel.h1, | ||
icon: Icon, | ||
...props | ||
}: EmptyStateHeaderProps) => ( | ||
<div className={css(`${styles.emptyState}__header`, className)} {...props}> | ||
{icon} | ||
{(titleText || children) && ( | ||
<div className={css(`${styles.emptyState}__title`)}> | ||
{titleText && ( | ||
<HeadingLevel className={css(styles.emptyStateTitleText, titleClassName)}>{titleText}</HeadingLevel> | ||
)} | ||
{children} | ||
</div> | ||
)} | ||
{Icon && <EmptyStateIcon icon={Icon} />} | ||
<div className={css(`${styles.emptyState}__title`)}> | ||
<HeadingLevel className={css(styles.emptyStateTitleText, titleClassName)}>{titleText}</HeadingLevel> | ||
</div> | ||
</div> | ||
); | ||
|
||
EmptyStateHeader.displayName = 'EmptyStateHeader'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,14 +2,7 @@ import * as React from 'react'; | |
import { css } from '@patternfly/react-styles'; | ||
import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; | ||
import { Spinner } from '../Spinner'; | ||
import cssIconColor from '@patternfly/react-tokens/dist/esm/c_empty_state__icon_Color'; | ||
|
||
export interface IconProps extends Omit<React.HTMLProps<SVGElement>, 'size'> { | ||
/** Changes the color of the icon. */ | ||
color?: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Color prop removed as the status prop will allow color customization in a themed way. If they really need to consumers can still apply colors directly to the icon they pass in. |
||
} | ||
|
||
export interface EmptyStateIconProps extends IconProps { | ||
export interface EmptyStateIconProps { | ||
/** Additional classes added to the empty state icon */ | ||
className?: string; | ||
/** Icon component to be rendered. Can also be a spinner component */ | ||
|
@@ -21,15 +14,12 @@ const isSpinner = (icon: React.ReactElement<any>) => icon.type === Spinner; | |
export const EmptyStateIcon: React.FunctionComponent<EmptyStateIconProps> = ({ | ||
className, | ||
icon: IconComponent, | ||
color, | ||
...props | ||
}: EmptyStateIconProps) => { | ||
const iconIsSpinner = isSpinner(<IconComponent />); | ||
|
||
return ( | ||
<div | ||
className={css(styles.emptyStateIcon)} | ||
{...(color && !iconIsSpinner && { style: { [cssIconColor.name]: color } as React.CSSProperties })} | ||
> | ||
<div className={css(styles.emptyStateIcon)}> | ||
<IconComponent className={className} aria-hidden={!iconIsSpinner} {...props} /> | ||
</div> | ||
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
children
changed to optional becausetitleText
has been lifted and changed to required.