diff --git a/.vscode/custom.css-data.json b/.vscode/custom.css-data.json index f0ccbd5..216bb8f 100644 --- a/.vscode/custom.css-data.json +++ b/.vscode/custom.css-data.json @@ -1,4 +1,5 @@ { + // https://github.com/microsoft/vscode-custom-data "version": 1.1, "properties": [ { "name": "interpolate-size" }, diff --git a/src/components/actions/Button/Button.module.scss b/src/components/actions/Button/Button.module.scss index ac91775..cd08692 100644 --- a/src/components/actions/Button/Button.module.scss +++ b/src/components/actions/Button/Button.module.scss @@ -16,7 +16,10 @@ cursor: pointer; margin: 0; - padding: calc(bk.$spacing-2 - 0.125lh) bk.$spacing-3; /* Note: compensate for line-height difference with Figma */ + padding: 0; + &:not(.bk-button--compact) { + padding: calc(bk.$spacing-2 - 0.125lh) bk.$spacing-3; /* Note: compensate for line-height difference with Figma */ + } /* Transparent border for consistency with other variants that have a border */ border: bk.$size-1 solid transparent; @@ -67,7 +70,7 @@ --bk-button-color-contrast: #{bk.$theme-button-primary-text-non-active}; cursor: not-allowed; } - + @media (prefers-reduced-motion: no-preference) { transition: none 150ms ease-in-out; transition-property: border, background, color; diff --git a/src/components/actions/Button/Button.stories.tsx b/src/components/actions/Button/Button.stories.tsx index 4b6129c..099d16e 100644 --- a/src/components/actions/Button/Button.stories.tsx +++ b/src/components/actions/Button/Button.stories.tsx @@ -10,7 +10,7 @@ import * as React from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import { Icon } from '../../graphics/Icon/Icon.tsx'; -import { Alert } from '../../containers/Alert/Alert.tsx'; +import { Banner } from '../../containers/Banner/Banner.tsx'; import { Button } from './Button.tsx'; @@ -40,10 +40,12 @@ export default { Story => ( - -

Error: {error?.message}

-

- -); +const ExampleActionButton = () => + alert('clicked')}>Button; +const ExampleActionIcon = () => + alert('clicked')}>; export const BannerStandard: Story = {}; @@ -53,21 +77,33 @@ export const BannerWithCloseButton: Story = { args: { onClose: () => {}, }, - render: (args) => , }; export const BannerWithMessage: Story = { args: { - message: 'This is the main message of the banner.', + children: 'This is the main message of the banner.', onClose: () => {}, }, }; export const BannerWithButton: Story = { args: { - message: 'Message text', + children: 'Message text', onClose: () => {}, - actions: , + actions: , + }, +}; + +export const BannerWithButtonAndIcon: Story = { + args: { + children: 'Message text', + onClose: () => {}, + actions: ( + <> + + + + ), }, }; @@ -76,34 +112,54 @@ export const BannerWithTitleOverflow: Story = { args: { title: loremIpsum(), onClose: () => {}, - actions: , + actions: , }, }; export const BannerWithTextWrap: Story = { args: { - message: , + children: , onClose: () => {}, - actions: , + actions: , }, }; export const BannerWithTitleOverflowAndTextWrap: Story = { args: { title: loremIpsum(), - message: , + children: , onClose: () => {}, - actions: , + actions: , + }, +}; + +export const BannerWithThemedContent: Story = { + args: { + title: loremIpsum(), + children: ( +

+

+ Banners look visually light, even in dark mode. The following components should always have a light theme: +

+

+ +

+ +
+ ), }, }; export const BannerInformational: Story = { args: { - variant: 'informational', + variant: 'info', title: loremIpsum(), - message: , + children: , onClose: () => {}, - actions: , + actions: , }, }; @@ -111,9 +167,9 @@ export const BannerSuccess: Story = { args: { variant: 'success', title: loremIpsum(), - message: , + children: , onClose: () => {}, - actions: , + actions: , }, }; @@ -121,9 +177,9 @@ export const BannerWarning: Story = { args: { variant: 'warning', title: loremIpsum(), - message: , + children: , onClose: () => {}, - actions: , + actions: , }, }; @@ -131,8 +187,19 @@ export const BannerError: Story = { args: { variant: 'error', title: loremIpsum(), - message: , + children: , onClose: () => {}, - actions: , + actions: , }, }; + +export const BannersStacked: Story = { + render: args => ( + <> + {}}/> + {}}/> + {}}/> + {}}/> + + ), +}; diff --git a/src/components/containers/Banner/Banner.tsx b/src/components/containers/Banner/Banner.tsx index ce33c5d..25ce003 100644 --- a/src/components/containers/Banner/Banner.tsx +++ b/src/components/containers/Banner/Banner.tsx @@ -9,116 +9,145 @@ import { classNames as cx, type ComponentProps } from '../../../util/componentUt import { type IconName, type IconProps, Icon } from '../../graphics/Icon/Icon.tsx'; import { Button } from '../../actions/Button/Button.tsx'; +import { TooltipProvider } from '../../overlays/Tooltip/TooltipProvider.tsx'; import cl from './Banner.module.scss'; export { cl as BannerClassNames }; -type BannerVariant = 'informational' | 'warning' | 'error' | 'success'; +type BannerVariant = 'info' | 'warning' | 'error' | 'success'; -type BannerIconProps = Omit & { +type BannerVariantIconProps = Omit & { icon?: IconProps['icon'], // Make optional variant: BannerVariant, }; -const BannerIcon = (props: BannerIconProps) => { - const { variant } = props; +const BannerVariantIcon = ({ variant, ...propsRest }: BannerVariantIconProps) => { const icon = ((): IconName => { switch (variant) { - case 'informational': return 'info'; + case 'info': return 'info'; case 'warning': return 'warning'; case 'error': return 'status-failed'; case 'success': return 'status-success'; default: return assertUnreachable(variant); } })(); - return ; + return ; }; + +export type ActionButtonProps = ComponentProps; +/** + * A customized version of the ` +
+ + + +
} - {actions} - - ); -}; - -export type BannerActionProps = ComponentProps<'div'>; -/** - * A wrapper component, intended to easily add some styling to children's `