@spark-web/checkbox
Version:
--- title: Checkbox storybookPath: forms-checkbox--default isExperimentalPackage: false ---
190 lines (186 loc) • 7.68 kB
JavaScript
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
import { ControlLabel } from '@spark-web/control-label';
import { useFieldIds, FieldMessage } from '@spark-web/field';
import { Stack } from '@spark-web/stack';
import { forwardRef } from 'react';
import { css } from '@emotion/react';
import { useFocusRing } from '@spark-web/a11y';
import { Box } from '@spark-web/box';
import { CheckIcon } from '@spark-web/icon';
import { useTheme } from '@spark-web/theme';
import { isEmpty } from 'lodash';
import { jsxs, jsx } from '@emotion/react/jsx-runtime';
var _excluded$1 = ["size", "css"],
_excluded2 = ["className"],
_excluded3 = ["checked"];
var CheckboxPrimitive = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
var _ref$size = _ref.size,
size = _ref$size === void 0 ? 'small' : _ref$size,
cssObj = _ref.css,
inputProps = _objectWithoutProperties(_ref, _excluded$1);
var theme = useTheme();
var _useCheckbox = useCheckbox(size),
className = _useCheckbox.className,
restCheckboxStyles = _objectWithoutProperties(_useCheckbox, _excluded2);
var responsiveStyles = theme.utils.responsiveStyles({
mobile: {
height: theme.typography.text.small.mobile.capHeight
},
tablet: {
height: theme.typography.text.small.tablet.capHeight
}
});
return jsxs(Box, {
display: "flex",
alignItems: "center",
flexShrink: 0,
css: css(responsiveStyles, cssObj),
children: [jsx(Box, _objectSpread(_objectSpread(_objectSpread({}, inputProps), restCheckboxStyles), {}, {
css: css(className),
"aria-checked": inputProps.checked,
"aria-disabled": inputProps.disabled,
ref: forwardedRef,
as: "input",
type: "checkbox"
})), jsx(CheckIcon, {
size: sizeToScaleKey[size]
})]
});
});
CheckboxPrimitive.displayName = 'CheckboxPrimitive';
var sizeToScaleKey = {
small: 'xxsmall',
medium: 'xsmall'
};
function useCheckbox(size) {
var _focusChecked$border;
var theme = useTheme();
var focusRingStyles = useFocusRing({
always: true
});
var checkboxToken = theme.components.checkbox;
var _ref2 = (checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.focus) || {},
focusChecked = _ref2.checked,
focus = _objectWithoutProperties(_ref2, _excluded3);
var outerSize = sizeToScaleKey[size];
var transitionProperties = {
transitionProperty: 'color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter',
transitionTimingFunction: theme.animation.standard.easing,
transitionDuration: "".concat(theme.animation.standard.duration, "ms")
};
return {
border: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.border["default"],
borderRadius: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.border.radius,
borderWidth: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.border.width,
background: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.background,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
flex: 1,
height: outerSize,
width: outerSize,
position: 'relative',
shadow: 'small',
className: _objectSpread(_objectSpread({
appearance: 'none',
verticalAlign: 'text-bottom'
}, transitionProperties), {}, {
'&::before': _objectSpread({
content: '""',
position: 'absolute',
margin: 'auto',
top: 0,
right: 0,
bottom: 0,
left: 0,
height: 0,
width: 0,
overflow: 'hidden'
}, transitionProperties),
'label:hover &:not([disabled], &[aria-disabled=true])': {
borderColor: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.label.hover.border
},
'& + svg': {
position: 'absolute',
pointerEvents: 'none',
opacity: 0
},
'&:focus': !isEmpty(focus) ? focus : focusRingStyles,
'&:checked': {
background: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.checked.background,
borderColor: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.checked.border.color,
'+ svg': {
opacity: 1,
stroke: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.checked.icon.stroke
},
'&:focus': focusChecked ? {
background: focusChecked.background,
borderColor: (_focusChecked$border = focusChecked.border) === null || _focusChecked$border === void 0 ? void 0 : _focusChecked$border.color
} : undefined
},
'label:hover &:not([disabled], &[aria-disabled=true]):checked': {
// TODO: checkbox gets lighter on hover instead of darker like in the designs, will fix once tokens are revised
background: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.label.checked.hover.background,
border: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.label.checked.hover.border
},
'&[disabled]:checked, &[aria-disabled=true]:checked': {
// TODO: using a `border` color for background here as we don't have a token for it just yet
background: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.checked.disabled.background,
border: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.checked.disabled.border,
'+ svg': {
stroke: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.checked.disabled.icon.stroke
}
},
'&[disabled]:checked::before, &[aria-disabled=true]:checked::before': {
background: checkboxToken === null || checkboxToken === void 0 ? void 0 : checkboxToken.checked.disabled.before.background
}
})
};
}
var _excluded = ["children", "data", "disabled", "id", "message", "size", "tone", "alignItems"];
var Checkbox = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
var children = _ref.children,
data = _ref.data,
_ref$disabled = _ref.disabled,
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
idProp = _ref.id,
message = _ref.message,
_ref$size = _ref.size,
size = _ref$size === void 0 ? 'small' : _ref$size,
_ref$tone = _ref.tone,
tone = _ref$tone === void 0 ? 'neutral' : _ref$tone,
_ref$alignItems = _ref.alignItems,
alignItems = _ref$alignItems === void 0 ? 'start' : _ref$alignItems,
inputProps = _objectWithoutProperties(_ref, _excluded);
var _useFieldIds = useFieldIds(idProp),
inputId = _useFieldIds.inputId,
messageId = _useFieldIds.messageId;
var a11yProps = {
'aria-describedby': message && messageId
};
return jsxs(Stack, {
gap: "small",
position: "relative",
children: [jsx(ControlLabel, {
control: jsx(CheckboxPrimitive, _objectSpread(_objectSpread(_objectSpread({}, inputProps), a11yProps), {}, {
ref: forwardedRef,
disabled: disabled,
size: size,
id: inputId,
data: data
})),
disabled: disabled,
htmlFor: inputId,
size: size,
alignItems: alignItems,
children: children
}), message && jsx(FieldMessage, {
tone: tone,
id: messageId,
message: message
})]
});
});
Checkbox.displayName = 'Checkbox';
export { Checkbox, CheckboxPrimitive };