libs/designer-ui/src/lib/checkbox/index.tsx (95 lines of code) (raw):
import { calloutContentStyles, checkboxStyles } from '../fabric';
import type { ICheckbox } from '@fluentui/react';
import { Callout, Checkbox as FluentCheckbox, css, DirectionalHint, Icon } from '@fluentui/react';
import { useRef, useState } from 'react';
import { useIntl } from 'react-intl';
export interface CheckboxProps {
ariaLabel?: string;
className?: string;
descriptionText?: string;
disabled?: boolean;
id?: string;
initialChecked?: boolean;
text?: string;
onChange?(checked: boolean): void;
}
export interface CheckboxState {
checkboxDescriptionExpanded: boolean;
checked: boolean;
}
export const Checkbox: React.FC<CheckboxProps> = ({
ariaLabel,
className,
descriptionText,
id,
initialChecked = false,
text,
disabled,
onChange,
}) => {
const [checkboxDescriptionExpanded, setCheckboxDescriptionExpanded] = useState(false);
const [checked, setChecked] = useState<boolean>(initialChecked);
const checkboxDescriptionButtonRef = useRef<HTMLButtonElement | null>();
const checkboxRef = useRef<ICheckbox>();
const intl = useIntl();
const handleCheckboxDescriptionDismiss = () => {
setCheckboxDescriptionExpanded(false);
};
const handleChange: React.MouseEventHandler<HTMLInputElement> = () => {
setChecked(!checked);
if (onChange) {
onChange(checked);
}
};
const handleCheckboxDescriptionButtonClick: React.MouseEventHandler<HTMLButtonElement> = (e) => {
e.preventDefault();
setCheckboxDescriptionExpanded(!checkboxDescriptionExpanded);
};
const moreInfoMessage = intl.formatMessage({
defaultMessage: 'More info',
id: 'XY5SKM',
description: 'Shown as an aria label on button and as the tooltip shown after you select the button.',
});
return (
<div className={css(className, 'msla-checkbox')}>
<FluentCheckbox
ariaLabel={ariaLabel}
componentRef={(e) => (checkboxRef.current = e as any)}
checked={checked}
className="msla-checkbox-label"
id={id}
label={text}
styles={checkboxStyles}
disabled={disabled}
onChange={handleChange as any}
/>
{descriptionText ? (
<button
ref={(ref) => (checkboxDescriptionButtonRef.current = ref)}
aria-label={moreInfoMessage}
className="msla-button msla-checkbox-description-icon-button"
title={moreInfoMessage}
onClick={handleCheckboxDescriptionButtonClick}
>
<Icon className="msla-checkbox-description-icon" iconName="Info" />
</button>
) : null}
{checkboxDescriptionExpanded ? (
<Callout
ariaLabel={descriptionText}
className="msla-checkbox-description-callout"
directionalHint={DirectionalHint.rightCenter}
gapSpace={0}
setInitialFocus={true}
styles={calloutContentStyles}
target={checkboxDescriptionButtonRef.current}
onDismiss={handleCheckboxDescriptionDismiss}
>
<div data-is-focusable={true} role="dialog" tabIndex={0}>
{descriptionText}
</div>
</Callout>
) : null}
</div>
);
};