Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LG-4658: Compact Button #2535

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/mean-gorillas-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@leafygreen-ui/confirmation-modal': patch
'@lg-chat/message-feedback': patch
'@leafygreen-ui/number-input': patch
'@leafygreen-ui/split-button': patch
'@leafygreen-ui/form-footer': patch
'@leafygreen-ui/code': patch
---

Omitting `compact` Button prop when passing through props
5 changes: 5 additions & 0 deletions .changeset/perfect-birds-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/button': minor
---

Adds a `compact` prop enabling less padded and square glyph-only buttons
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export type InlineMessageFeedbackProps = Required<
/**
* Override props for the cancel Button
*/
cancelButtonProps?: ButtonProps;
cancelButtonProps?: Omit<ButtonProps, 'compact'>;

/**
* Text displayed inside the submit Button
Expand All @@ -35,7 +35,7 @@ export type InlineMessageFeedbackProps = Required<
/**
* Override props for the submit Button
*/
submitButtonProps?: ButtonProps;
submitButtonProps?: Omit<ButtonProps, 'compact'>;

/**
* Event handler called when the form is submitted
Expand Down
11 changes: 11 additions & 0 deletions packages/button/src/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const meta: StoryMetaType<typeof Button> = {
leftGlyph: [undefined, <Icon glyph={'Cloud'} />],
children: ['MongoDB', undefined],
variant: Object.values(Variant),
compact: [undefined, true],
},
excludeCombinations: [
{
Expand All @@ -47,6 +48,10 @@ const meta: StoryMetaType<typeof Button> = {
leftGlyph: <Icon glyph={'Cloud'} />,
children: undefined,
},
{
children: 'MongoDB',
compact: true,
},
],
},
},
Expand All @@ -56,6 +61,7 @@ const meta: StoryMetaType<typeof Button> = {
leftGlyph: undefined,
rightGlyph: undefined,
baseFontSize: BaseFontSize.Body1,
compact: false,
},
argTypes: {
...filteredStorybookArgTypes,
Expand All @@ -82,6 +88,11 @@ const meta: StoryMetaType<typeof Button> = {
options: Object.values(Size),
defaultValue: Size.Default,
},
compact: {
description: 'Show the button with less horizontal padding. Note: Cannot be used with `children`',
control: { type: 'boolean' },
defaultValue: false,
},
href: {
control: 'text',
},
Expand Down
5 changes: 5 additions & 0 deletions packages/button/src/Button/Button.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,10 @@ describe('packages/button', () => {
test('accepts a component as `as`', () => {
<Button as={() => <>JSX</>} />;
});

test('rejects children when compact', () => {
// @ts-expect-error - Cannot use compact with children
<Button compact>MongoDB</Button>;
});
});
});
10 changes: 9 additions & 1 deletion packages/button/src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const Button = React.forwardRef(function Button(
{
variant = Variant.Default,
size = Size.Default,
compact = false,
darkMode: darkModeProp,
'data-lgid': dataLgId = LGIDS_BUTTON.root,
baseFontSize = BaseFontSize.Body1,
Expand Down Expand Up @@ -77,11 +78,18 @@ export const Button = React.forwardRef(function Button(
isLoading,
loadingIndicator,
loadingText,
// Never pass children when compact
...compact ? {
compact: true
} : {
compact: false,
children,
} as const
} as const;

return (
<Box {...buttonProps}>
<ButtonContent {...contentProps}>{children}</ButtonContent>
<ButtonContent {...contentProps} />
</Box>
);
});
Expand Down
22 changes: 22 additions & 0 deletions packages/button/src/ButtonContent/ButtonContent.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@ export const buttonContentSizeStyle: Record<Size, string> = {
`,
};

export const buttonContentCompactSizeStyle: Partial<Record<Size, string>> = {
[Size.XSmall]: css`
padding: 0 3px; // 4px - 1px border
gap: 6px;
`,

[Size.Small]: css`
padding: 0 5px; // 6px - 1px border
gap: 6px;
`,

[Size.Default]: css`
padding: 0 9px; // 10px - 1px border
gap: 6px;
`,

[Size.Large]: css`
padding: 0 13px; // 14px - 1px border
gap: 8px;
`,
};

export const centeredSpinnerContainerStyles = css`
position: absolute;
`;
Expand Down
4 changes: 3 additions & 1 deletion packages/button/src/ButtonContent/ButtonContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';
import { registerRipple } from '@leafygreen-ui/ripple';

import {
buttonContentCompactSizeStyle,
buttonContentSizeStyle,
buttonContentStyle,
buttonSpinnerSize,
Expand All @@ -28,6 +29,7 @@ export const ButtonContent = (props: ButtonContentProps) => {
disabled,
variant,
size,
compact,
isLoading,
loadingText,
loadingIndicator,
Expand Down Expand Up @@ -69,7 +71,7 @@ export const ButtonContent = (props: ButtonContentProps) => {
return (
<>
<div
className={cx(buttonContentStyle, buttonContentSizeStyle[size], {
className={cx(buttonContentStyle, compact ? buttonContentCompactSizeStyle[size] : buttonContentSizeStyle[size], {
[centeredSpinnerContainerStyles]: !loadingText,
})}
>
Expand Down
4 changes: 3 additions & 1 deletion packages/button/src/ButtonContent/DefaultContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { cx } from '@leafygreen-ui/emotion';
import ButtonIcon from '../ButtonIcon/ButtonIcon';

import {
buttonContentCompactSizeStyle,
buttonContentSizeStyle,
buttonContentStyle,
darkModeRightGlyphStyles,
Expand All @@ -24,6 +25,7 @@ const DefaultContent = ({
children,
variant,
size,
compact,
darkMode,
disabled,
}: DefaultContentProps) => {
Expand All @@ -33,7 +35,7 @@ const DefaultContent = ({
<div
className={cx(
buttonContentStyle,
buttonContentSizeStyle[size],
compact ? buttonContentCompactSizeStyle[size] : buttonContentSizeStyle[size],
{
[darkModeRightGlyphStyles]: !!rightGlyph && darkMode,
},
Expand Down
45 changes: 39 additions & 6 deletions packages/button/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const FontSize = {

export type FontSize = (typeof FontSize)[keyof typeof FontSize];

export interface ButtonProps extends LgIdProps {
export interface BaseButtonProps extends LgIdProps {
// Would prefer to use Pick<> to extract these properties, but they would not be correctly imported into Storybook otherwise.
// https://github.com/storybookjs/storybook/issues/14798

Expand Down Expand Up @@ -94,11 +94,6 @@ export interface ButtonProps extends LgIdProps {
*/
size?: Size;

