chore: add strict-boolean-expressions rule (#27852)

## Description
Add `@typescript-eslint/strict-boolean-expressions` eslint rule for
packages.
This commit is contained in:
Valera Melnikov 2023-10-06 16:05:32 +03:00 committed by GitHub
parent e32e51b2fe
commit 22e10c6fdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 109 additions and 78 deletions

View File

@ -3,6 +3,12 @@
"$schema": "http://json.schemastore.org/eslintrc", "$schema": "http://json.schemastore.org/eslintrc",
"root": true, "root": true,
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"ignorePatterns": [
"jest.config.js",
"jest.setup.ts",
"rollup.config.js",
".eslintrc.js"
],
"plugins": [ "plugins": [
"react", "react",
"@typescript-eslint", "@typescript-eslint",
@ -25,9 +31,11 @@
"sourceType": "module", // Allows for the use of imports "sourceType": "module", // Allows for the use of imports
"ecmaFeatures": { "ecmaFeatures": {
"jsx": true // Allows for the parsing of JSX "jsx": true // Allows for the parsing of JSX
} },
"project": "./tsconfig.json"
}, },
"rules": { "rules": {
"@typescript-eslint/strict-boolean-expressions": "error",
"@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-unused-vars": "error",
"jest/no-focused-tests": "error", "jest/no-focused-tests": "error",

View File

@ -13,6 +13,7 @@ const baseNoRestrictedImports =
const eslintConfig = { const eslintConfig = {
extends: ["./.eslintrc.base.json"], extends: ["./.eslintrc.base.json"],
rules: { rules: {
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"react/display-name": "off", "react/display-name": "off",
"react/prop-types": "off", "react/prop-types": "off",

View File

@ -1,7 +1,7 @@
{ {
"src/**/*.{js,ts,tsx}": ["npx eslint --fix"], "src/**/*.{js,ts,tsx}": ["npx eslint --fix"],
"src/**/*.{js,ts,tsx,css,md,json}": ["npx prettier --write"], "src/**/*.{js,ts,tsx,css,md,json}": ["npx prettier --write"],
"cypress/**/*.{js,ts}": ["npx eslint --fix"], "cypress/**/*.{js,ts}": ["cd ./cypress && npx eslint -c .eslintrc.json --fix"],
"cypress/**/*.{js,ts,json}": ["npx prettier --write"], "cypress/**/*.{js,ts,json}": ["npx prettier --write"],
"packages/**/*.{js,ts,tsx}": ["npx eslint --fix"], "packages/**/*.{js,ts,tsx}": ["npx eslint --fix"],
"packages/**/*.{js,ts,tsx,css,mdx,json}": ["npx prettier --write"] "packages/**/*.{js,ts,tsx,css,mdx,json}": ["npx prettier --write"]

View File

@ -1,9 +1,11 @@
{ {
"extends": ["../.eslintrc.base.json"], "extends": ["../.eslintrc.base.json"],
"ignorePatterns": ["locators", "fixtures"],
"env": { "env": {
"cypress/globals": true "cypress/globals": true
}, },
"rules": { "rules": {
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-array-constructor": "off", "@typescript-eslint/no-array-constructor": "off",
"@typescript-eslint/no-namespace": "off", "@typescript-eslint/no-namespace": "off",
"@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "off",

View File

@ -32,5 +32,5 @@
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"types": ["cypress", "node", "cypress-tags", "cypress-real-events"] "types": ["cypress", "node", "cypress-tags", "cypress-real-events"]
}, },
"include": ["/**/*.ts", "../packages/rts/src/version.js"] "include": ["./", "../packages/rts/src/version.js"]
} }

View File

@ -34,7 +34,7 @@
"generate:widget": "plop --plopfile generators/index.js", "generate:widget": "plop --plopfile generators/index.js",
"postinstall": "node cypress/apply-patches.js && yarn init-husky", "postinstall": "node cypress/apply-patches.js && yarn init-husky",
"storybook": "yarn workspace @design-system/storybook storybook", "storybook": "yarn workspace @design-system/storybook storybook",
"lint": "eslint --cache --ext .js,.ts,.tsx ./src && eslint --cache --ext .js,.ts ./cypress", "lint": "eslint --cache ./src && cd ./cypress && eslint -c .eslintrc.json --cache ./",
"g:lint": "cd $INIT_CWD && eslint --cache .", "g:lint": "cd $INIT_CWD && eslint --cache .",
"lint:ci": "yarn workspaces foreach -ptv run lint", "lint:ci": "yarn workspaces foreach -ptv run lint",
"prettier": "prettier --check ./src && prettier --check ./cypress", "prettier": "prettier --check ./src && prettier --check ./cypress",

View File

@ -2,6 +2,7 @@
"extends": ["../../.eslintrc.base.json"], "extends": ["../../.eslintrc.base.json"],
"ignorePatterns": ["build"], "ignorePatterns": ["build"],
"rules": { "rules": {
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-explicit-any": "off" "@typescript-eslint/no-explicit-any": "off"
} }
} }

View File

@ -20,7 +20,13 @@ export type ButtonRef = React.Ref<HTMLButtonElement>;
type ButtonRefObject = React.RefObject<HTMLButtonElement>; type ButtonRefObject = React.RefObject<HTMLButtonElement>;
const _Button = (props: ButtonProps, ref: ButtonRef) => { const _Button = (props: ButtonProps, ref: ButtonRef) => {
const { autoFocus, children, className, draggable, isDisabled } = props; const {
autoFocus,
children,
className,
draggable = false,
isDisabled = false,
} = props;
const { hoverProps, isHovered } = useHover({ isDisabled }); const { hoverProps, isHovered } = useHover({ isDisabled });
const { focusProps, isFocusVisible } = useFocusRing({ autoFocus }); const { focusProps, isFocusVisible } = useFocusRing({ autoFocus });
const { buttonProps, isPressed } = useButton(props, ref as ButtonRefObject); const { buttonProps, isPressed } = useButton(props, ref as ButtonRefObject);
@ -28,8 +34,8 @@ const _Button = (props: ButtonProps, ref: ButtonRef) => {
return ( return (
<button <button
{...mergeProps(buttonProps, hoverProps, focusProps)} {...mergeProps(buttonProps, hoverProps, focusProps)}
aria-busy={props["aria-busy"] ? true : undefined} aria-busy={props["aria-busy"] ?? undefined}
aria-disabled={props["aria-disabled"] ? true : undefined} aria-disabled={props["aria-disabled"] ?? undefined}
className={className} className={className}
data-active={isPressed ? "" : undefined} data-active={isPressed ? "" : undefined}
data-disabled={isDisabled ? "" : undefined} data-disabled={isDisabled ? "" : undefined}

View File

@ -51,7 +51,7 @@ const _Checkbox = (props: CheckboxProps, ref: CheckboxRef) => {
const context = useContext(CheckboxGroupContext) as CheckboxGroupContextType; const context = useContext(CheckboxGroupContext) as CheckboxGroupContextType;
const isDisabled = isDisabledProp || context?.isDisabled; const isDisabled = isDisabledProp || context?.isDisabled;
const { hoverProps, isHovered } = useHover({ isDisabled }); const { hoverProps, isHovered } = useHover({ isDisabled });
const { inputProps } = context?.state const { inputProps } = Boolean(context?.state)
? // eslint-disable-next-line react-hooks/rules-of-hooks ? // eslint-disable-next-line react-hooks/rules-of-hooks
useCheckboxGroupItem( useCheckboxGroupItem(
{ {
@ -74,7 +74,7 @@ const _Checkbox = (props: CheckboxProps, ref: CheckboxRef) => {
const dataState = isIndeterminate const dataState = isIndeterminate
? "indeterminate" ? "indeterminate"
: inputProps.checked : Boolean(inputProps.checked)
? "checked" ? "checked"
: "unchecked"; : "unchecked";
@ -82,7 +82,7 @@ const _Checkbox = (props: CheckboxProps, ref: CheckboxRef) => {
<label <label
{...hoverProps} {...hoverProps}
className={className} className={className}
data-disabled={isDisabled ? "" : undefined} data-disabled={Boolean(isDisabled) ? "" : undefined}
data-focused={isFocusVisible ? "" : undefined} data-focused={isFocusVisible ? "" : undefined}
data-hovered={isHovered ? "" : undefined} data-hovered={isHovered ? "" : undefined}
data-invalid={validationState === "invalid" ? "" : undefined} data-invalid={validationState === "invalid" ? "" : undefined}

View File

@ -20,7 +20,12 @@ export interface CheckboxGroupProps
} }
const _CheckboxGroup = (props: CheckboxGroupProps, ref: CheckboxGroupRef) => { const _CheckboxGroup = (props: CheckboxGroupProps, ref: CheckboxGroupRef) => {
const { children, className, isDisabled, orientation = "vertical" } = props; const {
children,
className,
isDisabled = false,
orientation = "vertical",
} = props;
const domRef = useDOMRef(ref); const domRef = useDOMRef(ref);
const state = useCheckboxGroupState(props); const state = useCheckboxGroupState(props);
const { descriptionProps, errorMessageProps, groupProps, labelProps } = const { descriptionProps, errorMessageProps, groupProps, labelProps } =
@ -38,7 +43,7 @@ const _CheckboxGroup = (props: CheckboxGroupProps, ref: CheckboxGroupRef) => {
> >
<div <div
{...groupProps} {...groupProps}
data-disabled={props.isDisabled ? "" : undefined} data-disabled={isDisabled ? "" : undefined}
data-field-group="" data-field-group=""
data-orientation={orientation} data-orientation={orientation}
> >

View File

@ -19,7 +19,7 @@ function _HelpText(props: HelpTextProps, ref: DOMRef<HTMLDivElement>) {
validationState, validationState,
} = props; } = props;
const domRef = useDOMRef(ref); const domRef = useDOMRef(ref);
const isErrorMessage = errorMessage && validationState === "invalid"; const isErrorMessage = Boolean(errorMessage) && validationState === "invalid";
return ( return (
<div ref={domRef}> <div ref={domRef}>

View File

@ -27,7 +27,7 @@ const _Field = (props: FieldProps, ref: FieldRef) => {
elementType, elementType,
errorMessage, errorMessage,
errorMessageProps = {}, errorMessageProps = {},
isDisabled, isDisabled = false,
label, label,
labelProps, labelProps,
validationState, validationState,
@ -39,7 +39,8 @@ const _Field = (props: FieldProps, ref: FieldRef) => {
fieldType = "field", fieldType = "field",
} = props; } = props;
const hasHelpText = const hasHelpText =
!!description || (errorMessage && validationState === "invalid"); Boolean(description) ||
(Boolean(errorMessage) && validationState === "invalid");
const renderHelpText = () => { const renderHelpText = () => {
return ( return (
@ -56,12 +57,12 @@ const _Field = (props: FieldProps, ref: FieldRef) => {
const labelAndContextualHelp = ( const labelAndContextualHelp = (
<div data-field-label-wrapper=""> <div data-field-label-wrapper="">
{label && ( {Boolean(label) && (
<Label {...labelProps} elementType={elementType}> <Label {...labelProps} elementType={elementType}>
{label} {label}
</Label> </Label>
)} )}
{label && contextualHelp} {Boolean(label) && contextualHelp}
</div> </div>
); );

View File

@ -19,7 +19,7 @@ function _HelpText(props: HelpTextProps, ref: DOMRef<HTMLDivElement>) {
validationState, validationState,
} = props; } = props;
const domRef = useDOMRef(ref); const domRef = useDOMRef(ref);
const isErrorMessage = errorMessage && validationState === "invalid"; const isErrorMessage = Boolean(errorMessage) && validationState === "invalid";
return ( return (
<div ref={domRef}> <div ref={domRef}>

View File

@ -30,7 +30,9 @@ const _Label = (props: LabelProps, ref: DOMRef<HTMLLabelElement>) => {
<ElementType <ElementType
data-field-label="" data-field-label=""
{...filterDOMProps(otherProps)} {...filterDOMProps(otherProps)}
htmlFor={ElementType === "label" ? labelFor || htmlFor : undefined} htmlFor={
ElementType === "label" ? Boolean(labelFor) || htmlFor : undefined
}
onClick={onClick} onClick={onClick}
ref={domRef} ref={domRef}
> >

View File

@ -21,13 +21,11 @@ export function Icon(props: IconProps) {
...otherProps ...otherProps
} = props; } = props;
const ariaHidden = !ariaHiddenProp ? undefined : ariaHiddenProp;
return React.cloneElement(children, { return React.cloneElement(children, {
...filterDOMProps(otherProps), ...filterDOMProps(otherProps),
focusable: "false", focusable: "false",
"aria-label": ariaLabel, "aria-label": ariaLabel,
"aria-hidden": ariaLabel ? ariaHidden || undefined : true, "aria-hidden": Boolean(ariaLabel) ? ariaHiddenProp ?? undefined : true,
role, role,
"data-icon": "", "data-icon": "",
className, className,

View File

@ -50,7 +50,7 @@ const _Radio = (props: RadioProps, ref: RadioRef) => {
<label <label
{...hoverProps} {...hoverProps}
className={className} className={className}
data-disabled={isDisabled ? "" : undefined} data-disabled={Boolean(isDisabled) ? "" : undefined}
data-focused={isFocusVisible ? "" : undefined} data-focused={isFocusVisible ? "" : undefined}
data-hovered={isHovered ? "" : undefined} data-hovered={isHovered ? "" : undefined}
data-invalid={validationState === "invalid" ? "" : undefined} data-invalid={validationState === "invalid" ? "" : undefined}

View File

@ -44,7 +44,7 @@ const _Switch = (props: SwitchProps, ref: SwitchRef) => {
const context = useContext(CheckboxGroupContext) as CheckboxGroupContextType; const context = useContext(CheckboxGroupContext) as CheckboxGroupContextType;
const isDisabled = isDisabledProp || context?.isDisabled; const isDisabled = isDisabledProp || context?.isDisabled;
const { hoverProps, isHovered } = useHover({ isDisabled }); const { hoverProps, isHovered } = useHover({ isDisabled });
const { inputProps } = context?.state const { inputProps } = Boolean(context?.state)
? // eslint-disable-next-line react-hooks/rules-of-hooks ? // eslint-disable-next-line react-hooks/rules-of-hooks
useCheckboxGroupItem( useCheckboxGroupItem(
{ {
@ -65,13 +65,13 @@ const _Switch = (props: SwitchProps, ref: SwitchRef) => {
: // eslint-disable-next-line react-hooks/rules-of-hooks : // eslint-disable-next-line react-hooks/rules-of-hooks
useSwitch(props, state, inputRef); useSwitch(props, state, inputRef);
const dataState = inputProps.checked ? "checked" : "unchecked"; const dataState = Boolean(inputProps.checked) ? "checked" : "unchecked";
return ( return (
<label <label
{...hoverProps} {...hoverProps}
className={className} className={className}
data-disabled={isDisabled ? "" : undefined} data-disabled={Boolean(isDisabled) ? "" : undefined}
data-focused={isFocusVisible ? "" : undefined} data-focused={isFocusVisible ? "" : undefined}
data-hovered={isHovered ? "" : undefined} data-hovered={isHovered ? "" : undefined}
data-invalid={validationState === "invalid" ? "" : undefined} data-invalid={validationState === "invalid" ? "" : undefined}

View File

@ -32,7 +32,7 @@ function TextArea(props: TextAreaProps, ref: TextAreaRef) {
const onHeightChange = useCallback(() => { const onHeightChange = useCallback(() => {
// Quiet textareas always grow based on their text content. // Quiet textareas always grow based on their text content.
// Standard textareas also grow by default, unless an explicit height is set. // Standard textareas also grow by default, unless an explicit height is set.
if (!props.height && inputRef.current) { if (props.height == null && inputRef.current) {
const input = inputRef.current; const input = inputRef.current;
const prevAlignment = input.style.alignSelf; const prevAlignment = input.style.alignSelf;
const prevOverflow = input.style.overflow; const prevOverflow = input.style.overflow;
@ -60,7 +60,7 @@ function TextArea(props: TextAreaProps, ref: TextAreaRef) {
} }
}, [onHeightChange, inputValue, inputRef.current]); }, [onHeightChange, inputValue, inputRef.current]);
if (props.placeholder) { if (props.placeholder != null) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.warn( console.warn(
"Placeholders are deprecated due to accessibility issues. Please use help text instead. See the docs for details: https://react-spectrum.adobe.com/react-spectrum/TextArea.html#help-text", "Placeholders are deprecated due to accessibility issues. Please use help text instead. See the docs for details: https://react-spectrum.adobe.com/react-spectrum/TextArea.html#help-text",

View File

@ -14,7 +14,7 @@ function TextInput(props: TextInputProps, ref: TextInputRef) {
const { descriptionProps, errorMessageProps, inputProps, labelProps } = const { descriptionProps, errorMessageProps, inputProps, labelProps } =
useTextField(rest, inputRef); useTextField(rest, inputRef);
if (props.placeholder) { if (props.placeholder != null) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.warn( console.warn(
"Placeholders are deprecated due to accessibility issues. Please use help text instead. See the docs for details: https://react-spectrum.adobe.com/react-spectrum/TextField.html#help-text", "Placeholders are deprecated due to accessibility issues. Please use help text instead. See the docs for details: https://react-spectrum.adobe.com/react-spectrum/TextField.html#help-text",

View File

@ -17,10 +17,10 @@ function TextInputBase(props: TextInputBaseProps, ref: Ref<HTMLDivElement>) {
inputClassName, inputClassName,
inputProps, inputProps,
inputRef: userInputRef, inputRef: userInputRef,
isDisabled, isDisabled = false,
isLoading, isLoading = false,
labelProps, labelProps,
multiLine, multiLine = false,
onBlur, onBlur,
onFocus, onFocus,
startIcon, startIcon,
@ -32,8 +32,10 @@ function TextInputBase(props: TextInputBaseProps, ref: Ref<HTMLDivElement>) {
const defaultInputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null); const defaultInputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);
const inputRef = userInputRef || defaultInputRef; const inputRef = userInputRef || defaultInputRef;
const ElementType: React.ElementType = multiLine ? "textarea" : "input"; const ElementType: React.ElementType = Boolean(multiLine)
const isInvalid = validationState === "invalid" && !isDisabled; ? "textarea"
: "input";
const isInvalid = validationState === "invalid" && !Boolean(isDisabled);
const { focusProps, isFocusVisible } = useFocusRing({ const { focusProps, isFocusVisible } = useFocusRing({
isTextInput: true, isTextInput: true,

View File

@ -26,7 +26,7 @@ const _TooltipTrigger = (
"data-state": context.open ? "open" : "closed", "data-state": context.open ? "open" : "closed",
// when the trigger is disabled, we want to make sure that the tooltip is // when the trigger is disabled, we want to make sure that the tooltip is
// accessible with keyboard but visually disabled only // accessible with keyboard but visually disabled only
visuallyDisabled: children.props.isDisabled ? true : undefined, visuallyDisabled: Boolean(children.props.isDisabled) ? true : undefined,
}), }),
); );
} }

View File

@ -56,7 +56,7 @@ export function useTheme(props: UseThemeProps = {}) {
}, [colorMode]); }, [colorMode]);
useEffect(() => { useEffect(() => {
if (borderRadius) { if (borderRadius != null) {
tokensAccessor.updateBorderRadius({ tokensAccessor.updateBorderRadius({
1: borderRadius, 1: borderRadius,
}); });
@ -71,7 +71,7 @@ export function useTheme(props: UseThemeProps = {}) {
}, [borderRadius]); }, [borderRadius]);
useEffect(() => { useEffect(() => {
if (seedColor) { if (seedColor != null) {
let color; let color;
try { try {
@ -107,7 +107,7 @@ export function useTheme(props: UseThemeProps = {}) {
}, [fontFamily]); }, [fontFamily]);
useEffect(() => { useEffect(() => {
if (rootUnitRatioProp) { if (rootUnitRatioProp != null) {
setRootUnitRatio(rootUnitRatioProp); setRootUnitRatio(rootUnitRatioProp);
} }
}, [rootUnitRatioProp]); }, [rootUnitRatioProp]);

View File

@ -5,7 +5,7 @@ export const cssRule = (tokens: Theme) => {
let styles = ""; let styles = "";
Object.values(tokens).forEach((token) => { Object.values(tokens).forEach((token) => {
if (!token) return; if (token == null) return;
Object.keys(token).forEach((key) => { Object.keys(token).forEach((key) => {
//@ts-expect-error: type mismatch //@ts-expect-error: type mismatch

View File

@ -1,6 +1,7 @@
{ {
"extends": ["../../../.eslintrc.base.json"], "extends": ["../../../.eslintrc.base.json"],
"rules": { "rules": {
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"react/display-name": "off" "react/display-name": "off"
} }

View File

@ -20,12 +20,13 @@ const _Button = (props: ButtonProps, ref: HeadlessButtonRef) => {
color = "accent", color = "accent",
icon: Icon, icon: Icon,
iconPosition = "start", iconPosition = "start",
isLoading, isDisabled = false,
isLoading = false,
loadingText = "Loading...", loadingText = "Loading...",
// eslint-disable-next-line -- TODO add onKeyUp when the bug is fixed https://github.com/adobe/react-spectrum/issues/4350 // eslint-disable-next-line -- TODO add onKeyUp when the bug is fixed https://github.com/adobe/react-spectrum/issues/4350
onKeyUp, onKeyUp,
variant = "filled", variant = "filled",
visuallyDisabled, visuallyDisabled = false,
...rest ...rest
} = props; } = props;
const { visuallyHiddenProps } = useVisuallyHidden(); const { visuallyHiddenProps } = useVisuallyHidden();
@ -39,7 +40,7 @@ const _Button = (props: ButtonProps, ref: HeadlessButtonRef) => {
<Icon /> <Icon />
</HeadlessIcon> </HeadlessIcon>
)} )}
{children && ( {Boolean(children) && (
<Text fontWeight={600} lineClamp={1} textAlign="center"> <Text fontWeight={600} lineClamp={1} textAlign="center">
{children} {children}
</Text> </Text>
@ -58,7 +59,7 @@ const _Button = (props: ButtonProps, ref: HeadlessButtonRef) => {
<HeadlessButton <HeadlessButton
aria-busy={isLoading ? true : undefined} aria-busy={isLoading ? true : undefined}
aria-disabled={ aria-disabled={
visuallyDisabled || isLoading || props.isDisabled ? true : undefined visuallyDisabled || isLoading || isDisabled ? true : undefined
} }
className={clsx(styles.button, getTypographyClassName("body"))} className={clsx(styles.button, getTypographyClassName("body"))}
data-button="" data-button=""
@ -67,6 +68,7 @@ const _Button = (props: ButtonProps, ref: HeadlessButtonRef) => {
data-loading={isLoading ? "" : undefined} data-loading={isLoading ? "" : undefined}
data-variant={variant} data-variant={variant}
draggable draggable
isDisabled={isDisabled}
ref={ref} ref={ref}
{...rest} {...rest}
> >
@ -83,9 +85,10 @@ export const Button = forwardRef(_Button);
* when the button is visually disabled * when the button is visually disabled
*/ */
const useVisuallyDisabled = (props: ButtonProps) => { const useVisuallyDisabled = (props: ButtonProps) => {
const { isLoading = false, visuallyDisabled = false } = props;
let computedProps = props; let computedProps = props;
if (props.visuallyDisabled || props.isLoading) { if (visuallyDisabled || isLoading) {
computedProps = { computedProps = {
...props, ...props,
isDisabled: false, isDisabled: false,

View File

@ -25,7 +25,7 @@ const _Checkbox = (props: CheckboxProps, ref: HeadlessCheckboxRef) => {
inlineLabelStyles["inline-label"], inlineLabelStyles["inline-label"],
)} )}
> >
{children && <Text>{children}</Text>} {Boolean(children) && <Text>{children}</Text>}
</HeadlessCheckbox> </HeadlessCheckbox>
); );
}; };

View File

@ -18,10 +18,10 @@ const _CheckboxGroup = (
ref: HeadlessCheckboxGroupRef, ref: HeadlessCheckboxGroupRef,
) => { ) => {
const { errorMessage, label, ...rest } = props; const { errorMessage, label, ...rest } = props;
const wrappedErrorMessage = errorMessage && ( const wrappedErrorMessage = Boolean(errorMessage) && (
<Text variant="footnote">{errorMessage}</Text> <Text variant="footnote">{errorMessage}</Text>
); );
const wrappedLabel = label && <Text>{label}</Text>; const wrappedLabel = Boolean(label) && <Text>{label}</Text>;
return ( return (
<HeadlessCheckboxGroup <HeadlessCheckboxGroup

View File

@ -141,5 +141,5 @@ const cssVarValue = (value: CssVarValues) => {
}; };
const hiddenValue = (value: FlexCssProps["isHidden"]) => { const hiddenValue = (value: FlexCssProps["isHidden"]) => {
return value ? "none" : "flex"; return Boolean(value) ? "none" : "flex";
}; };

View File

@ -1,2 +0,0 @@
export { IconButton } from "./IconButton";
export type { IconButtonProps } from "./IconButton";

View File

@ -23,7 +23,7 @@ const _Radio = (props: RadioProps, ref: HeadlessRadioRef) => {
ref={ref} ref={ref}
{...rest} {...rest}
> >
{children && <Text>{children}</Text>} {Boolean(children) && <Text>{children}</Text>}
</HeadlessRadio> </HeadlessRadio>
); );
}; };

View File

@ -15,8 +15,10 @@ export interface RadioGroupProps extends HeadlessRadioGroupProps {
const _RadioGroup = (props: RadioGroupProps, ref: HeadlessRadioGroupRef) => { const _RadioGroup = (props: RadioGroupProps, ref: HeadlessRadioGroupRef) => {
const { errorMessage, label, ...rest } = props; const { errorMessage, label, ...rest } = props;
const wrappedErrorMessage = errorMessage && <Text>{errorMessage}</Text>; const wrappedErrorMessage = Boolean(errorMessage) && (
const wrappedLabel = label && <Text>{label}</Text>; <Text>{errorMessage}</Text>
);
const wrappedLabel = Boolean(label) && <Text>{label}</Text>;
return ( return (
<HeadlessRadioGroup <HeadlessRadioGroup

View File

@ -23,7 +23,7 @@ const _Switch = (props: SwitchProps, ref: HeadlessSwitchRef) => {
ref={ref} ref={ref}
{...rest} {...rest}
> >
{children && <Text>{children}</Text>} {Boolean(children) && <Text>{children}</Text>}
</HeadlessSwitch> </HeadlessSwitch>
); );
}; };

View File

@ -25,7 +25,7 @@ const _Text = (props: TextProps, ref: Ref<HTMLParagraphElement>) => {
const getFontWeight = ( const getFontWeight = (
fontWeight?: keyof typeof TYPOGRAPHY_FONT_WEIGHTS, fontWeight?: keyof typeof TYPOGRAPHY_FONT_WEIGHTS,
isBold?: boolean, isBold = false,
) => { ) => {
if (fontWeight) return fontWeight; if (fontWeight) return fontWeight;

View File

@ -34,7 +34,7 @@ const _TextArea = (props: TextAreaProps, ref: HeadlessTextAreaRef) => {
...rest ...rest
} = props; } = props;
const wrappedLabel = label && ( const wrappedLabel = Boolean(label) && (
<Label <Label
includeNecessityIndicatorInAccessibilityName={ includeNecessityIndicatorInAccessibilityName={
includeNecessityIndicatorInAccessibilityName includeNecessityIndicatorInAccessibilityName
@ -45,10 +45,10 @@ const _TextArea = (props: TextAreaProps, ref: HeadlessTextAreaRef) => {
/> />
); );
const wrappedDescription = description && ( const wrappedDescription = Boolean(description) && (
<Text variant="footnote">{description}</Text> <Text variant="footnote">{description}</Text>
); );
const wrappedErrorMessage = errorMessage && ( const wrappedErrorMessage = Boolean(errorMessage) && (
<Text variant="footnote">{errorMessage}</Text> <Text variant="footnote">{errorMessage}</Text>
); );

View File

@ -1,2 +0,0 @@
export { TextArea } from "./TextArea";
export type { TextAreaProps } from "./TextArea";

View File

@ -8,7 +8,7 @@ export type LabelProps = TextInputProps;
const _Label = (props: LabelProps) => { const _Label = (props: LabelProps) => {
const { const {
includeNecessityIndicatorInAccessibilityName, includeNecessityIndicatorInAccessibilityName,
isRequired, isRequired = false,
label, label,
necessityIndicator = "icon", necessityIndicator = "icon",
} = props; } = props;
@ -16,7 +16,9 @@ const _Label = (props: LabelProps) => {
const icon = ( const icon = (
<span <span
aria-label={ aria-label={
includeNecessityIndicatorInAccessibilityName ? "(required)" : undefined Boolean(includeNecessityIndicatorInAccessibilityName)
? "(required)"
: undefined
} }
data-field-necessity-indicator-icon="" data-field-necessity-indicator-icon=""
> >
@ -36,7 +38,7 @@ const _Label = (props: LabelProps) => {
{necessityIndicator === "label" && ( {necessityIndicator === "label" && (
<span <span
aria-hidden={ aria-hidden={
!includeNecessityIndicatorInAccessibilityName includeNecessityIndicatorInAccessibilityName == null
? isRequired ? isRequired
: undefined : undefined
} }

View File

@ -38,6 +38,7 @@ const _TextInput = (props: TextInputProps, ref: HeadlessTextInputRef) => {
endIcon, endIcon,
errorMessage, errorMessage,
includeNecessityIndicatorInAccessibilityName, includeNecessityIndicatorInAccessibilityName,
isLoading = false,
isRequired, isRequired,
label, label,
loaderPosition = "auto", loaderPosition = "auto",
@ -48,7 +49,7 @@ const _TextInput = (props: TextInputProps, ref: HeadlessTextInputRef) => {
} = props; } = props;
const [showPassword, togglePassword] = useState(false); const [showPassword, togglePassword] = useState(false);
const wrappedLabel = label && ( const wrappedLabel = Boolean(label) && (
<Label <Label
includeNecessityIndicatorInAccessibilityName={ includeNecessityIndicatorInAccessibilityName={
includeNecessityIndicatorInAccessibilityName includeNecessityIndicatorInAccessibilityName
@ -59,15 +60,15 @@ const _TextInput = (props: TextInputProps, ref: HeadlessTextInputRef) => {
/> />
); );
const contextualHelp = label && contextualHelpProp && ( const contextualHelp = Boolean(label) && Boolean(contextualHelpProp) && (
<ContextualHelp contextualHelp={contextualHelpProp} /> <ContextualHelp contextualHelp={contextualHelpProp} />
); );
const wrappedDescription = description && ( const wrappedDescription = Boolean(description) && (
<Text variant="footnote">{description}</Text> <Text variant="footnote">{description}</Text>
); );
const wrappedErrorMessage = errorMessage && ( const wrappedErrorMessage = Boolean(errorMessage) && (
<Text variant="footnote">{errorMessage}</Text> <Text variant="footnote">{errorMessage}</Text>
); );
@ -77,9 +78,9 @@ const _TextInput = (props: TextInputProps, ref: HeadlessTextInputRef) => {
const renderStartIcon = () => { const renderStartIcon = () => {
const showLoadingIndicator = const showLoadingIndicator =
props.isLoading && isLoading &&
(loaderPosition === "start" || (loaderPosition === "start" ||
Boolean(startIcon && loaderPosition !== "end")); (Boolean(startIcon) && loaderPosition !== "end"));
if (!showLoadingIndicator) return startIcon; if (!showLoadingIndicator) return startIcon;
@ -101,9 +102,9 @@ const _TextInput = (props: TextInputProps, ref: HeadlessTextInputRef) => {
} }
const showLoadingIndicator = const showLoadingIndicator =
props.isLoading && isLoading &&
(loaderPosition === "end" || (loaderPosition === "end" ||
Boolean(loaderPosition === "auto" && !startIcon)); Boolean(loaderPosition === "auto" && Boolean(startIcon)));
if (!showLoadingIndicator) return endIcon; if (!showLoadingIndicator) return endIcon;

View File

@ -11,7 +11,7 @@ export type TooltipProps = {
export function Tooltip(props: TooltipProps) { export function Tooltip(props: TooltipProps) {
const { children, tooltip, ...rest } = props; const { children, tooltip, ...rest } = props;
if (!tooltip) return children; if (tooltip == null) return children;
return ( return (
<TooltipRoot {...rest}> <TooltipRoot {...rest}>

View File

@ -174,10 +174,10 @@ export const ColorGrid = (props: any) => {
> >
<button <button
className={styles["color-grid"]} className={styles["color-grid"]}
data-active={isActive ? "" : undefined} data-active={Boolean(isActive) ? "" : undefined}
data-disabled={isDisabled ? "" : undefined} data-disabled={Boolean(isDisabled) ? "" : undefined}
data-focused={isFocused ? "" : undefined} data-focused={Boolean(isFocused) ? "" : undefined}
data-hovered={isHovered ? "" : undefined} data-hovered={Boolean(isHovered) ? "" : undefined}
data-variant={variant} data-variant={variant}
> >
<Text lineClamp={2} textAlign="center" variant="footnote"> <Text lineClamp={2} textAlign="center" variant="footnote">

View File

@ -1,7 +1,8 @@
{ {
"extends": ["../../.eslintrc.base.json"], "extends": ["../../.eslintrc.base.json"],
"ignorePatterns": ["dist"], "ignorePatterns": ["dist", "server.test.ts"],
"rules": { "rules": {
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-explicit-any": "off" "@typescript-eslint/no-explicit-any": "off"
} }
} }