diff --git a/.betterer.results b/.betterer.results index 02e5fbfddc0..33eb03face1 100644 --- a/.betterer.results +++ b/.betterer.results @@ -6230,12 +6230,6 @@ exports[`no undocumented stories`] = { "packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.story.tsx:5381": [ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"] ], - "packages/grafana-ui/src/components/ColorPicker/NamedColorsPalette.story.tsx:5381": [ - [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"] - ], - "packages/grafana-ui/src/components/ColorPicker/SpectrumPalette.story.tsx:5381": [ - [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"] - ], "packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.story.tsx:5381": [ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"] ], @@ -6269,10 +6263,13 @@ exports[`no undocumented stories`] = { "packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx:5381": [ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"] ], - "packages/grafana-ui/src/components/StatsPicker/StatsPicker.story.tsx:5381": [ + "packages/grafana-ui/src/components/Slider/RangeSlider.story.tsx:5381": [ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"] ], - "packages/grafana-ui/src/components/Tabs/Tabs.story.tsx:5381": [ + "packages/grafana-ui/src/components/Slider/Slider.story.tsx:5381": [ + [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"] + ], + "packages/grafana-ui/src/components/StatsPicker/StatsPicker.story.tsx:5381": [ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"] ], "packages/grafana-ui/src/components/ThemeDemos/ThemeDemo.story.tsx:5381": [ diff --git a/.betterer.ts b/.betterer.ts index e35ea673f96..f525fc62ba2 100644 --- a/.betterer.ts +++ b/.betterer.ts @@ -1,6 +1,6 @@ import { BettererFileTest } from '@betterer/betterer'; +import { promises as fs } from 'fs'; import { ESLint, Linter } from 'eslint'; -import { existsSync } from 'fs'; import path from 'path'; import glob from 'glob'; @@ -14,14 +14,19 @@ export default { function countUndocumentedStories() { return new BettererFileTest(async (filePaths, fileTestResult) => { - filePaths.forEach((filePath) => { - if (!existsSync(filePath.replace(/\.story.tsx$/, '.mdx'))) { - // In this case the file contents don't matter: - const file = fileTestResult.addFile(filePath, ''); - // Add the issue to the first character of the file: - file.addIssue(0, 0, 'No undocumented stories are allowed, please add an .mdx file with some documentation'); - } - }); + await Promise.all( + filePaths.map(async (filePath) => { + // look for .mdx import in the story file + const regex = new RegExp("^import.*.mdx';$", 'gm'); + const fileText = await fs.readFile(filePath, 'utf8'); + if (!regex.test(fileText)) { + // In this case the file contents don't matter: + const file = fileTestResult.addFile(filePath, ''); + // Add the issue to the first character of the file: + file.addIssue(0, 0, 'No undocumented stories are allowed, please add an .mdx file with some documentation'); + } + }) + ); }); } diff --git a/packages/grafana-ui/src/components/Alert/Alert.mdx b/packages/grafana-ui/src/components/Alert/Alert.mdx index eee11214278..075ac9943a3 100644 --- a/packages/grafana-ui/src/components/Alert/Alert.mdx +++ b/packages/grafana-ui/src/components/Alert/Alert.mdx @@ -1,4 +1,4 @@ -import { Meta, Props } from '@storybook/addon-docs/blocks'; +import { Meta, Props, ArgsTable } from '@storybook/addon-docs/blocks'; import { Alert } from './Alert'; @@ -6,12 +6,153 @@ import { Alert } from './Alert'; # Alert An alert displays an important message in a way that attracts the user's attention without interrupting the user's task. -`onRemove` handler can be used to enable manually dismissing the alert. -# Usage +--- + +About Alert component: + +1. [Behaviors](#behaviors) +2. [Types](#types) +3. [Message type](#message-type) +4. [Main elements](#main-elements) +5. [Usage:](#usage)\ + 5.1. [Inline banner](#alert-inline)\ + 5.2. [Toast](#alert-toast) + +
+
+
+## Behaviors + +1. **Persistent**: They are usually urgent and intrusive, require immediate attention and require action to be dismissed. +2. **Passive**: Are informational, report a system issue that does not require any action by users. +
+ +##
Types + +Within Grafana, we have two different types of alerts and they can be used depending on the context and content. + +1. **[Inline banner](#alert-inline)**: + - To notify users of the status of an action. They appear at the top or bottom of the main content area + - Passive or Persistent +1. **[Toast](#alert-toast)**: + - These temporary window elements are used to display short messages; they appear at the top-right corner of the screen and can be dismissed by clicking the [x] or it will disappear after a few seconds + - Passive +
+ +##
Message Type + +1. **Informational** + - To provide information to users, and don’t interrupt any current actions + - Does not require immediate action and can be dismissed by a user clicking the [X] or passively display until the display timer expires + - Shows blue color on the background and uses the `info-circle` icon +2. **Success** + - To confirm a task is completed as expected or an action is successful. + - Typically does not require further action and can be dismissed automatically or persist in a nonintrusive manner + - Shows green color on the background and uses the `check` icon +3. **Warning** + - To inform users that an action is undesirable + - Often persists until users have taken action to dismiss the notification or taken steps to resolve the issue + - Shows yellow color on background and uses the `exclamation-triangle` icon +4. **Error** + - To inform that an action hasn't happened as expected, usually something has failed and the user is expected to take action + - Always persists until the user has taken steps to remedy the issue that triggered the notification + - Shows red color on background and uses the `exclamation-triangle` icon +
+ +##
Main elements + +- Icon status: represents the importance of the message through the color and icon for each status. + +- Alert title: should be explicit, clear and short, conveying the most important part of the information. + +- Details: precise description for the notification, telling users what they need to do. + +- Button and text links: only persistent notifications should contain text links or buttons. + +- Close icon: appears when the notification can be dismissed by the user. +
+ +##
Usage + +
+###
Inline Banner + +Inline Banners are task-oriented alerts that notify users of the status of an action or system. These alerts are contextual — appearing above or below main content areas — allowing users to address issues or to read messages quickly. + +#### Do's + + - Use the appropriate status for the message (info/success/warning/error). + - Use plain, simple language for the messages to ensure users understand them and know how to address them. + - Focus on notifications if they are relevant to the users' current workflow and should be addressed immediately. + +#### Don'ts + + - Do not use Primary calls to actions. + - Do not hide other content with inline notifications. + - Do not repeat the alert copy/title on the details message. + +#### When to use + + - To inform at that time how to continue a task in which users must perform an action. + - To provide some options for users to take action. + - To explain in detail the reasons why something can’t be done by users. + +#### Placement + + - Should be placed immediately above or below the related element. ```jsx - + + +
Child content that includes some alert details, like maybe what actually happened.
+
+
``` - +###
Toast + +Toast notifications are short messages that appear in the top-right corner of the page and are automatically hidden after a certain amount of time – they provide live notifications, without interrupting the user experience or requiring an action to be taken. + +#### Do's + + - Use this component using `AppEvents` and `getAppEvents()`. + - Show the `Toast` publishing the `appEvent` with the proper type and payload needed. + +```jsx +import { AppEvents } from '@grafana/data'; +import { getAppEvents } from '@grafana/runtime'; + +const appEvents = getAppEvents(); +appEvents.publish({ + type: AppEvents.alertSuccess.name, + payload: [text + ': ' + resp.status + ' (' + resp.statusText + ')'], +}); +``` + +#### Don'ts + + - Do not use this component directly. Instead, emit the `appEvent` to trigger it's appearance. + +#### When to use + + - To convey general confirmation or non-critical actions. + - Immediately after an event is taken, such as a permission is updated or some Dashboards are imported or deleted. + - Status according to use cases: + - *Success*: When any action is successful, it is confirmed when a task is completed as expected. + - *Warning*: It is used to report a current status that users should be aware of or that could have serious consequences. + - *Error*: Inform users of an error, and sometimes provide more information about how to fix the error. + +#### Placement + + - Slide in and out from the top right corner of the page. + +```jsx + + +
Child content that includes some alert details, like maybe what actually happened.
+
+
+``` + + diff --git a/packages/grafana-ui/src/components/Alert/Alert.story.tsx b/packages/grafana-ui/src/components/Alert/Alert.story.tsx deleted file mode 100644 index 4b28f8b653a..00000000000 --- a/packages/grafana-ui/src/components/Alert/Alert.story.tsx +++ /dev/null @@ -1,192 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { ComponentStory, ComponentMeta } from '@storybook/react'; -import React from 'react'; - -import { Alert, AlertVariant, VerticalGroup } from '@grafana/ui'; - -import { StoryExample } from '../../utils/storybook/StoryExample'; -import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory'; -import mdx from '../Alert/Alert.mdx'; - -const severities: AlertVariant[] = ['error', 'warning', 'info', 'success']; - -const meta: ComponentMeta = { - title: 'Overlays/Alert', - component: Alert, - decorators: [withCenteredStory, withHorizontallyCenteredStory], - parameters: { - docs: { - page: mdx, - }, - knobs: { - disable: true, - }, - controls: { - exclude: ['onRemove'], - }, - }, - argTypes: { - severity: { control: { type: 'select', options: severities } }, - }, -}; - -export const Examples: ComponentStory = ({ severity, title, buttonContent }) => { - return ( - - - {buttonContent}} - onRemove={action('Remove button clicked')} - > - -
Child content that includes some alert details, like maybe what actually happened.
-
-
-
- - - - - - - - - {severities.map((severity) => ( - - ))} - - - - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam metus urna, aliquam eu scelerisque non, - facilisis eget est. Morbi eleifend egestas massa id vulputate. Fusce dignissim magna lacus, ut molestie odio - feugiat sed. Cras fringilla justo sit amet turpis scelerisque, a volutpat purus iaculis. Nunc sagittis - molestie faucibus. Curabitur at neque luctus, pellentesque urna eget, posuere urna. Nunc malesuada elit in - ipsum dictum egestas. Praesent convallis mauris massa, porta mattis ex gravida ut. Proin consectetur ultrices - tortor sit amet efficitur. Suspendisse nec turpis dapibus mauris venenatis maximus quis eget orci. Ut semper - enim magna, ullamcorper elementum sapien pharetra vitae. Vivamus at nulla ut metus bibendum ornare et ut leo. - Proin ante turpis, ornare a malesuada et, rutrum nec lorem. Maecenas vestibulum orci vel nibh convallis - eleifend. Quisque vitae consectetur massa, vitae elementum mauris. Pellentesque sit amet ligula lorem. Fusce - sit amet lorem non augue rutrum varius. Donec sed imperdiet libero, eget venenatis elit. Fusce porttitor - dapibus urna. Duis fringilla ante vel tempor tincidunt. In euismod vestibulum odio sit amet iaculis. Donec vel - dapibus libero. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi lacinia commodo lectus. Aenean - in magna eget lectus luctus suscipit et vitae erat. Pellentesque quis ligula id lorem egestas sollicitudin sit - amet sed sem. Nullam et nibh a odio rhoncus efficitur sed nec est. Sed commodo lacus vitae sem congue, - accumsan dignissim metus iaculis. Praesent in dignissim nisl. Aliquam facilisis, sapien eget porttitor - ultrices, massa libero bibendum odio, at ornare diam arcu ac massa. Vestibulum egestas leo eget lorem congue - condimentum. Praesent egestas, neque id gravida vehicula, augue ex scelerisque lectus, finibus pellentesque - enim dolor vel ante. Cras convallis, sem at malesuada tincidunt, diam urna auctor leo, sed laoreet est ex in - libero. Ut condimentum ante eget ex gravida, id tempus metus ultricies. Pellentesque placerat, massa id - laoreet molestie, justo nisl varius metus, maximus vehicula erat libero vitae nulla. Mauris rhoncus ligula - vitae volutpat auctor. Suspendisse potenti. Quisque quis orci faucibus, ullamcorper dolor eget, mollis massa. - Etiam eu molestie ipsum. Sed laoreet diam metus, luctus maximus erat viverra quis. Ut eu felis dictum, - tincidunt erat sit amet, scelerisque neque. Orci varius natoque penatibus et magnis dis parturient montes, - nascetur ridiculus mus. Phasellus sit amet est tristique, fermentum massa ut, viverra metus. Interdum et - malesuada fames ac ante ipsum primis in faucibus. Nunc iaculis nunc elit, ut feugiat ipsum egestas eget. - Vestibulum pulvinar ligula mi, quis lacinia diam suscipit eget. Etiam consectetur vel nunc at hendrerit. - Pellentesque blandit eleifend aliquam. Etiam et malesuada purus, et bibendum sapien. Phasellus tincidunt - consequat eros consequat sodales. Vestibulum quis viverra neque. Integer sit amet lacinia nunc. Ut cursus, - elit id faucibus elementum, elit nunc dapibus tellus, non ornare nisi sapien et eros. Nunc sit amet suscipit - arcu. Nulla ut nunc tempor, auctor massa sed, consectetur orci. Pellentesque erat ante, placerat eget dictum - elementum, dapibus et ipsum. Nunc sit amet nulla gravida, finibus felis vel, tempus sem. In urna purus, - accumsan quis aliquam et, condimentum ac urna. Nullam volutpat ullamcorper sapien, quis ultricies purus - dignissim aliquam. Mauris quis enim ante. Etiam vulputate faucibus placerat. Ut pellentesque, purus vitae - euismod cursus, lacus enim vulputate sapien, in porttitor erat dui eu lectus. Duis eleifend, massa vel - vehicula gravida, magna urna rutrum ligula, vitae mollis ipsum neque id enim. Donec varius tristique nisi, et - vestibulum dolor efficitur eget. Cras mauris leo, bibendum eget pretium a, tincidunt faucibus massa. - Vestibulum hendrerit arcu magna, vel consequat est euismod nec. Vestibulum non lacus porttitor, congue tortor - ut, venenatis elit. Duis at lectus arcu. Nunc quis sapien eu ipsum rutrum accumsan. Orci varius natoque - penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus quis sapien luctus, volutpat nulla - eget, gravida nunc. Aenean placerat a felis quis imperdiet. Sed sapien tellus, ultrices non ipsum eget, - pretium rhoncus quam. Aliquam erat volutpat. Maecenas at interdum turpis, eu mattis ligula. Class aptent - taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In lobortis felis a leo - ultricies, venenatis mollis felis lobortis. Suspendisse placerat vel ante vel euismod. Aenean sit amet - ullamcorper mauris, id consectetur est. Ut ultricies enim non quam condimentum, et congue arcu commodo. - Praesent convallis eleifend turpis, vitae feugiat turpis imperdiet sit amet. Class aptent taciti sociosqu ad - litora torquent per conubia nostra, per inceptos himenaeos. Quisque vulputate porttitor mattis. Pellentesque - sed ullamcorper lectus. Suspendisse velit tortor, viverra eget facilisis condimentum, accumsan sit amet felis. - Cras lobortis mi fermentum ligula consectetur, vitae tincidunt mauris scelerisque. Aenean ac condimentum erat, - quis lacinia lacus. Ut magna nibh, tempor et ligula suscipit, placerat laoreet ipsum. In semper semper nisl. - Donec risus lorem, tempor sed sollicitudin vitae, fringilla et mi. Vivamus pulvinar quam nisl, et tincidunt - justo tempus quis. Duis semper magna nunc, vitae faucibus lectus facilisis sed. Phasellus consequat arcu vel - interdum fermentum. In condimentum euismod neque, sed aliquet mauris posuere nec. Etiam metus eros, - pellentesque eget scelerisque id, porttitor at ligula. Curabitur eget nibh maximus enim lobortis sodales. - Etiam vulputate ligula lobortis vestibulum pulvinar. Curabitur eros justo, accumsan sed elit ac, mattis - lacinia nisi. Suspendisse ullamcorper lectus sit amet tellus condimentum porttitor. Duis cursus, neque et - aliquam congue, odio lectus porta elit, id lacinia dolor justo non leo. Aliquam vehicula at tellus ullamcorper - tincidunt. Phasellus neque nibh, convallis sit amet arcu sit amet, convallis egestas tortor. Etiam sit amet - vehicula quam. Praesent id consequat lacus, ac facilisis quam. Integer tristique lorem eros, id consequat - lorem lobortis vitae. Aliquam luctus purus eget sem molestie iaculis. Duis nisl risus, sodales sit amet nunc - vitae, volutpat cursus augue. Pellentesque congue massa eu metus pellentesque consectetur at vel neque. Donec - bibendum hendrerit erat, vitae dictum enim lobortis a. Quisque ac dapibus tellus, sit amet facilisis orci. - Cras pretium tortor non condimentum semper. Phasellus mollis condimentum blandit. Pellentesque at arcu risus. - Vivamus sit amet dui semper, suscipit est nec, elementum arcu. Praesent ante turpis, convallis ac leo eget, - rutrum bibendum ante. Sed venenatis vehicula lobortis. Phasellus consectetur velit nec congue venenatis. - Interdum et malesuada fames ac ante ipsum primis in faucibus. Nullam sagittis, arcu quis sagittis vestibulum, - odio lorem tempus massa, non condimentum enim turpis ut orci. Vivamus sit amet dignissim eros. Vestibulum ante - ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Phasellus efficitur est eu semper - luctus. Nunc gravida tristique urna, et mollis leo porttitor suscipit. In hac habitasse platea dictumst. Etiam - tempus varius mattis. Suspendisse potenti. Duis finibus ornare tortor, a auctor lacus dictum id. Suspendisse - eget auctor lorem, sollicitudin placerat ipsum. Aliquam suscipit ante at gravida tincidunt. Donec vel turpis - dui. Ut facilisis, dui id fermentum ultrices, nunc mi pretium ex, eu lobortis sem tellus porttitor nulla. Nam - sit amet mauris justo. Maecenas libero est, dignissim vel dolor ac, rutrum accumsan tellus. Nulla in lacinia - orci, facilisis feugiat mi. Nunc sit amet ultricies dolor. Sed ac interdum lacus. Quisque facilisis viverra - orci vel tincidunt. Suspendisse feugiat ligula non justo molestie viverra. Cras sed ultricies quam. Duis - aliquam ante lacus, non posuere neque pretium id. Fusce at orci facilisis, pretium justo eu, vestibulum sem. - Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis at lorem ultrices, - tincidunt nulla ac, molestie ligula. Phasellus erat nunc, consectetur ut velit vel, porta fringilla ante. - Vestibulum laoreet lorem erat, ultricies porta ex venenatis vel. Donec vestibulum enim id suscipit - pellentesque. Donec vitae dictum arcu. In ac tellus dignissim, imperdiet tellus quis, malesuada nisl. Aliquam - finibus urna commodo purus ultricies, non vulputate risus ullamcorper. Cras semper ultrices posuere. Etiam - massa nisi, vehicula sit amet volutpat sit amet, commodo vel mi. Maecenas commodo consectetur ipsum nec - ultrices. Sed hendrerit quam nulla, ut tincidunt tortor commodo eget. Vestibulum euismod condimentum - porttitor. Mauris egestas posuere justo ac suscipit. Nulla auctor tellus nec eros rhoncus, a congue odio - accumsan. Phasellus tempus risus ut orci commodo, sed lobortis ex porta. Nullam ligula erat, pretium ut nibh - volutpat, tincidunt pellentesque purus. Vivamus cursus eget nisi id ornare. Phasellus ut aliquet turpis. - Vestibulum ornare ex eros, quis accumsan neque porta id. Pellentesque eleifend, tortor eget dignissim - convallis, nisl felis fringilla dolor, dapibus bibendum mauris lacus dignissim metus. Cras cursus faucibus - condimentum. Curabitur non libero risus. Morbi nisi augue, aliquam quis neque sit amet, commodo ullamcorper - justo. Aenean pulvinar accumsan nibh, vel bibendum turpis rutrum vitae. Donec condimentum justo vel luctus - consectetur. Donec id nisl eu erat sollicitudin venenatis at eget justo. Mauris ac nulla laoreet, semper - tortor sed, egestas odio. Fusce ex ligula, aliquet sed tortor sit amet, porta malesuada libero. Aenean varius - tellus in enim fringilla tristique. Duis risus diam, condimentum ac ornare sed, imperdiet non lectus. Mauris - auctor condimentum pulvinar. Pellentesque dapibus ultricies neque eu egestas. Phasellus molestie volutpat - tincidunt. Aenean tristique felis aliquam consectetur fringilla. Pellentesque a mauris nibh. Maecenas commodo - dignissim sem, eget laoreet purus laoreet eu. Sed arcu mi, facilisis quis finibus ac, pulvinar ut sem. Nulla - facilisi. Maecenas in elit diam. Vivamus aliquam enim eget enim condimentum fermentum. Sed convallis tellus - nisl, eget congue diam hendrerit et. Nulla posuere, sem non condimentum aliquet, leo arcu scelerisque leo, sit - amet maximus ante massa in odio. Nunc dictum nibh ac dui luctus, sit amet tempor massa imperdiet. Nunc dictum - ligula augue, a auctor odio rutrum a. Cras auctor, mi vitae maximus dictum, purus mauris ornare libero, ac - consequat mauris diam sit amet mauris. In egestas eu felis ut volutpat. Etiam dignissim justo vitae sagittis - venenatis. Vestibulum fermentum lectus nisl, vitae tempor ipsum lobortis nec. Nam porttitor est vel libero - mollis, vel accumsan nisi iaculis. Suspendisse interdum consequat sapien, quis aliquam leo condimentum ut. In - ut risus sit amet quam viverra facilisis. Mauris dapibus tortor id purus egestas mollis. Quisque vitae ornare - ex. Vivamus non accumsan lectus. Mauris at iaculis ex. Curabitur rutrum magna nibh, eu accumsan felis - tristique in. Donec in fringilla orci. Quisque ante dolor, tempor vitae lacinia non, malesuada at dui. Ut - tincidunt bibendum magna vitae ornare. Suspendisse a ipsum ut nulla ornare pretium. Donec malesuada rhoncus - facilisis. Integer nulla mi, sagittis vel purus non, viverra sodales lectus. Pellentesque habitant morbi - tristique senectus et netus et malesuada fames ac turpis egestas. Aenean tristique turpis neque, nec elementum - ipsum condimentum tempor. Pellentesque mauris magna, venenatis ac sodales et, fermentum sed nunc. Pellentesque - dignissim lacinia suscipit. Pellentesque mollis tellus justo, eu facilisis neque tempor a. Aenean id metus - gravida, consectetur ligula eget, tincidunt sapien. Morbi in tellus id ex vestibulum sagittis sed vitae risus. - In vehicula sed arcu auctor ullamcorper. Etiam elementum mollis fringilla. - - -
- ); -}; - -Examples.args = { - severity: 'error', - title: 'Some very important message', - buttonContent: 'Close', -}; - -export default meta; diff --git a/packages/grafana-ui/src/components/Alert/Alert.tsx b/packages/grafana-ui/src/components/Alert/Alert.tsx index b9ae2e94f53..4da17e027ca 100644 --- a/packages/grafana-ui/src/components/Alert/Alert.tsx +++ b/packages/grafana-ui/src/components/Alert/Alert.tsx @@ -24,18 +24,6 @@ export interface Props extends HTMLAttributes { topSpacing?: number; } -export function getIconFromSeverity(severity: AlertVariant): IconName { - switch (severity) { - case 'error': - case 'warning': - return 'exclamation-triangle'; - case 'info': - return 'info-circle'; - case 'success': - return 'check'; - } -} - export const Alert = React.forwardRef( ( { @@ -103,6 +91,18 @@ export const Alert = React.forwardRef( Alert.displayName = 'Alert'; +export const getIconFromSeverity = (severity: AlertVariant): IconName => { + switch (severity) { + case 'error': + case 'warning': + return 'exclamation-triangle'; + case 'info': + return 'info-circle'; + case 'success': + return 'check'; + } +}; + const getStyles = ( theme: GrafanaTheme2, severity: AlertVariant, diff --git a/packages/grafana-ui/src/components/Alert/InlineBanner.story.tsx b/packages/grafana-ui/src/components/Alert/InlineBanner.story.tsx new file mode 100644 index 00000000000..a9f45c3cfe6 --- /dev/null +++ b/packages/grafana-ui/src/components/Alert/InlineBanner.story.tsx @@ -0,0 +1,63 @@ +import { action } from '@storybook/addon-actions'; +import { ComponentStory, Meta } from '@storybook/react'; +import React from 'react'; + +import { Alert, AlertVariant, VerticalGroup } from '@grafana/ui'; + +import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory'; +import mdx from '../Alert/Alert.mdx'; + +const severities: AlertVariant[] = ['error', 'warning', 'info', 'success']; + +const meta: Meta = { + title: 'Overlays/Alert/InlineBanner', + component: Alert, + decorators: [withCenteredStory, withHorizontallyCenteredStory], + parameters: { + docs: { + page: mdx, + }, + controls: { exclude: ['onRemove'] }, + }, + argTypes: { + severity: { + control: { type: 'select', options: severities }, + }, + }, +}; + +export const Basic: ComponentStory = (args) => { + return ( +
+ + +
Child content that includes some alert details, like maybe what actually happened.
+
+
+
+ ); +}; + +Basic.args = { + severity: 'error', + title: 'Basic', +}; + +export const WithActions: ComponentStory = (args) => { + return ( + + +
Child content that includes some alert details, like maybe what actually happened.
+
+
+ ); +}; + +WithActions.args = { + title: 'With action', + severity: 'error', + onRemove: action('Remove button clicked'), + buttonContent: 'Close', +}; + +export default meta; diff --git a/packages/grafana-ui/src/components/Alert/Toast.story.tsx b/packages/grafana-ui/src/components/Alert/Toast.story.tsx new file mode 100644 index 00000000000..852242eead5 --- /dev/null +++ b/packages/grafana-ui/src/components/Alert/Toast.story.tsx @@ -0,0 +1,44 @@ +import { action } from '@storybook/addon-actions'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; +import React from 'react'; + +import { Alert, AlertVariant, VerticalGroup } from '@grafana/ui'; + +import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory'; +import mdx from '../Alert/Alert.mdx'; + +const severities: AlertVariant[] = ['error', 'warning', 'info', 'success']; + +const meta: ComponentMeta = { + title: 'Overlays/Alert/Toast', + component: Alert, + decorators: [withCenteredStory, withHorizontallyCenteredStory], + parameters: { + docs: { + page: mdx, + }, + controls: { exclude: ['onRemove'] }, + }, + argTypes: { + severity: { control: { type: 'select', options: severities } }, + }, + args: { + title: 'Toast', + severity: 'error', + onRemove: action('Remove button clicked'), + }, +}; + +export const Toast: ComponentStory = (args) => { + return ( +
+ + +
Child content that includes some alert details, like maybe what actually happened.
+
+
+
+ ); +}; + +export default meta;