/**
* The content that will appear inside of the `<Button />` component.
*/
children?: React.ReactNode;

/**
* An icon glyph rendered before the button text.
* To use a custom icon, see {@link Icon} {@link https://github.com/mongodb/leafygreen-ui/blob/main/packages/icon/README.md#usage-registering-custom-icon-sets | createIconComponent} docs
Expand Down Expand Up @@ -149,4 +144,42 @@ export interface ButtonProps extends LgIdProps {
* @default button
*/
as?: React.ElementType<any>;

/**
* Show the button with less horizontal padding.
* Note: Cannot be used with `children`.
*
* @default false
*/
compact?: boolean;
}

type ConstrainedButtonProps = {
/**
* Show the button with less horizontal padding.
* Note: Cannot be used with `children`.
*
* @default false
*/
compact: true;

/**
* Cannot pass `children` when `compact`.
*/
children?: never;
} | {
/**
* Show the button with less horizontal padding.
* Note: Cannot be used with `children`.
*
* @default false
*/
compact?: false;

/**
* The content that will appear inside of the `<Button />` component.
*/
children?: React.ReactNode;
};

export type ButtonProps = BaseButtonProps & ConstrainedButtonProps;
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import Button, { ButtonProps } from '@leafygreen-ui/button';
* @internal
*/
export const CustomSelectMenuButton = React.forwardRef(
({ children, ...props }: ButtonProps, ref) => (
<Button {...props} ref={ref}>
{children}
</Button>
(props: ButtonProps, ref) => (
<Button {...props} ref={ref} />
),
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export type Variant = (typeof Variant)[keyof typeof Variant];
interface CustomButtonOnClick {
onClick?: () => void;
}
type CustomConfirmButtonProps = Omit<ButtonProps, 'variant' | 'onClick'> &
type CustomConfirmButtonProps = Omit<ButtonProps, 'variant' | 'onClick' | 'compact'> &
CustomButtonOnClick;
type CustomCancelButtonProps = Omit<ButtonProps, 'onClick' | 'children'> &
type CustomCancelButtonProps = Omit<ButtonProps, 'onClick' | 'children' | 'compact'> &
CustomButtonOnClick;

export interface ConfirmationModalProps extends Omit<ModalProps, 'size'> {
Expand Down
8 changes: 4 additions & 4 deletions packages/form-footer/src/FormFooter.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { DarkModeProps, HTMLElementProps } from '@leafygreen-ui/lib';

import { PrimaryButtonProps } from './PrimaryButton';

type ButtonPropsOmittingVariant = Omit<ButtonProps, 'variant'>;
type ButtonPropsOmittingVariantAndCompact = Omit<ButtonProps, 'variant' | 'compact'>;
type ButtonPropsWithRequiredChildren = Required<Pick<ButtonProps, 'children'>>;

export type CustomCancelButtonProps = ButtonPropsOmittingVariant;
export type CustomBackButtonProps = ButtonPropsOmittingVariant & {
export type CustomCancelButtonProps = ButtonPropsOmittingVariantAndCompact;
export type CustomBackButtonProps = ButtonPropsOmittingVariantAndCompact & {
variant?: Extract<Variant, 'default' | 'dangerOutline'>;
};
export type CustomPrimaryButtonProps = ButtonPropsOmittingVariant &
export type CustomPrimaryButtonProps = ButtonPropsOmittingVariantAndCompact &
ButtonPropsWithRequiredChildren & {
variant?: Extract<Variant, 'primary' | 'danger'>;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ export type UnitSelectButtonProps = {
* The select option that is shown in the select menu button.
*/
displayName?: string;
} & ButtonProps &
} & Omit<ButtonProps, 'compact'> &
PopoverProps;
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export interface MenuProps extends SelectedMenuProps {

export interface SplitButtonProps
extends DarkModeProps,
ButtonProps,
Omit<ButtonProps, 'compact'>,
MenuProps {
/**
* Sets the variant for both Buttons.
Expand Down
Loading