From 4c0bf72f8161872779883fe11962d66e195b3746 Mon Sep 17 00:00:00 2001 From: dkilgore-eightfold Date: Mon, 2 May 2022 10:05:57 -0700 Subject: [PATCH 1/3] fix: button: fixes button height and min width in flex layouts --- src/components/Button/button.module.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/Button/button.module.scss b/src/components/Button/button.module.scss index db0471872..2a341a901 100644 --- a/src/components/Button/button.module.scss +++ b/src/components/Button/button.module.scss @@ -55,6 +55,7 @@ border-radius: $corner-radius-s; cursor: pointer; display: inline-block; + min-width: max-content; transition: all $motion-duration-extra-fast $motion-easing-easeinout 0s; white-space: nowrap; @@ -142,6 +143,7 @@ font-weight: $text-font-weight-semibold; font-size: $text-font-size-5; line-height: $text-line-height-3; + max-height: 44px; &.counter { font-size: $text-font-size-4; @@ -162,6 +164,7 @@ font-weight: $text-font-weight-semibold; font-size: $text-font-size-3; line-height: $text-line-height-2; + max-height: 36px; &.counter { font-size: $text-font-size-2; @@ -183,6 +186,7 @@ font-weight: $text-font-weight-semibold; font-size: $text-font-size-2; line-height: $text-line-height-1; + max-height: 28px; &.counter { font-size: $text-font-size-1; From 9b696488bc7b61a5ff8ca3ed27e3d924385d194e Mon Sep 17 00:00:00 2001 From: dkilgore-eightfold Date: Mon, 2 May 2022 15:44:21 -0700 Subject: [PATCH 2/3] feat: props: normalize label, classnames, button alignment and iconprops BREAKING CHANGE: classnames and icon props must be updated to match latest --- src/__snapshots__/storybook.test.js.snap | 572 ++++++++++++++---- src/components/Button/BaseButton.tsx | 44 +- src/components/Button/Button.stories.tsx | 68 ++- src/components/Button/Button.types.ts | 37 +- .../Button/DefaultButton/DefaultButton.tsx | 19 +- .../Button/NeutralButton/NeutralButton.tsx | 19 +- .../Button/PrimaryButton/PrimaryButton.tsx | 19 +- .../SecondaryButton/SecondaryButton.tsx | 19 +- .../Button/SplitButton/SplitButton.tsx | 31 +- .../Button/TwoStateButton/TwoStateButton.tsx | 35 +- src/components/Button/button.module.scss | 24 + src/components/COMPONENTS.md | 14 +- .../ConfigProvider/ConfigProvider.stories.tsx | 12 +- .../Dialog/BaseDialog/BaseDialog.tsx | 35 +- .../Dialog/BaseDialog/BaseDialog.types.ts | 20 +- src/components/Dialog/Dialog.tsx | 33 +- src/components/Dropdown/Dropdown.tsx | 16 +- src/components/Dropdown/Dropdown.types.ts | 8 +- src/components/Icon/Icon.tsx | 9 +- src/components/Icon/Icon.types.ts | 2 +- src/components/InfoBar/InfoBar.tsx | 14 +- src/components/InfoBar/InfoBar.types.ts | 4 +- src/components/Inputs/Input.types.ts | 67 +- .../Inputs/SearchBox/SearchBox.stories.tsx | 40 +- src/components/Inputs/SearchBox/SearchBox.tsx | 12 +- .../Inputs/TextArea/TextArea.stories.tsx | 21 +- src/components/Inputs/TextArea/TextArea.tsx | 60 +- .../Inputs/TextInput/TextInput.stories.tsx | 43 +- src/components/Inputs/TextInput/TextInput.tsx | 78 +-- src/components/Inputs/input.module.scss | 47 -- src/components/Label/Label.stories.tsx | 53 ++ src/components/Label/Label.test.tsx | 16 + src/components/Label/Label.tsx | 79 +++ src/components/Label/Label.types.ts | 72 +++ src/components/Label/index.ts | 2 + src/components/Label/label.module.scss | 76 +++ src/components/List/List.tsx | 12 +- src/components/List/List.types.ts | 8 +- src/components/Menu/Menu.stories.tsx | 6 +- src/components/Menu/Menu.tsx | 8 +- src/components/Modal/Modal.tsx | 37 +- src/components/Modal/Modal.types.ts | 4 +- src/components/Panel/Panel.tsx | 32 +- src/components/Panel/Panel.types.ts | 20 +- src/components/Pills/Pill.tsx | 20 +- src/components/Pills/Pills.stories.tsx | 12 +- src/components/Pills/Pills.types.ts | 8 +- src/components/Snackbar/Snackbar.tsx | 8 +- src/components/Snackbar/SnackbarContainer.tsx | 4 +- src/components/Tabs/Tab/Tab.tsx | 8 +- src/components/Tabs/Tabs.types.ts | 4 +- src/components/Tabs/Tabs/AnimatedTabs.tsx | 8 +- src/components/Tooltip/Tooltip.tsx | 10 +- src/components/Tooltip/Tooltip.types.ts | 4 +- src/shared/utilities.ts | 4 +- 55 files changed, 1230 insertions(+), 707 deletions(-) create mode 100644 src/components/Label/Label.stories.tsx create mode 100644 src/components/Label/Label.test.tsx create mode 100644 src/components/Label/Label.tsx create mode 100644 src/components/Label/Label.types.ts create mode 100644 src/components/Label/index.ts create mode 100644 src/components/Label/label.module.scss diff --git a/src/__snapshots__/storybook.test.js.snap b/src/__snapshots__/storybook.test.js.snap index 27e21852b..bedae0333 100644 --- a/src/__snapshots__/storybook.test.js.snap +++ b/src/__snapshots__/storybook.test.js.snap @@ -49,7 +49,7 @@ Array [ , +
, +
, +

+ Text + Right Icon +

, + + +
+ A tooltip +
+
+ +
, +
, +
, +

+ Medium +

, +
+ + +
+ +
+
+ A tooltip +
+
+ +
, +
, +
, +

+ Small +

, +
+ + +
+ +
+
+ A tooltip +
+
+ +
, +
, +
, +] +`; + exports[`Storyshots List Default 1`] = ` Array [

@@ -4759,7 +5065,7 @@ Array [ aria-disabled={false} aria-expanded={false} aria-haspopup={true} - className="referenceWrapper button buttonDefault" + className="button buttonDefault" defaultChecked={false} disabled={false} onClick={[Function]} @@ -4785,7 +5091,7 @@ Array [ aria-disabled={false} aria-expanded={false} aria-haspopup={true} - className="referenceWrapper button buttonDefault buttonDisruptive" + className="button buttonDefault buttonDisruptive" defaultChecked={false} disabled={false} onClick={[Function]} @@ -5170,7 +5476,7 @@ Array [ ); diff --git a/src/components/Button/button.module.scss b/src/components/Button/button.module.scss index 2a341a901..a86f08d55 100644 --- a/src/components/Button/button.module.scss +++ b/src/components/Button/button.module.scss @@ -125,6 +125,30 @@ } } + &.icon-left { + span { + transform: none; + } + } + + &.icon-right { + span { + transform: scaleX(-1); + } + + &.left { + span { + justify-content: right; + } + } + + &.right { + span { + justify-content: left; + } + } + } + &:disabled, &.disabled { opacity: $disabled-alpha-value; diff --git a/src/components/COMPONENTS.md b/src/components/COMPONENTS.md index 40b8f8e84..b36b443b0 100644 --- a/src/components/COMPONENTS.md +++ b/src/components/COMPONENTS.md @@ -40,21 +40,21 @@ Create a file called `/src/components/Component/Component.tsx` ```tsx import React, { FC } from 'react'; import { ComponentProps, ComponentType } from './Component.types'; -import { classNames } from '../../shared/utilities'; +import { mergeClasses } from '../../shared/utilities'; import styles from 'component.module.scss'; export const Component: FC = ({ - className, + classNames, style, // How to set defaults for props type = ComponentType.base, ... }) => { - // Combining class names can be done using the classNames utility - const componentClasses: string = classNames([ + // Combining class names can be done using the mergeClasses utility + const componentClasses: string = mergeClasses([ styles.componentWrapper, - className, + classNames, // Conditional classes can also be handled as follows { [styles.active]: type === ComponentType.base } ]); @@ -109,10 +109,10 @@ export interface ComponentProps { */ children: React.ReactNode; /** - * Custom class name + * Custom class names * @default null */ - className?: string; + classNames?: string; /** * Style of the component * @default null diff --git a/src/components/ConfigProvider/ConfigProvider.stories.tsx b/src/components/ConfigProvider/ConfigProvider.stories.tsx index 106070c0f..4dfc948e5 100644 --- a/src/components/ConfigProvider/ConfigProvider.stories.tsx +++ b/src/components/ConfigProvider/ConfigProvider.stories.tsx @@ -105,13 +105,13 @@ const ThemedComponents = () => { ariaLabel="Primary Button" onClick={click} size={ButtonSize.Large} - icon={IconName.mdiCardsHeart} + iconProps={{ path: IconName.mdiCardsHeart }} />

@@ -126,7 +126,7 @@ const ThemedComponents = () => { /> @@ -135,7 +135,7 @@ const ThemedComponents = () => { onClick={click} size={ButtonSize.Large} text="Secondary Button" - icon={IconName.mdiCardsHeart} + iconProps={{ path: IconName.mdiCardsHeart }} />

@@ -149,13 +149,13 @@ const ThemedComponents = () => { /> = ({ width, zIndex, header, - headerClassName, + headerClassNames, body, - bodyClassName, + bodyClassNames, actions, - actionsClassName, - dialogWrapperClassName, - dialogClassName, + actionsClassNames, + dialogWrapperClassNames, + dialogClassNames, }) => { const labelId = uniqueId('dialog-label-'); const { lockScroll, unlockScroll } = useScrollLock(parent); - const dialogBackdropClasses: string = classNames([ + const dialogBackdropClasses: string = mergeClasses([ styles.dialogBackdrop, - dialogWrapperClassName, + dialogWrapperClassNames, { [styles.visible]: visible }, ]); - const dialogClasses: string = classNames([styles.dialog, dialogClassName]); + const dialogClasses: string = mergeClasses([ + styles.dialog, + dialogClassNames, + ]); - const headerClasses: string = classNames([styles.header, headerClassName]); + const headerClasses: string = mergeClasses([ + styles.header, + headerClassNames, + ]); const dialogStyle: React.CSSProperties = { zIndex, @@ -76,10 +82,13 @@ export const BaseDialog: FC = ({ >
{header} - +
-
{body}
- {actions &&
{actions}
} +
{body}
+ {actions &&
{actions}
} ); diff --git a/src/components/Dialog/BaseDialog/BaseDialog.types.ts b/src/components/Dialog/BaseDialog/BaseDialog.types.ts index 3783e754d..3ec9eea8a 100644 --- a/src/components/Dialog/BaseDialog/BaseDialog.types.ts +++ b/src/components/Dialog/BaseDialog/BaseDialog.types.ts @@ -25,25 +25,25 @@ export interface BaseDialogProps { */ onVisibleChange?: (visible: boolean) => void; /** - * Custom class for the dialog wrapper + * Custom classes for the dialog wrapper */ - dialogWrapperClassName?: string; + dialogWrapperClassNames?: string; /** - * Custom class for the dialog + * Custom classes for the dialog */ - dialogClassName?: string; + dialogClassNames?: string; /** - * Custom class for the header + * Custom classes for the header */ - headerClassName?: string; + headerClassNames?: string; /** - * Custom class for the body + * Custom classes for the body */ - bodyClassName?: string; + bodyClassNames?: string; /** - * Custom class for the actions wrapper + * Custom classes for the actions wrapper */ - actionsClassName?: string; + actionsClassNames?: string; /** * The header of the dialog */ diff --git a/src/components/Dialog/Dialog.tsx b/src/components/Dialog/Dialog.tsx index 8c0748be3..a2cce9bb0 100644 --- a/src/components/Dialog/Dialog.tsx +++ b/src/components/Dialog/Dialog.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react'; import { DialogProps, DialogSize } from './Dialog.types'; -import { classNames } from '../../shared/utilities'; +import { mergeClasses } from '../../shared/utilities'; import { DefaultButton, PrimaryButton } from '../Button'; import { BaseDialog } from './BaseDialog/BaseDialog'; @@ -9,39 +9,42 @@ import styles from './dialog.module.scss'; export const Dialog: FC = ({ parent = document.body, size = DialogSize.medium, - headerClassName, - bodyClassName, - actionsClassName, - dialogClassName, + headerClassNames, + bodyClassNames, + actionsClassNames, + dialogClassNames, okButtonProps, cancelButtonProps, onOk, onCancel, ...rest }) => { - const dialogClasses: string = classNames([ + const dialogClasses: string = mergeClasses([ styles.dialog, - dialogClassName, + dialogClassNames, { [styles.small]: size === DialogSize.small }, { [styles.medium]: size === DialogSize.medium }, ]); - const headerClasses: string = classNames([styles.header, headerClassName]); + const headerClasses: string = mergeClasses([ + styles.header, + headerClassNames, + ]); - const bodyClasses: string = classNames([styles.body, bodyClassName]); + const bodyClasses: string = mergeClasses([styles.body, bodyClassNames]); - const actionClasses: string = classNames([ + const actionClasses: string = mergeClasses([ styles.actions, - actionsClassName, + actionsClassNames, ]); return ( {cancelButtonProps && ( diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index f91e4328b..71d933f32 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -2,7 +2,7 @@ import React, { cloneElement, FC, useEffect, useRef, useState } from 'react'; import { DropdownProps } from './Dropdown.types'; import { autoUpdate, shift, useFloating } from '@floating-ui/react-dom'; import { offset as fOffset } from '@floating-ui/core'; -import { classNames, uniqueId } from '../../shared/utilities'; +import { mergeClasses, uniqueId } from '../../shared/utilities'; import { useOnClickOutside } from '../../hooks/useOnClickOutside'; import styles from './dropdown.module.scss'; @@ -17,9 +17,9 @@ const ANIMATION_DURATION = 200; export const Dropdown: FC = ({ trigger = 'click', - className, + classNames, style, - dropdownClassName, + dropdownClassNames, dropdownStyle, children, placement = 'bottom-start', @@ -80,19 +80,19 @@ export const Dropdown: FC = ({ ); }, [refs.reference, refs.floating, update]); - const dropdownClasses: string = classNames([ - dropdownClassName, + const dropdownClasses: string = mergeClasses([ + dropdownClassNames, styles.dropdownWrapper, { [styles.open]: visible }, { [styles.close]: closing }, ]); - const mainWrapperClasses: string = classNames([ - className, + const mainWrapperClasses: string = mergeClasses([ + classNames, styles.mainWrapper, ]); - const referenceWrapperClasses: string = classNames([ + const referenceWrapperClasses: string = mergeClasses([ styles.referenceWrapper, { [styles.disabled]: false }, ]); diff --git a/src/components/Dropdown/Dropdown.types.ts b/src/components/Dropdown/Dropdown.types.ts index 7c17396f1..56c81fd90 100644 --- a/src/components/Dropdown/Dropdown.types.ts +++ b/src/components/Dropdown/Dropdown.types.ts @@ -20,9 +20,9 @@ export interface DropdownProps { */ disabled?: boolean; /** - * Class name of the main wrapper + * Class names of the main wrapper */ - className?: string; + classNames?: string; /** * Style of the main wrapper */ @@ -43,9 +43,9 @@ export interface DropdownProps { */ offset?: number; /** - * Custom dropdown class name + * Custom dropdown class names */ - dropdownClassName?: string; + dropdownClassNames?: string; /** * Dropdown custom style */ diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx index 264da5d16..57cdd1e83 100644 --- a/src/components/Icon/Icon.tsx +++ b/src/components/Icon/Icon.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react'; -import { classNames } from '../../shared/utilities'; +import { mergeClasses } from '../../shared/utilities'; import { Icon as MdiIcon } from '@mdi/react'; import { IconProps, IconSize } from './index'; @@ -7,7 +7,7 @@ import styles from './icon.module.scss'; export const Icon: FC = ({ ariaHidden = false, - className, + classNames, color, description, horizontal, @@ -20,7 +20,10 @@ export const Icon: FC = ({ title, vertical, }) => { - const iconClassNames: string = classNames([className, styles.iconWrapper]); + const iconClassNames: string = mergeClasses([ + classNames, + styles.iconWrapper, + ]); return ( = ({ closable, onClose, style, - className, + classNames, closeIcon = IconName.mdiClose, closeButtonProps, actionButtonProps, role = 'presentation', }) => { - const infoBarClasses: string = classNames([ + const infoBarClasses: string = mergeClasses([ styles.infoBar, - className, + classNames, { [styles.neutral]: type === InfoBarType.neutral }, { [styles.positive]: type === InfoBarType.positive }, { [styles.warning]: type === InfoBarType.warning }, { [styles.disruptive]: type === InfoBarType.disruptive }, ]); - const messageClasses: string = classNames([styles.message, 'body2']); + const messageClasses: string = mergeClasses([styles.message, 'body2']); const getIconName = (): IconName => { if (icon) { @@ -47,12 +47,12 @@ export const InfoBar: FC = ({ return (
- +
{content}
{actionButtonProps && } {closable && ( { /** * The icon img alt text. */ alt?: string; /** - * The icon is aria-hidden. - * @default false - */ - ariaHidden?: boolean; - /** - * The icon color. - */ - color?: string; - /** - * The icon description. + * The optional icon svg path name. */ - description?: string; - /** - * The icon is horizontal. - * @default false - */ - horizontal?: boolean; - /** - * The icon id. - */ - id?: string; + path?: IconName; /** * The icon image source url. */ imageSrc?: string; - /** - * The icon svg path name. - */ - path?: IconName; - /** - * The icon is rotated. - * @default 0 - */ - rotate?: number; - /** - * The icon title. - */ - title?: string; - /** - * The icon is vertical. - * @default false - */ - vertical?: boolean; } export interface InputIconButtonProps { @@ -96,9 +61,9 @@ export interface InputIconButtonProps { */ htmlType?: 'button' | 'submit' | 'reset'; /** - * The input button icon path. + * The input button icon props. */ - icon?: IconName; + iconProps?: IconProps; /** * The input icon button id. */ @@ -125,13 +90,9 @@ export interface InputLabelIconButtonProps { */ disabled?: boolean; /** - * The label icon button path. + * The label icon button props. */ - icon?: IconName; - /** - * The label icon button color. - */ - iconColor?: string; + iconProps?: IconProps; /** * The label icon button id. */ @@ -232,7 +193,7 @@ export interface InputProps { /** * The input class names. */ - className?: string; + classNames?: string; /** * The input clear button aria label text. */ @@ -264,13 +225,9 @@ export interface InputProps { */ imageSource?: string; /** - * The input label text. - */ - label?: string; - /** - * The input label icon button props. + * The input label props. */ - labelIconButtonProps?: InputLabelIconButtonProps; + labelProps?: LabelProps; /** * The input maxlength. */ diff --git a/src/components/Inputs/SearchBox/SearchBox.stories.tsx b/src/components/Inputs/SearchBox/SearchBox.stories.tsx index 55f9d4146..71e309bb5 100644 --- a/src/components/Inputs/SearchBox/SearchBox.stories.tsx +++ b/src/components/Inputs/SearchBox/SearchBox.stories.tsx @@ -11,21 +11,27 @@ export const Search = () => ( <>

Search Boxes

Search Box Stretch (Rectangle)

- +

Search Box with Icon and Icon Button (Rectangle)

+ _alertClicked(_event), + }, + text: 'Label', + }} iconProps={{ path: IconName.mdiCardsHeart, color: 'red' }} iconButtonProps={{ - icon: IconName.mdiMagnify, - onClick: (_event: React.MouseEvent) => _alertClicked(_event), - }} - labelIconButtonProps={{ - show: true, - toolTipContent: 'A tooltip', - toolTipPlacement: 'top', + iconProps: { path: IconName.mdiMagnify }, onClick: (_event: React.MouseEvent) => _alertClicked(_event), }} /> @@ -33,13 +39,13 @@ export const Search = () => (

Search Box with Image Icon (Rectangle)

_alertClicked(_event), }} /> @@ -47,11 +53,11 @@ export const Search = () => (

Search Box Stretch (Pill)

_alertClicked(_event), }} /> @@ -59,10 +65,10 @@ export const Search = () => (

Search Box with Icon (Pill)

_alertClicked(_event), }} shape={TextInputShape.Pill} @@ -71,13 +77,13 @@ export const Search = () => (

Search Box with Image Icon (Pill)

_alertClicked(_event), }} shape={TextInputShape.Pill} diff --git a/src/components/Inputs/SearchBox/SearchBox.tsx b/src/components/Inputs/SearchBox/SearchBox.tsx index 559ce3ad1..b12e18bb6 100644 --- a/src/components/Inputs/SearchBox/SearchBox.tsx +++ b/src/components/Inputs/SearchBox/SearchBox.tsx @@ -12,18 +12,17 @@ export const SearchBox: FC = ({ allowDisabledFocus = false, ariaLabel, autoFocus = false, - className, + classNames, clearButtonAriaLabel, disabled = false, iconProps, iconButtonProps = { allowDisabledFocus: false, disabled: false, - icon: IconName.mdiMagnify, + iconProps: { path: IconName.mdiMagnify }, }, inputWidth = TextInputWidth.fitContent, - label, - labelIconButtonProps, + labelProps, maxlength, minlength, name, @@ -43,15 +42,14 @@ export const SearchBox: FC = ({ allowDisabledFocus={allowDisabledFocus} ariaLabel={ariaLabel} autoFocus={autoFocus} - className={className} + classNames={classNames} clearButtonAriaLabel={clearButtonAriaLabel} disabled={disabled} htmlType="search" iconProps={iconProps} iconButtonProps={iconButtonProps} inputWidth={inputWidth} - label={label} - labelIconButtonProps={labelIconButtonProps} + labelProps={labelProps} maxlength={maxlength} minlength={minlength} name={name} diff --git a/src/components/Inputs/TextArea/TextArea.stories.tsx b/src/components/Inputs/TextArea/TextArea.stories.tsx index 7095d387a..34b237843 100644 --- a/src/components/Inputs/TextArea/TextArea.stories.tsx +++ b/src/components/Inputs/TextArea/TextArea.stories.tsx @@ -10,23 +10,28 @@ export const Area = () => ( <>

Text Areas

Text Area No Expand Stretch (Rectangle)

-