From ea1b22473b997b9acf8f98bcf7c0ba7be42e6de8 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 27 Jul 2023 15:46:35 +0100 Subject: [PATCH 01/26] Improve loading for controls --- code/addons/controls/src/ControlsPanel.tsx | 48 +-- .../src/components/ArgsTable/ArgsTable.tsx | 334 ++++++++---------- .../src/components/ArgsTable/Skeleton.tsx | 97 +++++ .../src/components/DocsPage.stories.tsx | 1 - 4 files changed, 265 insertions(+), 215 deletions(-) create mode 100644 code/ui/blocks/src/components/ArgsTable/Skeleton.tsx diff --git a/code/addons/controls/src/ControlsPanel.tsx b/code/addons/controls/src/ControlsPanel.tsx index e5583589d007..5038e65b8e98 100644 --- a/code/addons/controls/src/ControlsPanel.tsx +++ b/code/addons/controls/src/ControlsPanel.tsx @@ -7,12 +7,7 @@ import { useParameter, useStorybookState, } from '@storybook/manager-api'; -import { - PureArgsTable as ArgsTable, - NoControlsWarning, - type PresetColor, - type SortType, -} from '@storybook/blocks'; +import { PureArgsTable as ArgsTable, type PresetColor, type SortType } from '@storybook/blocks'; import type { ArgTypes } from '@storybook/types'; import { PARAM_KEY } from './constants'; @@ -29,16 +24,11 @@ export const ControlsPanel: FC = () => { const [globals] = useGlobals(); const rows = useArgTypes(); const isArgsStory = useParameter('__isArgsStory', false); - const { - expanded, - sort, - presetColors, - hideNoControlsWarning = false, - } = useParameter(PARAM_KEY, {}); + const isLoading = !isArgsStory; + const { expanded, sort, presetColors } = useParameter(PARAM_KEY, {}); const { path } = useStorybookState(); const hasControls = Object.values(rows).some((arg) => arg?.control); - const showWarning = !(hasControls && isArgsStory) && !hideNoControlsWarning; const withPresetColors = Object.entries(rows).reduce((acc, [key, arg]) => { if (arg?.control?.type !== 'color' || arg?.control?.presetColors) acc[key] = arg; @@ -46,22 +36,22 @@ export const ControlsPanel: FC = () => { return acc; }, {} as ArgTypes); + console.log('isLoading in ControlsPanel', isLoading); + return ( - <> - {showWarning && } - - + ); }; diff --git a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx index a54dc89d95f5..b2c326ae41a8 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx @@ -12,170 +12,156 @@ import { SectionRow } from './SectionRow'; import type { ArgType, ArgTypes, Args, Globals } from './types'; // eslint-disable-next-line import/no-cycle import { EmptyBlock } from '..'; +import { Skeleton } from './Skeleton'; export const TableWrapper = styled.table<{ compact?: boolean; inAddonPanel?: boolean; isLoading?: boolean; -}>( - ({ theme, compact, inAddonPanel }) => ({ - '&&': { - // Resets for cascading/system styles - borderSpacing: 0, - color: theme.color.defaultText, - - 'td, th': { - padding: 0, - border: 'none', - verticalAlign: 'top', - textOverflow: 'ellipsis', - }, - // End Resets +}>(({ theme, compact, inAddonPanel }) => ({ + '&&': { + // Resets for cascading/system styles + borderSpacing: 0, + color: theme.color.defaultText, + + 'td, th': { + padding: 0, + border: 'none', + verticalAlign: 'top', + textOverflow: 'ellipsis', + }, + // End Resets - fontSize: theme.typography.size.s2 - 1, - lineHeight: '20px', - textAlign: 'left', - width: '100%', + fontSize: theme.typography.size.s2 - 1, + lineHeight: '20px', + textAlign: 'left', + width: '100%', - // Margin collapse - marginTop: inAddonPanel ? 0 : 25, - marginBottom: inAddonPanel ? 0 : 40, + // Margin collapse + marginTop: inAddonPanel ? 0 : 25, + marginBottom: inAddonPanel ? 0 : 40, - 'thead th:first-of-type, td:first-of-type': { - // intentionally specify thead here - width: '25%', - }, + 'thead th:first-of-type, td:first-of-type': { + // intentionally specify thead here + width: '25%', + }, - 'th:first-of-type, td:first-of-type': { - paddingLeft: 20, - }, + 'th:first-of-type, td:first-of-type': { + paddingLeft: 20, + }, - 'th:nth-of-type(2), td:nth-of-type(2)': { - ...(compact - ? null - : { - // Description column - width: '35%', - }), - }, + 'th:nth-of-type(2), td:nth-of-type(2)': { + ...(compact + ? null + : { + // Description column + width: '35%', + }), + }, - 'td:nth-of-type(3)': { - ...(compact - ? null - : { - // Defaults column - width: '15%', - }), - }, + 'td:nth-of-type(3)': { + ...(compact + ? null + : { + // Defaults column + width: '15%', + }), + }, - 'th:last-of-type, td:last-of-type': { - paddingRight: 20, - ...(compact - ? null - : { - // Controls column - width: '25%', - }), - }, + 'th:last-of-type, td:last-of-type': { + paddingRight: 20, + ...(compact + ? null + : { + // Controls column + width: '25%', + }), + }, - th: { - color: - theme.base === 'light' - ? transparentize(0.25, theme.color.defaultText) - : transparentize(0.45, theme.color.defaultText), - paddingTop: 10, - paddingBottom: 10, + th: { + color: + theme.base === 'light' + ? transparentize(0.25, theme.color.defaultText) + : transparentize(0.45, theme.color.defaultText), + paddingTop: 10, + paddingBottom: 10, + paddingLeft: 15, + paddingRight: 15, + }, + + td: { + paddingTop: '10px', + paddingBottom: '10px', + + '&:not(:first-of-type)': { paddingLeft: 15, paddingRight: 15, }, - td: { - paddingTop: '10px', - paddingBottom: '10px', - - '&:not(:first-of-type)': { - paddingLeft: 15, - paddingRight: 15, - }, - - '&:last-of-type': { - paddingRight: 20, - }, + '&:last-of-type': { + paddingRight: 20, }, + }, - // Makes border alignment consistent w/other DocBlocks - marginLeft: inAddonPanel ? 0 : 1, - marginRight: inAddonPanel ? 0 : 1, - - tbody: { - // Safari doesn't love shadows on tbody so we need to use a shadow filter. In order to do this, - // the table cells all need to be solid so they have a background color applied. - // I wasn't sure what kinds of content go in these tables so I was extra specific with selectors - // to avoid unexpected surprises. - ...(inAddonPanel - ? null - : { - filter: - theme.base === 'light' - ? `drop-shadow(0px 1px 3px rgba(0, 0, 0, 0.10))` - : `drop-shadow(0px 1px 3px rgba(0, 0, 0, 0.20))`, - }), - - '> tr > *': { - // For filter to work properly, the table cells all need to be opaque. - background: theme.background.content, - borderTop: `1px solid ${theme.appBorderColor}`, - }, - - ...(inAddonPanel - ? null - : { - // This works and I don't know why. :) - '> tr:first-of-type > *': { - borderBlockStart: `1px solid ${theme.appBorderColor}`, - }, - '> tr:last-of-type > *': { - borderBlockEnd: `1px solid ${theme.appBorderColor}`, - }, - '> tr > *:first-of-type': { - borderInlineStart: `1px solid ${theme.appBorderColor}`, - }, - '> tr > *:last-of-type': { - borderInlineEnd: `1px solid ${theme.appBorderColor}`, - }, - - // Thank you, Safari, for making me write code like this. - '> tr:first-of-type > td:first-of-type': { - borderTopLeftRadius: theme.appBorderRadius, - }, - '> tr:first-of-type > td:last-of-type': { - borderTopRightRadius: theme.appBorderRadius, - }, - '> tr:last-of-type > td:first-of-type': { - borderBottomLeftRadius: theme.appBorderRadius, - }, - '> tr:last-of-type > td:last-of-type': { - borderBottomRightRadius: theme.appBorderRadius, - }, - }), + // Makes border alignment consistent w/other DocBlocks + marginLeft: inAddonPanel ? 0 : 1, + marginRight: inAddonPanel ? 0 : 1, + + tbody: { + // Safari doesn't love shadows on tbody so we need to use a shadow filter. In order to do this, + // the table cells all need to be solid so they have a background color applied. + // I wasn't sure what kinds of content go in these tables so I was extra specific with selectors + // to avoid unexpected surprises. + ...(inAddonPanel + ? null + : { + filter: + theme.base === 'light' + ? `drop-shadow(0px 1px 3px rgba(0, 0, 0, 0.10))` + : `drop-shadow(0px 1px 3px rgba(0, 0, 0, 0.20))`, + }), + + '> tr > *': { + // For filter to work properly, the table cells all need to be opaque. + background: theme.background.content, + borderTop: `1px solid ${theme.appBorderColor}`, }, - // End awesome table styling + + ...(inAddonPanel + ? null + : { + // This works and I don't know why. :) + '> tr:first-of-type > *': { + borderBlockStart: `1px solid ${theme.appBorderColor}`, + }, + '> tr:last-of-type > *': { + borderBlockEnd: `1px solid ${theme.appBorderColor}`, + }, + '> tr > *:first-of-type': { + borderInlineStart: `1px solid ${theme.appBorderColor}`, + }, + '> tr > *:last-of-type': { + borderInlineEnd: `1px solid ${theme.appBorderColor}`, + }, + + // Thank you, Safari, for making me write code like this. + '> tr:first-of-type > td:first-of-type': { + borderTopLeftRadius: theme.appBorderRadius, + }, + '> tr:first-of-type > td:last-of-type': { + borderTopRightRadius: theme.appBorderRadius, + }, + '> tr:last-of-type > td:first-of-type': { + borderBottomLeftRadius: theme.appBorderRadius, + }, + '> tr:last-of-type > td:last-of-type': { + borderBottomRightRadius: theme.appBorderRadius, + }, + }), }, - }), - ({ isLoading, theme }) => - isLoading - ? { - 'th span, td span, td button': { - display: 'inline', - backgroundColor: theme.appBorderColor, - animation: `${theme.animation.glow} 1.5s ease-in-out infinite`, - color: 'transparent', - boxShadow: 'none', - borderRadius: 0, - }, - } - : {} -); + // End awesome table styling + }, +})); const StyledIconButton = styled(IconButton as any)(({ theme }) => ({ color: theme.barTextColor, @@ -212,40 +198,17 @@ export interface ArgsTableOptionProps { isLoading?: boolean; sort?: SortType; } -export interface ArgsTableDataProps { +interface ArgsTableDataProps { rows: ArgTypes; args?: Args; globals?: Globals; } -export interface ArgsTableErrorProps { +interface ArgsTableErrorProps { error: ArgsTableError; } -export interface ArgsTableLoadingProps { - isLoading: true; -} -const rowLoadingData = (key: string) => ({ - key, - name: 'propertyName', - description: 'This is a short description', - control: { type: 'text' }, - table: { - type: { summary: 'summary' }, - defaultValue: { summary: 'defaultValue' }, - }, -}); - -export const argsTableLoadingData: ArgsTableDataProps = { - rows: { - row1: rowLoadingData('row1'), - row2: rowLoadingData('row2'), - row3: rowLoadingData('row3'), - }, -}; - -export type ArgsTableProps = ArgsTableOptionProps & - (ArgsTableDataProps | ArgsTableErrorProps | ArgsTableLoadingProps); +export type ArgsTableProps = ArgsTableOptionProps & (ArgsTableDataProps | ArgsTableErrorProps); type Rows = ArgType[]; type Subsection = Rows; @@ -337,10 +300,21 @@ const safeIncludeConditionalArg = (row: ArgType, args: Args, globals: Globals) = * ArgDefs, usually derived from docgen info for the component. */ export const ArgsTable: FC = (props) => { + const { + updateArgs, + resetArgs, + compact, + inAddonPanel, + initialExpandedArgs, + sort = 'none', + isLoading, + } = props; + if ('error' in props) { + const { error } = props; return ( - {props.error}  + {error}  Read the docs @@ -348,17 +322,10 @@ export const ArgsTable: FC = (props) => { ); } - const { - updateArgs, - resetArgs, - compact, - inAddonPanel, - initialExpandedArgs, - sort = 'none', - } = props; - const isLoading = 'isLoading' in props; - const { rows, args, globals } = 'rows' in props ? props : argsTableLoadingData; + // If the story is loading, show a skeleton + if (isLoading) return ; + const { rows, args, globals } = 'rows' in props && props; const groups = groupRows( pickBy( rows, @@ -367,6 +334,7 @@ export const ArgsTable: FC = (props) => { sort ); + // If there are no controls, show the empty state if ( groups.ungrouped.length === 0 && Object.entries(groups.sections).length === 0 && @@ -391,11 +359,7 @@ export const ArgsTable: FC = (props) => { return ( - + diff --git a/code/ui/blocks/src/components/ArgsTable/Skeleton.tsx b/code/ui/blocks/src/components/ArgsTable/Skeleton.tsx new file mode 100644 index 000000000000..ebdcbbc2d673 --- /dev/null +++ b/code/ui/blocks/src/components/ArgsTable/Skeleton.tsx @@ -0,0 +1,97 @@ +import { styled } from '@storybook/theming'; +import type { FC } from 'react'; +import React from 'react'; + +const Row = styled.div(({ theme }) => ({ + display: 'flex', + gap: 16, + borderBottom: `1px solid ${theme.appBorderColor}`, + + '&:last-child': { + borderBottom: 0, + }, +})); + +const Column = styled.div<{ numColumn: number }>(({ numColumn }) => ({ + display: 'flex', + flexDirection: 'column', + flex: numColumn || 1, + gap: 5, + padding: '12px 20px', +})); + +const SkeletonText = styled.div<{ width?: number | string; height?: number }>( + ({ theme, width, height }) => ({ + animation: `${theme.animation.glow} 1.5s ease-in-out infinite`, + background: theme.appBorderColor, + width: width || '100%', + height: height || 16, + borderRadius: 3, + }) +); + +const columnWidth = [2, 4, 2, 2]; + +export const Skeleton: FC = () => ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); diff --git a/code/ui/blocks/src/components/DocsPage.stories.tsx b/code/ui/blocks/src/components/DocsPage.stories.tsx index e7ab2d64220d..1d1f4b6db03d 100644 --- a/code/ui/blocks/src/components/DocsPage.stories.tsx +++ b/code/ui/blocks/src/components/DocsPage.stories.tsx @@ -43,7 +43,6 @@ export const Loading = () => ( - )} /> ); From fd67d96a281bb3413620405bdb0e283fa70214f5 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 09:55:37 +0200 Subject: [PATCH 02/26] Made loading works --- code/addons/controls/package.json | 1 + code/addons/controls/src/ControlsPanel.tsx | 30 +++++++++++++++---- .../src/components/ArgsTable/ArgsTable.tsx | 3 ++ .../blocks/src/components/ArgsTable/Empty.tsx | 9 ++++++ code/yarn.lock | 1 + 5 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 code/ui/blocks/src/components/ArgsTable/Empty.tsx diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index f250d87e0e1e..394c0ef58635 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -72,6 +72,7 @@ "@storybook/client-logger": "workspace:*", "@storybook/components": "workspace:*", "@storybook/core-common": "workspace:*", + "@storybook/core-events": "workspace:*", "@storybook/manager-api": "workspace:*", "@storybook/node-logger": "workspace:*", "@storybook/preview-api": "workspace:*", diff --git a/code/addons/controls/src/ControlsPanel.tsx b/code/addons/controls/src/ControlsPanel.tsx index 5038e65b8e98..f74010680904 100644 --- a/code/addons/controls/src/ControlsPanel.tsx +++ b/code/addons/controls/src/ControlsPanel.tsx @@ -1,15 +1,18 @@ import type { FC } from 'react'; -import React from 'react'; +import React, { useEffect } from 'react'; import { useArgs, useGlobals, useArgTypes, useParameter, useStorybookState, + useChannel, } from '@storybook/manager-api'; +import { STORY_CHANGED, STORY_PREPARED } from '@storybook/core-events'; import { PureArgsTable as ArgsTable, type PresetColor, type SortType } from '@storybook/blocks'; import type { ArgTypes } from '@storybook/types'; +import { set } from 'lodash'; import { PARAM_KEY } from './constants'; interface ControlsParameters { @@ -20,14 +23,24 @@ interface ControlsParameters { } export const ControlsPanel: FC = () => { + const [isLoading, setIsLoading] = React.useState(true); const [args, updateArgs, resetArgs] = useArgs(); const [globals] = useGlobals(); const rows = useArgTypes(); const isArgsStory = useParameter('__isArgsStory', false); - const isLoading = !isArgsStory; const { expanded, sort, presetColors } = useParameter(PARAM_KEY, {}); const { path } = useStorybookState(); + // If the story is prepared, then show the args table + useChannel({ + [STORY_PREPARED]: () => setIsLoading(false), + }); + + // If the story changes, then show the loading state + useEffect(() => { + setIsLoading(true); + }, [path]); + const hasControls = Object.values(rows).some((arg) => arg?.control); const withPresetColors = Object.entries(rows).reduce((acc, [key, arg]) => { @@ -36,8 +49,6 @@ export const ControlsPanel: FC = () => { return acc; }, {} as ArgTypes); - console.log('isLoading in ControlsPanel', isLoading); - return ( { resetArgs, inAddonPanel: true, sort, + isLoading, }} - isLoading={isLoading} /> ); }; + +// storiesOf("Button").add("Basic0", () => - - @@ -77,16 +62,16 @@ export const WithIcon: Story = { export const Sizes: Story = { render: () => (
- - - -
@@ -106,22 +91,22 @@ export const IconOnly: Story = { }, render: () => ( <> - - - - - - @@ -134,22 +119,22 @@ export const IconOnly: Story = { export const IconOnlyActive: Story = { render: () => (
- - - - - -
diff --git a/code/ui/components/src/new/FakeIcon.tsx b/code/ui/components/src/new/FakeIcon.tsx new file mode 100644 index 000000000000..51ce84f446f0 --- /dev/null +++ b/code/ui/components/src/new/FakeIcon.tsx @@ -0,0 +1,18 @@ +import type { FC } from 'react'; +import React from 'react'; + +export const FakeIcon: FC = () => ( + + + + +); diff --git a/code/ui/components/src/new/Link/Link.stories.tsx b/code/ui/components/src/new/Link/Link.stories.tsx new file mode 100644 index 000000000000..3f303e17c04f --- /dev/null +++ b/code/ui/components/src/new/Link/Link.stories.tsx @@ -0,0 +1,93 @@ +import type { ComponentProps } from 'react'; +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { Link } from './Link'; +import { FakeIcon } from '../FakeIcon'; + +const onClick = action('onClick'); + +export default { + component: Link, +}; + +export const CancelWOnClick = { + args: { + href: '/', + onClick, + children: 'Try clicking with different mouse buttons and modifier keys (shift/ctrl/alt/cmd)', + }, + name: 'Cancel w/ onClick', +}; + +export const CancelWHref = { + args: { + href: 'http://example.com', + children: 'Link', + }, + name: 'Cancel w/ href', +}; + +export const NoCancelWOnClick = { + args: { + href: '/', + children: 'Any click will go through', + onClick, + }, + name: 'No-cancel w/ onClick', +}; + +export const NoCancelWHref = { + args: { + href: 'http://example.com', + children: 'Link', + }, + name: 'No-cancel w/ href', +}; + +export const StyledLinks = { + render: (args: ComponentProps) => ( +
+ + Default + +
+ + Secondary + +
+ + tertiary + +
+ + nochrome + +
+ + + With icon in front + +
+ + {/* A linked icon by itself */} + + +
+ + With arrow behind + +
+ + + Inverted colors + + +
+
+ ), + name: 'Styled links', +}; diff --git a/code/ui/components/src/new/Link/Link.test.tsx b/code/ui/components/src/new/Link/Link.test.tsx new file mode 100644 index 000000000000..3dde3ecab07a --- /dev/null +++ b/code/ui/components/src/new/Link/Link.test.tsx @@ -0,0 +1,72 @@ +import type { AnchorHTMLAttributes } from 'react'; +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { ThemeProvider, themes, convert } from '@storybook/theming'; +import type { LinkProps } from './Link'; +import { Link } from './Link'; + +const LEFT_BUTTON = 0; +const MIDDLE_BUTTON = 1; +const RIGHT_BUTTON = 2; + +function ThemedLink(props: LinkProps & AnchorHTMLAttributes) { + return ( + + + + ); +} + +describe('Link', () => { + describe('events', () => { + it('should call onClick on a plain left click', () => { + const handleClick = jest.fn(); + render(Content); + userEvent.click(screen.getByText('Content'), { button: LEFT_BUTTON }); + expect(handleClick).toHaveBeenCalled(); + }); + + it("shouldn't call onClick on a middle click", () => { + const handleClick = jest.fn(); + render(Content); + userEvent.click(screen.getByText('Content'), { button: MIDDLE_BUTTON }); + expect(handleClick).not.toHaveBeenCalled(); + }); + + it("shouldn't call onClick on a right click", () => { + const handleClick = jest.fn(); + render(Content); + userEvent.click(screen.getByText('Content'), { button: RIGHT_BUTTON }); + expect(handleClick).not.toHaveBeenCalled(); + }); + + it("shouldn't call onClick on alt+click", () => { + const handleClick = jest.fn(); + render(Content); + userEvent.click(screen.getByText('Content'), { altKey: true }); + expect(handleClick).not.toHaveBeenCalled(); + }); + + it("shouldn't call onClick on ctrl+click", () => { + const handleClick = jest.fn(); + render(Content); + userEvent.click(screen.getByText('Content'), { ctrlKey: true }); + expect(handleClick).not.toHaveBeenCalled(); + }); + + it("shouldn't call onClick on cmd+click / win+click", () => { + const handleClick = jest.fn(); + render(Content); + userEvent.click(screen.getByText('Content'), { metaKey: true }); + expect(handleClick).not.toHaveBeenCalled(); + }); + + it("shouldn't call onClick on shift+click", () => { + const handleClick = jest.fn(); + render(Content); + userEvent.click(screen.getByText('Content'), { shiftKey: true }); + expect(handleClick).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/code/ui/components/src/new/Link/Link.tsx b/code/ui/components/src/new/Link/Link.tsx new file mode 100644 index 000000000000..37de0003f603 --- /dev/null +++ b/code/ui/components/src/new/Link/Link.tsx @@ -0,0 +1,214 @@ +import type { AnchorHTMLAttributes, FC, MouseEvent } from 'react'; +import React from 'react'; +import { styled } from '@storybook/theming'; +import { darken } from 'polished'; +import { FakeIcon } from '../FakeIcon'; + +// Cmd/Ctrl/Shift/Alt + Click should trigger default browser behavior. Same applies to non-left clicks +const LEFT_BUTTON = 0; + +const isPlainLeftClick = (e: MouseEvent) => + e.button === LEFT_BUTTON && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey; + +const cancelled = (e: MouseEvent, cb: (_e: MouseEvent) => void) => { + if (isPlainLeftClick(e)) { + e.preventDefault(); + cb(e); + } +}; + +export interface LinkStylesProps { + secondary?: boolean; + tertiary?: boolean; + nochrome?: boolean; + inverse?: boolean; + isButton?: boolean; +} + +export interface LinkInnerProps { + withArrow?: boolean; + containsIcon?: boolean; +} + +const LinkInner = styled.span( + ({ withArrow }) => + withArrow + ? { + '> svg:last-of-type': { + height: '0.7em', + width: '0.7em', + marginRight: 0, + marginLeft: '0.25em', + bottom: 'auto', + verticalAlign: 'inherit', + }, + } + : {}, + ({ containsIcon }) => + containsIcon + ? { + svg: { + height: '1em', + width: '1em', + verticalAlign: 'middle', + position: 'relative', + bottom: 0, + marginRight: 0, + }, + } + : {} +); + +type AProps = AnchorHTMLAttributes; + +const A = styled.a( + ({ theme }) => ({ + display: 'inline-block', + transition: 'all 150ms ease-out', + textDecoration: 'none', + + color: theme.color.secondary, + + '&:hover, &:focus': { + cursor: 'pointer', + color: darken(0.07, theme.color.secondary), + 'svg path': { + fill: darken(0.07, theme.color.secondary), + }, + }, + '&:active': { + color: darken(0.1, theme.color.secondary), + 'svg path': { + fill: darken(0.1, theme.color.secondary), + }, + }, + + svg: { + display: 'inline-block', + height: '1em', + width: '1em', + verticalAlign: 'text-top', + position: 'relative', + bottom: '-0.125em', + marginRight: '0.4em', + + '& path': { + fill: theme.color.secondary, + }, + }, + }), + ({ theme, secondary, tertiary }) => { + let colors; + if (secondary) { + colors = [theme.textMutedColor, theme.color.dark, theme.color.darker]; + } + if (tertiary) { + colors = [theme.color.dark, theme.color.darkest, theme.textMutedColor]; + } + + return colors + ? { + color: colors[0], + 'svg path': { + fill: colors[0], + }, + + '&:hover': { + color: colors[1], + 'svg path': { + fill: colors[1], + }, + }, + + '&:active': { + color: colors[2], + 'svg path': { + fill: colors[2], + }, + }, + } + : {}; + }, + ({ nochrome }) => + nochrome + ? { + color: 'inherit', + + '&:hover, &:active': { + color: 'inherit', + textDecoration: 'underline', + }, + } + : {}, + ({ theme, inverse }) => + inverse + ? { + color: theme.color.lightest, + 'svg path': { + fill: theme.color.lightest, + }, + + '&:hover': { + color: theme.color.lighter, + 'svg path': { + fill: theme.color.lighter, + }, + }, + + '&:active': { + color: theme.color.light, + 'svg path': { + fill: theme.color.light, + }, + }, + } + : {}, + ({ isButton }) => + isButton + ? { + border: 0, + borderRadius: 0, + background: 'none', + padding: 0, + fontSize: 'inherit', + } + : {} +); + +export interface LinkProps extends LinkInnerProps, LinkStylesProps { + cancel?: boolean; + className?: string; + style?: object; + onClick?: (e: MouseEvent) => void; + href?: string; +} + +export const Link: FC = ({ + cancel, + children, + onClick, + withArrow, + containsIcon, + className, + ...rest +}) => ( + cancelled(e, onClick) : onClick} + className={className} + > + + {children} + {withArrow && } + + +); + +Link.defaultProps = { + cancel: true, + className: undefined, + style: undefined, + onClick: undefined, + withArrow: false, + containsIcon: false, +}; diff --git a/code/ui/manager/src/globals/exports.ts b/code/ui/manager/src/globals/exports.ts index b1f66314186a..505b077e5eef 100644 --- a/code/ui/manager/src/globals/exports.ts +++ b/code/ui/manager/src/globals/exports.ts @@ -114,7 +114,7 @@ export default { 'resetComponents', 'withReset', ], - '@storybook/components/experimental': ['Button'], + '@storybook/components/experimental': ['Button', 'Input', 'Link', 'Select'], '@storybook/channels': [ 'Channel', 'PostMessageTransport', From 81d6bd92f9869ff5a2b130d1db93adf43d2ca778 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 15:31:53 +0200 Subject: [PATCH 06/26] Update --- .../src/components/ArgsTable/ArgsTable.tsx | 9 +- .../blocks/src/components/ArgsTable/Empty.tsx | 52 +++- .../components/src/new/Link/Link.stories.tsx | 133 +++++----- code/ui/components/src/new/Link/Link.test.tsx | 72 ----- code/ui/components/src/new/Link/Link.tsx | 248 ++++-------------- 5 files changed, 168 insertions(+), 346 deletions(-) delete mode 100644 code/ui/components/src/new/Link/Link.test.tsx diff --git a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx index 67bc827586f5..aeb55050c605 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx @@ -6,6 +6,7 @@ import { transparentize } from 'polished'; import { includeConditionalArg } from '@storybook/csf'; import { once } from '@storybook/client-logger'; import { IconButton, Icons, ResetWrapper } from '@storybook/components'; +import { Link } from '@storybook/components/experimental'; import { ArgRow } from './ArgRow'; import { SectionRow } from './SectionRow'; @@ -321,9 +322,9 @@ export const ArgsTable: FC = (props) => { return ( {error}  - {/* + Read the docs - */} + ); } @@ -351,9 +352,9 @@ export const ArgsTable: FC = (props) => { return ( No inputs found for this component.  - {/* + Read the docs - */} + ); } diff --git a/code/ui/blocks/src/components/ArgsTable/Empty.tsx b/code/ui/blocks/src/components/ArgsTable/Empty.tsx index 56e9e28758bb..44fd97eb98c8 100644 --- a/code/ui/blocks/src/components/ArgsTable/Empty.tsx +++ b/code/ui/blocks/src/components/ArgsTable/Empty.tsx @@ -1,9 +1,57 @@ import type { FC } from 'react'; import React from 'react'; import { styled } from '@storybook/theming'; +import { Link } from '@storybook/components/experimental'; const Wrapper = styled.div({ - backgroundColor: 'red', + height: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column', + gap: 15, }); -export const Empty: FC = () => Hello World; +const Content = styled.div({ + display: 'flex', + flexDirection: 'column', + gap: 4, + maxWidth: 415, +}); + +const Title = styled.div(({ theme }) => ({ + fontWeight: theme.typography.weight.bold, + fontSize: theme.typography.size.s2 - 1, + textAlign: 'center', +})); + +const Description = styled.div(({ theme }) => ({ + fontWeight: theme.typography.weight.regular, + fontSize: theme.typography.size.s2 - 1, + textAlign: 'center', +})); + +const Links = styled.div(({ theme }) => ({ + display: 'flex', + gap: 25, +})); + +export const Empty: FC = () => ( + + + Interactive story playground + + Controls give you an easy to use interface to test your components. Set your story args and + you'll see controls appearing here automatically. + + + + + Watch 5m video + + + Read docs + + + +); diff --git a/code/ui/components/src/new/Link/Link.stories.tsx b/code/ui/components/src/new/Link/Link.stories.tsx index 3f303e17c04f..3137bac04399 100644 --- a/code/ui/components/src/new/Link/Link.stories.tsx +++ b/code/ui/components/src/new/Link/Link.stories.tsx @@ -1,93 +1,86 @@ -import type { ComponentProps } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; -import { action } from '@storybook/addon-actions'; + import { Link } from './Link'; import { FakeIcon } from '../FakeIcon'; -const onClick = action('onClick'); - -export default { +const meta: Meta = { + title: 'Link', component: Link, + tags: ['autodocs'], }; -export const CancelWOnClick = { - args: { - href: '/', - onClick, - children: 'Try clicking with different mouse buttons and modifier keys (shift/ctrl/alt/cmd)', - }, - name: 'Cancel w/ onClick', -}; +export default meta; +type Story = StoryObj; -export const CancelWHref = { - args: { - href: 'http://example.com', - children: 'Link', - }, - name: 'Cancel w/ href', +export const Base = { + args: { children: 'Link' }, }; -export const NoCancelWOnClick = { - args: { - href: '/', - children: 'Any click will go through', - onClick, - }, - name: 'No-cancel w/ onClick', -}; - -export const NoCancelWHref = { - args: { - href: 'http://example.com', - children: 'Link', - }, - name: 'No-cancel w/ href', +export const Variants: Story = { + render: () => ( +
+ + Primary + + + Secondary + + + Tertiary + +
+ ), }; -export const StyledLinks = { - render: (args: ComponentProps) => ( -
- - Default +export const Active: Story = { + render: () => ( +
+ + Primary -
- + Secondary -
- - tertiary + + Tertiary + +
+ ), +}; + +export const WithIcon: Story = { + render: () => ( +
+ }> + Primary -
- - nochrome + }> + Secondary -
- - - With icon in front + }> + Tertiary -
- - {/* A linked icon by itself */} - +
+ ), +}; + +export const Sizes: Story = { + render: () => ( +
+ }> + Small Link -
- - With arrow behind + }> + Medium Link -
- - - Inverted colors - - -
), - name: 'Styled links', +}; + +export const Disabled: Story = { + args: { + disabled: true, + children: 'Disabled Link', + }, }; diff --git a/code/ui/components/src/new/Link/Link.test.tsx b/code/ui/components/src/new/Link/Link.test.tsx deleted file mode 100644 index 3dde3ecab07a..000000000000 --- a/code/ui/components/src/new/Link/Link.test.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import type { AnchorHTMLAttributes } from 'react'; -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { ThemeProvider, themes, convert } from '@storybook/theming'; -import type { LinkProps } from './Link'; -import { Link } from './Link'; - -const LEFT_BUTTON = 0; -const MIDDLE_BUTTON = 1; -const RIGHT_BUTTON = 2; - -function ThemedLink(props: LinkProps & AnchorHTMLAttributes) { - return ( - - - - ); -} - -describe('Link', () => { - describe('events', () => { - it('should call onClick on a plain left click', () => { - const handleClick = jest.fn(); - render(Content); - userEvent.click(screen.getByText('Content'), { button: LEFT_BUTTON }); - expect(handleClick).toHaveBeenCalled(); - }); - - it("shouldn't call onClick on a middle click", () => { - const handleClick = jest.fn(); - render(Content); - userEvent.click(screen.getByText('Content'), { button: MIDDLE_BUTTON }); - expect(handleClick).not.toHaveBeenCalled(); - }); - - it("shouldn't call onClick on a right click", () => { - const handleClick = jest.fn(); - render(Content); - userEvent.click(screen.getByText('Content'), { button: RIGHT_BUTTON }); - expect(handleClick).not.toHaveBeenCalled(); - }); - - it("shouldn't call onClick on alt+click", () => { - const handleClick = jest.fn(); - render(Content); - userEvent.click(screen.getByText('Content'), { altKey: true }); - expect(handleClick).not.toHaveBeenCalled(); - }); - - it("shouldn't call onClick on ctrl+click", () => { - const handleClick = jest.fn(); - render(Content); - userEvent.click(screen.getByText('Content'), { ctrlKey: true }); - expect(handleClick).not.toHaveBeenCalled(); - }); - - it("shouldn't call onClick on cmd+click / win+click", () => { - const handleClick = jest.fn(); - render(Content); - userEvent.click(screen.getByText('Content'), { metaKey: true }); - expect(handleClick).not.toHaveBeenCalled(); - }); - - it("shouldn't call onClick on shift+click", () => { - const handleClick = jest.fn(); - render(Content); - userEvent.click(screen.getByText('Content'), { shiftKey: true }); - expect(handleClick).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/code/ui/components/src/new/Link/Link.tsx b/code/ui/components/src/new/Link/Link.tsx index 37de0003f603..cb6520b2212e 100644 --- a/code/ui/components/src/new/Link/Link.tsx +++ b/code/ui/components/src/new/Link/Link.tsx @@ -1,214 +1,66 @@ -import type { AnchorHTMLAttributes, FC, MouseEvent } from 'react'; -import React from 'react'; +import type { MouseEvent, ReactNode } from 'react'; +import React, { forwardRef } from 'react'; import { styled } from '@storybook/theming'; import { darken } from 'polished'; -import { FakeIcon } from '../FakeIcon'; - -// Cmd/Ctrl/Shift/Alt + Click should trigger default browser behavior. Same applies to non-left clicks -const LEFT_BUTTON = 0; - -const isPlainLeftClick = (e: MouseEvent) => - e.button === LEFT_BUTTON && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey; - -const cancelled = (e: MouseEvent, cb: (_e: MouseEvent) => void) => { - if (isPlainLeftClick(e)) { - e.preventDefault(); - cb(e); - } -}; - -export interface LinkStylesProps { - secondary?: boolean; - tertiary?: boolean; - nochrome?: boolean; - inverse?: boolean; - isButton?: boolean; -} - -export interface LinkInnerProps { +import type { PropsOf } from '../utils/types'; + +export interface LinkProps { + as?: T; + children: string; + size?: 'small' | 'medium'; + variant?: 'primary' | 'secondary' | 'tertiary'; + icon?: ReactNode; + onClick?: (e: MouseEvent) => void; withArrow?: boolean; - containsIcon?: boolean; + disabled?: boolean; + active?: boolean; } -const LinkInner = styled.span( - ({ withArrow }) => - withArrow - ? { - '> svg:last-of-type': { - height: '0.7em', - width: '0.7em', - marginRight: 0, - marginLeft: '0.25em', - bottom: 'auto', - verticalAlign: 'inherit', - }, - } - : {}, - ({ containsIcon }) => - containsIcon - ? { - svg: { - height: '1em', - width: '1em', - verticalAlign: 'middle', - position: 'relative', - bottom: 0, - marginRight: 0, - }, - } - : {} -); +export const Link: { + ( + props: LinkProps & Omit, keyof LinkProps> + ): JSX.Element; + displayName?: string; +} = forwardRef(({ as, children, icon, ...props }: LinkProps, ref: React.Ref) => { + return ( + + {icon} + {children} + + ); +}); -type AProps = AnchorHTMLAttributes; +Link.displayName = 'Link'; -const A = styled.a( - ({ theme }) => ({ - display: 'inline-block', +const StyledLink = styled.a>( + ({ theme, variant = 'primary', size = 'medium' }) => ({ + display: 'inline-flex', transition: 'all 150ms ease-out', textDecoration: 'none', - - color: theme.color.secondary, + color: `${(() => { + if (variant === 'primary') return theme.color.secondary; + if (variant === 'secondary') return theme.color.darkest; + if (variant === 'tertiary') return theme.textMutedColor; + return theme.color.secondary; + })()}`, '&:hover, &:focus': { cursor: 'pointer', - color: darken(0.07, theme.color.secondary), - 'svg path': { - fill: darken(0.07, theme.color.secondary), - }, + color: `${(() => { + if (variant === 'primary') return darken(0.07, theme.color.secondary); + if (variant === 'secondary') return theme.color.darkest; + if (variant === 'tertiary') return theme.darkest; + return darken(0.07, theme.color.secondary); + })()}`, }, - '&:active': { - color: darken(0.1, theme.color.secondary), - 'svg path': { - fill: darken(0.1, theme.color.secondary), - }, - }, - - svg: { - display: 'inline-block', - height: '1em', - width: '1em', - verticalAlign: 'text-top', - position: 'relative', - bottom: '-0.125em', - marginRight: '0.4em', - '& path': { - fill: theme.color.secondary, - }, + '&:active': { + color: `${(() => { + if (variant === 'primary') return darken(0.1, theme.color.secondary); + if (variant === 'secondary') return theme.color.darkest; + if (variant === 'tertiary') return theme.textMutedColor; + return darken(0.1, theme.color.secondary); + })()}`, }, - }), - ({ theme, secondary, tertiary }) => { - let colors; - if (secondary) { - colors = [theme.textMutedColor, theme.color.dark, theme.color.darker]; - } - if (tertiary) { - colors = [theme.color.dark, theme.color.darkest, theme.textMutedColor]; - } - - return colors - ? { - color: colors[0], - 'svg path': { - fill: colors[0], - }, - - '&:hover': { - color: colors[1], - 'svg path': { - fill: colors[1], - }, - }, - - '&:active': { - color: colors[2], - 'svg path': { - fill: colors[2], - }, - }, - } - : {}; - }, - ({ nochrome }) => - nochrome - ? { - color: 'inherit', - - '&:hover, &:active': { - color: 'inherit', - textDecoration: 'underline', - }, - } - : {}, - ({ theme, inverse }) => - inverse - ? { - color: theme.color.lightest, - 'svg path': { - fill: theme.color.lightest, - }, - - '&:hover': { - color: theme.color.lighter, - 'svg path': { - fill: theme.color.lighter, - }, - }, - - '&:active': { - color: theme.color.light, - 'svg path': { - fill: theme.color.light, - }, - }, - } - : {}, - ({ isButton }) => - isButton - ? { - border: 0, - borderRadius: 0, - background: 'none', - padding: 0, - fontSize: 'inherit', - } - : {} + }) ); - -export interface LinkProps extends LinkInnerProps, LinkStylesProps { - cancel?: boolean; - className?: string; - style?: object; - onClick?: (e: MouseEvent) => void; - href?: string; -} - -export const Link: FC = ({ - cancel, - children, - onClick, - withArrow, - containsIcon, - className, - ...rest -}) => ( - cancelled(e, onClick) : onClick} - className={className} - > - - {children} - {withArrow && } - - -); - -Link.defaultProps = { - cancel: true, - className: undefined, - style: undefined, - onClick: undefined, - withArrow: false, - containsIcon: false, -}; From 4a717d932bd390de0130e530db204a558708b251 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 16:11:19 +0200 Subject: [PATCH 07/26] Fix links --- code/ui/components/package.json | 12 ++++++------ .../src/{experimantal.ts => experimental.ts} | 0 code/ui/components/src/new/Icon/Icon.tsx | 0 3 files changed, 6 insertions(+), 6 deletions(-) rename code/ui/components/src/{experimantal.ts => experimental.ts} (100%) create mode 100644 code/ui/components/src/new/Icon/Icon.tsx diff --git a/code/ui/components/package.json b/code/ui/components/package.json index 7bb130e5f7c2..b7c2c93af1fd 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -28,10 +28,10 @@ "import": "./dist/index.mjs" }, "./experimental": { - "types": "./dist/experimantal.d.ts", - "node": "./dist/experimantal.js", - "require": "./dist/experimantal.js", - "import": "./dist/experimantal.mjs" + "types": "./dist/experimental.d.ts", + "node": "./dist/experimental.js", + "require": "./dist/experimental.js", + "import": "./dist/experimental.mjs" }, "./html": { "types": "./dist/html.d.ts", @@ -52,7 +52,7 @@ "dist/html.d.ts" ], "experimental": [ - "dist/experimantal.d.ts" + "dist/experimental.d.ts" ] } }, @@ -102,7 +102,7 @@ "bundler": { "entries": [ "./src/index.ts", - "./src/experimantal.ts" + "./src/experimental.ts" ], "platform": "neutral" }, diff --git a/code/ui/components/src/experimantal.ts b/code/ui/components/src/experimental.ts similarity index 100% rename from code/ui/components/src/experimantal.ts rename to code/ui/components/src/experimental.ts diff --git a/code/ui/components/src/new/Icon/Icon.tsx b/code/ui/components/src/new/Icon/Icon.tsx new file mode 100644 index 000000000000..e69de29bb2d1 From 3ed5f7a7bcb7ab9f6a051b5928061a1d5bbe0261 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 16:34:05 +0200 Subject: [PATCH 08/26] Improve Link + Icons --- code/ui/components/package.json | 1 + code/ui/components/src/experimental.ts | 1 + code/ui/components/src/new/Icon/Icon.tsx | 1 + .../components/src/new/Link/Link.stories.tsx | 13 +- code/yarn.lock | 471 ++++++++++++++++-- 5 files changed, 451 insertions(+), 36 deletions(-) diff --git a/code/ui/components/package.json b/code/ui/components/package.json index b7c2c93af1fd..c0b17f363f4e 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -71,6 +71,7 @@ "@storybook/client-logger": "workspace:*", "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.0.6", "@storybook/theming": "workspace:*", "@storybook/types": "workspace:*", "memoizerific": "^1.11.3", diff --git a/code/ui/components/src/experimental.ts b/code/ui/components/src/experimental.ts index ea9cb71aee64..47764d881891 100644 --- a/code/ui/components/src/experimental.ts +++ b/code/ui/components/src/experimental.ts @@ -11,3 +11,4 @@ export { Button } from './new/Button/Button'; export { Input } from './new/Input/Input'; export { Select } from './new/Select/Select'; export { Link } from './new/Link/Link'; +export { Icon } from './new/Icon/Icon'; diff --git a/code/ui/components/src/new/Icon/Icon.tsx b/code/ui/components/src/new/Icon/Icon.tsx index e69de29bb2d1..14219a539c9e 100644 --- a/code/ui/components/src/new/Icon/Icon.tsx +++ b/code/ui/components/src/new/Icon/Icon.tsx @@ -0,0 +1 @@ +export * as Icon from '@storybook/icons'; diff --git a/code/ui/components/src/new/Link/Link.stories.tsx b/code/ui/components/src/new/Link/Link.stories.tsx index 3137bac04399..f3cfd46b4d7e 100644 --- a/code/ui/components/src/new/Link/Link.stories.tsx +++ b/code/ui/components/src/new/Link/Link.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; -import React from 'react'; +import React, { Suspense } from 'react'; +import { Icon } from '@storybook/components/experimental'; import { Link } from './Link'; import { FakeIcon } from '../FakeIcon'; @@ -52,7 +53,15 @@ export const Active: Story = { export const WithIcon: Story = { render: () => (
- }> + Loading
}> + + + } + > Primary }> diff --git a/code/yarn.lock b/code/yarn.lock index 5bcc03f98140..a8035420d6d8 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -2296,7 +2296,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.11.5, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.4, @babel/types@npm:^7.22.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.6.1, @babel/types@npm:^7.7.0, @babel/types@npm:^7.7.2, @babel/types@npm:^7.8.3, @babel/types@npm:^7.8.6, @babel/types@npm:^7.8.7, @babel/types@npm:^7.9.6": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.11.5, @babel/types@npm:^7.12.6, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.4, @babel/types@npm:^7.22.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.6.1, @babel/types@npm:^7.7.0, @babel/types@npm:^7.7.2, @babel/types@npm:^7.8.3, @babel/types@npm:^7.8.6, @babel/types@npm:^7.8.7, @babel/types@npm:^7.9.6": version: 7.22.5 resolution: "@babel/types@npm:7.22.5" dependencies: @@ -6561,6 +6561,7 @@ __metadata: "@storybook/client-logger": "workspace:*" "@storybook/csf": ^0.1.0 "@storybook/global": ^5.0.0 + "@storybook/icons": ^1.0.6 "@storybook/theming": "workspace:*" "@storybook/types": "workspace:*" "@types/react-syntax-highlighter": 11.0.5 @@ -6882,6 +6883,25 @@ __metadata: languageName: unknown linkType: soft +"@storybook/icons@npm:^1.0.6": + version: 1.0.6 + resolution: "@storybook/icons@npm:1.0.6" + dependencies: + "@svgr/core": 5.5.0 + "@svgr/plugin-prettier": 5.5.0 + "@svgr/plugin-svgo": 5.5.0 + axios: 1.4.0 + chalk: 4.1.2 + dotenv: 16.3.1 + figma-api-exporter: 0.0.2 + fs-extra: 11.1.1 + peerDependencies: + react: ">=17" + react-dom: ">=17" + checksum: 481ecafe1af8c11acb54244adc4e15b77ae93b8a16736406953ec4c551181e3a0b85e5e21a25907c5b75e6ac76f3194a23e346a68f09001a052f5f5822807c62 + languageName: node + linkType: hard + "@storybook/instrumenter@workspace:*, @storybook/instrumenter@workspace:lib/instrumenter": version: 0.0.0-use.local resolution: "@storybook/instrumenter@workspace:lib/instrumenter" @@ -8155,6 +8175,131 @@ __metadata: languageName: node linkType: hard +"@svgr/babel-plugin-add-jsx-attribute@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:5.4.0" + checksum: f7f7681f0353a265c85a9fa0a6682c2c39c2eba35d6c855bbf25ea9739b339bf1fdd826b61fb3875642bf607c77bf41e6a66a97a4f07fb6e84bd521a363749e5 + languageName: node + linkType: hard + +"@svgr/babel-plugin-remove-jsx-attribute@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-remove-jsx-attribute@npm:5.4.0" + checksum: 0562c4c1597aecab0248fbd250e45e630de373307468568b7508c78d315a93f29920dffad2f5f54aad8e2aad9da440e16867e54961f3e6402d9855e5fc836948 + languageName: node + linkType: hard + +"@svgr/babel-plugin-remove-jsx-empty-expression@npm:^5.0.1": + version: 5.0.1 + resolution: "@svgr/babel-plugin-remove-jsx-empty-expression@npm:5.0.1" + checksum: 80e2d736528ee553f54916acb9a9a0414e4a06730df420fb2a14788446125728abcb5125bfca6b15ce6fd99771397160f02ec95828871777c1a7803fcf258a44 + languageName: node + linkType: hard + +"@svgr/babel-plugin-replace-jsx-attribute-value@npm:^5.0.1": + version: 5.0.1 + resolution: "@svgr/babel-plugin-replace-jsx-attribute-value@npm:5.0.1" + checksum: fb9e267ba961a0daf1f37f2954552617e09ad1d8e97f033aefc28d2a7d7824831318a5324e8e873341b53c9bb10a0c266665c7871251fd0dd2a8294fe1546fac + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-dynamic-title@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-svg-dynamic-title@npm:5.4.0" + checksum: e6d1a1ef2f4b91473152bf5153a6857585857e7f0e7897df2d18e14d567811814a5590c9d10d80cf3f2964a5b7bd93d3e4cbd15c8d006c5dd83d4e6839646636 + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-em-dimensions@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-svg-em-dimensions@npm:5.4.0" + checksum: 1dc247f376ed110d1407b96c1c919c0bfa2907cd02b2eaa98d40209f21f1ff3602a46f0eb0528e514826a843dc411c06ed251cf8c691efbc961f0cbe0aaf860d + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-react-native-svg@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-transform-react-native-svg@npm:5.4.0" + checksum: 3ad2f074d0e5857d07758492d0c98d1d862f2def9fab48939c69c5a3c4387065d01b0e8ac62c53a402a9ce09ed3de099bdf41cd2a597e7d58ddf47fb3a3b2c3e + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-svg-component@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/babel-plugin-transform-svg-component@npm:5.5.0" + checksum: 73bfb09933d4a85a0ee8ec364684a0915a9ce05e668d024c073369cc36d78dcde41ddcdb493dde6440f5ee5649ed75b95ac8add226eaee32b20dc54894ac2974 + languageName: node + linkType: hard + +"@svgr/babel-preset@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/babel-preset@npm:5.5.0" + dependencies: + "@svgr/babel-plugin-add-jsx-attribute": ^5.4.0 + "@svgr/babel-plugin-remove-jsx-attribute": ^5.4.0 + "@svgr/babel-plugin-remove-jsx-empty-expression": ^5.0.1 + "@svgr/babel-plugin-replace-jsx-attribute-value": ^5.0.1 + "@svgr/babel-plugin-svg-dynamic-title": ^5.4.0 + "@svgr/babel-plugin-svg-em-dimensions": ^5.4.0 + "@svgr/babel-plugin-transform-react-native-svg": ^5.4.0 + "@svgr/babel-plugin-transform-svg-component": ^5.5.0 + checksum: a737592044ee3aea22506fa7178464fc0e1e6e6f3005cbc8db12d6963f18b8a097c97a2d4ede93dd1d3309074f84f47272924614cd74d2c7900c649f0356e349 + languageName: node + linkType: hard + +"@svgr/core@npm:5.5.0": + version: 5.5.0 + resolution: "@svgr/core@npm:5.5.0" + dependencies: + "@svgr/plugin-jsx": ^5.5.0 + camelcase: ^6.2.0 + cosmiconfig: ^7.0.0 + checksum: a8f8ac7f829ea92a6d0305c746afb33feba3b1c7000e6f22d83b8bad13fdcd5aacc3ebde60330368830eebf23ff3090ddd3ef959d41a90d694f4b7914aea6686 + languageName: node + linkType: hard + +"@svgr/hast-util-to-babel-ast@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/hast-util-to-babel-ast@npm:5.5.0" + dependencies: + "@babel/types": ^7.12.6 + checksum: 1758afd99594b094ec3d0966ba0e81e5ca8acea075801b8a93c5e97269b046eca1fd8dac7c7efbc3b5775e2496adb6880530fd1d6ccaaf8792afd567773a4f64 + languageName: node + linkType: hard + +"@svgr/plugin-jsx@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/plugin-jsx@npm:5.5.0" + dependencies: + "@babel/core": ^7.12.3 + "@svgr/babel-preset": ^5.5.0 + "@svgr/hast-util-to-babel-ast": ^5.5.0 + svg-parser: ^2.0.2 + checksum: 96f84139dae94cdda7e24896ab23e9d41e699fc8ecbbd11e280604eb7a67dfec55f126ec12ea3c622b8df6b0fccce5eb261d96f6ca8c59366d3963f13e411ec6 + languageName: node + linkType: hard + +"@svgr/plugin-prettier@npm:5.5.0": + version: 5.5.0 + resolution: "@svgr/plugin-prettier@npm:5.5.0" + dependencies: + deepmerge: ^4.2.2 + prettier: ^2.1.2 + checksum: 0b83c229d2f19e1820ab06ec7956a13fd8166ae093a60bf1d70f87150f393dd216e1bd1a8f9c03d6d59f199d30b383d2c1a48a448520d05cecb80e43ed5afdd3 + languageName: node + linkType: hard + +"@svgr/plugin-svgo@npm:5.5.0": + version: 5.5.0 + resolution: "@svgr/plugin-svgo@npm:5.5.0" + dependencies: + cosmiconfig: ^7.0.0 + deepmerge: ^4.2.2 + svgo: ^1.2.2 + checksum: 7494f7417ac339422f4eb2219489badaa51cdd79de2b5b3ff772c602036c5a38faf92fdefaab47414175f7c83406c4db195c35e619aae88d0573d7b199ec4503 + languageName: node + linkType: hard + "@swc/core-darwin-arm64@npm:1.3.71": version: 1.3.71 resolution: "@swc/core-darwin-arm64@npm:1.3.71" @@ -9139,6 +9284,13 @@ __metadata: languageName: node linkType: hard +"@types/q@npm:^1.5.1": + version: 1.5.5 + resolution: "@types/q@npm:1.5.5" + checksum: 0a22134a75de86196adf4ad1052f35fdbb9d8a053b2034fb97f328b30ada26f321d7241681cd1cb76e8311f7ead85cc88aa65a42d316828a4a813caed4b55e7c + languageName: node + linkType: hard + "@types/qs@npm:*, @types/qs@npm:^6, @types/qs@npm:^6.9.5": version: 6.9.7 resolution: "@types/qs@npm:6.9.7" @@ -10858,6 +11010,19 @@ __metadata: languageName: node linkType: hard +"array.prototype.reduce@npm:^1.0.5": + version: 1.0.5 + resolution: "array.prototype.reduce@npm:1.0.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + es-array-method-boxes-properly: ^1.0.0 + is-string: ^1.0.7 + checksum: 0c6c589d22d6cda4a32458c6fd57a41f420a4fa6cd184a3f6fe7b507f457bc4a073aff6accd595bcd6ac29cad856e7ac306549f127acdb098f401eea13c54901 + languageName: node + linkType: hard + "array.prototype.tosorted@npm:^1.1.1": version: 1.1.1 resolution: "array.prototype.tosorted@npm:1.1.1" @@ -11115,17 +11280,7 @@ __metadata: languageName: node linkType: hard -"axios@npm:^0.27.2": - version: 0.27.2 - resolution: "axios@npm:0.27.2" - dependencies: - follow-redirects: ^1.14.9 - form-data: ^4.0.0 - checksum: 76d673d2a90629944b44d6f345f01e58e9174690f635115d5ffd4aca495d99bcd8f95c590d5ccb473513f5ebc1d1a6e8934580d0c57cdd0498c3a101313ef771 - languageName: node - linkType: hard - -"axios@npm:^1.0.0": +"axios@npm:1.4.0, axios@npm:^1.0.0": version: 1.4.0 resolution: "axios@npm:1.4.0" dependencies: @@ -11136,6 +11291,34 @@ __metadata: languageName: node linkType: hard +"axios@npm:^0.19.1": + version: 0.19.2 + resolution: "axios@npm:0.19.2" + dependencies: + follow-redirects: 1.5.10 + checksum: b775abf2db44ea4f182f4c2bfa4bf84a723b86f5aa001f222f12193fa45ba243b7e3f27b66289c6afa51d696402b05c82715fd621a34add5b538e850adcdbce1 + languageName: node + linkType: hard + +"axios@npm:^0.21.1": + version: 0.21.4 + resolution: "axios@npm:0.21.4" + dependencies: + follow-redirects: ^1.14.0 + checksum: fbcff55ec68f71f02d3773d467db2fcecdf04e749826c82c2427a232f9eba63242150a05f15af9ef15818352b814257541155de0281f8fb2b7e8a5b79f7f2142 + languageName: node + linkType: hard + +"axios@npm:^0.27.2": + version: 0.27.2 + resolution: "axios@npm:0.27.2" + dependencies: + follow-redirects: ^1.14.9 + form-data: ^4.0.0 + checksum: 76d673d2a90629944b44d6f345f01e58e9174690f635115d5ffd4aca495d99bcd8f95c590d5ccb473513f5ebc1d1a6e8934580d0c57cdd0498c3a101313ef771 + languageName: node + linkType: hard + "axobject-query@npm:^3.1.1, axobject-query@npm:^3.2.1": version: 3.2.1 resolution: "axobject-query@npm:3.2.1" @@ -11660,7 +11843,7 @@ __metadata: languageName: node linkType: hard -"boolbase@npm:^1.0.0": +"boolbase@npm:^1.0.0, boolbase@npm:~1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" checksum: e4b53deb4f2b85c52be0e21a273f2045c7b6a6ea002b0e139c744cb6f95e9ec044439a52883b0d74dedd1ff3da55ed140cfdddfed7fb0cccbed373de5dce1bcf @@ -12388,6 +12571,16 @@ __metadata: languageName: node linkType: hard +"chalk@npm:4.1.2, chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.1, chalk@npm:^4.1.2": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: 4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 + languageName: node + linkType: hard + "chalk@npm:5.2.0": version: 5.2.0 resolution: "chalk@npm:5.2.0" @@ -12395,7 +12588,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.0.0, chalk@npm:^2.1.0, chalk@npm:^2.3.0, chalk@npm:^2.4.2": +"chalk@npm:^2.0.0, chalk@npm:^2.1.0, chalk@npm:^2.3.0, chalk@npm:^2.4.1, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -12416,16 +12609,6 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.1, chalk@npm:^4.1.2": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: ^4.1.0 - supports-color: ^7.1.0 - checksum: 4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 - languageName: node - linkType: hard - "chalk@npm:^5.2.0": version: 5.3.0 resolution: "chalk@npm:5.3.0" @@ -12867,6 +13050,17 @@ __metadata: languageName: node linkType: hard +"coa@npm:^2.0.2": + version: 2.0.2 + resolution: "coa@npm:2.0.2" + dependencies: + "@types/q": ^1.5.1 + chalk: ^2.4.1 + q: ^1.1.2 + checksum: 0264392e3b691a8551e619889f3e67558b4f755eeb09d67625032a25c37634731e778fabbd9d14df6477d6ae770e30ea9405d18e515b2ec492b0eb90bb8d7f43 + languageName: node + linkType: hard + "code-red@npm:^1.0.3": version: 1.0.3 resolution: "code-red@npm:1.0.3" @@ -13627,6 +13821,25 @@ __metadata: languageName: node linkType: hard +"css-select-base-adapter@npm:^0.1.1": + version: 0.1.1 + resolution: "css-select-base-adapter@npm:0.1.1" + checksum: 17f28a0d9e8596c541de250e48958e72a65399c9e15ba5689915d6631a451068187c19d674f08187843a61cb949951cb33c7db82bd7341536769523baed867dc + languageName: node + linkType: hard + +"css-select@npm:^2.0.0": + version: 2.1.0 + resolution: "css-select@npm:2.1.0" + dependencies: + boolbase: ^1.0.0 + css-what: ^3.2.1 + domutils: ^1.7.0 + nth-check: ^1.0.2 + checksum: 47832492c8218ffd92ed18eaa325397bd0bd8e4bcf3bc71767c5e1ed8b4f39b672ba157b0b5e693ef50006017d78c19e46791a75b43bb192c4db3680a331afc7 + languageName: node + linkType: hard + "css-select@npm:^4.1.3": version: 4.3.0 resolution: "css-select@npm:4.3.0" @@ -13660,6 +13873,26 @@ __metadata: languageName: node linkType: hard +"css-tree@npm:1.0.0-alpha.37": + version: 1.0.0-alpha.37 + resolution: "css-tree@npm:1.0.0-alpha.37" + dependencies: + mdn-data: 2.0.4 + source-map: ^0.6.1 + checksum: 8f3c197baea919f4f55d0e84b1665d5e7d5fd74cb192fd0bf951828929b9cd5fd71de074afb685705bf5b40d7b04d4c5a206bfab26954378f04f2f5ce426d2f8 + languageName: node + linkType: hard + +"css-tree@npm:^1.1.2": + version: 1.1.3 + resolution: "css-tree@npm:1.1.3" + dependencies: + mdn-data: 2.0.14 + source-map: ^0.6.1 + checksum: 499a507bfa39b8b2128f49736882c0dd636b0cd3370f2c69f4558ec86d269113286b7df469afc955de6a68b0dba00bc533e40022a73698081d600072d5d83c1c + languageName: node + linkType: hard + "css-tree@npm:^2.0.1, css-tree@npm:^2.3.1": version: 2.3.1 resolution: "css-tree@npm:2.3.1" @@ -13670,6 +13903,13 @@ __metadata: languageName: node linkType: hard +"css-what@npm:^3.2.1": + version: 3.4.2 + resolution: "css-what@npm:3.4.2" + checksum: 454dca1b9dff8cf740d666d24a6c517562f374fe3a160891ebf8c82a9dd76864757913573c4db30537a959f5f595750420be00552ea6d5a9456ee68acc2349bf + languageName: node + linkType: hard + "css-what@npm:^6.0.1, css-what@npm:^6.1.0": version: 6.1.0 resolution: "css-what@npm:6.1.0" @@ -13716,6 +13956,15 @@ __metadata: languageName: node linkType: hard +"csso@npm:^4.0.2": + version: 4.2.0 + resolution: "csso@npm:4.2.0" + dependencies: + css-tree: ^1.1.2 + checksum: f8c6b1300efaa0f8855a7905ae3794a29c6496e7f16a71dec31eb6ca7cfb1f058a4b03fd39b66c4deac6cb06bf6b4ba86da7b67d7320389cb9994d52b924b903 + languageName: node + linkType: hard + "cssom@npm:^0.5.0": version: 0.5.0 resolution: "cssom@npm:0.5.0" @@ -13884,6 +14133,15 @@ __metadata: languageName: node linkType: hard +"debug@npm:=3.1.0": + version: 3.1.0 + resolution: "debug@npm:3.1.0" + dependencies: + ms: 2.0.0 + checksum: 5bff34a352d7b2eaa31886eeaf2ee534b5461ec0548315b2f9f80bd1d2533cab7df1fa52e130ce27bc31c3945fbffb0fc72baacdceb274b95ce853db89254ea4 + languageName: node + linkType: hard + "debug@npm:^3.2.6, debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" @@ -14462,7 +14720,7 @@ __metadata: languageName: node linkType: hard -"domutils@npm:^1.5.1": +"domutils@npm:^1.5.1, domutils@npm:^1.7.0": version: 1.7.0 resolution: "domutils@npm:1.7.0" dependencies: @@ -14529,7 +14787,7 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^16.0.0": +"dotenv@npm:16.3.1, dotenv@npm:^16.0.0": version: 16.3.1 resolution: "dotenv@npm:16.3.1" checksum: b95ff1bbe624ead85a3cd70dbd827e8e06d5f05f716f2d0cbc476532d54c7c9469c3bc4dd93ea519f6ad711cb522c00ac9a62b6eb340d5affae8008facc3fbd7 @@ -15094,7 +15352,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.20.4": +"es-abstract@npm:^1.17.2, es-abstract@npm:^1.19.0, es-abstract@npm:^1.20.4, es-abstract@npm:^1.21.2": version: 1.22.1 resolution: "es-abstract@npm:1.22.1" dependencies: @@ -16395,6 +16653,36 @@ __metadata: languageName: node linkType: hard +"figma-api-exporter@npm:0.0.2": + version: 0.0.2 + resolution: "figma-api-exporter@npm:0.0.2" + dependencies: + axios: ^0.19.1 + figma-js: ^1.9.0 + figma-transformer: ^1.0.0 + fs: ^0.0.1-security + ramda: ^0.26.1 + rimraf: ^3.0.0 + checksum: 346b8731d4ad3bb50a5743341735c36d3249487b5f2a594952bf22b07991b6333e9eb4ae43bcbc3177eeab4bb90dba803fd4d165cca67f281fed26ebebe0c743 + languageName: node + linkType: hard + +"figma-js@npm:^1.9.0": + version: 1.16.0 + resolution: "figma-js@npm:1.16.0" + dependencies: + axios: ^0.21.1 + checksum: d806bc10d2cf345d45aac2fde72bb41e45b0f290f76674f7f3a99d87dbac212d166bdb17034edfdfa0ebed4e5c9e1deb1b48f5e033f38978e1f8b73dfe91603e + languageName: node + linkType: hard + +"figma-transformer@npm:^1.0.0": + version: 1.0.0 + resolution: "figma-transformer@npm:1.0.0" + checksum: 81022133c7e2cf8af71af1acd65e7d94adf45d8ce048b83aa2c4c0b6aeaba65456bd021d2967f71838eb1279881748a3741e3cae3083dc6b1f887f2d9e42ec65 + languageName: node + linkType: hard + "figures@npm:3.2.0, figures@npm:^3.0.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -16674,7 +16962,16 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": +"follow-redirects@npm:1.5.10": + version: 1.5.10 + resolution: "follow-redirects@npm:1.5.10" + dependencies: + debug: =3.1.0 + checksum: f56ca26dcf3c9996a6cf8868b61e369a35d4000ade0292bdd27b5e0934902681b037060b9fabe58e7042bb8b85166d5db8bbcf027f1825c1577e4cffd904fd3f + languageName: node + linkType: hard + +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": version: 1.15.2 resolution: "follow-redirects@npm:1.15.2" peerDependenciesMeta: @@ -16992,6 +17289,13 @@ __metadata: languageName: node linkType: hard +"fs@npm:^0.0.1-security": + version: 0.0.1-security + resolution: "fs@npm:0.0.1-security" + checksum: e0c0b585ec6f7483d63d067215d9d6bb2e0dba5912060d32554c8e566a0e22ee65e4c2a2b0567476efbbfb47682554b4711d69cab49950d01f227a3dfa7d671a + languageName: node + linkType: hard + "fsevents@npm:2.3.2, fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" @@ -17786,7 +18090,7 @@ __metadata: languageName: node linkType: hard -"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": +"has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": version: 1.0.3 resolution: "has-symbols@npm:1.0.3" checksum: e6922b4345a3f37069cdfe8600febbca791c94988c01af3394d86ca3360b4b93928bbf395859158f88099cb10b19d98e3bbab7c9ff2c1bd09cf665ee90afa2c3 @@ -21885,6 +22189,13 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.0.14": + version: 2.0.14 + resolution: "mdn-data@npm:2.0.14" + checksum: 67241f8708c1e665a061d2b042d2d243366e93e5bf1f917693007f6d55111588b952dcbfd3ea9c2d0969fb754aad81b30fdcfdcc24546495fc3b24336b28d4bd + languageName: node + linkType: hard + "mdn-data@npm:2.0.30": version: 2.0.30 resolution: "mdn-data@npm:2.0.30" @@ -21892,6 +22203,13 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.0.4": + version: 2.0.4 + resolution: "mdn-data@npm:2.0.4" + checksum: a935c4530b938407481f7d0ccb82119ae618d9c673d2ee78bb10dcba8bd0ccbe2e2c7fe850ddc60b67e08f4c9d97f50b900993f6c2f2926e64a52ed6baa00b3a + languageName: node + linkType: hard + "media-typer@npm:0.3.0": version: 0.3.0 resolution: "media-typer@npm:0.3.0" @@ -22801,7 +23119,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^0.5.0, mkdirp@npm:^0.5.1, mkdirp@npm:^0.5.4, mkdirp@npm:^0.5.6": +"mkdirp@npm:^0.5.0, mkdirp@npm:^0.5.1, mkdirp@npm:^0.5.4, mkdirp@npm:^0.5.6, mkdirp@npm:~0.5.1": version: 0.5.6 resolution: "mkdirp@npm:0.5.6" dependencies: @@ -23638,6 +23956,15 @@ __metadata: languageName: node linkType: hard +"nth-check@npm:^1.0.2": + version: 1.0.2 + resolution: "nth-check@npm:1.0.2" + dependencies: + boolbase: ~1.0.0 + checksum: 1a67ce53a99e276eea672f892d712b29f3e6802bbbef7285ffab72ecea4f972e8244defac1ebded0daffabf459def31355bb9c64e5657ac2ab032c13f185d0fd + languageName: node + linkType: hard + "nth-check@npm:^2.0.0, nth-check@npm:^2.0.1": version: 2.1.1 resolution: "nth-check@npm:2.1.1" @@ -23927,6 +24254,19 @@ __metadata: languageName: node linkType: hard +"object.getownpropertydescriptors@npm:^2.1.0": + version: 2.1.6 + resolution: "object.getownpropertydescriptors@npm:2.1.6" + dependencies: + array.prototype.reduce: ^1.0.5 + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.21.2 + safe-array-concat: ^1.0.0 + checksum: 9c401557a1cd47d873810b8df61dba350bc39848753180a2c7bdc8b9a67907b7c12e5aa9318fde7fe68d3b62c88b9cbd729b3cc8bbdf02655619b9d2a99b5c2a + languageName: node + linkType: hard + "object.hasown@npm:^1.1.2": version: 1.1.2 resolution: "object.hasown@npm:1.1.2" @@ -23946,7 +24286,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.1, object.values@npm:^1.1.5, object.values@npm:^1.1.6": +"object.values@npm:^1.1.0, object.values@npm:^1.1.1, object.values@npm:^1.1.5, object.values@npm:^1.1.6": version: 1.1.6 resolution: "object.values@npm:1.1.6" dependencies: @@ -25291,7 +25631,7 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^1.18.2 || ^2.0.0, prettier@npm:^2.8.0": +"prettier@npm:^1.18.2 || ^2.0.0, prettier@npm:^2.1.2, prettier@npm:^2.8.0": version: 2.8.8 resolution: "prettier@npm:2.8.8" bin: @@ -25831,7 +26171,7 @@ __metadata: languageName: node linkType: hard -"q@npm:^1.5.1": +"q@npm:^1.1.2, q@npm:^1.5.1": version: 1.5.1 resolution: "q@npm:1.5.1" checksum: 7855fbdba126cb7e92ef3a16b47ba998c0786ec7fface236e3eb0135b65df36429d91a86b1fff3ab0927b4ac4ee88a2c44527c7c3b8e2a37efbec9fe34803df4 @@ -25953,6 +26293,13 @@ __metadata: languageName: node linkType: hard +"ramda@npm:^0.26.1": + version: 0.26.1 + resolution: "ramda@npm:0.26.1" + checksum: af591bdb593a7bd4c715af306f9a1c591ed0eccabc9bb5166dd17e68b182e6ff313b35c057f9dc300715d060c3ed2f56e424a42499fe2b27b40446fb447838ba + languageName: node + linkType: hard + "randexp@npm:0.4.6": version: 0.4.6 resolution: "randexp@npm:0.4.6" @@ -27705,7 +28052,7 @@ __metadata: languageName: node linkType: hard -"sax@npm:^1.2.4": +"sax@npm:^1.2.4, sax@npm:~1.2.4": version: 1.2.4 resolution: "sax@npm:1.2.4" checksum: 6e9b05ff443ee5e5096ce92d31c0740a20d33002fad714ebcb8fc7a664d9ee159103ebe8f7aef0a1f7c5ecacdd01f177f510dff95611c589399baf76437d3fe3 @@ -28577,6 +28924,13 @@ __metadata: languageName: node linkType: hard +"stable@npm:^0.1.8": + version: 0.1.8 + resolution: "stable@npm:0.1.8" + checksum: df74b5883075076e78f8e365e4068ecd977af6c09da510cfc3148a303d4b87bc9aa8f7c48feb67ed4ef970b6140bd9eabba2129e28024aa88df5ea0114cba39d + languageName: node + linkType: hard + "stack-utils@npm:^2.0.3": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" @@ -29173,6 +29527,36 @@ __metadata: languageName: node linkType: hard +"svg-parser@npm:^2.0.2": + version: 2.0.4 + resolution: "svg-parser@npm:2.0.4" + checksum: 02f6cb155dd7b63ebc2f44f36365bc294543bebb81b614b7628f1af3c54ab64f7e1cec20f06e252bf95bdde78441ae295a412c68ad1678f16a6907d924512b7a + languageName: node + linkType: hard + +"svgo@npm:^1.2.2": + version: 1.3.2 + resolution: "svgo@npm:1.3.2" + dependencies: + chalk: ^2.4.1 + coa: ^2.0.2 + css-select: ^2.0.0 + css-select-base-adapter: ^0.1.1 + css-tree: 1.0.0-alpha.37 + csso: ^4.0.2 + js-yaml: ^3.13.1 + mkdirp: ~0.5.1 + object.values: ^1.1.0 + sax: ~1.2.4 + stable: ^0.1.8 + unquote: ~1.1.1 + util.promisify: ~1.0.0 + bin: + svgo: ./bin/svgo + checksum: 261a82b08acf63accd7a54b47b4ffcd2fc7e7d7f8efef3cbc61184583b24b4c5434656004c30190302821af0f6d7b047eac730b0dcdab5d179e6a74383ccc776 + languageName: node + linkType: hard + "swc-loader@npm:^0.2.3": version: 0.2.3 resolution: "swc-loader@npm:0.2.3" @@ -30510,6 +30894,13 @@ __metadata: languageName: node linkType: hard +"unquote@npm:~1.1.1": + version: 1.1.1 + resolution: "unquote@npm:1.1.1" + checksum: de59fb48cbaadc636002c6563dcb6b1bce95c91ebecb92addbc9bb47982cb03e7d8a8371c9617267b9e5746bbcb4403394139bc1310106b9ac4c26790ed57859 + languageName: node + linkType: hard + "unset-value@npm:^1.0.0": version: 1.0.0 resolution: "unset-value@npm:1.0.0" @@ -30699,6 +31090,18 @@ __metadata: languageName: node linkType: hard +"util.promisify@npm:~1.0.0": + version: 1.0.1 + resolution: "util.promisify@npm:1.0.1" + dependencies: + define-properties: ^1.1.3 + es-abstract: ^1.17.2 + has-symbols: ^1.0.1 + object.getownpropertydescriptors: ^2.1.0 + checksum: d72b7c1344816bc9c8713efbf5cb23b536730a8fb7df9ae50654d9efa4d24241fc5ecc69a7dc63b9a2f98cabc9635c303923671933f8c6f41fa7d64fe2188e27 + languageName: node + linkType: hard + "util@npm:^0.12.0, util@npm:^0.12.4": version: 0.12.5 resolution: "util@npm:0.12.5" From 89ecd7ee783d4175a4aab4401d5bcc80752f9a14 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 17:49:03 +0200 Subject: [PATCH 09/26] Icons are now working :) --- code/ui/components/package.json | 2 +- .../src/new/Button/Button.stories.tsx | 40 +++++++++---------- .../components/src/new/Link/Link.stories.tsx | 21 +++------- code/ui/manager/src/globals/exports.ts | 2 +- code/yarn.lock | 10 ++--- 5 files changed, 33 insertions(+), 42 deletions(-) diff --git a/code/ui/components/package.json b/code/ui/components/package.json index c0b17f363f4e..bc28eef2f094 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -71,7 +71,7 @@ "@storybook/client-logger": "workspace:*", "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.0.6", + "@storybook/icons": "^1.0.8", "@storybook/theming": "workspace:*", "@storybook/types": "workspace:*", "memoizerific": "^1.11.3", diff --git a/code/ui/components/src/new/Button/Button.stories.tsx b/code/ui/components/src/new/Button/Button.stories.tsx index 334472eec573..b88e16348e8a 100644 --- a/code/ui/components/src/new/Button/Button.stories.tsx +++ b/code/ui/components/src/new/Button/Button.stories.tsx @@ -1,8 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; +import { Icon } from '@storybook/components/experimental'; import { Button } from './Button'; -import { FakeIcon } from '../FakeIcon'; const meta: Meta = { title: 'Button', @@ -46,13 +46,13 @@ export const Active: Story = { export const WithIcon: Story = { render: () => (
- - -
@@ -62,16 +62,16 @@ export const WithIcon: Story = { export const Sizes: Story = { render: () => (
- - - -
@@ -91,22 +91,22 @@ export const IconOnly: Story = { }, render: () => ( <> - - - - - - @@ -119,22 +119,22 @@ export const IconOnly: Story = { export const IconOnlyActive: Story = { render: () => (
- - - - - -
diff --git a/code/ui/components/src/new/Link/Link.stories.tsx b/code/ui/components/src/new/Link/Link.stories.tsx index f3cfd46b4d7e..194b878e3d18 100644 --- a/code/ui/components/src/new/Link/Link.stories.tsx +++ b/code/ui/components/src/new/Link/Link.stories.tsx @@ -1,9 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react'; -import React, { Suspense } from 'react'; +import React from 'react'; import { Icon } from '@storybook/components/experimental'; import { Link } from './Link'; -import { FakeIcon } from '../FakeIcon'; const meta: Meta = { title: 'Link', @@ -53,21 +52,13 @@ export const Active: Story = { export const WithIcon: Story = { render: () => (
- Loading
}> - - - } - > + }> Primary - }> + }> Secondary - }> + }> Tertiary
@@ -77,10 +68,10 @@ export const WithIcon: Story = { export const Sizes: Story = { render: () => (
- }> + }> Small Link - }> + }> Medium Link
diff --git a/code/ui/manager/src/globals/exports.ts b/code/ui/manager/src/globals/exports.ts index 505b077e5eef..ffd247fdd30d 100644 --- a/code/ui/manager/src/globals/exports.ts +++ b/code/ui/manager/src/globals/exports.ts @@ -114,7 +114,7 @@ export default { 'resetComponents', 'withReset', ], - '@storybook/components/experimental': ['Button', 'Input', 'Link', 'Select'], + '@storybook/components/experimental': ['Button', 'Icon', 'Input', 'Link', 'Select'], '@storybook/channels': [ 'Channel', 'PostMessageTransport', diff --git a/code/yarn.lock b/code/yarn.lock index a8035420d6d8..3ea6f98f8656 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6561,7 +6561,7 @@ __metadata: "@storybook/client-logger": "workspace:*" "@storybook/csf": ^0.1.0 "@storybook/global": ^5.0.0 - "@storybook/icons": ^1.0.6 + "@storybook/icons": ^1.0.8 "@storybook/theming": "workspace:*" "@storybook/types": "workspace:*" "@types/react-syntax-highlighter": 11.0.5 @@ -6883,9 +6883,9 @@ __metadata: languageName: unknown linkType: soft -"@storybook/icons@npm:^1.0.6": - version: 1.0.6 - resolution: "@storybook/icons@npm:1.0.6" +"@storybook/icons@npm:^1.0.8": + version: 1.0.8 + resolution: "@storybook/icons@npm:1.0.8" dependencies: "@svgr/core": 5.5.0 "@svgr/plugin-prettier": 5.5.0 @@ -6898,7 +6898,7 @@ __metadata: peerDependencies: react: ">=17" react-dom: ">=17" - checksum: 481ecafe1af8c11acb54244adc4e15b77ae93b8a16736406953ec4c551181e3a0b85e5e21a25907c5b75e6ac76f3194a23e346a68f09001a052f5f5822807c62 + checksum: fc1931f156dc3305fde19ba558e67c1601241293c8186ed8cc54040a15987dec9d5813595c4021c39afca999a524873f8f799ceb5c79181d7e00452463147f1a languageName: node linkType: hard From 75935b925c7f365c38468c115ba5f84038f88197 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 22:06:45 +0200 Subject: [PATCH 10/26] Improve Link component --- .../components/src/new/Link/Link.stories.tsx | 70 +++++++++------- code/ui/components/src/new/Link/Link.tsx | 82 ++++++++++--------- 2 files changed, 81 insertions(+), 71 deletions(-) diff --git a/code/ui/components/src/new/Link/Link.stories.tsx b/code/ui/components/src/new/Link/Link.stories.tsx index 194b878e3d18..d90438b9bfd4 100644 --- a/code/ui/components/src/new/Link/Link.stories.tsx +++ b/code/ui/components/src/new/Link/Link.stories.tsx @@ -33,22 +33,6 @@ export const Variants: Story = { ), }; -export const Active: Story = { - render: () => ( -
- - Primary - - - Secondary - - - Tertiary - -
- ), -}; - export const WithIcon: Story = { render: () => (
@@ -65,22 +49,46 @@ export const WithIcon: Story = { ), }; -export const Sizes: Story = { +export const WithArrow: Story = { render: () => ( -
- }> - Small Link - - }> - Medium Link - +
+
+ + Primary + + + Secondary + + + Tertiary + +
+
+ } + withArrow + > + Primary + + } + withArrow + > + Secondary + + } + withArrow + > + Tertiary + +
), }; - -export const Disabled: Story = { - args: { - disabled: true, - children: 'Disabled Link', - }, -}; diff --git a/code/ui/components/src/new/Link/Link.tsx b/code/ui/components/src/new/Link/Link.tsx index cb6520b2212e..e9965330a3e8 100644 --- a/code/ui/components/src/new/Link/Link.tsx +++ b/code/ui/components/src/new/Link/Link.tsx @@ -2,18 +2,16 @@ import type { MouseEvent, ReactNode } from 'react'; import React, { forwardRef } from 'react'; import { styled } from '@storybook/theming'; import { darken } from 'polished'; +import { Icon } from '@storybook/components/experimental'; import type { PropsOf } from '../utils/types'; export interface LinkProps { as?: T; children: string; - size?: 'small' | 'medium'; variant?: 'primary' | 'secondary' | 'tertiary'; icon?: ReactNode; onClick?: (e: MouseEvent) => void; withArrow?: boolean; - disabled?: boolean; - active?: boolean; } export const Link: { @@ -21,46 +19,50 @@ export const Link: { props: LinkProps & Omit, keyof LinkProps> ): JSX.Element; displayName?: string; -} = forwardRef(({ as, children, icon, ...props }: LinkProps, ref: React.Ref) => { - return ( - - {icon} - {children} - - ); -}); +} = forwardRef( + ({ as, children, icon, withArrow, ...props }: LinkProps, ref: React.Ref) => { + return ( + + {icon} + {children} + {withArrow && } + + ); + } +); Link.displayName = 'Link'; -const StyledLink = styled.a>( - ({ theme, variant = 'primary', size = 'medium' }) => ({ - display: 'inline-flex', - transition: 'all 150ms ease-out', - textDecoration: 'none', +const StyledLink = styled.a>(({ theme, variant = 'primary' }) => ({ + display: 'inline-flex', + gap: 5, + alignItems: 'center', + fontSize: theme.typography.size.s3, + transition: 'all 150ms ease-out', + textDecoration: 'none', + color: `${(() => { + if (variant === 'primary') return theme.color.secondary; + if (variant === 'secondary') return theme.textMutedColor; + if (variant === 'tertiary') return theme.color.dark; + return theme.color.secondary; + })()}`, + + '&:hover, &:focus': { + cursor: 'pointer', color: `${(() => { - if (variant === 'primary') return theme.color.secondary; - if (variant === 'secondary') return theme.color.darkest; - if (variant === 'tertiary') return theme.textMutedColor; - return theme.color.secondary; + if (variant === 'primary') return darken(0.07, theme.color.secondary); + if (variant === 'secondary') return theme.color.dark; + if (variant === 'tertiary') return theme.color.darkest; + return darken(0.07, theme.color.secondary); })()}`, + }, - '&:hover, &:focus': { - cursor: 'pointer', - color: `${(() => { - if (variant === 'primary') return darken(0.07, theme.color.secondary); - if (variant === 'secondary') return theme.color.darkest; - if (variant === 'tertiary') return theme.darkest; - return darken(0.07, theme.color.secondary); - })()}`, - }, - - '&:active': { - color: `${(() => { - if (variant === 'primary') return darken(0.1, theme.color.secondary); - if (variant === 'secondary') return theme.color.darkest; - if (variant === 'tertiary') return theme.textMutedColor; - return darken(0.1, theme.color.secondary); - })()}`, - }, - }) -); + '&:active': { + color: `${(() => { + if (variant === 'primary') return darken(0.1, theme.color.secondary); + if (variant === 'secondary') return theme.color.darker; + if (variant === 'tertiary') return theme.textMutedColor; + return darken(0.1, theme.color.secondary); + })()}`, + }, +})); From d156fb971eb7ffe63a07f1b90a114bb832b67171 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 22:25:26 +0200 Subject: [PATCH 11/26] Improve Link --- .../blocks/src/components/ArgsTable/Empty.tsx | 33 +++++++++++++++++-- code/ui/components/src/new/Link/Link.tsx | 3 +- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/code/ui/blocks/src/components/ArgsTable/Empty.tsx b/code/ui/blocks/src/components/ArgsTable/Empty.tsx index 44fd97eb98c8..de44fde66a39 100644 --- a/code/ui/blocks/src/components/ArgsTable/Empty.tsx +++ b/code/ui/blocks/src/components/ArgsTable/Empty.tsx @@ -1,7 +1,7 @@ import type { FC } from 'react'; import React from 'react'; import { styled } from '@storybook/theming'; -import { Link } from '@storybook/components/experimental'; +import { Icon, Link } from '@storybook/components/experimental'; const Wrapper = styled.div({ height: '100%', @@ -23,17 +23,35 @@ const Title = styled.div(({ theme }) => ({ fontWeight: theme.typography.weight.bold, fontSize: theme.typography.size.s2 - 1, textAlign: 'center', + color: theme.textColor, })); const Description = styled.div(({ theme }) => ({ fontWeight: theme.typography.weight.regular, fontSize: theme.typography.size.s2 - 1, textAlign: 'center', + color: theme.textMutedColor, })); -const Links = styled.div(({ theme }) => ({ +const Links = styled.div({ display: 'flex', gap: 25, +}); + +const Divider = styled.div(({ theme }) => ({ + width: 1, + height: 16, + backgroundColor: theme.appBorderColor, +})); + +const VideoIcon = styled.div(({ theme }) => ({ + width: 24, + height: 18, + borderRadius: theme.appBorderRadius, + border: `1px solid ${theme.color.secondary}`, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', })); export const Empty: FC = () => ( @@ -46,9 +64,18 @@ export const Empty: FC = () => ( - + + + + } + withArrow + > Watch 5m video + Read docs diff --git a/code/ui/components/src/new/Link/Link.tsx b/code/ui/components/src/new/Link/Link.tsx index e9965330a3e8..8d91dd2ae109 100644 --- a/code/ui/components/src/new/Link/Link.tsx +++ b/code/ui/components/src/new/Link/Link.tsx @@ -35,11 +35,12 @@ Link.displayName = 'Link'; const StyledLink = styled.a>(({ theme, variant = 'primary' }) => ({ display: 'inline-flex', - gap: 5, + gap: 10, alignItems: 'center', fontSize: theme.typography.size.s3, transition: 'all 150ms ease-out', textDecoration: 'none', + lineHeight: 1, color: `${(() => { if (variant === 'primary') return theme.color.secondary; if (variant === 'secondary') return theme.textMutedColor; From a3a6327d93b319ab3513063943abf82ec5877a44 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 22:48:13 +0200 Subject: [PATCH 12/26] Improve link --- .../src/components/ArgsTable/ArgsTable.stories.tsx | 5 +++-- code/ui/blocks/src/components/ArgsTable/Empty.tsx | 9 +++++++-- code/ui/components/src/new/Link/Link.tsx | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/code/ui/blocks/src/components/ArgsTable/ArgsTable.stories.tsx b/code/ui/blocks/src/components/ArgsTable/ArgsTable.stories.tsx index 6220c2a895cb..31267adda8ea 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgsTable.stories.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgsTable.stories.tsx @@ -141,8 +141,9 @@ export const Error = { }; export const Empty = { - args: { - rows: {}, + args: {}, + parameters: { + layout: 'centered', }, }; diff --git a/code/ui/blocks/src/components/ArgsTable/Empty.tsx b/code/ui/blocks/src/components/ArgsTable/Empty.tsx index de44fde66a39..1eed514e6321 100644 --- a/code/ui/blocks/src/components/ArgsTable/Empty.tsx +++ b/code/ui/blocks/src/components/ArgsTable/Empty.tsx @@ -65,7 +65,8 @@ export const Empty: FC = () => ( @@ -76,7 +77,11 @@ export const Empty: FC = () => ( Watch 5m video - + Read docs diff --git a/code/ui/components/src/new/Link/Link.tsx b/code/ui/components/src/new/Link/Link.tsx index 8d91dd2ae109..e75c2e42c40e 100644 --- a/code/ui/components/src/new/Link/Link.tsx +++ b/code/ui/components/src/new/Link/Link.tsx @@ -37,7 +37,7 @@ const StyledLink = styled.a>(({ theme, variant = 'pr display: 'inline-flex', gap: 10, alignItems: 'center', - fontSize: theme.typography.size.s3, + fontSize: theme.typography.size.s2 - 1, transition: 'all 150ms ease-out', textDecoration: 'none', lineHeight: 1, From 22cfba6224f32d196cd055be4c766e602ac18f2c Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 23:16:27 +0200 Subject: [PATCH 13/26] Update Empty.tsx --- code/ui/blocks/src/components/ArgsTable/Empty.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ui/blocks/src/components/ArgsTable/Empty.tsx b/code/ui/blocks/src/components/ArgsTable/Empty.tsx index 1eed514e6321..56ce12dc3495 100644 --- a/code/ui/blocks/src/components/ArgsTable/Empty.tsx +++ b/code/ui/blocks/src/components/ArgsTable/Empty.tsx @@ -78,7 +78,7 @@ export const Empty: FC = () => ( From 716064cb0b168d14652de89194c50f0f75d644fd Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 31 Jul 2023 23:43:48 +0200 Subject: [PATCH 14/26] Remove FakeIcon --- code/ui/components/src/new/FakeIcon.tsx | 18 ------------------ .../components/src/new/Select/SelectItem.tsx | 9 ++------- 2 files changed, 2 insertions(+), 25 deletions(-) delete mode 100644 code/ui/components/src/new/FakeIcon.tsx diff --git a/code/ui/components/src/new/FakeIcon.tsx b/code/ui/components/src/new/FakeIcon.tsx deleted file mode 100644 index 51ce84f446f0..000000000000 --- a/code/ui/components/src/new/FakeIcon.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import type { FC } from 'react'; -import React from 'react'; - -export const FakeIcon: FC = () => ( - - - - -); diff --git a/code/ui/components/src/new/Select/SelectItem.tsx b/code/ui/components/src/new/Select/SelectItem.tsx index 6206e76095ca..6bcf9cf82c02 100644 --- a/code/ui/components/src/new/Select/SelectItem.tsx +++ b/code/ui/components/src/new/Select/SelectItem.tsx @@ -1,25 +1,20 @@ import * as RadixSelect from '@radix-ui/react-select'; import React, { forwardRef } from 'react'; import { styled } from '@storybook/theming'; +import { Icon } from '@storybook/components/experimental'; interface SelectItemProps { children: React.ReactNode; value: string; } -const FakeIcon = styled.div(({ theme }) => ({ - width: 12, - height: 12, - backgroundColor: theme.color.mediumdark, -})); - export const SelectItem = forwardRef( ({ children, ...props }, forwardedRef) => { return ( {children} - + ); From f524837c4f807cc3ffbe39ec00a9080b55a35cda Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 1 Aug 2023 08:05:47 +0200 Subject: [PATCH 15/26] Add hover link when not set up --- .../src/components/ArgsTable/ArgControl.tsx | 17 +++++++++++++++-- .../blocks/src/components/ArgsTable/ArgRow.tsx | 7 ++++--- code/ui/components/src/new/Link/Link.tsx | 14 +++++++++++--- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/code/ui/blocks/src/components/ArgsTable/ArgControl.tsx b/code/ui/blocks/src/components/ArgsTable/ArgControl.tsx index eb548636159f..7a1061f14e7a 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgControl.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgControl.tsx @@ -1,6 +1,7 @@ import type { FC } from 'react'; import React, { useCallback, useState, useEffect } from 'react'; +import { Link } from '@storybook/components/experimental'; import { BooleanControl, ColorControl, @@ -18,6 +19,7 @@ export interface ArgControlProps { row: ArgType; arg: any; updateArgs: (args: Args) => void; + isHovered: boolean; } const Controls: Record = { @@ -40,7 +42,7 @@ const Controls: Record = { const NoControl = () => <>-; -export const ArgControl: FC = ({ row, arg, updateArgs }) => { +export const ArgControl: FC = ({ row, arg, updateArgs, isHovered }) => { const { key, control } = row; const [isFocused, setFocused] = useState(false); @@ -63,7 +65,18 @@ export const ArgControl: FC = ({ row, arg, updateArgs }) => { const onBlur = useCallback(() => setFocused(false), []); const onFocus = useCallback(() => setFocused(true), []); - if (!control || control.disable) return ; + if (!control || control.disable) + return isHovered ? ( + + Setup controls + + ) : ( + + ); // row.name is a display name and not a suitable DOM input id or name - i might contain whitespace etc. // row.key is a hash key and therefore a much safer choice diff --git a/code/ui/blocks/src/components/ArgsTable/ArgRow.tsx b/code/ui/blocks/src/components/ArgsTable/ArgRow.tsx index ea5f856c0027..d6f02f4dc2a7 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgRow.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgRow.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import React from 'react'; +import React, { useState } from 'react'; import Markdown from 'markdown-to-jsx'; import { transparentize } from 'polished'; import { styled } from '@storybook/theming'; @@ -76,6 +76,7 @@ const StyledTd = styled.td<{ expandable: boolean }>(({ theme, expandable }) => ( })); export const ArgRow: FC = (props) => { + const [isHovered, setIsHovered] = useState(false); const { row, updateArgs, compact, expandable, initialExpandedArgs } = props; const { name, description } = row; const table = (row.table || {}) as TableAnnotation; @@ -85,7 +86,7 @@ export const ArgRow: FC = (props) => { const hasDescription = description != null && description !== ''; return ( - + setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}> {name} {required ? * : null} @@ -118,7 +119,7 @@ export const ArgRow: FC = (props) => { )} {updateArgs ? ( - + ) : null} diff --git a/code/ui/components/src/new/Link/Link.tsx b/code/ui/components/src/new/Link/Link.tsx index e75c2e42c40e..1a19b6202f8e 100644 --- a/code/ui/components/src/new/Link/Link.tsx +++ b/code/ui/components/src/new/Link/Link.tsx @@ -23,8 +23,10 @@ export const Link: { ({ as, children, icon, withArrow, ...props }: LinkProps, ref: React.Ref) => { return ( - {icon} - {children} + + {icon} + {children} + {withArrow && } ); @@ -35,7 +37,7 @@ Link.displayName = 'Link'; const StyledLink = styled.a>(({ theme, variant = 'primary' }) => ({ display: 'inline-flex', - gap: 10, + gap: 5, alignItems: 'center', fontSize: theme.typography.size.s2 - 1, transition: 'all 150ms ease-out', @@ -67,3 +69,9 @@ const StyledLink = styled.a>(({ theme, variant = 'pr })()}`, }, })); + +const StyledLeft = styled.span({ + display: 'inline-flex', + gap: 10, + alignItems: 'center', +}); From e5734eb49eae614782f4db7d4a8a5755c959735e Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 1 Aug 2023 08:57:15 +0200 Subject: [PATCH 16/26] Update Link.tsx --- code/ui/components/src/new/Link/Link.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ui/components/src/new/Link/Link.tsx b/code/ui/components/src/new/Link/Link.tsx index 1a19b6202f8e..a170dfd92050 100644 --- a/code/ui/components/src/new/Link/Link.tsx +++ b/code/ui/components/src/new/Link/Link.tsx @@ -2,7 +2,7 @@ import type { MouseEvent, ReactNode } from 'react'; import React, { forwardRef } from 'react'; import { styled } from '@storybook/theming'; import { darken } from 'polished'; -import { Icon } from '@storybook/components/experimental'; +import { Icon } from '../Icon/Icon'; import type { PropsOf } from '../utils/types'; export interface LinkProps { From 90eb84153bcce2f48d9f22f15a124511bd410248 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 1 Aug 2023 09:11:50 +0200 Subject: [PATCH 17/26] Fix some icons names --- code/ui/components/package.json | 2 +- .../src/new/Button/Button.stories.tsx | 38 +++++++++---------- .../components/src/new/Link/Link.stories.tsx | 12 +++--- .../components/src/new/Select/SelectItem.tsx | 2 +- code/yarn.lock | 10 ++--- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/code/ui/components/package.json b/code/ui/components/package.json index bc28eef2f094..e3ae6d1987f7 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -71,7 +71,7 @@ "@storybook/client-logger": "workspace:*", "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.0.8", + "@storybook/icons": "^1.1.0", "@storybook/theming": "workspace:*", "@storybook/types": "workspace:*", "memoizerific": "^1.11.3", diff --git a/code/ui/components/src/new/Button/Button.stories.tsx b/code/ui/components/src/new/Button/Button.stories.tsx index b88e16348e8a..443d62d53839 100644 --- a/code/ui/components/src/new/Button/Button.stories.tsx +++ b/code/ui/components/src/new/Button/Button.stories.tsx @@ -46,13 +46,13 @@ export const Active: Story = { export const WithIcon: Story = { render: () => (
- - -
@@ -62,16 +62,16 @@ export const WithIcon: Story = { export const Sizes: Story = { render: () => (
- - - -
@@ -91,22 +91,22 @@ export const IconOnly: Story = { }, render: () => ( <> - - - - - - @@ -119,22 +119,22 @@ export const IconOnly: Story = { export const IconOnlyActive: Story = { render: () => (
- - - - - -
diff --git a/code/ui/components/src/new/Link/Link.stories.tsx b/code/ui/components/src/new/Link/Link.stories.tsx index d90438b9bfd4..356329f8e53c 100644 --- a/code/ui/components/src/new/Link/Link.stories.tsx +++ b/code/ui/components/src/new/Link/Link.stories.tsx @@ -36,13 +36,13 @@ export const Variants: Story = { export const WithIcon: Story = { render: () => (
- }> + }> Primary - }> + }> Secondary - }> + }> Tertiary
@@ -67,7 +67,7 @@ export const WithArrow: Story = { } + icon={} withArrow > Primary @@ -75,7 +75,7 @@ export const WithArrow: Story = { } + icon={} withArrow > Secondary @@ -83,7 +83,7 @@ export const WithArrow: Story = { } + icon={} withArrow > Tertiary diff --git a/code/ui/components/src/new/Select/SelectItem.tsx b/code/ui/components/src/new/Select/SelectItem.tsx index 6bcf9cf82c02..f60f084cd3ae 100644 --- a/code/ui/components/src/new/Select/SelectItem.tsx +++ b/code/ui/components/src/new/Select/SelectItem.tsx @@ -14,7 +14,7 @@ export const SelectItem = forwardRef( {children} - + ); diff --git a/code/yarn.lock b/code/yarn.lock index 6dd22a35e406..c8e22d59c64b 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6560,7 +6560,7 @@ __metadata: "@storybook/client-logger": "workspace:*" "@storybook/csf": ^0.1.0 "@storybook/global": ^5.0.0 - "@storybook/icons": ^1.0.8 + "@storybook/icons": ^1.1.0 "@storybook/theming": "workspace:*" "@storybook/types": "workspace:*" "@types/react-syntax-highlighter": 11.0.5 @@ -6883,9 +6883,9 @@ __metadata: languageName: unknown linkType: soft -"@storybook/icons@npm:^1.0.8": - version: 1.0.8 - resolution: "@storybook/icons@npm:1.0.8" +"@storybook/icons@npm:^1.1.0": + version: 1.1.0 + resolution: "@storybook/icons@npm:1.1.0" dependencies: "@svgr/core": 5.5.0 "@svgr/plugin-prettier": 5.5.0 @@ -6898,7 +6898,7 @@ __metadata: peerDependencies: react: ">=17" react-dom: ">=17" - checksum: fc1931f156dc3305fde19ba558e67c1601241293c8186ed8cc54040a15987dec9d5813595c4021c39afca999a524873f8f799ceb5c79181d7e00452463147f1a + checksum: 1ed443bdec1be98f5db4a68679a8bdc571e4744638fba922bac12d01f3debac605bf58a6f483f050cf0d44c26ae5f51349c80bfaa3d8a4303a890804f876cb04 languageName: node linkType: hard From ce53df810e968f368950414528ef2837cc9f10ba Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 1 Aug 2023 09:50:42 +0200 Subject: [PATCH 18/26] Update DocsPage.stories.tsx --- code/ui/blocks/src/components/DocsPage.stories.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/code/ui/blocks/src/components/DocsPage.stories.tsx b/code/ui/blocks/src/components/DocsPage.stories.tsx index 1d1f4b6db03d..8ae13eb51846 100644 --- a/code/ui/blocks/src/components/DocsPage.stories.tsx +++ b/code/ui/blocks/src/components/DocsPage.stories.tsx @@ -1,5 +1,4 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ -import type { ComponentProps } from 'react'; import React from 'react'; import { Global, css } from '@storybook/theming'; import { Source, ArgsTable } from '.'; From 681cd17b300ca256a71263e403a61b315b93ad31 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Tue, 1 Aug 2023 10:24:02 +0200 Subject: [PATCH 19/26] add icons to verdaccio proxy config --- scripts/verdaccio.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/verdaccio.yaml b/scripts/verdaccio.yaml index aa59cf7d5e78..c0ec0bd642d2 100644 --- a/scripts/verdaccio.yaml +++ b/scripts/verdaccio.yaml @@ -31,6 +31,10 @@ packages: access: $all publish: $all proxy: npmjs + '@storybook/icons': + access: $all + publish: $all + proxy: npmjs '@storybook/global': access: $all publish: $all From 1b6eb11551ddf8ad95aa9c5dcba6d6f7799db6f4 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Tue, 1 Aug 2023 11:04:12 +0200 Subject: [PATCH 20/26] add proper alias for components/experimental --- .../builder-webpack5/src/preview/iframe-webpack.config.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts index d2f6ec6affbc..c99a1df1da81 100644 --- a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts +++ b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts @@ -31,6 +31,10 @@ const getAbsolutePath = (input: I): I => dirname(require.resolve(join(input, 'package.json'))) as any; const storybookPaths: Record = { + // this is a temporary hack to get webpack to alias this correctly + [`@storybook/components/experimental`]: `${getAbsolutePath( + `@storybook/components` + )}/dist/experimental`, ...[ // these packages are not pre-bundled because of react dependencies 'components', From 04ab1d23ffc421570f96a5dabd8edc6ed4129e35 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 1 Aug 2023 11:26:57 +0200 Subject: [PATCH 21/26] Remove NoControlWarning --- code/addons/controls/src/ControlsPanel.tsx | 2 ++ .../doc-injectable/doc-injectable.stories.ts | 3 --- .../argTypes/doc-pipe/doc-pipe.stories.ts | 3 --- .../blocks/src/blocks/Description.stories.tsx | 1 - .../ArgsTable/ArgsTable.stories.tsx | 18 ++++++------- .../ArgsTable/NoControlsWarning.tsx | 25 ------------------- .../blocks/src/components/ArgsTable/index.ts | 1 - code/ui/blocks/src/index.ts | 2 +- 8 files changed, 11 insertions(+), 44 deletions(-) delete mode 100644 code/ui/blocks/src/components/ArgsTable/NoControlsWarning.tsx diff --git a/code/addons/controls/src/ControlsPanel.tsx b/code/addons/controls/src/ControlsPanel.tsx index fbc66a802bc3..ac9d662a8f3b 100644 --- a/code/addons/controls/src/ControlsPanel.tsx +++ b/code/addons/controls/src/ControlsPanel.tsx @@ -18,6 +18,8 @@ interface ControlsParameters { sort?: SortType; expanded?: boolean; presetColors?: PresetColor[]; + + /** @deprecated No longer used, will be removed in Storybook 8.0 */ hideNoControlsWarning?: boolean; } diff --git a/code/frameworks/angular/template/stories/argTypes/doc-injectable/doc-injectable.stories.ts b/code/frameworks/angular/template/stories/argTypes/doc-injectable/doc-injectable.stories.ts index d662a3de255f..eca5e10fb11d 100644 --- a/code/frameworks/angular/template/stories/argTypes/doc-injectable/doc-injectable.stories.ts +++ b/code/frameworks/angular/template/stories/argTypes/doc-injectable/doc-injectable.stories.ts @@ -2,9 +2,6 @@ import { DocInjectableService } from './doc-injectable.service'; export default { component: DocInjectableService, - parameters: { - controls: { hideNoControlsWarning: true }, - }, }; const modules = { diff --git a/code/frameworks/angular/template/stories/argTypes/doc-pipe/doc-pipe.stories.ts b/code/frameworks/angular/template/stories/argTypes/doc-pipe/doc-pipe.stories.ts index ba6f0f282f63..6ab616f16ee2 100644 --- a/code/frameworks/angular/template/stories/argTypes/doc-pipe/doc-pipe.stories.ts +++ b/code/frameworks/angular/template/stories/argTypes/doc-pipe/doc-pipe.stories.ts @@ -2,9 +2,6 @@ import { DocPipe } from './doc-pipe.pipe'; export default { component: DocPipe, - parameters: { - controls: { hideNoControlsWarning: true }, - }, }; const modules = { diff --git a/code/ui/blocks/src/blocks/Description.stories.tsx b/code/ui/blocks/src/blocks/Description.stories.tsx index a8f6bac08fd5..a00a22f7a0b5 100644 --- a/code/ui/blocks/src/blocks/Description.stories.tsx +++ b/code/ui/blocks/src/blocks/Description.stories.tsx @@ -12,7 +12,6 @@ const meta: Meta = { parameters: { controls: { include: [], - hideNoControlsWarning: true, }, // workaround for https://github.com/storybookjs/storybook/issues/20505 docs: { source: { type: 'code' } }, diff --git a/code/ui/blocks/src/components/ArgsTable/ArgsTable.stories.tsx b/code/ui/blocks/src/components/ArgsTable/ArgsTable.stories.tsx index 31267adda8ea..d575ddda9162 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgsTable.stories.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgsTable.stories.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; import { styled } from '@storybook/theming'; import { ArgsTable, ArgsTableError } from './ArgsTable'; -import { NoControlsWarning } from './NoControlsWarning'; import * as ArgRow from './ArgRow.stories'; export default { @@ -58,15 +57,14 @@ export const InAddonPanel = { decorators: [(storyFn: any) => {storyFn()}], }; -export const InAddonPanelWithWarning = { - render: (args: any) => ( - <> - - - - ), - // @ts-expect-error (not strict) - args: { ...InAddonPanel.args, updateArgs: null }, +export const InAddonPanelNoControls = { + render: (args: any) => , + args: { + rows: { + stringType: { ...stringType, control: false }, + numberType: { ...numberType, control: false }, + }, + }, decorators: InAddonPanel.decorators, }; diff --git a/code/ui/blocks/src/components/ArgsTable/NoControlsWarning.tsx b/code/ui/blocks/src/components/ArgsTable/NoControlsWarning.tsx deleted file mode 100644 index 5347cad17d42..000000000000 --- a/code/ui/blocks/src/components/ArgsTable/NoControlsWarning.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import { styled } from '@storybook/theming'; -import { Link } from '@storybook/components'; - -const NoControlsWrapper = styled.div(({ theme }) => ({ - background: theme.background.warning, - color: theme.color.darkest, - padding: '10px 15px', - lineHeight: '20px', - boxShadow: `${theme.appBorderColor} 0 -1px 0 0 inset`, -})); - -export const NoControlsWarning = () => ( - - This story is not configured to handle controls.{' '} - - Learn how to add controls - - -); diff --git a/code/ui/blocks/src/components/ArgsTable/index.ts b/code/ui/blocks/src/components/ArgsTable/index.ts index 421acb17e863..e3b1f1528205 100644 --- a/code/ui/blocks/src/components/ArgsTable/index.ts +++ b/code/ui/blocks/src/components/ArgsTable/index.ts @@ -3,4 +3,3 @@ export * from './types'; export * from './ArgsTable'; export * from './TabbedArgsTable'; -export * from './NoControlsWarning'; diff --git a/code/ui/blocks/src/index.ts b/code/ui/blocks/src/index.ts index b02a892d1fb0..f9cbbfe66f18 100644 --- a/code/ui/blocks/src/index.ts +++ b/code/ui/blocks/src/index.ts @@ -1,6 +1,6 @@ // FIXME: sort this out, maybe with package.json exports map // https://medium.com/swlh/npm-new-package-json-exports-field-1a7d1f489ccf -export { ArgsTable as PureArgsTable, NoControlsWarning } from './components'; +export { ArgsTable as PureArgsTable } from './components'; export type { SortType } from './components'; export * from './blocks'; From c5f66772cd21a5947ef5a9685db028678cc7231e Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 1 Aug 2023 17:14:32 +0200 Subject: [PATCH 22/26] Test --- code/addons/controls/src/ControlsPanel.tsx | 14 ++++++++++---- .../src/components/ArgsTable/ArgsTable.tsx | 16 +++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/code/addons/controls/src/ControlsPanel.tsx b/code/addons/controls/src/ControlsPanel.tsx index ac9d662a8f3b..7a7de090c624 100644 --- a/code/addons/controls/src/ControlsPanel.tsx +++ b/code/addons/controls/src/ControlsPanel.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { useArgs, useGlobals, @@ -24,7 +24,8 @@ interface ControlsParameters { } export const ControlsPanel: FC = () => { - const [isLoading, setIsLoading] = React.useState(true); + const [isLoading, setIsLoading] = useState(true); + const [isSoftLoading, setIsSoftLoading] = useState(true); const [args, updateArgs, resetArgs] = useArgs(); const [globals] = useGlobals(); const rows = useArgTypes(); @@ -32,13 +33,17 @@ export const ControlsPanel: FC = () => { const { path } = useStorybookState(); // If the story is prepared, then show the args table + // and reset the loading states useChannel({ - [STORY_PREPARED]: () => setIsLoading(false), + [STORY_PREPARED]: () => { + setIsLoading(false); + setIsSoftLoading(false); + }, }); // If the story changes, then show the loading state useEffect(() => { - setIsLoading(true); + setIsSoftLoading(true); }, [path]); const hasControls = Object.values(rows).some((arg) => arg?.control); @@ -61,6 +66,7 @@ export const ControlsPanel: FC = () => { inAddonPanel sort={sort} isLoading={isLoading} + isSoftLoading={isSoftLoading} /> ); }; diff --git a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx index aeb55050c605..137571d1af28 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx @@ -198,6 +198,7 @@ export interface ArgsTableOptionProps { inAddonPanel?: boolean; initialExpandedArgs?: boolean; isLoading?: boolean; + isSoftLoading?: boolean; sort?: SortType; } interface ArgsTableDataProps { @@ -315,6 +316,7 @@ export const ArgsTable: FC = (props) => { initialExpandedArgs, sort = 'none', isLoading, + isSoftLoading, } = props; if ('error' in props) { @@ -330,8 +332,13 @@ export const ArgsTable: FC = (props) => { } // If the story is loading, show a skeleton + // This happen when you load the manager and the story is not yet loaded if (isLoading) return ; + // If the story is soft loading, don't show anything + // This happens when you switch stories and the story is not yet loaded + if (isSoftLoading) return null; + const { rows, args, globals } = 'rows' in props && props; const groups = groupRows( pickBy( @@ -348,15 +355,6 @@ export const ArgsTable: FC = (props) => { Object.entries(groups.ungroupedSubsections).length === 0 ) { return ; - - return ( - - No inputs found for this component.  - - Read the docs - - - ); } let colSpan = 1; From 1b138a902ad67bccf97b5b46ccf8bbda8330f353 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 1 Aug 2023 17:38:54 +0200 Subject: [PATCH 23/26] Cleaning loading state --- code/addons/controls/src/ControlsPanel.tsx | 12 +----------- .../ui/blocks/src/components/ArgsTable/ArgsTable.tsx | 6 ------ 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/code/addons/controls/src/ControlsPanel.tsx b/code/addons/controls/src/ControlsPanel.tsx index 7a7de090c624..75656fb4a5c3 100644 --- a/code/addons/controls/src/ControlsPanel.tsx +++ b/code/addons/controls/src/ControlsPanel.tsx @@ -25,7 +25,6 @@ interface ControlsParameters { export const ControlsPanel: FC = () => { const [isLoading, setIsLoading] = useState(true); - const [isSoftLoading, setIsSoftLoading] = useState(true); const [args, updateArgs, resetArgs] = useArgs(); const [globals] = useGlobals(); const rows = useArgTypes(); @@ -35,17 +34,9 @@ export const ControlsPanel: FC = () => { // If the story is prepared, then show the args table // and reset the loading states useChannel({ - [STORY_PREPARED]: () => { - setIsLoading(false); - setIsSoftLoading(false); - }, + [STORY_PREPARED]: () => setIsLoading(false), }); - // If the story changes, then show the loading state - useEffect(() => { - setIsSoftLoading(true); - }, [path]); - const hasControls = Object.values(rows).some((arg) => arg?.control); const withPresetColors = Object.entries(rows).reduce((acc, [key, arg]) => { @@ -66,7 +57,6 @@ export const ControlsPanel: FC = () => { inAddonPanel sort={sort} isLoading={isLoading} - isSoftLoading={isSoftLoading} /> ); }; diff --git a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx index 137571d1af28..b6c6359b6f0b 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx @@ -198,7 +198,6 @@ export interface ArgsTableOptionProps { inAddonPanel?: boolean; initialExpandedArgs?: boolean; isLoading?: boolean; - isSoftLoading?: boolean; sort?: SortType; } interface ArgsTableDataProps { @@ -316,7 +315,6 @@ export const ArgsTable: FC = (props) => { initialExpandedArgs, sort = 'none', isLoading, - isSoftLoading, } = props; if ('error' in props) { @@ -335,10 +333,6 @@ export const ArgsTable: FC = (props) => { // This happen when you load the manager and the story is not yet loaded if (isLoading) return ; - // If the story is soft loading, don't show anything - // This happens when you switch stories and the story is not yet loaded - if (isSoftLoading) return null; - const { rows, args, globals } = 'rows' in props && props; const groups = groupRows( pickBy( From e206d2174a397fcc367b56d5f04590a51800b67a Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 1 Aug 2023 17:47:24 +0200 Subject: [PATCH 24/26] Update ControlsPanel.tsx --- code/addons/controls/src/ControlsPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/addons/controls/src/ControlsPanel.tsx b/code/addons/controls/src/ControlsPanel.tsx index 75656fb4a5c3..f04982077020 100644 --- a/code/addons/controls/src/ControlsPanel.tsx +++ b/code/addons/controls/src/ControlsPanel.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { useArgs, useGlobals, From 8a5ce35e9d02d81b760699c760a22a86715fee36 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 2 Aug 2023 08:08:52 +0200 Subject: [PATCH 25/26] Fix the Link style --- code/ui/components/src/new/Link/Link.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/ui/components/src/new/Link/Link.tsx b/code/ui/components/src/new/Link/Link.tsx index a170dfd92050..f374b21b16a3 100644 --- a/code/ui/components/src/new/Link/Link.tsx +++ b/code/ui/components/src/new/Link/Link.tsx @@ -27,7 +27,7 @@ export const Link: { {icon} {children} - {withArrow && } + {withArrow && } ); } @@ -37,7 +37,7 @@ Link.displayName = 'Link'; const StyledLink = styled.a>(({ theme, variant = 'primary' }) => ({ display: 'inline-flex', - gap: 5, + gap: 4, alignItems: 'center', fontSize: theme.typography.size.s2 - 1, transition: 'all 150ms ease-out', @@ -72,6 +72,6 @@ const StyledLink = styled.a>(({ theme, variant = 'pr const StyledLeft = styled.span({ display: 'inline-flex', - gap: 10, + gap: 6, alignItems: 'center', }); From b22fd145329d8c38715e9957c95621097ac22a48 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 2 Aug 2023 10:08:41 +0200 Subject: [PATCH 26/26] Add delay to empty state to prevent flickering --- code/addons/controls/src/ControlsPanel.tsx | 12 ++- .../src/components/ArgsTable/ArgsTable.tsx | 11 +-- .../blocks/src/components/ArgsTable/Empty.tsx | 85 +++++++++++-------- 3 files changed, 60 insertions(+), 48 deletions(-) diff --git a/code/addons/controls/src/ControlsPanel.tsx b/code/addons/controls/src/ControlsPanel.tsx index f04982077020..fc7c2085abd4 100644 --- a/code/addons/controls/src/ControlsPanel.tsx +++ b/code/addons/controls/src/ControlsPanel.tsx @@ -1,14 +1,12 @@ import type { FC } from 'react'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useArgs, useGlobals, useArgTypes, useParameter, useStorybookState, - useChannel, } from '@storybook/manager-api'; -import { STORY_PREPARED } from '@storybook/core-events'; import { PureArgsTable as ArgsTable, type PresetColor, type SortType } from '@storybook/blocks'; import type { ArgTypes } from '@storybook/types'; @@ -29,13 +27,13 @@ export const ControlsPanel: FC = () => { const [globals] = useGlobals(); const rows = useArgTypes(); const { expanded, sort, presetColors } = useParameter(PARAM_KEY, {}); - const { path } = useStorybookState(); + const { path, previewInitialized } = useStorybookState(); // If the story is prepared, then show the args table // and reset the loading states - useChannel({ - [STORY_PREPARED]: () => setIsLoading(false), - }); + useEffect(() => { + if (previewInitialized) setIsLoading(false); + }, [previewInitialized]); const hasControls = Object.values(rows).some((arg) => arg?.control); diff --git a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx index b6c6359b6f0b..c47ae35f00ec 100644 --- a/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx +++ b/code/ui/blocks/src/components/ArgsTable/ArgsTable.tsx @@ -343,13 +343,10 @@ export const ArgsTable: FC = (props) => { ); // If there are no controls, show the empty state - if ( - groups.ungrouped.length === 0 && - Object.entries(groups.sections).length === 0 && - Object.entries(groups.ungroupedSubsections).length === 0 - ) { - return ; - } + const hasNoUngrouped = groups.ungrouped.length === 0; + const hasNoSections = Object.entries(groups.sections).length === 0; + const hasNoUngroupedSubsections = Object.entries(groups.ungroupedSubsections).length === 0; + if (hasNoUngrouped && hasNoSections && hasNoUngroupedSubsections) return ; let colSpan = 1; if (updateArgs) colSpan += 1; diff --git a/code/ui/blocks/src/components/ArgsTable/Empty.tsx b/code/ui/blocks/src/components/ArgsTable/Empty.tsx index 56ce12dc3495..a7accea12de1 100644 --- a/code/ui/blocks/src/components/ArgsTable/Empty.tsx +++ b/code/ui/blocks/src/components/ArgsTable/Empty.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { styled } from '@storybook/theming'; import { Icon, Link } from '@storybook/components/experimental'; @@ -54,36 +54,53 @@ const VideoIcon = styled.div(({ theme }) => ({ justifyContent: 'center', })); -export const Empty: FC = () => ( - - - Interactive story playground - - Controls give you an easy to use interface to test your components. Set your story args and - you'll see controls appearing here automatically. - - - - - - - } - withArrow - > - Watch 5m video - - - - Read docs - - - -); +export const Empty: FC = () => { + const [isLoading, setIsLoading] = useState(true); + + // We are adding a small delay to avoid flickering when the story is loading. + // It takes a bit of time for the controls to appear, so we don't want + // to show the empty state for a split second. + useEffect(() => { + const load = setTimeout(() => { + setIsLoading(false); + }, 100); + + return () => clearTimeout(load); + }, []); + + if (isLoading) return null; + + return ( + + + Interactive story playground + + Controls give you an easy to use interface to test your components. Set your story args + and you'll see controls appearing here automatically. + + + + + + + } + withArrow + > + Watch 5m video + + + + Read docs + + + + ); +};