diff --git a/.plop/templates/component/component.stories.tsx.hbs b/.plop/templates/component/component.stories.tsx.hbs index 5a03aade..9c093b58 100644 --- a/.plop/templates/component/component.stories.tsx.hbs +++ b/.plop/templates/component/component.stories.tsx.hbs @@ -8,6 +8,9 @@ const meta = { component: {{pascalCase name}}, parameters: { badges: ['accessible'], + // Link a Figma design to show it in the toolbar, or set `figma: false` + // to hide the tool on pages with no matching design (e.g. hook docs): + // figma: { path: 'Figma file › Page › Section › Component', url: 'https://www.figma.com/design/…?node-id=…' }, }, } satisfies Meta diff --git a/.storybook/badges/BadgesTool.tsx b/.storybook/badges/BadgesTool.tsx deleted file mode 100644 index f9154e57..00000000 --- a/.storybook/badges/BadgesTool.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React, { memo, useMemo } from 'react' -import type { CSSProperties } from 'react' -import { useParameter } from 'storybook/manager-api' - -import { resolveBadges } from './badges' -import { BADGES_CONFIG_PARAMETER, BADGES_PARAMETER, TOOL_ID } from './constants' - -const containerStyle: CSSProperties = { - alignItems: 'center', - display: 'inline-flex', - gap: '4px', - marginInline: '6px', -} - -const badgeStyle: CSSProperties = { - alignItems: 'center', - border: '1px solid currentColor', - borderRadius: '3px', - boxSizing: 'border-box', - display: 'inline-flex', - fontWeight: 600, - minHeight: '20px', - padding: '2px 6px', - whiteSpace: 'nowrap', -} - -const emptyBadges: unknown[] = [] -const emptyBadgesConfig: Record = {} - -export const BadgesTool = memo(function BadgesTool() { - const badgesParameter = useParameter(BADGES_PARAMETER, emptyBadges) - const badgesConfigParameter = useParameter(BADGES_CONFIG_PARAMETER, emptyBadgesConfig) - - const badges = useMemo( - () => resolveBadges(badgesParameter, badgesConfigParameter), - [badgesParameter, badgesConfigParameter], - ) - - if (badges.length === 0) { - return null - } - - return ( -
title).join(', ')} - > - {badges.map(({ id, title, styles }, index) => ( - - {title} - - ))} -
- ) -}) diff --git a/.storybook/badges/badges-tool.tsx b/.storybook/badges/badges-tool.tsx new file mode 100644 index 00000000..0e6e525f --- /dev/null +++ b/.storybook/badges/badges-tool.tsx @@ -0,0 +1,34 @@ +import * as React from 'react' + +import { useParameter } from 'storybook/manager-api' + +import { Badge } from '../../src/badge/badge' +import { Inline } from '../../src/inline' + +import { resolveBadges } from './badges' +import { BADGES_CONFIG_PARAMETER, BADGES_PARAMETER } from './constants' + +const emptyBadges: unknown[] = [] +const emptyBadgesConfig: Record = {} + +export const BadgesTool = React.memo(function BadgesTool() { + const badgesParameter = useParameter(BADGES_PARAMETER, emptyBadges) + const badgesConfigParameter = useParameter(BADGES_CONFIG_PARAMETER, emptyBadgesConfig) + + const badges = React.useMemo( + () => resolveBadges(badgesParameter, badgesConfigParameter), + [badgesParameter, badgesConfigParameter], + ) + + if (badges.length === 0) { + return null + } + + return ( + + {badges.map(({ id, title, tone }) => ( + + ))} + + ) +}) diff --git a/.storybook/badges/badges.test.ts b/.storybook/badges/badges.test.ts index 277e0855..768643bf 100644 --- a/.storybook/badges/badges.test.ts +++ b/.storybook/badges/badges.test.ts @@ -6,42 +6,46 @@ describe('resolveBadges', () => { resolveBadges(['accessible', 'deprecated'], { accessible: { title: 'Accessible', - styles: { color: 'green' }, + tone: 'positive', }, deprecated: { title: 'Deprecated', - styles: { color: 'red' }, + tone: 'attention', }, }), ).toEqual([ { id: 'accessible', title: 'Accessible', - styles: { color: 'green' }, + tone: 'positive', }, { id: 'deprecated', title: 'Deprecated', - styles: { color: 'red' }, + tone: 'attention', }, ]) }) it('filters unknown badges and invalid badge entries', () => { expect( - resolveBadges(['accessible', 'missing', 42, 'untitled'], { + resolveBadges(['accessible', 'missing', 42, 'untitled', 'untoned'], { accessible: { title: 'Accessible', + tone: 'positive', }, untitled: { - styles: { color: 'orange' }, + tone: 'positive', + }, + untoned: { + title: 'Untoned', }, }), ).toEqual([ { id: 'accessible', title: 'Accessible', - styles: undefined, + tone: 'positive', }, ]) }) @@ -53,20 +57,14 @@ describe('resolveBadges', () => { expect(resolveBadges(['accessible'], [])).toEqual([]) }) - it('ignores non-object styles', () => { + it('rejects an unknown tone', () => { expect( resolveBadges(['accessible'], { accessible: { title: 'Accessible', - styles: 'color: green', + tone: 'rainbow', }, }), - ).toEqual([ - { - id: 'accessible', - title: 'Accessible', - styles: undefined, - }, - ]) + ).toEqual([]) }) }) diff --git a/.storybook/badges/badges.ts b/.storybook/badges/badges.ts index 2432a75c..b7b69f4b 100644 --- a/.storybook/badges/badges.ts +++ b/.storybook/badges/badges.ts @@ -1,28 +1,30 @@ -import type { CSSProperties } from 'react' +import type { BadgeProps } from '../../src/badge/badge' -type UnknownRecord = Record - -type BadgeConfig = { - title?: unknown - styles?: unknown -} +type BadgeTone = BadgeProps['tone'] type ResolvedBadge = { id: string title: string - styles: CSSProperties | undefined + tone: BadgeTone } -function isRecord(value: unknown): value is UnknownRecord { - return typeof value === 'object' && value !== null && !Array.isArray(value) +// Ensure valid tones are checked against the Badge's tone prop +const TONE_SET: Record = { + info: true, + positive: true, + promote: true, + attention: true, + warning: true, } -function isBadgeConfig(value: unknown): value is BadgeConfig { - return isRecord(value) +const VALID_TONES = Object.keys(TONE_SET) as BadgeTone[] + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value) } -function resolveStyles(styles: unknown): CSSProperties | undefined { - return isRecord(styles) ? (styles as CSSProperties) : undefined +function isBadgeTone(value: unknown): value is BadgeTone { + return typeof value === 'string' && (VALID_TONES as readonly string[]).includes(value) } function resolveBadges(badges: unknown, badgesConfig: unknown): ResolvedBadge[] { @@ -37,7 +39,11 @@ function resolveBadges(badges: unknown, badgesConfig: unknown): ResolvedBadge[] const badgeConfig = badgesConfig[badge] - if (!isBadgeConfig(badgeConfig) || typeof badgeConfig.title !== 'string') { + if (!isRecord(badgeConfig) || typeof badgeConfig.title !== 'string') { + return [] + } + + if (!isBadgeTone(badgeConfig.tone)) { return [] } @@ -45,7 +51,7 @@ function resolveBadges(badges: unknown, badgesConfig: unknown): ResolvedBadge[] { id: badge, title: badgeConfig.title, - styles: resolveStyles(badgeConfig.styles), + tone: badgeConfig.tone, }, ] }) diff --git a/.storybook/badges/index.ts b/.storybook/badges/index.ts index d77c0a38..62979061 100644 --- a/.storybook/badges/index.ts +++ b/.storybook/badges/index.ts @@ -1,2 +1,2 @@ -export { BadgesTool } from './BadgesTool' +export { BadgesTool } from './badges-tool' export { ADDON_ID, TOOL_ID } from './constants' diff --git a/.storybook/figma/constants.ts b/.storybook/figma/constants.ts new file mode 100644 index 00000000..0dfbe9da --- /dev/null +++ b/.storybook/figma/constants.ts @@ -0,0 +1,3 @@ +export const ADDON_ID = 'reactist/figma' +export const TOOL_ID = `${ADDON_ID}/tool` +export const FIGMA_PARAMETER = 'figma' diff --git a/.storybook/figma/figma-icon.tsx b/.storybook/figma/figma-icon.tsx new file mode 100644 index 00000000..9241a2f6 --- /dev/null +++ b/.storybook/figma/figma-icon.tsx @@ -0,0 +1,14 @@ +import * as React from 'react' + +// https://www.figma.com/using-the-figma-brand/ +export function FigmaIcon() { + return ( + + ) +} diff --git a/.storybook/figma/figma-tool.tsx b/.storybook/figma/figma-tool.tsx new file mode 100644 index 00000000..dd5172c2 --- /dev/null +++ b/.storybook/figma/figma-tool.tsx @@ -0,0 +1,39 @@ +import * as React from 'react' + +import { useParameter } from 'storybook/manager-api' + +import { Badge } from '../../src/badge/badge' +import { IconButton } from '../../src/button/button' +import { Inline } from '../../src/inline' + +import { FIGMA_PARAMETER } from './constants' +import { resolveFigmaLinks } from './figma' +import { FigmaIcon } from './figma-icon' + +export const FigmaTool = React.memo(function FigmaTool() { + const figmaParameter = useParameter(FIGMA_PARAMETER, undefined) + const links = React.useMemo(() => resolveFigmaLinks(figmaParameter), [figmaParameter]) + + if (figmaParameter === false) { + return null + } + + return ( + + {links.length === 0 ? ( + + ) : ( + links.map((link) => ( + } + aria-label={`View in Figma: ${link.path}`} + tooltip={link.path} + render={} + /> + )) + )} + + ) +}) diff --git a/.storybook/figma/figma.test.ts b/.storybook/figma/figma.test.ts new file mode 100644 index 00000000..d0323894 --- /dev/null +++ b/.storybook/figma/figma.test.ts @@ -0,0 +1,47 @@ +import { resolveFigmaLinks } from './figma' + +describe('resolveFigmaLinks', () => { + it('resolves an object with path and url', () => { + expect( + resolveFigmaLinks({ + path: 'Web › Buttons › Button', + url: 'https://figma.com/design/abc?node-id=1-2', + }), + ).toEqual([ + { + path: 'Web › Buttons › Button', + url: 'https://figma.com/design/abc?node-id=1-2', + }, + ]) + }) + + it('falls back to the url as path when path is missing', () => { + expect(resolveFigmaLinks({ url: 'https://figma.com/design/abc' })).toEqual([ + { path: 'https://figma.com/design/abc', url: 'https://figma.com/design/abc' }, + ]) + }) + + it('resolves an array, dropping malformed entries', () => { + expect( + resolveFigmaLinks([ + { path: 'B', url: 'https://figma.com/b' }, + { path: 'C' }, + { url: 42 }, + '', + null, + ]), + ).toEqual([{ path: 'B', url: 'https://figma.com/b' }]) + }) + + it('treats malformed and empty params as no links', () => { + expect(resolveFigmaLinks(undefined)).toEqual([]) + expect(resolveFigmaLinks(null)).toEqual([]) + expect(resolveFigmaLinks(false)).toEqual([]) + expect(resolveFigmaLinks('https://figma.com/x')).toEqual([]) + expect(resolveFigmaLinks('')).toEqual([]) + expect(resolveFigmaLinks({})).toEqual([]) + expect(resolveFigmaLinks({ path: 'no url' })).toEqual([]) + expect(resolveFigmaLinks({ url: 42 })).toEqual([]) + expect(resolveFigmaLinks([])).toEqual([]) + }) +}) diff --git a/.storybook/figma/figma.ts b/.storybook/figma/figma.ts new file mode 100644 index 00000000..766ed666 --- /dev/null +++ b/.storybook/figma/figma.ts @@ -0,0 +1,29 @@ +type ResolvedFigmaLink = { + path: string + url: string +} + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value) +} + +function resolveEntry(entry: unknown): ResolvedFigmaLink[] { + if (isRecord(entry) && typeof entry.url === 'string' && entry.url.length > 0) { + const path = + typeof entry.path === 'string' && entry.path.length > 0 ? entry.path : entry.url + return [{ path, url: entry.url }] + } + + return [] +} + +function resolveFigmaLinks(param: unknown): ResolvedFigmaLink[] { + if (Array.isArray(param)) { + return param.flatMap(resolveEntry) + } + + return resolveEntry(param) +} + +export { resolveFigmaLinks } +export type { ResolvedFigmaLink } diff --git a/.storybook/figma/index.ts b/.storybook/figma/index.ts new file mode 100644 index 00000000..d9a9a8df --- /dev/null +++ b/.storybook/figma/index.ts @@ -0,0 +1,2 @@ +export { FigmaTool } from './figma-tool' +export { ADDON_ID, TOOL_ID } from './constants' diff --git a/.storybook/manager.ts b/.storybook/manager.ts index 2011d3dd..d569db37 100644 --- a/.storybook/manager.ts +++ b/.storybook/manager.ts @@ -1,11 +1,22 @@ import { addons, types } from 'storybook/manager-api' +import '../src/styles/design-tokens.css' import { ADDON_ID, BadgesTool, TOOL_ID } from './badges' +import { ADDON_ID as FIGMA_ADDON_ID, FigmaTool, TOOL_ID as FIGMA_TOOL_ID } from './figma' import theme from './theme' addons.setConfig({ theme, }) +addons.register(FIGMA_ADDON_ID, () => { + addons.add(FIGMA_TOOL_ID, { + title: 'Figma', + type: types.TOOL, + match: ({ viewMode }) => viewMode === 'story' || viewMode === 'docs', + render: FigmaTool, + }) +}) + addons.register(ADDON_ID, () => { addons.add(TOOL_ID, { title: 'Badges', diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 1b1e662c..9714e256 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -4,11 +4,6 @@ import BaseDecorator from './BaseDecorator' import '../src/styles/design-tokens.css' import '../stories/components/styles/story.css' -const badgeFontStyles = { - fontSize: '12px', - lineHeight: '14px', -} - const preview: Preview = { decorators: [BaseDecorator], parameters: { @@ -42,42 +37,24 @@ const preview: Preview = { chromatic: { disableSnapshot: true, }, + // The \uFE0E after each symbol forces text (not emoji) presentation, so the glyph + // inherits the badge tint color instead of falling back to the black emoji font. badgesConfig: { accessible: { - title: '✔ Accessible (WCAG 2.0 AA)', - styles: { - backgroundColor: 'rgba(5, 133, 39, 0.1)', - borderColor: 'rgb(5, 133, 39)', - color: 'rgb(5, 133, 39)', - ...badgeFontStyles, - }, + title: '✔\uFE0E Accessible (WCAG 2.0 AA)', + tone: 'positive', }, partiallyAccessible: { - title: '⚠ Partially Accessible', - styles: { - backgroundColor: 'rgba(235, 141, 19, 0.1)', - borderColor: 'rgb(235, 141, 19)', - color: 'rgb(235, 141, 19)', - ...badgeFontStyles, - }, + title: '⚠\uFE0E Partially Accessible', + tone: 'warning', }, notAccessible: { - title: '✖ Not accessible', - styles: { - backgroundColor: 'rgba(209, 69, 59, 0.1)', - borderColor: 'rgb(209, 69, 59)', - color: 'rgb(209, 69, 59)', - ...badgeFontStyles, - }, + title: '✖\uFE0E Not accessible', + tone: 'attention', }, deprecated: { - title: '✖ Deprecated', - styles: { - backgroundColor: 'rgba(209, 69, 59, 0.1)', - borderColor: 'rgb(209, 69, 59)', - color: 'rgb(209, 69, 59)', - ...badgeFontStyles, - }, + title: '✖\uFE0E Deprecated', + tone: 'attention', }, }, }, diff --git a/src/avatar/avatar.stories.tsx b/src/avatar/avatar.stories.tsx index 534ba12a..cd88227a 100644 --- a/src/avatar/avatar.stories.tsx +++ b/src/avatar/avatar.stories.tsx @@ -187,6 +187,10 @@ const meta = { component: Avatar, parameters: { badges: ['accessible'], + figma: { + path: 'Global › Avatar', + url: 'https://www.figma.com/design/xo9yAsH8PQUpi0eTJh9pmR/Product-Library---Global?node-id=6957-36532', + }, }, } satisfies Meta diff --git a/src/badge/badge.stories.jsx b/src/badge/badge.stories.jsx index 02bbfff4..6e01cbf6 100644 --- a/src/badge/badge.stories.jsx +++ b/src/badge/badge.stories.jsx @@ -101,6 +101,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Badge', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=9038-280657', + }, }, } diff --git a/src/banner/banner.stories.jsx b/src/banner/banner.stories.jsx index 988c8dac..c8d406da 100644 --- a/src/banner/banner.stories.jsx +++ b/src/banner/banner.stories.jsx @@ -388,6 +388,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Banner › Banner', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=15487-102766', + }, }, } diff --git a/src/button/button.stories.jsx b/src/button/button.stories.jsx index 0ec3fd9a..7fe436e1 100644 --- a/src/button/button.stories.jsx +++ b/src/button/button.stories.jsx @@ -188,6 +188,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Buttons › Button', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=507-10', + }, }, } diff --git a/src/button/icon-button.stories.jsx b/src/button/icon-button.stories.jsx index b5306c38..1cb67f95 100644 --- a/src/button/icon-button.stories.jsx +++ b/src/button/icon-button.stories.jsx @@ -106,6 +106,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Buttons › Button (Variant=Icon)', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=507-10', + }, }, } diff --git a/src/heading/heading.stories.tsx b/src/heading/heading.stories.tsx index 58363448..2a4238a9 100644 --- a/src/heading/heading.stories.tsx +++ b/src/heading/heading.stories.tsx @@ -10,6 +10,10 @@ export default { component: Heading, parameters: { badges: ['accessible'], + figma: { + path: 'Global › Text Styles › SF *FOR WEB* › Header 1', + url: 'https://www.figma.com/design/xo9yAsH8PQUpi0eTJh9pmR/Product-Library---Global?node-id=2524-3589', + }, }, } diff --git a/src/hooks/use-previous/use-previous.mdx b/src/hooks/use-previous/use-previous.mdx index 08c356de..3e08e5c4 100644 --- a/src/hooks/use-previous/use-previous.mdx +++ b/src/hooks/use-previous/use-previous.mdx @@ -1,7 +1,7 @@ import { Meta } from '@storybook/addon-docs/blocks' import { usePrevious } from './use-previous' - + # usePrevious diff --git a/src/loading/loading.stories.jsx b/src/loading/loading.stories.jsx index 73b10cb5..326ed38e 100644 --- a/src/loading/loading.stories.jsx +++ b/src/loading/loading.stories.jsx @@ -21,6 +21,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Progress › Progress circular', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=20195-258612', + }, }, } diff --git a/src/menu/menu.stories.jsx b/src/menu/menu.stories.jsx index 4c9a655d..9b549abd 100644 --- a/src/menu/menu.stories.jsx +++ b/src/menu/menu.stories.jsx @@ -64,6 +64,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Context Menus › Context Menu', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=2057-40323', + }, }, } diff --git a/src/modal/modal-docs.mdx b/src/modal/modal-docs.mdx index 24c106f9..1c9921d3 100644 --- a/src/modal/modal-docs.mdx +++ b/src/modal/modal-docs.mdx @@ -6,6 +6,10 @@ import { Modal, ModalHeader, ModalBody, ModalFooter, ModalActions, ModalCloseBut component={Modal} parameters={{ badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Settings › Modal / Header', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=7443-241153', + }, }} /> diff --git a/src/modal/modal-examples.stories.tsx b/src/modal/modal-examples.stories.tsx index f90ab2bb..b30751f0 100644 --- a/src/modal/modal-examples.stories.tsx +++ b/src/modal/modal-examples.stories.tsx @@ -37,6 +37,10 @@ export default { parameters: { viewMode: 'story', badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Settings › Modal / Header', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=7443-241153', + }, layout: 'fullscreen', }, decorators: [ diff --git a/src/notice/notice.stories.jsx b/src/notice/notice.stories.jsx index 6e4751be..2699581a 100644 --- a/src/notice/notice.stories.jsx +++ b/src/notice/notice.stories.jsx @@ -33,6 +33,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Banner › Banner', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=15487-102766', + }, }, } diff --git a/src/password-field/password-field.stories.jsx b/src/password-field/password-field.stories.jsx index b586c9cb..6dba0af2 100644 --- a/src/password-field/password-field.stories.jsx +++ b/src/password-field/password-field.stories.jsx @@ -46,6 +46,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: '24Q3 Foundation › Password', + url: 'https://www.figma.com/design/5gTX7MuUxhCIvL6WK87JVA/24Q3-Foundation?node-id=2295-76983', + }, }, } diff --git a/src/prose/prose.stories.tsx b/src/prose/prose.stories.tsx index 89e63011..81181990 100644 --- a/src/prose/prose.stories.tsx +++ b/src/prose/prose.stories.tsx @@ -12,6 +12,10 @@ export default { component: Prose, parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Markdown › MarkdownElement', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=7391-224517', + }, }, } diff --git a/src/select-field/select-field.stories.jsx b/src/select-field/select-field.stories.jsx index 33cff7e5..c0545f4c 100644 --- a/src/select-field/select-field.stories.jsx +++ b/src/select-field/select-field.stories.jsx @@ -45,6 +45,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Context Menus › Dropdown', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=20744-678051', + }, }, } diff --git a/src/switch-field/switch-field.stories.jsx b/src/switch-field/switch-field.stories.jsx index 1fa64501..1fbcb6bf 100644 --- a/src/switch-field/switch-field.stories.jsx +++ b/src/switch-field/switch-field.stories.jsx @@ -15,6 +15,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Forms › Input Field (Input type=Binary)', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=533-60', + }, }, } diff --git a/src/tabs/tabs.stories.jsx b/src/tabs/tabs.stories.jsx index 38451941..414ba263 100644 --- a/src/tabs/tabs.stories.jsx +++ b/src/tabs/tabs.stories.jsx @@ -51,6 +51,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Tabs › Tab Group', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=8371-275288', + }, }, } diff --git a/src/text-area/text-area.stories.jsx b/src/text-area/text-area.stories.jsx index e64dccb0..25886ff8 100644 --- a/src/text-area/text-area.stories.jsx +++ b/src/text-area/text-area.stories.jsx @@ -87,6 +87,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: '24Q3 Foundation › Multi-line text field', + url: 'https://www.figma.com/design/5gTX7MuUxhCIvL6WK87JVA/24Q3-Foundation?node-id=1987-546972', + }, }, } diff --git a/src/text-field/text-field.stories.jsx b/src/text-field/text-field.stories.jsx index af5f747f..ee08a5c6 100644 --- a/src/text-field/text-field.stories.jsx +++ b/src/text-field/text-field.stories.jsx @@ -190,6 +190,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: '24Q3 Foundation › Text field', + url: 'https://www.figma.com/design/5gTX7MuUxhCIvL6WK87JVA/24Q3-Foundation?node-id=1987-64913', + }, }, } diff --git a/src/text-link/text-link.stories.jsx b/src/text-link/text-link.stories.jsx index 9d5b2131..eb0ab333 100644 --- a/src/text-link/text-link.stories.jsx +++ b/src/text-link/text-link.stories.jsx @@ -10,6 +10,10 @@ export default { parameters: { badges: ['accessible'], + figma: { + path: '24Q3 Foundation › Link styling', + url: 'https://www.figma.com/design/5gTX7MuUxhCIvL6WK87JVA/24Q3-Foundation?node-id=1530-49073', + }, }, } diff --git a/src/text/text.stories.tsx b/src/text/text.stories.tsx index be318bc6..a4c51645 100644 --- a/src/text/text.stories.tsx +++ b/src/text/text.stories.tsx @@ -10,6 +10,10 @@ export default { component: Text, parameters: { badges: ['accessible'], + figma: { + path: 'Global › Text Styles › SF *FOR WEB* › Body 1', + url: 'https://www.figma.com/design/xo9yAsH8PQUpi0eTJh9pmR/Product-Library---Global?node-id=2524-3594', + }, }, } diff --git a/src/toast/toast.stories.tsx b/src/toast/toast.stories.tsx index 7116c91c..fec548ee 100644 --- a/src/toast/toast.stories.tsx +++ b/src/toast/toast.stories.tsx @@ -26,6 +26,10 @@ export default { title: '💬 Feedback/Toast', parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Toast › Toast', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=6654-220700', + }, layout: 'fullscreen', }, decorators: [ diff --git a/src/tooltip/tooltip.stories.tsx b/src/tooltip/tooltip.stories.tsx index 12637afc..17f70e50 100644 --- a/src/tooltip/tooltip.stories.tsx +++ b/src/tooltip/tooltip.stories.tsx @@ -20,6 +20,10 @@ export default { title: '🪟 Overlays/Tooltip', parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Tooltips', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=14597-177215', + }, }, } diff --git a/stories/components/KeyboardShortcut.stories.tsx b/stories/components/KeyboardShortcut.stories.tsx index 0367983b..cad8236e 100644 --- a/stories/components/KeyboardShortcut.stories.tsx +++ b/stories/components/KeyboardShortcut.stories.tsx @@ -10,6 +10,10 @@ export default { title: '📊 Data display/KeyboardShortcut', parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Keyboard Shortcuts › Shortcut', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=9140-282739', + }, }, } diff --git a/stories/components/ProgressBar.stories.tsx b/stories/components/ProgressBar.stories.tsx index 427a90af..04d83005 100644 --- a/stories/components/ProgressBar.stories.tsx +++ b/stories/components/ProgressBar.stories.tsx @@ -11,6 +11,10 @@ export default { component: ProgressBar, parameters: { badges: ['accessible'], + figma: { + path: 'Web › Components / Todoist › Progress › Progress bar', + url: 'https://www.figma.com/design/LYlWNzvhMDh907l07mPPQk/Product-Library---Web?node-id=20195-258607', + }, }, } diff --git a/stories/reactist/Reactist.mdx b/stories/reactist/Reactist.mdx index 92c6fcba..6f4cec78 100644 --- a/stories/reactist/Reactist.mdx +++ b/stories/reactist/Reactist.mdx @@ -1,6 +1,6 @@ import { Story, Meta } from '@storybook/addon-docs/blocks' - + ## Welcome diff --git a/stories/reactist/nesting-vs-polymorphism.mdx b/stories/reactist/nesting-vs-polymorphism.mdx index 87a034a4..784302e6 100644 --- a/stories/reactist/nesting-vs-polymorphism.mdx +++ b/stories/reactist/nesting-vs-polymorphism.mdx @@ -1,6 +1,6 @@ import { Story, Meta } from '@storybook/addon-docs/blocks' - + # Nesting vs. combining via polymorphism diff --git a/stories/reactist/simplified-nested-markup.mdx b/stories/reactist/simplified-nested-markup.mdx index b323cf5f..8944c118 100644 --- a/stories/reactist/simplified-nested-markup.mdx +++ b/stories/reactist/simplified-nested-markup.mdx @@ -1,6 +1,9 @@ import { Story, Meta } from '@storybook/addon-docs/blocks' - + # Simplified markup of the `Stack` and `Inline` components diff --git a/stories/reactist/single-child-stack-columns.mdx b/stories/reactist/single-child-stack-columns.mdx index 78e47dee..92ad1c06 100644 --- a/stories/reactist/single-child-stack-columns.mdx +++ b/stories/reactist/single-child-stack-columns.mdx @@ -1,6 +1,9 @@ import { Story, Meta } from '@storybook/addon-docs/blocks' - + # About `Stack` or `Columns` with a single child diff --git a/tsconfig.json b/tsconfig.json index e60c62b6..82bde444 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "extends": "@doist/tsconfig", - "include": ["src", "types", ".storybook"], + "include": ["src", "types", ".storybook", ".storybook/figma/**/*", ".storybook/badges/**/*"], "compilerOptions": { "allowJs": true, "module": "esnext", @@ -17,6 +17,7 @@ "@storybook/react": ["node_modules/@storybook/react/dist/index.d.ts"], "@storybook/react-vite": ["node_modules/@storybook/react-vite/dist/index.d.ts"], "storybook/actions": ["node_modules/storybook/dist/actions/index.d.ts"], + "storybook/manager-api": ["node_modules/storybook/dist/manager-api/index.d.ts"], "storybook/test": ["node_modules/storybook/dist/test/index.d.ts"], "*": ["src/*", "node_modules/*"] }, diff --git a/tsconfig.react18.json b/tsconfig.react18.json index 9594bbc4..7d9d292d 100644 --- a/tsconfig.react18.json +++ b/tsconfig.react18.json @@ -6,6 +6,7 @@ "@storybook/react": ["node_modules/@storybook/react/dist/index.d.ts"], "@storybook/react-vite": ["node_modules/@storybook/react-vite/dist/index.d.ts"], "storybook/actions": ["node_modules/storybook/dist/actions/index.d.ts"], + "storybook/manager-api": ["node_modules/storybook/dist/manager-api/index.d.ts"], "storybook/test": ["node_modules/storybook/dist/test/index.d.ts"], "react": ["node_modules/@types/react-18"], "react/*": ["node_modules/@types/react-18/*"],