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
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import { Button } from '@patternfly/react-core';
import { Button, KeyTypes } from '@patternfly/react-core';

const handleKeydown = (event: React.KeyboardEvent<HTMLButtonElement>) => {
const { key } = event;
const isEnterKey: boolean = key === 'Enter';
const isEnterOrSpaceKey: boolean = isEnterKey || key === 'Space';
const isEnterKey: boolean = key === KeyTypes.Enter;
const isEnterOrSpaceKey: boolean = isEnterKey || key === KeyTypes.Space;

if (isEnterOrSpaceKey) {
event.preventDefault();
Expand Down
46 changes: 40 additions & 6 deletions packages/react-core/src/components/Form/FormGroupLabelHelp.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { Button, ButtonProps } from '../Button';
import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon';
import { KeyTypes } from '../../helpers/constants';

/** A help button to be passed to the FormGroup's labelHelp property. This should be wrapped or linked
* to our Popover component.
Expand All @@ -10,15 +11,48 @@ export interface FormGroupLabelHelpProps extends ButtonProps {
'aria-label': string;
/** Additional classes added to the help button. */
className?: string;
/** @hide Forwarded ref */
innerRef?: React.Ref<HTMLSpanElement>;
}

export const FormGroupLabelHelp: React.FunctionComponent<FormGroupLabelHelpProps> = ({
const FormGroupLabelHelpBase: React.FunctionComponent<FormGroupLabelHelpProps> = ({
'aria-label': ariaLabel,
className,
innerRef,
...props
}) => (
<Button aria-label={ariaLabel} className={className} variant="plain" hasNoPadding {...props}>
<QuestionCircleIcon />
</Button>
);
}) => {
const ref = React.useRef<HTMLSpanElement>(null);
const buttonRef = innerRef || ref;

const isMutableRef = (ref: React.Ref<HTMLSpanElement>): ref is React.MutableRefObject<HTMLSpanElement> =>
typeof ref === 'object' && ref !== null && 'current' in ref && ref.current !== undefined;

const handleKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
if ([KeyTypes.Space, KeyTypes.Enter].includes(event.key) && isMutableRef(buttonRef) && buttonRef.current) {
event.preventDefault();
buttonRef.current.click();
}
};

return (
<Button
component="span"
isInline
ref={buttonRef}
onKeyDown={handleKeyDown}
aria-label={ariaLabel}
className={className}
variant="plain"
hasNoPadding
{...props}
>
<QuestionCircleIcon />
</Button>
);
};

export const FormGroupLabelHelp = React.forwardRef((props: FormGroupLabelHelpProps, ref: React.Ref<any>) => (
<FormGroupLabelHelpBase innerRef={ref} {...props} />
));

