diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 11de3b6c8..783952da7 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -79,6 +79,7 @@ export const parameters = { ], }, badgesConfig: { + ...createInitialReleaseConfig('2.0'), ...createInitialReleaseConfig('1.3'), ...createInitialReleaseConfig('1.2'), ...createInitialReleaseConfig('1.1'), diff --git a/src/components/AppNotification/AppNotification.module.css b/src/components/AppNotification/AppNotification.module.css new file mode 100644 index 000000000..e5e702994 --- /dev/null +++ b/src/components/AppNotification/AppNotification.module.css @@ -0,0 +1,55 @@ +/*------------------------------------*\ + # APP NOTIFICATION +\*------------------------------------*/ + +/** + * AppNotification + */ +.app-notification { + padding: 1.5rem; + + &.app-notification--color-dark { + color: var(--eds-theme-color-text-utility-inverse); + background-color: var(--eds-theme-color-background-utility-default-high-emphasis); + } + + &.app-notification--color-light { + color: var(--eds-theme-color-text-utility-default-primary-active); + background-color: var(--eds-theme-color-background-utility-container); + } + + @media (min-width: $eds-bp-sm) { + padding-left: calc(var(--eds-size-6) * 1px); + padding-right: calc(var(--eds-size-6) * 1px); + } + + @media (min-width: $eds-bp-xl) { + .app-notification__content { + margin: 0 auto; + } + } +} + +.app-notification__title { + margin-bottom: 0.5rem; +} + +/* .app-notification__sub-title { +} */ + +.app-notification__actions { + margin-top: 1.5rem; +} + +.app-notification__content { + /* TODO-AH: how to define this magic number */ + max-width: 1320px; + display: flex; + gap: 0.5rem; +} + +.app-notification__close-btn { + flex-shrink: 0; + margin-top: -0.5rem; + margin-right: -0.5rem; +} \ No newline at end of file diff --git a/src/components/AppNotification/AppNotification.stories.tsx b/src/components/AppNotification/AppNotification.stories.tsx new file mode 100644 index 000000000..2cf458d6d --- /dev/null +++ b/src/components/AppNotification/AppNotification.stories.tsx @@ -0,0 +1,79 @@ +import { BADGE } from '@geometricpanda/storybook-addon-badges'; +import type { StoryObj, Meta } from '@storybook/react'; + +import React from 'react'; + +import { AppNotification } from './AppNotification'; +import { ButtonV2 as Button } from '../Button'; +import { ButtonGroupV2 as ButtonGroup } from '../ButtonGroup'; + +export default { + title: 'Components/V2/AppNotification', + component: AppNotification, + parameters: { + badges: [BADGE.BETA, 'intro-2.0', 'current-2.0'], + }, + args: { + title: 'This is an AppNotification title', + subTitle: + 'Lorem ipsum dolor sit amet consectetur. At et vitae quis amet felis mollis in vitae. Eget in neque et molestie. Luctus sed id commodo volutpat. In a eu in id molestie consectetur pellentesque.', + }, + argTypes: { + children: { + control: { + type: null, + }, + }, + }, +} as Meta; + +type Args = React.ComponentProps; + +export const Default: StoryObj = { + args: {}, +}; + +export const WithControls: StoryObj = { + args: { + children: ( + + + + + ), + }, +}; + +export const LightColor: StoryObj = { + args: { + color: 'light', + children: ( + + + + + ), + }, +}; + +export const WithDismissAndControls: StoryObj = { + args: { + ...WithControls.args, + onDismiss: () => { + console.log('dismissing!'); + }, + }, +}; + +export const LightWithDismissAndControls: StoryObj = { + args: { + ...LightColor.args, + onDismiss: () => { + console.log('dismissing!'); + }, + }, +}; diff --git a/src/components/AppNotification/AppNotification.test.ts b/src/components/AppNotification/AppNotification.test.ts new file mode 100644 index 000000000..5d0312458 --- /dev/null +++ b/src/components/AppNotification/AppNotification.test.ts @@ -0,0 +1,8 @@ +import { generateSnapshots } from '@chanzuckerberg/story-utils'; +import type { StoryFile } from '@storybook/testing-react'; + +import * as stories from './AppNotification.stories'; + +describe('', () => { + generateSnapshots(stories as StoryFile); +}); diff --git a/src/components/AppNotification/AppNotification.tsx b/src/components/AppNotification/AppNotification.tsx new file mode 100644 index 000000000..3f4cbb684 --- /dev/null +++ b/src/components/AppNotification/AppNotification.tsx @@ -0,0 +1,94 @@ +import clsx from 'clsx'; +import React from 'react'; +import { ButtonV2 as Button } from '../Button'; +import Text from '../Text'; +import styles from './AppNotification.module.css'; + +export interface Props { + // Design API + /** + * The title/heading of the notification + */ + title: string; + /** + * Secondary text used to describe the notification in more detail + */ + subTitle: React.ReactNode; + /** + * Treatment for component (whether it is dark on light text, or light on dark text) + */ + color: 'dark' | 'light'; + + // Component API + /** + * Contents of the component below the title and sub-title (used mainly for `ButtonGroup`) + */ + children?: React.ReactNode; + /** + * CSS class names that can be appended to the component. + */ + className?: string; + /** + * Callback when banner is dismissed. When passed in, renders banner with a close icon in the top right. + */ + onDismiss?: () => void; +} + +/** + * `import {AppNotification} from "@chanzuckerberg/eds";` + * + * An alert placed at the top of an application which persists across pages. + */ +export const AppNotification = ({ + className, + children, + color = 'dark', + onDismiss, + subTitle, + title, + ...other +}: Props) => { + const componentClassName = clsx( + styles['app-notification'], + color && styles[`app-notification--color-${color}`], + className, + ); + + return ( +
+
+
+ + {title} + + + {subTitle} + +
{children}
+
+ {onDismiss && ( + + )} +
+
+ ); +}; diff --git a/src/components/AppNotification/__snapshots__/AppNotification.test.ts.snap b/src/components/AppNotification/__snapshots__/AppNotification.test.ts.snap new file mode 100644 index 000000000..d04aac9a0 --- /dev/null +++ b/src/components/AppNotification/__snapshots__/AppNotification.test.ts.snap @@ -0,0 +1,284 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` Default story renders snapshot 1`] = ` +
+
+
+
+ This is an AppNotification title +
+

+ Lorem ipsum dolor sit amet consectetur. At et vitae quis amet felis mollis in vitae. Eget in neque et molestie. Luctus sed id commodo volutpat. In a eu in id molestie consectetur pellentesque. +

+
+
+
+
+`; + +exports[` LightColor story renders snapshot 1`] = ` +
+
+
+
+ This is an AppNotification title +
+

+ Lorem ipsum dolor sit amet consectetur. At et vitae quis amet felis mollis in vitae. Eget in neque et molestie. Luctus sed id commodo volutpat. In a eu in id molestie consectetur pellentesque. +

+
+
+ + +
+
+
+
+
+`; + +exports[` LightWithDismissAndControls story renders snapshot 1`] = ` +
+
+
+
+ This is an AppNotification title +
+

+ Lorem ipsum dolor sit amet consectetur. At et vitae quis amet felis mollis in vitae. Eget in neque et molestie. Luctus sed id commodo volutpat. In a eu in id molestie consectetur pellentesque. +

+
+
+ + +
+
+
+ +
+
+`; + +exports[` WithControls story renders snapshot 1`] = ` +
+
+
+
+ This is an AppNotification title +
+

+ Lorem ipsum dolor sit amet consectetur. At et vitae quis amet felis mollis in vitae. Eget in neque et molestie. Luctus sed id commodo volutpat. In a eu in id molestie consectetur pellentesque. +

+
+
+ + +
+
+
+
+
+`; + +exports[` WithDismissAndControls story renders snapshot 1`] = ` +
+
+
+
+ This is an AppNotification title +
+

+ Lorem ipsum dolor sit amet consectetur. At et vitae quis amet felis mollis in vitae. Eget in neque et molestie. Luctus sed id commodo volutpat. In a eu in id molestie consectetur pellentesque. +

+
+
+ + +
+
+
+ +
+
+`; diff --git a/src/components/AppNotification/index.ts b/src/components/AppNotification/index.ts new file mode 100644 index 000000000..1f8a5d741 --- /dev/null +++ b/src/components/AppNotification/index.ts @@ -0,0 +1 @@ +export { AppNotification as default } from './AppNotification'; diff --git a/src/components/Button/Button-v2.module.css b/src/components/Button/Button-v2.module.css index 6f644df03..645c79a2a 100644 --- a/src/components/Button/Button-v2.module.css +++ b/src/components/Button/Button-v2.module.css @@ -127,7 +127,7 @@ /* stylelint-disable-next-line eds/no-tier-1-color-variable */ .button.button--variant-inverse:focus-visible { outline: none; - box-shadow: 0 0 0 0.125rem var(--eds-color-black), 0 0 0 0.25rem var(--eds-theme-color-background-utility-base-1); + box-shadow: 0 0 0 0.125rem rgb(var(--eds-color-black) / 1), 0 0 0 0.25rem var(--eds-theme-color-background-utility-base-1); } /** diff --git a/src/components/ButtonGroup/ButtonGroup-v2.module.css b/src/components/ButtonGroup/ButtonGroup-v2.module.css index 1e3caa088..905f4c040 100644 --- a/src/components/ButtonGroup/ButtonGroup-v2.module.css +++ b/src/components/ButtonGroup/ButtonGroup-v2.module.css @@ -25,4 +25,8 @@ .button-group--horizontal-progressive { flex-direction: row-reverse; justify-content: space-between; +} + +.button-group--horizontal-align-left { + flex-direction: row; } \ No newline at end of file diff --git a/src/components/ButtonGroup/ButtonGroup-v2.stories.tsx b/src/components/ButtonGroup/ButtonGroup-v2.stories.tsx index 1c5a8b03d..29353fc98 100644 --- a/src/components/ButtonGroup/ButtonGroup-v2.stories.tsx +++ b/src/components/ButtonGroup/ButtonGroup-v2.stories.tsx @@ -17,6 +17,9 @@ export default { ), }, argTypes: { + buttonLayout: { + options: ['horizontal', 'vertical', 'horizontal-progressive'], + }, children: { control: { type: null, diff --git a/src/components/ButtonGroup/ButtonGroup-v2.tsx b/src/components/ButtonGroup/ButtonGroup-v2.tsx index 679010ae0..b3e63a8f0 100644 --- a/src/components/ButtonGroup/ButtonGroup-v2.tsx +++ b/src/components/ButtonGroup/ButtonGroup-v2.tsx @@ -19,8 +19,14 @@ type ButtonGroupProps = { // Design API /** * Whether the buttons should be laid out horizontally or stacked vertically (along with relative button position). + * + * (**Note**: `horizontal-align-left` should ONLY be used in combination with `AppNotification`) */ - buttonLayout?: 'horizontal' | 'vertical' | 'horizontal-progressive'; + buttonLayout?: + | 'horizontal' + | 'vertical' + | 'horizontal-progressive' + | 'horizontal-align-left'; }; /** diff --git a/src/index.ts b/src/index.ts index 1580fe71c..5c3a197c1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -52,6 +52,7 @@ export type { IconName } from './components/Icon'; * 2.0 component and type exports */ export { AccordionV2 } from './components/Accordion'; +export { default as AppNotificationV2 } from './components/AppNotification'; export { ButtonV2 } from './components/Button'; export { ButtonGroupV2 } from './components/ButtonGroup'; export { CardV2 } from './components/Card';