Skip to content

Commit

Permalink
Add size prop to large variant components (#7234)
Browse files Browse the repository at this point in the history
  • Loading branch information
ggdouglas authored Feb 18, 2025
1 parent 167ec31 commit 69b7ff6
Show file tree
Hide file tree
Showing 20 changed files with 197 additions and 73 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export {
type MaybeElement,
} from "./props";
export { getRef, isRefCallback, isRefObject, mergeRefs, refHandler, setRef } from "./refs";
export type { Size } from "./size";
export type { Size, NonSmallSize } from "./size";

import * as Classes from "./classes";
import * as Utils from "./utils";
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/common/size.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
*/

export type Size = "small" | "medium" | "large";

export type NonSmallSize = Exclude<Size, "small">;
2 changes: 1 addition & 1 deletion packages/core/src/components/control-card/controlCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export interface ControlCardProps extends SupportedCardProps, SupportedControlPr
/**
* HTML input attributes to forward to the control `<input>` element.
*/
inputProps?: HTMLInputProps;
inputProps?: Omit<HTMLInputProps, "size">;

/**
* Whether the component should use "selected" Card styling when checked.
Expand Down
18 changes: 15 additions & 3 deletions packages/core/src/components/forms/controlProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import type * as React from "react";

import type { Alignment } from "../../common";
import type { Alignment, NonSmallSize } from "../../common";
import type { HTMLInputProps, Props } from "../../common/props";

export interface CheckedControlProps {
Expand All @@ -36,7 +36,7 @@ export interface CheckedControlProps {
export interface ControlProps
extends CheckedControlProps,
Props,
HTMLInputProps,
Omit<HTMLInputProps, "size">,
React.RefAttributes<HTMLLabelElement> {
// NOTE: Some HTML props are duplicated here to provide control-specific documentation

Expand Down Expand Up @@ -75,9 +75,21 @@ export interface ControlProps
*/
labelElement?: React.ReactNode;

/** Whether this control should use large styles. */
/**
* Whether this control should use large styles.
*
* @deprecated use `size="large"` instead
* @default false
*/
large?: boolean;

/**
* Size of the control.
*
* @default "medium"
*/
size?: NonSmallSize;

/**
* Name of the HTML tag that wraps the checkbox.
*
Expand Down
89 changes: 58 additions & 31 deletions packages/core/src/components/forms/controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ import classNames from "classnames";
import * as React from "react";

import { Alignment, Classes, mergeRefs } from "../../common";
import { ALIGN_INDICATOR_CENTER, ALIGN_INDICATOR_LEFT, ALIGN_INDICATOR_RIGHT } from "../../common/errors";
import {
ALIGN_INDICATOR_CENTER,
ALIGN_INDICATOR_LEFT,
ALIGN_INDICATOR_RIGHT,
logDeprecatedSizeWarning,
} from "../../common/errors";
import { DISPLAYNAME_PREFIX } from "../../common/props";
import { useValidateProps } from "../../hooks/useValidateProps";

Expand Down Expand Up @@ -46,7 +51,9 @@ const ControlInternal: React.FC<ControlInternalProps> = React.forwardRef<HTMLLab
inputRef,
label,
labelElement,
// eslint-disable-next-line @typescript-eslint/no-deprecated
large,
size = "medium",
style,
type,
typeClassName,
Expand Down Expand Up @@ -74,9 +81,9 @@ const ControlInternal: React.FC<ControlInternalProps> = React.forwardRef<HTMLLab
{
[Classes.DISABLED]: htmlProps.disabled,
[Classes.INLINE]: inline,
[Classes.LARGE]: large,
},
Classes.alignmentClass(alignIndicator),
Classes.sizeClass(size, { large }),
className,
);

Expand Down Expand Up @@ -121,32 +128,38 @@ export interface SwitchProps extends ControlProps {
*
* @see https://blueprintjs.com/docs/#core/components/switch
*/
export const Switch: React.FC<SwitchProps> = React.forwardRef(
({ innerLabelChecked, innerLabel, ...controlProps }, ref) => {
const switchLabels =
innerLabel || innerLabelChecked
? [
<div key="checked" className={Classes.CONTROL_INDICATOR_CHILD}>
<div className={Classes.SWITCH_INNER_TEXT}>
{innerLabelChecked ? innerLabelChecked : innerLabel}
</div>
</div>,
<div key="unchecked" className={Classes.CONTROL_INDICATOR_CHILD}>
<div className={Classes.SWITCH_INNER_TEXT}>{innerLabel}</div>
</div>,
]
: null;
return (
<ControlInternal
{...controlProps}
indicatorChildren={switchLabels}
ref={ref}
type="checkbox"
typeClassName={Classes.SWITCH}
/>
);
},
);
export const Switch: React.FC<SwitchProps> = React.forwardRef((props, ref) => {
const { innerLabelChecked, innerLabel, ...controlProps } = props;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const { large } = controlProps;

useValidateProps(() => {
logDeprecatedSizeWarning("Switch", { large });
}, [large]);

const switchLabels =
innerLabel || innerLabelChecked
? [
<div key="checked" className={Classes.CONTROL_INDICATOR_CHILD}>
<div className={Classes.SWITCH_INNER_TEXT}>
{innerLabelChecked ? innerLabelChecked : innerLabel}
</div>
</div>,
<div key="unchecked" className={Classes.CONTROL_INDICATOR_CHILD}>
<div className={Classes.SWITCH_INNER_TEXT}>{innerLabel}</div>
</div>,
]
: null;
return (
<ControlInternal
{...controlProps}
indicatorChildren={switchLabels}
ref={ref}
type="checkbox"
typeClassName={Classes.SWITCH}
/>
);
});
Switch.displayName = `${DISPLAYNAME_PREFIX}.Switch`;

//
Expand All @@ -163,9 +176,16 @@ export type RadioProps = ControlProps;
*
* @see https://blueprintjs.com/docs/#core/components/radio
*/
export const Radio: React.FC<RadioProps> = React.forwardRef((props, ref) => (
<ControlInternal {...props} ref={ref} type="radio" typeClassName={Classes.RADIO} />
));
export const Radio: React.FC<RadioProps> = React.forwardRef((props, ref) => {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const { large } = props;

useValidateProps(() => {
logDeprecatedSizeWarning("Radio", { large });
}, [large]);

return <ControlInternal {...props} ref={ref} type="radio" typeClassName={Classes.RADIO} />;
});
Radio.displayName = `${DISPLAYNAME_PREFIX}.Radio`;

//
Expand Down Expand Up @@ -197,6 +217,9 @@ export interface CheckboxProps extends ControlProps {
*/
export const Checkbox: React.FC<CheckboxProps> = React.forwardRef((props, ref) => {
const { defaultIndeterminate, indeterminate, onChange, ...controlProps } = props;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const { large } = controlProps;

const [isIndeterminate, setIsIndeterminate] = React.useState<boolean>(
indeterminate || defaultIndeterminate || false,
);
Expand All @@ -216,6 +239,10 @@ export const Checkbox: React.FC<CheckboxProps> = React.forwardRef((props, ref) =
[indeterminate, onChange],
);

useValidateProps(() => {
logDeprecatedSizeWarning("Checkbox", { large });
}, [large]);

React.useEffect(() => {
if (indeterminate !== undefined) {
setIsIndeterminate(indeterminate);
Expand Down
44 changes: 34 additions & 10 deletions packages/core/src/components/tabs/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
import classNames from "classnames";
import * as React from "react";

import { AbstractPureComponent, Classes, DISPLAYNAME_PREFIX, type Props, Utils } from "../../common";
import { AbstractPureComponent, Classes, DISPLAYNAME_PREFIX, type NonSmallSize, type Props, Utils } from "../../common";
import { logDeprecatedSizeWarning } from "../../common/errors";

import { Tab, type TabId, type TabProps } from "./tab";
import { TabPanel } from "./tabPanel";
Expand Down Expand Up @@ -65,10 +66,18 @@ export interface TabsProps extends Props {
* If set to `true`, the tab titles will display with larger styling.
* This will apply large styles only to the tabs at this level, not to nested tabs.
*
* @deprecated use `size="large"` instead
* @default false
*/
large?: boolean;

/**
* The size of the tab titles.
*
* @default "medium"
*/
size?: NonSmallSize;

/**
* Whether inactive tab panels should be removed from the DOM and unmounted in React.
* This can be a performance enhancement when rendering many complex panels, but requires
Expand Down Expand Up @@ -135,6 +144,7 @@ export class Tabs extends AbstractPureComponent<TabsProps, TabsState> {
fill: false,
large: false,
renderActiveTabPanelOnly: false,
size: "medium",
vertical: false,
};

Expand All @@ -161,27 +171,36 @@ export class Tabs extends AbstractPureComponent<TabsProps, TabsState> {
}

public render() {
const {
animate,
children,
className,
fill,
// eslint-disable-next-line @typescript-eslint/no-deprecated
large,
renderActiveTabPanelOnly,
size = "medium",
vertical,
} = this.props;
const { indicatorWrapperStyle, selectedTabId } = this.state;

const tabTitles = React.Children.map(this.props.children, this.renderTabTitle);
const tabTitles = React.Children.map(children, this.renderTabTitle);

const tabPanels = this.getTabChildren()
.filter(this.props.renderActiveTabPanelOnly ? tab => tab.props.id === selectedTabId : () => true)
.filter(renderActiveTabPanelOnly ? tab => tab.props.id === selectedTabId : () => true)
.map(this.renderTabPanel);

const tabIndicator = this.props.animate ? (
const tabIndicator = animate ? (
<div className={Classes.TAB_INDICATOR_WRAPPER} style={indicatorWrapperStyle}>
<div className={Classes.TAB_INDICATOR} />
</div>
) : null;

const classes = classNames(Classes.TABS, this.props.className, {
[Classes.VERTICAL]: this.props.vertical,
[Classes.FILL]: this.props.fill,
});
const tabListClasses = classNames(Classes.TAB_LIST, {
[Classes.LARGE]: this.props.large,
const classes = classNames(Classes.TABS, className, {
[Classes.VERTICAL]: vertical,
[Classes.FILL]: fill,
});
const tabListClasses = classNames(Classes.TAB_LIST, Classes.sizeClass(size, { large }));

return (
<div className={classes}>
Expand All @@ -201,6 +220,11 @@ export class Tabs extends AbstractPureComponent<TabsProps, TabsState> {
);
}

protected validateProps(props: TabsProps) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
logDeprecatedSizeWarning("Tabs", { large: props.large });
}

public componentDidMount() {
this.moveSelectionIndicator(false);
}
Expand Down
Loading

1 comment on commit 69b7ff6

@svc-palantir-github
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add `size` prop to `large` variant components (#7234)

Build artifact links for this commit: documentation | landing | table | demo

This is an automated comment from the deploy-preview CircleCI job.

Please sign in to comment.