FormGroupLabelHelp.displayName = 'FormGroupLabelHelp';
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const FormBasic: React.FunctionComponent = () => {
const [name, setName] = React.useState('');
const [email, setEmail] = React.useState('');
const [phone, setPhone] = React.useState('');
const labelHelpRef = React.useRef(null);

const handleNameChange = (_event, name: string) => {
setName(name);
Expand All @@ -37,6 +38,7 @@ export const FormBasic: React.FunctionComponent = () => {
label="Full name"
labelHelp={
<Popover
triggerRef={labelHelpRef}
headerContent={
<div>
The{' '}
Expand All @@ -63,7 +65,7 @@ export const FormBasic: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for name field" />
<FormGroupLabelHelp ref={labelHelpRef} aria-label="More info for name field" />
</Popover>
}
isRequired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {

export const FormGroupLabelInfo: React.FunctionComponent = () => {
const [name, setName] = React.useState('');
const labelHelpRef = React.useRef(null);

const handleNameChange = (_event, name: string) => {
setName(name);
Expand All @@ -24,6 +25,7 @@ export const FormGroupLabelInfo: React.FunctionComponent = () => {
labelInfo="Additional label info"
labelHelp={
<Popover
triggerRef={labelHelpRef}
headerContent={
<div>
The{' '}
Expand All @@ -50,7 +52,7 @@ export const FormGroupLabelInfo: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for name field" />
<FormGroupLabelHelp ref={labelHelpRef} aria-label="More info for name field" />
</Popover>
}
isRequired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const FormLimitWidth: React.FunctionComponent = () => {
const [name, setName] = React.useState('');
const [email, setEmail] = React.useState('');
const [phone, setPhone] = React.useState('');
const labelHelpRef = React.useRef(null);

const handleNameChange = (_event, name: string) => {
setName(name);
Expand All @@ -37,6 +38,7 @@ export const FormLimitWidth: React.FunctionComponent = () => {
label="Full name"
labelHelp={
<Popover
triggerRef={labelHelpRef}
headerContent={
<div>
The{' '}
Expand All @@ -63,7 +65,7 @@ export const FormLimitWidth: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for name field" />
<FormGroupLabelHelp ref={labelHelpRef} aria-label="More info for name field" />
</Popover>
}
isRequired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export const ModalWithForm: React.FunctionComponent = () => {
const [nameValue, setNameValue] = React.useState('');
const [emailValue, setEmailValue] = React.useState('');
const [addressValue, setAddressValue] = React.useState('');
const nameLabelHelpRef = React.useRef(null);
const emailLabelHelpRef = React.useRef(null);
const addressLabelHelpRef = React.useRef(null);

const handleModalToggle = (_event: KeyboardEvent | React.MouseEvent) => {
setModalOpen(!isModalOpen);
Expand Down Expand Up @@ -56,6 +59,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
label="Name"
labelHelp={
<Popover
triggerRef={nameLabelHelpRef}
headerContent={
<div>
The
Expand All @@ -82,7 +86,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for name field" />
<FormGroupLabelHelp ref={nameLabelHelpRef} aria-label="More info for name field" />
</Popover>
}
isRequired
Expand All @@ -101,6 +105,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
label="E-mail"
labelHelp={
<Popover
triggerRef={emailLabelHelpRef}
headerContent={
<div>
The
Expand All @@ -123,7 +128,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for e-mail field" />
<FormGroupLabelHelp ref={emailLabelHelpRef} aria-label="More info for e-mail field" />
</Popover>
}
isRequired
Expand All @@ -142,6 +147,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
label="Address"
labelHelp={
<Popover
triggerRef={addressLabelHelpRef}
headerContent={
<div>
The
Expand All @@ -163,7 +169,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for address field" />
<FormGroupLabelHelp ref={addressLabelHelpRef} aria-label="More info for address field" />
</Popover>
}
isRequired
Expand Down
4 changes: 2 additions & 2 deletions packages/react-core/src/demos/SearchInput/SearchInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ SearchAutocomplete = () => {
event.preventDefault(); // by default, the up and down arrow keys scroll the window
// the tab, enter, and space keys will close the menu, and the tab key will move browser
// focus forward one element (by default)
} else if (event.key === 'Tab' || event.key === 'Enter' || event.key === 'Space') {
} else if (event.key === 'Tab' || event.key === 'Enter' || event.key === ' ') {
setIsAutocompleteOpen(false);
if (event.key === 'Enter' || event.key === 'Space') {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,15 @@ export const PasswordStrengthDemo: React.FunctionComponent = () => {
}
};

const labelHelpRef = React.useRef(null);

const iconPopover = (
<Popover headerContent={<div>Password Requirements</div>} bodyContent={<div>Password rules</div>}>
<FormGroupLabelHelp aria-label="More info for name field" />
<Popover
triggerRef={labelHelpRef}
headerContent={<div>Password Requirements</div>}
bodyContent={<div>Password rules</div>}
>
<FormGroupLabelHelp ref={labelHelpRef} aria-label="More info for name field" />
</Popover>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export const ModalWithForm: React.FunctionComponent = () => {
const [nameValue, setNameValue] = React.useState('');
const [emailValue, setEmailValue] = React.useState('');
const [addressValue, setAddressValue] = React.useState('');
const nameLabelHelpRef = React.useRef(null);
const emailLabelHelpRef = React.useRef(null);
const addressLabelHelpRef = React.useRef(null);

const handleModalToggle = (_event: KeyboardEvent | React.MouseEvent) => {
setModalOpen(!isModalOpen);
Expand Down Expand Up @@ -47,6 +50,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
label="Name"
labelHelp={
<Popover
triggerRef={nameLabelHelpRef}
headerContent={
<div>
The
Expand All @@ -73,7 +77,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for name field" />
<FormGroupLabelHelp ref={nameLabelHelpRef} aria-label="More info for name field" />
</Popover>
}
isRequired
Expand All @@ -92,6 +96,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
label="E-mail"
labelHelp={
<Popover
triggerRef={emailLabelHelpRef}
headerContent={
<div>
The
Expand All @@ -114,7 +119,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for e-mail field" />
<FormGroupLabelHelp ref={emailLabelHelpRef} aria-label="More info for e-mail field" />
</Popover>
}
isRequired
Expand All @@ -133,6 +138,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
label="Address"
labelHelp={
<Popover
triggerRef={addressLabelHelpRef}
headerContent={
<div>
The
Expand All @@ -154,7 +160,7 @@ export const ModalWithForm: React.FunctionComponent = () => {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for address field" />
<FormGroupLabelHelp ref={addressLabelHelpRef} aria-label="More info for address field" />
</Popover>
}
isRequired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export class FormDemo extends Component<FormProps, FormState> {

this.handleCheckboxChange = this.handleCheckboxChange.bind(this);
}

labelHelpRef: React.RefObject<HTMLSpanElement> = React.createRef();

handleTextInputChange = (_event: React.FormEvent<HTMLInputElement>, value: string) => {
this.setState({ value, isValid: /^\d+$/.test(value) });
};
Expand Down Expand Up @@ -114,6 +117,7 @@ export class FormDemo extends Component<FormProps, FormState> {
labelInfo="Age info"
labelHelp={
<Popover
triggerRef={this.labelHelpRef}
headerContent={<div>The age of a person</div>}
bodyContent={
<div>
Expand All @@ -122,7 +126,7 @@ export class FormDemo extends Component<FormProps, FormState> {
</div>
}
>
<FormGroupLabelHelp aria-label="More info for name field" />
<FormGroupLabelHelp ref={this.labelHelpRef} aria-label="More info for name field" />
</Popover>
}
type="number"
Expand Down
4 changes: 2 additions & 2 deletions packages/react-table/src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import stylesTreeView from '@patternfly/react-styles/css/components/Table/table-
import { css } from '@patternfly/react-styles';
import { toCamel } from './utils';
import { IVisibility } from './utils/decorators/classNames';
import { useOUIAProps, OUIAProps, handleArrows, setTabIndex } from '@patternfly/react-core';
import { useOUIAProps, OUIAProps, handleArrows, setTabIndex, KeyTypes } from '@patternfly/react-core';
import { TableGridBreakpoint, TableVariant } from './TableTypes';

export interface BaseCellProps {
Expand Down Expand Up @@ -169,7 +169,7 @@ const TableBase: React.FunctionComponent<TableProps> = ({
const rows = (Array.from(tableRef.current.querySelectorAll('tbody tr')) as Element[]).filter(
(el) => !el.classList.contains('pf-m-disabled') && !(el as HTMLElement).hidden
);
if (key === 'Space' || key === 'Enter') {
if (key === KeyTypes.Space || key === KeyTypes.Enter) {
(activeElement as HTMLElement).click();
event.preventDefault();
}
Expand Down