@hypothesis/frontend-shared
Version:
Shared components, styles and utilities for Hypothesis projects
182 lines (169 loc) • 5.29 kB
JavaScript
var _jsxFileName = "/home/runner/work/frontend-shared/frontend-shared/src/components/buttons.js";
import classnames from 'classnames';
import { SvgIcon } from './SvgIcon';
/**
* @typedef ButtonProps
* @prop {import('preact').Ref<HTMLButtonElement>} [buttonRef]
* @prop {string} [classes] - Optional CSS class name(s) to use _in addition_
* to the button component's own clases
* @prop {string} [className] - Optional CSS class name that will _replace_
* the button component's own classes
* @prop {string|symbol} [icon] - Name of `SvgIcon` to render in the button
* @prop {'left'|'right'} [iconPosition] - Icon positioned to left or to
* right of button text
* @prop {boolean} [expanded] - Is the element associated with this button
* expanded (set `aria-expanded`)
* @prop {never} [aria-expanded] - Use `expanded` prop instead
* @prop {boolean} [pressed] - Is this button currently "active?" (set
* `aria-pressed` or `aria-selected` depending on button `role`)
* @prop {never} [aria-pressed] - Use `pressed` prop instead
* @prop {'small'|'medium'|'large'} [size='medium'] - Relative button size:
* affects padding
* @prop {string} [title] - Button title; used for `aria-label` attribute
* @prop {never} [aria-label] - Use `title` prop instead
* @prop {'normal'|'primary'|'light'|'dark'} [variant='normal'] - For styling: element variant
*/
/**
* Fold in HTML button prop definitions into ButtonProps, but ignore `size` because it's inherited
* from HTMLElement and conflicts with the _ButtonProps.size prop above. Ignore `icon`
* because it is typed to `string` only and we need to be able to accept {string|symbol}
*
* @typedef {Omit<import('preact').JSX.HTMLAttributes<HTMLButtonElement>, 'size' | 'icon'> } HTMLButtonElementProps
* @typedef {ButtonProps & HTMLButtonElementProps} ButtonBaseProps
*/
/**
* @typedef IconButtonBaseProps
* @prop {string|symbol} icon - Icon is required for icon buttons
* @prop {string} title - Title is required for icon buttons
* @prop {never} [children] - children are not allowed (use LabeledButton instead)
*/
/**
* @typedef {ButtonBaseProps & IconButtonBaseProps} IconButtonProps
*/
/**
* @param {ButtonBaseProps} props
*/
import { jsxDEV as _jsxDEV } from "preact/jsx-dev-runtime";
function ButtonBase({
// Custom props.
buttonRef,
classes,
className,
icon,
iconPosition = 'left',
size = 'medium',
variant = 'normal',
expanded,
pressed,
// Standard <button> props.
type = 'button',
...restProps
}) {
var _restProps$role;
const role = (_restProps$role = restProps === null || restProps === void 0 ? void 0 : restProps.role) !== null && _restProps$role !== void 0 ? _restProps$role : 'button';
const ariaProps = {
'aria-label': restProps.title
}; // aria-pressed and aria-expanded are not allowed for buttons with
// an aria role of `tab`. Instead, the aria-selected attribute is expected.
if (role === 'tab') {
ariaProps['aria-selected'] = pressed;
} else {
ariaProps['aria-pressed'] = pressed;
ariaProps['aria-expanded'] = expanded;
}
return _jsxDEV("button", {
ref: buttonRef,
className: classnames(className, `${className}--${size}`, `${className}--${variant}`, {
[`${className}--icon-${iconPosition}`]: icon
}, classes),
type: type,
...ariaProps,
...restProps
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 82,
columnNumber: 5
}, this);
}
/**
* An icon-only button
*
* @deprecated - Use re-implemented component in the input group
* @param {IconButtonProps} props
*/
export function IconButton({
className = 'Hyp-IconButton',
...restProps
}) {
const {
icon
} = restProps;
return _jsxDEV(ButtonBase, {
className: className,
...restProps,
children: _jsxDEV(SvgIcon, {
name: icon
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 110,
columnNumber: 7
}, this)
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 109,
columnNumber: 5
}, this);
}
/**
* A labeled button, with or without an icon
*
* @deprecated - Use re-implemented component in the input group
* @param {ButtonBaseProps} props
*/
export function LabeledButton({
children,
className = 'Hyp-LabeledButton',
...restProps
}) {
const {
icon,
iconPosition = 'left'
} = restProps;
return _jsxDEV(ButtonBase, {
className: className,
...restProps,
children: [icon && iconPosition === 'left' && _jsxDEV(SvgIcon, {
name: icon
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 129,
columnNumber: 43
}, this), children, icon && iconPosition === 'right' && _jsxDEV(SvgIcon, {
name: icon
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 131,
columnNumber: 44
}, this)]
}, void 0, true, {
fileName: _jsxFileName,
lineNumber: 128,
columnNumber: 5
}, this);
}
/**
* A button styled to appear as an HTML link (<a>)
*
* @param {ButtonBaseProps} props
*/
export function LinkButton(props) {
return _jsxDEV(ButtonBase, {
className: "Hyp-LinkButton",
...props
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 142,
columnNumber: 10
}, this);
}
//# sourceMappingURL=buttons.js.map