mirror of https://github.com/grafana/grafana.git
Storybook: Rearrange and tidy stories (#107270)
* Tidy up storybook a little bit * change sort order, delete some stories * More tidy up of actions * More tidy up of actions * tweak story sorting, again * Make all internal stories public * fix sort * Add ESLint rule to enforce storybook titles * update verify storybook test * simplify glob
This commit is contained in:
parent
d27d8f02b6
commit
a9e70d4a1d
|
@ -4128,6 +4128,15 @@ exports[`no undocumented stories`] = {
|
|||
"packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.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/CallToActionCard/CallToActionCard.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/ColorPickerInput.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/SeriesColorPicker.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"]
|
||||
],
|
||||
|
@ -4143,12 +4152,27 @@ exports[`no undocumented stories`] = {
|
|||
"packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.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/Dropdown/ButtonSelect.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/FormField/FormField.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/InfoTooltip/InfoTooltip.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/List/List.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/PageLayout/PageToolbar.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/QueryField/QueryField.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/SecretFormField/SecretFormField.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/SecretTextArea/SecretTextArea.story.tsx:5381": [
|
||||
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
|
||||
],
|
||||
|
@ -4161,6 +4185,9 @@ 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/Select/SelectPerf.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/Slider/RangeSlider.story.tsx:5381": [
|
||||
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
|
||||
],
|
||||
|
@ -4170,9 +4197,21 @@ exports[`no undocumented stories`] = {
|
|||
"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/TableInputCSV/TableInputCSV.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/BorderRadius.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/EmotionPerfTest.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": [
|
||||
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/ThemeDemos/Typography.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/UnitPicker/UnitPicker.story.tsx:5381": [
|
||||
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
|
||||
],
|
||||
|
@ -4184,6 +4223,9 @@ exports[`no undocumented stories`] = {
|
|||
],
|
||||
"packages/grafana-ui/src/components/VizTooltip/SeriesTable.story.tsx:5381": [
|
||||
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/utils/useDelayedSwitch.story.tsx:5381": [
|
||||
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
|
||||
]
|
||||
}`
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// NOTE: storybook must already be running (`yarn storybook`) for this test to work
|
||||
describe('Verify storybook', () => {
|
||||
it('Loads the button story correctly', () => {
|
||||
cy.visit('?path=/story/buttons-button--basic');
|
||||
cy.visit('?path=/story/inputs-button--basic');
|
||||
getIframeBody().find('button:contains("Example button")').should('be.visible');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -176,6 +176,13 @@ module.exports = [
|
|||
'react/react-in-jsx-scope': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'grafana/story-rules',
|
||||
files: ['packages/grafana-ui/src/**/*.story.tsx'],
|
||||
rules: {
|
||||
'@grafana/consistent-story-titles': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'grafana/public-dashboards-overrides',
|
||||
files: ['public/dashboards/scripted*.js'],
|
||||
|
|
|
@ -113,3 +113,30 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
|||
### `theme-token-usage`
|
||||
|
||||
Used to find all instances of `theme` tokens being used in the codebase and emit the counts as metrics. Should **not** be used as an actual lint rule!
|
||||
|
||||
### `consistent-story-titles`
|
||||
|
||||
Enforce consistent Storybook titles in `.story.tsx` files.
|
||||
|
||||
Storybook titles should not contain more than one `/` for sections (resulting in maximum 2 parts), unless one of the sections is 'Deprecated'. This helps maintain a clean and organized Storybook structure.
|
||||
|
||||
#### Examples
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
export default { title: 'Components/Forms/Button' };
|
||||
|
||||
// Good ✅
|
||||
export default { title: 'Components/Button' };
|
||||
|
||||
// Good ✅ - Deprecated allows any number of sections
|
||||
export default { title: 'Components/Deprecated/Forms/Button/Extra' };
|
||||
|
||||
// Good ✅ - Variable assignment pattern
|
||||
const storyConfig = { title: 'Components/Button' };
|
||||
export default storyConfig;
|
||||
|
||||
// Bad ❌ - Variable assignment with too many sections
|
||||
const storyConfig = { title: 'Components/Forms/Button' };
|
||||
export default storyConfig;
|
||||
```
|
||||
|
|
|
@ -3,6 +3,7 @@ const noBorderRadiusLiteral = require('./rules/no-border-radius-literal.cjs');
|
|||
const noUnreducedMotion = require('./rules/no-unreduced-motion.cjs');
|
||||
const themeTokenUsage = require('./rules/theme-token-usage.cjs');
|
||||
const noRestrictedImgSrcs = require('./rules/no-restricted-img-srcs.cjs');
|
||||
const consistentStoryTitles = require('./rules/consistent-story-titles.cjs');
|
||||
|
||||
module.exports = {
|
||||
rules: {
|
||||
|
@ -11,5 +12,6 @@ module.exports = {
|
|||
'no-border-radius-literal': noBorderRadiusLiteral,
|
||||
'theme-token-usage': themeTokenUsage,
|
||||
'no-restricted-img-srcs': noRestrictedImgSrcs,
|
||||
'consistent-story-titles': consistentStoryTitles,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
// @ts-check
|
||||
const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils');
|
||||
|
||||
const createRule = ESLintUtils.RuleCreator(
|
||||
(name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-eslint-rules/README.md#${name}`
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {string} title
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isValidStorybookTitle = (title) => {
|
||||
if (typeof title !== 'string') {
|
||||
return true; // Skip non-string titles
|
||||
}
|
||||
|
||||
const sections = title.split('/');
|
||||
|
||||
// Allow up to 3 sections if one of them is 'Deprecated'
|
||||
if (sections.some((section) => section.trim() === 'Deprecated')) {
|
||||
return sections.length <= 3;
|
||||
}
|
||||
|
||||
// Otherwise, limit to maximum 2 sections (1 slash)
|
||||
return sections.length <= 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('@typescript-eslint/utils').TSESTree.ObjectExpression} objectNode
|
||||
* @param {import('@typescript-eslint/utils/ts-eslint').RuleContext<'invalidTitle', []>} context
|
||||
*/
|
||||
const checkObjectForTitle = (objectNode, context) => {
|
||||
const titleProperty = objectNode.properties.find(
|
||||
(prop) =>
|
||||
prop.type === AST_NODE_TYPES.Property && prop.key.type === AST_NODE_TYPES.Identifier && prop.key.name === 'title'
|
||||
);
|
||||
|
||||
if (
|
||||
titleProperty &&
|
||||
titleProperty.type === AST_NODE_TYPES.Property &&
|
||||
titleProperty.value.type === AST_NODE_TYPES.Literal
|
||||
) {
|
||||
const titleValue = titleProperty.value.value;
|
||||
|
||||
if (typeof titleValue === 'string' && !isValidStorybookTitle(titleValue)) {
|
||||
context.report({
|
||||
node: titleProperty.value,
|
||||
messageId: 'invalidTitle',
|
||||
data: {
|
||||
title: titleValue,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const consistentStoryTitlesRule = createRule({
|
||||
create(context) {
|
||||
return {
|
||||
ExportDefaultDeclaration(node) {
|
||||
// Only check .story.tsx files
|
||||
const filename = context.filename;
|
||||
if (!filename || !filename.endsWith('.story.tsx')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.declaration.type === AST_NODE_TYPES.ObjectExpression) {
|
||||
// Handle direct object export: export default { title: '...' }
|
||||
checkObjectForTitle(node.declaration, context);
|
||||
} else if (node.declaration.type === AST_NODE_TYPES.Identifier) {
|
||||
// Handle variable reference export: export default storyConfig
|
||||
const variableName = node.declaration.name;
|
||||
const scope = context.sourceCode.getScope(node);
|
||||
const variable = scope.set.get(variableName);
|
||||
|
||||
if (variable) {
|
||||
// Find the variable declaration
|
||||
const declaration = variable.defs.find((def) => def.type === 'Variable');
|
||||
if (
|
||||
declaration &&
|
||||
declaration.node.init &&
|
||||
declaration.node.init.type === AST_NODE_TYPES.ObjectExpression
|
||||
) {
|
||||
checkObjectForTitle(declaration.node.init, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
name: 'consistent-story-titles',
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Enforce consistent Storybook titles with maximum two sections (1 slash) unless one is "Deprecated"',
|
||||
},
|
||||
messages: {
|
||||
invalidTitle:
|
||||
'Storybook title "{{ title }}" has too many sections. Use maximum 2 sections (1 slash) unless one section is "Deprecated".',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
});
|
||||
|
||||
module.exports = consistentStoryTitlesRule;
|
|
@ -0,0 +1,117 @@
|
|||
import { RuleTester } from 'eslint';
|
||||
|
||||
import consistentStories from '../rules/consistent-story-titles.cjs';
|
||||
|
||||
RuleTester.setDefaultConfig({
|
||||
languageOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const ruleTester = new RuleTester();
|
||||
|
||||
ruleTester.run('eslint consistent-stories', consistentStories, {
|
||||
valid: [
|
||||
{
|
||||
name: 'simple title',
|
||||
code: `export default { title: 'Button' };`,
|
||||
filename: 'Button.story.tsx',
|
||||
},
|
||||
{
|
||||
name: 'one section',
|
||||
code: `export default { title: 'Components/Button' };`,
|
||||
filename: 'Button.story.tsx',
|
||||
},
|
||||
{
|
||||
name: 'deprecated can have 3 sections',
|
||||
code: `export default { title: 'Components/Deprecated/Button' };`,
|
||||
filename: 'Button.story.tsx',
|
||||
},
|
||||
{
|
||||
name: 'not a story file',
|
||||
code: `export default { title: 'Components/Forms/Button/Extra/Section' };`,
|
||||
filename: 'Button.tsx',
|
||||
},
|
||||
{
|
||||
name: 'non-string title',
|
||||
code: `export default { title: 123 };`,
|
||||
filename: 'Button.story.tsx',
|
||||
},
|
||||
{
|
||||
name: 'no title property',
|
||||
code: `export default { component: Button };`,
|
||||
filename: 'Button.story.tsx',
|
||||
},
|
||||
{
|
||||
name: 'variable assignment - simple title',
|
||||
code: `
|
||||
const storyConfig = { title: 'Button' };
|
||||
export default storyConfig;`,
|
||||
filename: 'Button.story.tsx',
|
||||
},
|
||||
{
|
||||
name: 'variable assignment - one section',
|
||||
code: `
|
||||
const storyConfig = { title: 'Components/Button' };
|
||||
export default storyConfig;`,
|
||||
filename: 'Button.story.tsx',
|
||||
},
|
||||
{
|
||||
name: 'variable assignment - with Deprecated',
|
||||
code: `
|
||||
const storyConfig = { title: 'Components/Deprecated/Button' };
|
||||
export default storyConfig;`,
|
||||
filename: 'Button.story.tsx',
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
name: 'too many sections without Deprecated',
|
||||
code: `export default { title: 'Components/Forms/Button' };`,
|
||||
filename: 'Button.story.tsx',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'invalidTitle',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'too many sections without Deprecated',
|
||||
code: `export default { title: 'Components/Forms/Button/Extra' };`,
|
||||
filename: 'Button.story.tsx',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'invalidTitle',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'with spaces around sections',
|
||||
code: `export default { title: 'Components / Forms / Button' };`,
|
||||
filename: 'Button.story.tsx',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'invalidTitle',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'variable assignment - too many sections',
|
||||
code: `
|
||||
const storyConfig = { title: 'Components/Forms/Button' };
|
||||
export default storyConfig;`,
|
||||
filename: 'Button.story.tsx',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'invalidTitle',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -2,13 +2,7 @@ import path, { dirname, join } from 'node:path';
|
|||
import type { StorybookConfig } from '@storybook/react-webpack5';
|
||||
import { copyAssetsSync } from './copyAssets';
|
||||
|
||||
// Internal stories should only be visible during development
|
||||
const coreComponentsGlobs: StorybookConfig['stories'] = [
|
||||
'../src/Intro.mdx',
|
||||
process.env.NODE_ENV === 'production'
|
||||
? '../src/components/**/!(*.internal).story.tsx'
|
||||
: '../src/components/**/*.story.tsx',
|
||||
];
|
||||
const coreComponentsGlobs: StorybookConfig['stories'] = ['../src/Intro.mdx', '../src/**/*.story.tsx'];
|
||||
|
||||
const alertingComponentsGlobs: StorybookConfig['stories'] = [
|
||||
{
|
||||
|
|
|
@ -71,20 +71,84 @@ const preview: Preview = {
|
|||
// Sort stories first by Docs Overview, then alphabetically
|
||||
// We should be able to use the builtin alphabetical sort, but is broken in SB 7.0
|
||||
// https://github.com/storybookjs/storybook/issues/22470
|
||||
|
||||
// Story sorting is weird - All stories are sorted as a single 1D list, but then grouped in the UI.
|
||||
// Story titles are generally in the format of [Category]/[Component]/[Story]. However, some categories
|
||||
// will have an additional `Deprecated` sub folder before the [Component]
|
||||
//
|
||||
// We want to have multi-level sorting where:
|
||||
// - The top level category has an explicit order
|
||||
// - Components are sorted alphabetically within their category
|
||||
// - Except the Deprecated folder, which is sorted to the bottom
|
||||
// - Stories per component use the default file sort order
|
||||
storySort: (a, b) => {
|
||||
// Skip sorting for stories with nosort tag
|
||||
if (a.tags.includes('nosort') || b.tags.includes('nosort')) {
|
||||
return 0;
|
||||
const CATEGORY_ORDER = [
|
||||
// Should all be lowercase
|
||||
'docs overview',
|
||||
'foundations',
|
||||
'iconography',
|
||||
'layout',
|
||||
|
||||
'forms',
|
||||
'inputs',
|
||||
'pickers',
|
||||
'date time pickers',
|
||||
|
||||
'information',
|
||||
'overlays',
|
||||
'utilities',
|
||||
'navigation',
|
||||
|
||||
'plugins',
|
||||
'alerting',
|
||||
'developers',
|
||||
];
|
||||
|
||||
const aTitle = a.title.toLowerCase();
|
||||
const bTitle = b.title.toLowerCase();
|
||||
const [aCategory, aComponent] = aTitle.split('/');
|
||||
const [bCategory, bComponent] = bTitle.split('/');
|
||||
|
||||
//
|
||||
// Sort by category order first
|
||||
const aCategoryIndex = CATEGORY_ORDER.indexOf(aCategory);
|
||||
const bCategoryIndex = CATEGORY_ORDER.indexOf(bCategory);
|
||||
|
||||
if (aCategoryIndex === -1 || bCategoryIndex === -1) {
|
||||
const category = aCategoryIndex === -1 ? aCategory : bCategory;
|
||||
throw new Error(
|
||||
`Category ${category} not found in CATEGORY_ORDER. Prefer reusing the existing categories, or add to CATEGORY_ORDER.`
|
||||
);
|
||||
}
|
||||
if (a.title.startsWith('Docs Overview')) {
|
||||
if (b.title.startsWith('Docs Overview')) {
|
||||
return 0;
|
||||
|
||||
if (aCategoryIndex !== bCategoryIndex) {
|
||||
return aCategoryIndex - bCategoryIndex;
|
||||
}
|
||||
|
||||
//
|
||||
// Sort 'Deprecated' subfolders to the bottom
|
||||
if (aTitle.includes('deprecated') && !bTitle.includes('deprecated')) {
|
||||
return 1;
|
||||
} else if (bTitle.includes('deprecated') && !aTitle.includes('deprecated')) {
|
||||
return -1;
|
||||
} else if (b.title.startsWith('Docs Overview')) {
|
||||
}
|
||||
|
||||
//
|
||||
// Sort Docs to the top
|
||||
if (a.type === 'docs' && b.type !== 'docs') {
|
||||
return -1;
|
||||
} else if (a.type !== 'docs' && b.type === 'docs') {
|
||||
return 1;
|
||||
}
|
||||
return a.id === b.id ? 0 : a.id.localeCompare(b.id, undefined, { numeric: true });
|
||||
|
||||
//
|
||||
// If sorting different components, sort alphabetically
|
||||
if (aComponent !== bComponent) {
|
||||
return aComponent.localeCompare(bComponent, undefined, { numeric: true });
|
||||
}
|
||||
|
||||
// Otherwise, sort stories within componmments according to source order
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ import mdx from './Alert.mdx';
|
|||
const severities: AlertVariant[] = ['error', 'warning', 'info', 'success'];
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Overlays/Alert/InlineBanner',
|
||||
title: 'Information/Alert',
|
||||
component: Alert,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
@ -78,4 +78,15 @@ export const Examples: StoryFn<typeof Alert> = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export const Toast: StoryFn<typeof Alert> = (args) => {
|
||||
return <Alert {...args}>To use as a toast, set the elevated and onRemove props.</Alert>;
|
||||
};
|
||||
|
||||
Toast.args = {
|
||||
title: 'Toast',
|
||||
severity: 'error',
|
||||
onRemove: action('Remove button clicked'),
|
||||
elevated: true,
|
||||
};
|
||||
|
||||
export default meta;
|
|
@ -1,126 +0,0 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { StoryFn, Meta } from '@storybook/react';
|
||||
|
||||
import { StoryExample } from '../../utils/storybook/StoryExample';
|
||||
import { Stack } from '../Layout/Stack/Stack';
|
||||
|
||||
import { Alert, AlertVariant } from './Alert';
|
||||
import mdx from './Alert.mdx';
|
||||
|
||||
const severities: AlertVariant[] = ['error', 'warning', 'info', 'success'];
|
||||
|
||||
const meta: Meta<typeof Alert> = {
|
||||
title: 'Overlays/Alert/Toast',
|
||||
component: Alert,
|
||||
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 Basic: StoryFn<typeof Alert> = (args) => {
|
||||
return (
|
||||
<Alert {...args} elevated>
|
||||
Child content that includes some alert details, like maybe what actually happened.
|
||||
</Alert>
|
||||
);
|
||||
};
|
||||
|
||||
export function Examples() {
|
||||
return (
|
||||
<Stack direction="column">
|
||||
<StoryExample name="Severities">
|
||||
<Stack direction="column">
|
||||
{severities.map((severity) => (
|
||||
<Alert
|
||||
title={`Severity: ${severity}`}
|
||||
severity={severity}
|
||||
key={severity}
|
||||
onRemove={action('Remove button clicked')}
|
||||
elevated={true}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</StoryExample>
|
||||
<StoryExample name="With huge payload">
|
||||
<Alert title="Alert with huge payload" severity="error" elevated={true}>
|
||||
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,
|
||||
</Alert>
|
||||
</StoryExample>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default meta;
|
|
@ -12,7 +12,7 @@ import { AutoSaveField } from './AutoSaveField';
|
|||
import mdx from './AutoSaveField.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Forms/AutoSaveField',
|
||||
title: 'Inputs/AutoSaveField',
|
||||
component: AutoSaveField,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Badge } from './Badge';
|
|||
import mdx from './Badge.mdx';
|
||||
|
||||
const meta: Meta<typeof Badge> = {
|
||||
title: 'Data Display/Badge',
|
||||
title: 'Information/Badge',
|
||||
component: Badge,
|
||||
parameters: {
|
||||
docs: { page: mdx },
|
||||
|
|
|
@ -9,7 +9,7 @@ import { BarGauge, Props } from './BarGauge';
|
|||
import mdx from './BarGauge.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Visualizations/BarGauge',
|
||||
title: 'Plugins/BarGauge',
|
||||
component: BarGauge,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
import mdx from './BigValue.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Visualizations/BigValue',
|
||||
title: 'Plugins/BigValue',
|
||||
component: BigValue,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -12,7 +12,7 @@ import { ButtonGroup } from './ButtonGroup';
|
|||
const sizes: ComponentSize[] = ['lg', 'md', 'sm'];
|
||||
|
||||
export default {
|
||||
title: 'Buttons/Button',
|
||||
title: 'Inputs/Button',
|
||||
component: Button,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { StoryFn, Meta } from '@storybook/react';
|
|||
import { ButtonCascader } from './ButtonCascader';
|
||||
|
||||
const meta: Meta<typeof ButtonCascader> = {
|
||||
title: 'Forms/Cascader/ButtonCascader',
|
||||
title: 'Inputs/ButtonCascader',
|
||||
component: ButtonCascader,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Button } from '../Button/Button';
|
|||
import { CallToActionCard, CallToActionCardProps } from './CallToActionCard';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Layout/CallToActionCard',
|
||||
title: 'Information/Deprecated/CallToActionCard',
|
||||
component: CallToActionCard,
|
||||
parameters: {
|
||||
controls: {
|
|
@ -11,6 +11,7 @@ export interface CallToActionCardProps {
|
|||
className?: string;
|
||||
}
|
||||
|
||||
/** @deprecated Use <EmptyState variant="call-to-action" /> instead */
|
||||
export const CallToActionCard = ({ message, callToActionElement, footer, className }: CallToActionCardProps) => {
|
||||
const css = useStyles2(getStyles);
|
||||
|
||||
|
|
|
@ -9,10 +9,9 @@ import { Card } from './Card';
|
|||
const logo = 'https://grafana.com/static/assets/img/apple-touch-icon.png';
|
||||
|
||||
const meta: Meta<typeof Card> = {
|
||||
title: 'General/Card',
|
||||
title: 'Layout/Card',
|
||||
component: Card,
|
||||
// nosort is a custom tag used so the stories shown in docs keep the order they are defined in the file
|
||||
tags: ['autodocs', 'nosort'],
|
||||
tags: ['autodocs'],
|
||||
parameters: {
|
||||
controls: {
|
||||
exclude: ['onClick', 'href', 'heading', 'description', 'className', 'noMargin'],
|
||||
|
|
|
@ -15,7 +15,7 @@ const sampleImages = [
|
|||
];
|
||||
|
||||
const meta: Meta<typeof Carousel> = {
|
||||
title: 'Data Display/Carousel',
|
||||
title: 'Overlays/Carousel',
|
||||
component: Carousel,
|
||||
parameters: {
|
||||
docs: { page: mdx },
|
||||
|
|
|
@ -31,7 +31,7 @@ const options = [
|
|||
];
|
||||
|
||||
const meta: Meta<typeof Cascader> = {
|
||||
title: 'Forms/Cascader',
|
||||
title: 'Inputs/Cascader',
|
||||
component: Cascader,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { ClickOutsideWrapper } from './ClickOutsideWrapper';
|
|||
import mdx from './ClickOutsideWrapper.mdx';
|
||||
|
||||
const meta: Meta<typeof ClickOutsideWrapper> = {
|
||||
title: 'Layout/ClickOutsideWrapper',
|
||||
title: 'Utilities/ClickOutsideWrapper',
|
||||
component: ClickOutsideWrapper,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { ClipboardButton as ClipboardButtonImpl, Props } from './ClipboardButton
|
|||
import mdx from './ClipboardButton.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Buttons/ClipboardButton',
|
||||
title: 'Inputs/ClipboardButton',
|
||||
component: ClipboardButtonImpl,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -5,12 +5,11 @@ import { Meta, StoryFn } from '@storybook/react';
|
|||
import { useStyles2 } from '../../themes/ThemeContext';
|
||||
import { clearButtonStyles } from '../Button/Button';
|
||||
|
||||
import { ColorPicker, SeriesColorPicker } from './ColorPicker';
|
||||
import { ColorPicker } from './ColorPicker';
|
||||
import mdx from './ColorPicker.mdx';
|
||||
import { ColorPickerInput } from './ColorPickerInput';
|
||||
|
||||
const meta: Meta<typeof ColorPicker> = {
|
||||
title: 'Pickers and Editors/ColorPicker',
|
||||
title: 'Pickers/ColorPicker',
|
||||
component: ColorPicker,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
@ -43,24 +42,6 @@ export const Basic: StoryFn<typeof ColorPicker> = ({ color, enableNamedColors })
|
|||
);
|
||||
};
|
||||
|
||||
export const SeriesPicker: StoryFn<typeof SeriesColorPicker> = ({ color, enableNamedColors }) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'flex-start' }}>
|
||||
<SeriesColorPicker
|
||||
enableNamedColors={enableNamedColors}
|
||||
yaxis={1}
|
||||
onToggleAxis={() => {}}
|
||||
color={color}
|
||||
onChange={(color) => {
|
||||
action('Color changed')(color);
|
||||
updateArgs({ color });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const CustomTrigger: StoryFn<typeof ColorPicker> = ({ color, enableNamedColors }) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
const clearButton = useStyles2(clearButtonStyles);
|
||||
|
@ -89,19 +70,4 @@ export const CustomTrigger: StoryFn<typeof ColorPicker> = ({ color, enableNamedC
|
|||
);
|
||||
};
|
||||
|
||||
export const Input: StoryFn<typeof ColorPickerInput> = ({ color }) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
return (
|
||||
<div style={{ minHeight: '100dvh', display: 'grid', placeContent: 'center' }}>
|
||||
<ColorPickerInput
|
||||
value={color}
|
||||
onChange={(color) => {
|
||||
action('Color changed')(color);
|
||||
updateArgs({ color });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { useArgs } from '@storybook/preview-api';
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
|
||||
import { ColorPickerInput } from './ColorPickerInput';
|
||||
|
||||
const meta: Meta<typeof ColorPickerInput> = {
|
||||
title: 'Pickers/ColorPickerInput',
|
||||
component: ColorPickerInput,
|
||||
parameters: {
|
||||
controls: {
|
||||
exclude: ['onChange', 'onColorChange'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Basic: StoryFn<typeof ColorPickerInput> = ({ color }) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
return (
|
||||
<div style={{ minHeight: '100dvh', display: 'grid', placeContent: 'center' }}>
|
||||
<ColorPickerInput
|
||||
value={color}
|
||||
onChange={(color) => {
|
||||
action('Color changed')(color);
|
||||
updateArgs({ color });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default meta;
|
|
@ -1,52 +0,0 @@
|
|||
import { Meta } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useTheme2 } from '../../themes/ThemeContext';
|
||||
|
||||
import mdx from './ColorPicker.mdx';
|
||||
import { ColorPickerPopover } from './ColorPickerPopover';
|
||||
import { SeriesColorPickerPopover } from './SeriesColorPickerPopover';
|
||||
|
||||
const meta: Meta<typeof ColorPickerPopover> = {
|
||||
title: 'Pickers and Editors/ColorPicker/Popovers',
|
||||
component: ColorPickerPopover,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Basic = () => {
|
||||
return (
|
||||
<div style={{ position: 'absolute' }}>
|
||||
<ColorPickerPopover
|
||||
color="#BC67E6"
|
||||
onChange={(color: string) => {
|
||||
console.log(color);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const SeriesColorPickerPopoverExample = () => {
|
||||
const theme = useTheme2();
|
||||
const [yAxis, setYAxis] = useState(0);
|
||||
|
||||
return (
|
||||
<div style={{ position: 'absolute' }}>
|
||||
<SeriesColorPickerPopover
|
||||
theme={theme}
|
||||
yaxis={yAxis}
|
||||
onToggleAxis={() => (yAxis ? setYAxis(0) : setYAxis(2))}
|
||||
color="#BC67E6"
|
||||
onChange={(color: string) => {
|
||||
console.log(color);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default meta;
|
|
@ -1,43 +0,0 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { useArgs } from '@storybook/preview-api';
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import mdx from './ColorPicker.mdx';
|
||||
import { NamedColorsPalette } from './NamedColorsPalette';
|
||||
import SpectrumPalette from './SpectrumPalette';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Pickers and Editors/ColorPicker/Palettes',
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
controls: {
|
||||
exclude: ['theme', 'color'],
|
||||
},
|
||||
},
|
||||
args: {
|
||||
color: 'green',
|
||||
},
|
||||
};
|
||||
|
||||
export const NamedColors: StoryFn<typeof NamedColorsPalette> = ({ color }) => {
|
||||
const [colorVal, setColor] = useState(color);
|
||||
return <NamedColorsPalette color={colorVal} onChange={setColor} />;
|
||||
};
|
||||
|
||||
export const Spectrum: StoryFn<typeof SpectrumPalette> = ({ color }) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
return (
|
||||
<SpectrumPalette
|
||||
color={color}
|
||||
onChange={(color: string) => {
|
||||
action('Color changed')(color);
|
||||
updateArgs({ color });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default meta;
|
|
@ -0,0 +1,39 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { useArgs } from '@storybook/preview-api';
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
|
||||
import { SeriesColorPicker } from './ColorPicker';
|
||||
|
||||
const meta: Meta<typeof SeriesColorPicker> = {
|
||||
title: 'Pickers/SeriesColorPicker',
|
||||
component: SeriesColorPicker,
|
||||
parameters: {
|
||||
controls: {
|
||||
exclude: ['onChange', 'onColorChange'],
|
||||
},
|
||||
},
|
||||
args: {
|
||||
enableNamedColors: false,
|
||||
color: '#00ff00',
|
||||
},
|
||||
};
|
||||
|
||||
export const Basic: StoryFn<typeof SeriesColorPicker> = ({ color, enableNamedColors }) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'flex-start' }}>
|
||||
<SeriesColorPicker
|
||||
enableNamedColors={enableNamedColors}
|
||||
yaxis={1}
|
||||
onToggleAxis={() => {}}
|
||||
color={color}
|
||||
onChange={(color) => {
|
||||
action('Color changed')(color);
|
||||
updateArgs({ color });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default meta;
|
|
@ -16,7 +16,7 @@ type PropsAndCustomArgs<T extends string | number = string> = ComboboxProps<T> &
|
|||
type Story<T extends string | number = string> = StoryObj<PropsAndCustomArgs<T>>;
|
||||
|
||||
const meta: Meta<PropsAndCustomArgs> = {
|
||||
title: 'Forms/Combobox',
|
||||
title: 'Inputs/Combobox',
|
||||
component: Combobox,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -11,7 +11,7 @@ import { generateOptions, fakeSearchAPI, generateGroupingOptions } from './story
|
|||
import { ComboboxOption } from './types';
|
||||
|
||||
const meta: Meta<typeof MultiCombobox> = {
|
||||
title: 'Forms/MultiCombobox',
|
||||
title: 'Inputs/MultiCombobox',
|
||||
component: MultiCombobox,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -8,7 +8,7 @@ import mdx from './ConfirmButton.mdx';
|
|||
import { DeleteButton } from './DeleteButton';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Buttons/ConfirmButton',
|
||||
title: 'Inputs/ConfirmButton',
|
||||
component: ConfirmButton,
|
||||
// SB7 has broken subcomponent types due to dropping support for the feature
|
||||
// https://github.com/storybookjs/storybook/issues/20782
|
||||
|
|
|
@ -6,6 +6,8 @@ import { WithContextMenu } from './WithContextMenu';
|
|||
|
||||
A menu displaying additional options when it's not possible to show them at all times due to a space constraint.
|
||||
|
||||
`ContextMenu` wraps `Menu` to supply options as a list, and display at absolute coordinates.
|
||||
|
||||
### Usage
|
||||
|
||||
There are controlled and uncontrolled versions of the component available. With the controlled component (`ContextMenu`) the open/close logic needs to be handled separately. Uncontrolled component (`WithContextMenu`) handles this logic internally.
|
||||
|
|
|
@ -10,7 +10,7 @@ import { renderMenuItems } from './ContextMenuStoryHelper';
|
|||
import { WithContextMenu, WithContextMenuProps } from './WithContextMenu';
|
||||
|
||||
const meta: Meta<typeof ContextMenu> = {
|
||||
title: 'General/ContextMenu',
|
||||
title: 'Overlays/ContextMenu',
|
||||
component: ContextMenu,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -36,7 +36,7 @@ const settingsMock: HttpSettingsProps['dataSourceConfig'] = {
|
|||
};
|
||||
|
||||
const meta: Meta<typeof DataSourceHttpSettings> = {
|
||||
title: 'Data Source/DataSourceHttpSettings',
|
||||
title: 'Plugins/DataSourceHttpSettings',
|
||||
component: DataSourceHttpSettings,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { DatePicker, DatePickerProps } from './DatePicker';
|
|||
import mdx from './DatePicker.mdx';
|
||||
|
||||
const meta: Meta<typeof DatePicker> = {
|
||||
title: 'Pickers and Editors/TimePickers/Pickers And Editors/DatePicker',
|
||||
title: 'Date time pickers/DatePicker',
|
||||
component: DatePicker,
|
||||
argTypes: {
|
||||
minDate: { control: 'date' },
|
||||
|
|
|
@ -13,7 +13,7 @@ const minimumDate = new Date();
|
|||
minimumDate.setMonth(minimumDate.getMonth() - 1);
|
||||
|
||||
const meta: Meta<typeof DatePickerWithInput> = {
|
||||
title: 'Pickers and Editors/TimePickers/DatePickerWithInput',
|
||||
title: 'Date time pickers/DatePickerWithInput',
|
||||
component: DatePickerWithInput,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -15,7 +15,7 @@ const minimumDate = new Date();
|
|||
minimumDate.setDate(minimumDate.getDate() - 7);
|
||||
|
||||
const meta: Meta<typeof DateTimePicker> = {
|
||||
title: 'Pickers and Editors/TimePickers/DateTimePicker',
|
||||
title: 'Date time pickers/DateTimePicker',
|
||||
component: DateTimePicker,
|
||||
argTypes: {
|
||||
date: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Meta, StoryFn } from '@storybook/react';
|
|||
import { RelativeTimeRangePicker } from './RelativeTimeRangePicker';
|
||||
|
||||
const meta: Meta<typeof RelativeTimeRangePicker> = {
|
||||
title: 'Pickers and Editors/TimePickers/RelativeTimeRangePicker',
|
||||
title: 'Date time pickers/RelativeTimeRangePicker',
|
||||
component: RelativeTimeRangePicker,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { dateTime } from '@grafana/data';
|
|||
import { TimeOfDayPicker } from './TimeOfDayPicker';
|
||||
|
||||
const meta: Meta<typeof TimeOfDayPicker> = {
|
||||
title: 'Pickers and Editors/TimePickers/TimeOfDayPicker',
|
||||
title: 'Date time pickers/TimeOfDayPicker',
|
||||
component: TimeOfDayPicker,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -30,7 +30,7 @@ const nullRange = {
|
|||
};
|
||||
|
||||
const meta: Meta<typeof TimeRangeInput> = {
|
||||
title: 'Pickers and Editors/TimePickers/TimeRangeInput',
|
||||
title: 'Date time pickers/TimeRangeInput',
|
||||
component: TimeRangeInput,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -10,7 +10,7 @@ const to = dateTime();
|
|||
const from = to.subtract(6, 'h');
|
||||
|
||||
const meta: Meta<typeof TimeRangePicker> = {
|
||||
title: 'Pickers and Editors/TimePickers/TimeRangePicker',
|
||||
title: 'Date time pickers/TimeRangePicker',
|
||||
component: TimeRangePicker,
|
||||
args: {
|
||||
value: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Meta, StoryFn } from '@storybook/react';
|
|||
import { TimeZonePicker } from './TimeZonePicker';
|
||||
|
||||
const meta: Meta<typeof TimeZonePicker> = {
|
||||
title: 'Pickers and Editors/TimePickers/TimeZonePicker',
|
||||
title: 'Date time pickers/TimeZonePicker',
|
||||
component: TimeZonePicker,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Meta, StoryFn } from '@storybook/react';
|
|||
import { WeekStartPicker } from './WeekStartPicker';
|
||||
|
||||
const meta: Meta<typeof WeekStartPicker> = {
|
||||
title: 'Pickers and Editors/TimePickers/WeekStartPicker',
|
||||
title: 'Date time pickers/WeekStartPicker',
|
||||
component: WeekStartPicker,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Divider } from './Divider';
|
|||
import mdx from './Divider.mdx';
|
||||
|
||||
const meta: Meta<typeof Divider> = {
|
||||
title: 'General/Divider',
|
||||
title: 'Layout/Divider',
|
||||
component: Divider,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Meta, StoryFn } from '@storybook/react';
|
|||
import { ButtonSelect } from './ButtonSelect';
|
||||
|
||||
const meta: Meta<typeof ButtonSelect> = {
|
||||
title: 'Forms/Select/ButtonSelect',
|
||||
title: 'Inputs/Deprecated/ButtonSelect',
|
||||
component: ButtonSelect,
|
||||
parameters: {
|
||||
controls: {
|
|
@ -33,8 +33,7 @@ export interface Props<T> extends HTMLAttributes<HTMLButtonElement> {
|
|||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* A temporary component until we have a proper dropdown component
|
||||
* @deprecated Use Combobox or Dropdown instead
|
||||
*/
|
||||
const ButtonSelectComponent = <T,>(props: Props<T>) => {
|
||||
const { className, options, value, onChange, narrow, variant, ...restProps } = props;
|
||||
|
|
|
@ -4,7 +4,7 @@ import { EmptySearchResult } from './EmptySearchResult';
|
|||
import mdx from './EmptySearchResult.mdx';
|
||||
|
||||
const meta: Meta<typeof EmptySearchResult> = {
|
||||
title: 'Visualizations/EmptySearchResult',
|
||||
title: 'Information/Deprecated/EmptySearchResult',
|
||||
component: EmptySearchResult,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -8,6 +8,7 @@ export interface Props {
|
|||
children: JSX.Element | string;
|
||||
}
|
||||
|
||||
/** @deprecated Use <EmptyState variant="not-found" /> instead */
|
||||
const EmptySearchResult = ({ children }: Props) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
return <div className={styles.container}>{children}</div>;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { EmptyState } from './EmptyState';
|
|||
import mdx from './EmptyState.mdx';
|
||||
|
||||
const meta: Meta<typeof EmptyState> = {
|
||||
title: 'General/EmptyState',
|
||||
title: 'Information/EmptyState',
|
||||
component: EmptyState,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -9,7 +9,7 @@ import mdx from './ErrorBoundary.mdx';
|
|||
import { ErrorWithStack } from './ErrorWithStack';
|
||||
|
||||
const meta: Meta<typeof ErrorBoundary> = {
|
||||
title: 'General/ErrorBoundary',
|
||||
title: 'Utilities/ErrorBoundary',
|
||||
component: ErrorBoundary,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { FeatureBadge } from './FeatureBadge';
|
|||
import mdx from './FeatureBadge.mdx';
|
||||
|
||||
const meta: Meta<typeof FeatureBadge> = {
|
||||
title: 'Data Display/FeatureBadge',
|
||||
title: 'Information/FeatureBadge',
|
||||
component: FeatureBadge,
|
||||
parameters: {
|
||||
docs: { page: mdx },
|
||||
|
|
|
@ -4,7 +4,7 @@ import { FileDropzone } from './FileDropzone';
|
|||
import mdx from './FileDropzone.mdx';
|
||||
|
||||
const meta: Meta<typeof FileDropzone> = {
|
||||
title: 'Forms/FileDropzone',
|
||||
title: 'Inputs/FileDropzone',
|
||||
component: FileDropzone,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { FileListItem as FileListItemComponent, FileListItemProps } from './File
|
|||
import mdx from './FileListItem.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Forms/FileListItem',
|
||||
title: 'Inputs/FileListItem',
|
||||
component: FileListItemComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { FileUpload } from './FileUpload';
|
|||
import mdx from './FileUpload.mdx';
|
||||
|
||||
const meta: Meta<typeof FileUpload> = {
|
||||
title: 'Forms/FileUpload',
|
||||
title: 'Inputs/FileUpload',
|
||||
component: FileUpload,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { FilterPill } from './FilterPill';
|
|||
import mdx from './FilterPill.mdx';
|
||||
|
||||
const meta: Meta<typeof FilterPill> = {
|
||||
title: 'General/FilterPill',
|
||||
title: 'Inputs/FilterPill',
|
||||
component: FilterPill,
|
||||
argTypes: {
|
||||
icon: { control: { type: 'select', options: getAvailableIcons() } },
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Meta, StoryFn } from '@storybook/react';
|
|||
import { FormField } from './FormField';
|
||||
|
||||
const meta: Meta<typeof FormField> = {
|
||||
title: 'Forms/Legacy/FormField',
|
||||
title: 'Forms/Deprecated/FormField',
|
||||
component: FormField,
|
||||
parameters: {
|
||||
controls: {
|
|
@ -4,7 +4,7 @@ import { FormattedValueDisplay } from './FormattedValueDisplay';
|
|||
import mdx from './FormattedValueDisplay.mdx';
|
||||
|
||||
const meta: Meta<typeof FormattedValueDisplay> = {
|
||||
title: 'Visualizations/FormattedValueDisplay',
|
||||
title: 'Plugins/FormattedValueDisplay',
|
||||
component: FormattedValueDisplay,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -9,7 +9,7 @@ import mdx from './Checkbox.mdx';
|
|||
import { Field } from './Field';
|
||||
|
||||
const meta: Meta<typeof Checkbox> = {
|
||||
title: 'Forms/Checkbox',
|
||||
title: 'Inputs/Checkbox',
|
||||
component: Checkbox,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { zip, fromPairs } from 'lodash';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { EventsWithValidation } from '../../../../utils/validate';
|
||||
|
||||
import { Input } from './Input';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Forms/Legacy/Input',
|
||||
component: Input,
|
||||
parameters: {
|
||||
controls: {
|
||||
exclude: ['inputRef', 'onBlur', 'onFocus', 'onChange'],
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
validationEvents: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: fromPairs(zip(Object.keys(EventsWithValidation), Object.values(EventsWithValidation))),
|
||||
},
|
||||
},
|
||||
validation: { name: 'Validation regex (will do a partial match if you do not anchor it)' },
|
||||
},
|
||||
};
|
||||
|
||||
const Wrapper: StoryFn = (args) => {
|
||||
const [value, setValue] = useState('');
|
||||
const validations = {
|
||||
[args.validationEvents]: [
|
||||
{
|
||||
rule: (value: string) => {
|
||||
return !!value.match(args.validation);
|
||||
},
|
||||
errorMessage: args.validationErrorMessage,
|
||||
},
|
||||
],
|
||||
};
|
||||
return (
|
||||
<Input
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.currentTarget.value)}
|
||||
validationEvents={validations}
|
||||
hideErrorMessage={args.hideErrorMessage}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Basic = Wrapper.bind({});
|
||||
Basic.args = {
|
||||
validation: '',
|
||||
validationErrorMessage: 'Input not valid',
|
||||
validationEvents: EventsWithValidation.onBlur,
|
||||
hideErrorMessage: false,
|
||||
};
|
||||
|
||||
export default meta;
|
|
@ -1,113 +0,0 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { useArgs } from '@storybook/preview-api';
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
|
||||
import { Select, AsyncSelect as AsyncSelectComponent } from './Select';
|
||||
|
||||
const meta: Meta<typeof Select> = {
|
||||
title: 'Forms/Legacy/Select',
|
||||
component: Select,
|
||||
parameters: {
|
||||
controls: {
|
||||
exclude: [
|
||||
'className',
|
||||
'menuPlacement',
|
||||
'menuPosition',
|
||||
'maxMenuHeight',
|
||||
'minMenuHeight',
|
||||
'maxVisibleValues',
|
||||
'prefix',
|
||||
'renderControl',
|
||||
'value',
|
||||
'tooltipContent',
|
||||
'components',
|
||||
'inputValue',
|
||||
'id',
|
||||
'inputId',
|
||||
'defaultValue',
|
||||
'aria-label',
|
||||
'noOptionsMessage',
|
||||
'onChange',
|
||||
'onBlur',
|
||||
'onKeyDown',
|
||||
'filterOption',
|
||||
'formatCreateLabel',
|
||||
'getOptionLabel',
|
||||
'getOptionValue',
|
||||
'onCloseMenu',
|
||||
'onCreateOption',
|
||||
'onInputChange',
|
||||
'onOpenMenu',
|
||||
'isOptionDisabled',
|
||||
],
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
width: { control: { type: 'range', min: 5, max: 30 } },
|
||||
},
|
||||
};
|
||||
|
||||
const initialValue: SelectableValue<string> = { label: 'A label', value: 'A value' };
|
||||
|
||||
const options = [
|
||||
initialValue,
|
||||
{ label: 'Another label', value: 'Another value 1' },
|
||||
{ label: 'Another label', value: 'Another value 2' },
|
||||
{ label: 'Another label', value: 'Another value 3' },
|
||||
{ label: 'Another label', value: 'Another value 4' },
|
||||
{ label: 'Another label', value: 'Another value 5' },
|
||||
{ label: 'Another label', value: 'Another value ' },
|
||||
];
|
||||
|
||||
export const Basic: StoryFn<typeof Select> = (args) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
return (
|
||||
<Select
|
||||
{...args}
|
||||
onChange={(value) => {
|
||||
action('onChange fired')(value);
|
||||
updateArgs({ value });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
Basic.args = {
|
||||
placeholder: 'Choose...',
|
||||
options: options,
|
||||
width: 20,
|
||||
};
|
||||
|
||||
export const AsyncSelect: StoryFn<typeof AsyncSelectComponent> = (args) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
const loadAsyncOptions = useCallback(
|
||||
(inputValue: string) => {
|
||||
return new Promise<Array<SelectableValue<string>>>((resolve) => {
|
||||
setTimeout(() => {
|
||||
updateArgs({ isLoading: false });
|
||||
resolve(options.filter((option) => option.label && option.label.includes(inputValue)));
|
||||
}, 1000);
|
||||
});
|
||||
},
|
||||
[updateArgs]
|
||||
);
|
||||
return (
|
||||
<AsyncSelectComponent
|
||||
{...args}
|
||||
loadOptions={loadAsyncOptions}
|
||||
onChange={(value) => {
|
||||
action('onChange')(value);
|
||||
updateArgs({ value });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
AsyncSelect.args = {
|
||||
isLoading: true,
|
||||
defaultOptions: true,
|
||||
width: 20,
|
||||
};
|
||||
|
||||
export default meta;
|
|
@ -1,27 +0,0 @@
|
|||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { Switch } from './Switch';
|
||||
|
||||
const meta: Meta<typeof Switch> = {
|
||||
title: 'Forms/Legacy/Switch',
|
||||
component: Switch,
|
||||
parameters: {
|
||||
controls: {
|
||||
exclude: ['className', 'labelClass', 'switchClass', 'onChange'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const SwitchWrapper: StoryFn<typeof Switch> = ({ label, ...args }) => {
|
||||
const [checked, setChecked] = useState(false);
|
||||
return <Switch {...args} label={label} checked={checked} onChange={() => setChecked(!checked)} />;
|
||||
};
|
||||
|
||||
export const Basic = SwitchWrapper.bind({});
|
||||
Basic.args = {
|
||||
label: 'Label',
|
||||
tooltip: '',
|
||||
};
|
||||
|
||||
export default meta;
|
|
@ -5,7 +5,7 @@ import { RadioButtonGroup } from './RadioButtonGroup';
|
|||
import mdx from './RadioButtonGroup.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Forms/RadioButtonGroup',
|
||||
title: 'Inputs/RadioButtonGroup',
|
||||
component: RadioButtonGroup,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -17,7 +17,7 @@ const defaultOptions: Array<SelectableValue<string>> = [
|
|||
];
|
||||
|
||||
const meta: Meta<typeof RadioButtonList> = {
|
||||
title: 'Forms/RadioButtonList',
|
||||
title: 'Inputs/RadioButtonList',
|
||||
component: RadioButtonList,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -13,7 +13,7 @@ import { Icon } from './Icon';
|
|||
import mdx from './Icon.mdx';
|
||||
|
||||
const meta: Meta<typeof Icon> = {
|
||||
title: 'Docs overview/Icon',
|
||||
title: 'Iconography/Icon',
|
||||
component: Icon,
|
||||
parameters: {
|
||||
options: {
|
||||
|
|
|
@ -16,7 +16,7 @@ const defaultExcludes = ['ariaLabel', 'aria-label'];
|
|||
const additionalExcludes = ['size', 'name', 'variant', 'iconType'];
|
||||
|
||||
const meta: Meta<typeof IconButton> = {
|
||||
title: 'Buttons/IconButton',
|
||||
title: 'Inputs/IconButton',
|
||||
component: IconButton,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { InfoBox } from './InfoBox';
|
|||
import mdx from './InfoBox.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Layout/InfoBox',
|
||||
title: 'Information/Deprecated/InfoBox',
|
||||
component: InfoBox,
|
||||
decorators: [],
|
||||
parameters: {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Meta, StoryFn } from '@storybook/react';
|
|||
import { InfoTooltip } from './InfoTooltip';
|
||||
|
||||
const meta: Meta<typeof InfoTooltip> = {
|
||||
title: 'Overlays/TooltipInternal',
|
||||
title: 'Overlays/Deprecated/InfoTooltip',
|
||||
component: InfoTooltip,
|
||||
};
|
||||
|
|
@ -6,6 +6,7 @@ interface InfoTooltipProps extends Omit<TooltipProps, 'children' | 'content'> {
|
|||
children: PopoverContent;
|
||||
}
|
||||
|
||||
/** @deprecated Use <IconButton name="info-circle" tooltip={children} /> instead */
|
||||
export const InfoTooltip = ({ children, ...restProps }: InfoTooltipProps) => {
|
||||
return <IconButton name="info-circle" tooltip={children} {...restProps} />;
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@ import { InlineToast as InlineToastImpl, InlineToastProps } from './InlineToast'
|
|||
import mdx from './InlineToast.mdx';
|
||||
|
||||
const story: Meta = {
|
||||
title: 'InlineToast',
|
||||
title: 'Information/InlineToast',
|
||||
component: InlineToastImpl,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
@ -16,7 +16,6 @@ const story: Meta = {
|
|||
},
|
||||
},
|
||||
argTypes: {
|
||||
// foo is the property we want to remove from the UI
|
||||
referenceElement: {
|
||||
table: {
|
||||
disable: true,
|
|
@ -18,7 +18,7 @@ const prefixSuffixOpts = {
|
|||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Forms/Input/AutoSizeInput',
|
||||
title: 'Inputs/AutoSizeInput',
|
||||
component: AutoSizeInput,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -22,7 +22,7 @@ const prefixSuffixOpts = {
|
|||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Forms/Input',
|
||||
title: 'Inputs/Input',
|
||||
component: Input,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -103,7 +103,7 @@ const pageableData: CarData[] = [
|
|||
];
|
||||
|
||||
const meta: Meta<typeof InteractiveTable<CarData>> = {
|
||||
title: 'Experimental/InteractiveTable',
|
||||
title: 'Layout/InteractiveTable',
|
||||
component: InteractiveTable,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -23,7 +23,7 @@ const borderRadiusOptions: BorderRadius[] = ['default', 'pill', 'circle'];
|
|||
const boxShadowOptions: BoxShadow[] = ['z1', 'z2', 'z3'];
|
||||
|
||||
const meta: Meta<typeof Box> = {
|
||||
title: 'General/Layout/Box',
|
||||
title: 'Layout/Box',
|
||||
component: Box,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -11,7 +11,7 @@ const dimensions = Array.from({ length: 9 }).map(() => ({
|
|||
}));
|
||||
|
||||
const meta: Meta<typeof Grid> = {
|
||||
title: 'General/Layout/Grid',
|
||||
title: 'Layout/Grid',
|
||||
component: Grid,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -7,13 +7,9 @@ import { HorizontalGroup, Layout, LayoutProps, VerticalGroup } from './Layout';
|
|||
import mdx from './Layout.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Layout/Groups',
|
||||
title: 'Layout/Deprecated/Groups',
|
||||
component: Layout,
|
||||
decorators: [withStoryContainer],
|
||||
// SB7 has broken subcomponent types due to dropping support for the feature
|
||||
// https://github.com/storybookjs/storybook/issues/20782
|
||||
// @ts-ignore
|
||||
subcomponents: { HorizontalGroup, VerticalGroup },
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Space } from './Space';
|
|||
import mdx from './Space.mdx';
|
||||
|
||||
const meta: Meta<typeof Space> = {
|
||||
title: 'General/Layout/Space',
|
||||
title: 'Layout/Space',
|
||||
component: Space,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -9,6 +9,16 @@ import { JustifyContent, Wrap, Direction } from '../types';
|
|||
import { Stack } from './Stack';
|
||||
import mdx from './Stack.mdx';
|
||||
|
||||
const meta: Meta<typeof Stack> = {
|
||||
title: 'Layout/Stack',
|
||||
component: Stack,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Item = ({ color, text, height }: { color: string; text?: string | number; height?: string }) => {
|
||||
return (
|
||||
<div
|
||||
|
@ -26,16 +36,6 @@ const Item = ({ color, text, height }: { color: string; text?: string | number;
|
|||
);
|
||||
};
|
||||
|
||||
const meta: Meta<typeof Stack> = {
|
||||
title: 'General/Layout/Stack',
|
||||
component: Stack,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Basic: StoryFn<typeof Stack> = (args) => {
|
||||
const theme = useTheme2();
|
||||
return (
|
||||
|
|
|
@ -8,7 +8,7 @@ import { TextLink } from './TextLink';
|
|||
import mdx from './TextLink.mdx';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'General/TextLink',
|
||||
title: 'Foundations/TextLink',
|
||||
component: TextLink,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { PureComponent } from 'react';
|
|||
|
||||
import { ListProps, AbstractList } from './AbstractList';
|
||||
|
||||
/** @deprecated Use ul/li/arr.map directly instead */
|
||||
export class InlineList<T> extends PureComponent<ListProps<T>> {
|
||||
render() {
|
||||
return <AbstractList inline {...this.props} />;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { InlineList } from './InlineList';
|
|||
import { List } from './List';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Layout/List',
|
||||
title: 'Layout/Deprecated/List',
|
||||
component: List,
|
||||
parameters: {
|
||||
controls: {
|
|
@ -2,6 +2,7 @@ import { PureComponent } from 'react';
|
|||
|
||||
import { ListProps, AbstractList } from './AbstractList';
|
||||
|
||||
/** @deprecated Use ul/li/arr.map directly instead */
|
||||
export class List<T> extends PureComponent<ListProps<T>> {
|
||||
render() {
|
||||
return <AbstractList {...this.props} />;
|
||||
|
|
|
@ -10,7 +10,7 @@ import { LoadingBar, LoadingBarProps } from './LoadingBar';
|
|||
import mdx from './LoadingBar.mdx';
|
||||
|
||||
const meta: Meta<typeof LoadingBar> = {
|
||||
title: 'General/LoadingBar',
|
||||
title: 'Information/LoadingBar',
|
||||
component: LoadingBar,
|
||||
parameters: {
|
||||
controls: {},
|
||||
|
|
|
@ -4,7 +4,7 @@ import { LoadingPlaceholder, LoadingPlaceholderProps } from './LoadingPlaceholde
|
|||
import mdx from './LoadingPlaceholder.mdx';
|
||||
|
||||
const meta: Meta<typeof LoadingPlaceholder> = {
|
||||
title: 'General/LoadingPlaceholder',
|
||||
title: 'Information/LoadingPlaceholder',
|
||||
component: LoadingPlaceholder,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -11,7 +11,7 @@ A simple menu component.
|
|||
|
||||
### When to use
|
||||
|
||||
When you need to display a list of actions or navigation options in a dropdown.
|
||||
When you need to display a list of actions or navigation options, often used in combination with Dropdown.
|
||||
|
||||
### Usage
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Menu } from './Menu';
|
|||
import mdx from './Menu.mdx';
|
||||
|
||||
const meta: Meta<typeof Menu> = {
|
||||
title: 'General/Menu',
|
||||
title: 'Overlays/Menu',
|
||||
component: Menu,
|
||||
argTypes: {},
|
||||
parameters: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { CodeEditor } from './CodeEditor';
|
|||
import mdx from './CodeEditor.mdx';
|
||||
|
||||
const meta: Meta<typeof CodeEditor> = {
|
||||
title: 'CodeEditor',
|
||||
title: 'Inputs/CodeEditor',
|
||||
component: CodeEditor,
|
||||
parameters: {
|
||||
docs: {
|
|
@ -9,7 +9,7 @@ import { ToolbarButton } from '../ToolbarButton/ToolbarButton';
|
|||
import { PageToolbar } from './PageToolbar';
|
||||
|
||||
const meta: Meta<typeof PageToolbar> = {
|
||||
title: 'Layout/PageToolbar',
|
||||
title: 'Navigation/Deprecated/PageToolbar',
|
||||
component: PageToolbar,
|
||||
parameters: {},
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@ export interface Props {
|
|||
forceShowLeftItems?: boolean;
|
||||
}
|
||||
|
||||
/** @alpha */
|
||||
/** @deprecated Use Page instead */
|
||||
export const PageToolbar = memo(
|
||||
({
|
||||
title,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Pagination } from './Pagination';
|
|||
import mdx from './Pagination.mdx';
|
||||
|
||||
const meta: Meta<typeof Pagination> = {
|
||||
title: 'Buttons/Pagination',
|
||||
title: 'Navigation/Pagination',
|
||||
component: Pagination,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -22,7 +22,7 @@ const PANEL_WIDTH = 400;
|
|||
const PANEL_HEIGHT = 150;
|
||||
|
||||
const meta: Meta<typeof PanelChrome> = {
|
||||
title: 'Visualizations/PanelChrome',
|
||||
title: 'Plugins/PanelChrome',
|
||||
component: PanelChrome,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { PanelContainer } from './PanelContainer';
|
|||
import mdx from './PanelContainer.mdx';
|
||||
|
||||
const meta: Meta<typeof PanelContainer> = {
|
||||
title: 'General/PanelContainer',
|
||||
title: 'Layout/Deprecated/PanelContainer',
|
||||
component: PanelContainer,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -7,6 +7,8 @@ import { useStyles2 } from '../../themes/ThemeContext';
|
|||
|
||||
type Props = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||
|
||||
// TODO: Reimplement this with Box
|
||||
/** @deprecated Use Box instead */
|
||||
export const PanelContainer = ({ children, className, ...props }: Props) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
|
|
|
@ -6,7 +6,7 @@ import { PluginSignatureBadge } from './PluginSignatureBadge';
|
|||
import mdx from './PluginSignatureBadge.mdx';
|
||||
|
||||
const meta: Meta<typeof PluginSignatureBadge> = {
|
||||
title: 'Data Display/PluginSignatureBadge',
|
||||
title: 'Information/PluginSignatureBadge',
|
||||
component: PluginSignatureBadge,
|
||||
argTypes: {
|
||||
status: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { TypeaheadInput } from '../../types/completion';
|
|||
import { QueryField, QueryFieldProps } from './QueryField';
|
||||
|
||||
const meta: Meta<typeof QueryField> = {
|
||||
title: 'Data Source/QueryField',
|
||||
title: 'Inputs/Deprecated/QueryField',
|
||||
component: QueryField,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { RefreshPicker } from './RefreshPicker';
|
|||
import mdx from './RefreshPicker.mdx';
|
||||
|
||||
const meta: Meta<typeof RefreshPicker> = {
|
||||
title: 'Pickers and Editors/RefreshPicker',
|
||||
title: 'Pickers/RefreshPicker',
|
||||
component: RefreshPicker,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { RenderUserContentAsHTML } from './RenderUserContentAsHTML';
|
|||
import mdx from './RenderUserContentAsHTML.mdx';
|
||||
|
||||
const meta: Meta<typeof RenderUserContentAsHTML> = {
|
||||
title: 'General/RenderUserContentAsHTML',
|
||||
title: 'Utilities/RenderUserContentAsHTML',
|
||||
component: RenderUserContentAsHTML,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { ScrollContainer } from './ScrollContainer';
|
|||
import mdx from './ScrollContainer.mdx';
|
||||
|
||||
const meta: Meta<typeof ScrollContainer> = {
|
||||
title: 'General/Layout/ScrollContainer',
|
||||
title: 'Layout/ScrollContainer',
|
||||
component: ScrollContainer,
|
||||
parameters: {
|
||||
controls: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Meta, StoryFn } from '@storybook/react';
|
|||
import { SecretFormField } from './SecretFormField';
|
||||
|
||||
const meta: Meta<typeof SecretFormField> = {
|
||||
title: 'Forms/SecretFormField',
|
||||
title: 'Forms/Deprecated/SecretFormField',
|
||||
component: SecretFormField,
|
||||
parameters: {
|
||||
controls: {
|
|
@ -5,7 +5,7 @@ import { SecretInput } from './SecretInput';
|
|||
import mdx from './SecretInput.mdx';
|
||||
|
||||
const meta: Meta<typeof SecretInput> = {
|
||||
title: 'Forms/SecretInput',
|
||||
title: 'Inputs/SecretInput',
|
||||
component: SecretInput,
|
||||
parameters: {
|
||||
docs: {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue