From f075d21bd4995c3d0897980113d5c1e7f89d2ae1 Mon Sep 17 00:00:00 2001 From: Dima Vyshniakov Date: Wed, 20 Dec 2023 18:19:49 +0100 Subject: [PATCH 1/4] Add picture component --- src/lib/Picture/Picture.mdx | 24 +++++ src/lib/Picture/Picture.module.css | 3 + src/lib/Picture/Picture.stories.tsx | 74 +++++++++++++++ src/lib/Picture/Picture.tsx | 136 ++++++++++++++++++++++++++++ src/lib/Picture/index.ts | 1 + 5 files changed, 238 insertions(+) create mode 100644 src/lib/Picture/Picture.mdx create mode 100644 src/lib/Picture/Picture.module.css create mode 100644 src/lib/Picture/Picture.stories.tsx create mode 100644 src/lib/Picture/Picture.tsx create mode 100644 src/lib/Picture/index.ts diff --git a/src/lib/Picture/Picture.mdx b/src/lib/Picture/Picture.mdx new file mode 100644 index 00000000..d6f2363b --- /dev/null +++ b/src/lib/Picture/Picture.mdx @@ -0,0 +1,24 @@ +import { Meta, ArgsTable, Story, Canvas, Source, Markdown, Primary } from "@storybook/blocks"; +import {Picture} from './Picture.tsx'; +import * as PictureStories from "./Picture.stories.tsx"; + + + +# Picture + +## Description + +Picture is a React component. + +## Imports + +{` +\`\`\`ts +import {Picture} from 'react-forge-ui'; +\`\`\` +`} + + + + + diff --git a/src/lib/Picture/Picture.module.css b/src/lib/Picture/Picture.module.css new file mode 100644 index 00000000..983e5e08 --- /dev/null +++ b/src/lib/Picture/Picture.module.css @@ -0,0 +1,3 @@ +.picture { + --foo: "bar"; +} diff --git a/src/lib/Picture/Picture.stories.tsx b/src/lib/Picture/Picture.stories.tsx new file mode 100644 index 00000000..13e0b78c --- /dev/null +++ b/src/lib/Picture/Picture.stories.tsx @@ -0,0 +1,74 @@ +import type {Meta, StoryObj} from '@storybook/react'; +// import {fn} from '@storybook/test'; + +import {Picture} from './Picture.tsx'; + +const meta = { + title: 'Components/Picture', + component: Picture, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout + layout: 'centered', + }, + args: {}, + argTypes: { + id: { + table: { + disable: true, + }, + }, + role: { + table: { + disable: true, + }, + }, + className: { + table: { + disable: true, + }, + }, + }, +} as Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + render: function Render(args) { + return ; + }, + args: { + src: 'https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg', + width: 298, + height: 332, + alt: 'Image description', + sources: [ + { + src: 'https://interactive-examples.mdn.mozilla.net/media/cc0-images/surfer-240-200.jpg', + mediaCondition: '(orientation: portrait)', + }, + ], + }, +}; + +export const WithCode: Story = { + render: args => { + // here comes the code + return ; + }, +}; + +WithCode.args = { + id: 'foo', +}; + +WithCode.argTypes = {}; + +WithCode.parameters = { + docs: { + source: { + language: 'tsx', + type: 'code', + }, + }, +}; diff --git a/src/lib/Picture/Picture.tsx b/src/lib/Picture/Picture.tsx new file mode 100644 index 00000000..ccacd573 --- /dev/null +++ b/src/lib/Picture/Picture.tsx @@ -0,0 +1,136 @@ +import type {DetailedHTMLProps, ImgHTMLAttributes} from 'react'; +import {forwardRef} from 'react'; +import classNames from 'classnames'; + +import type {DataAttributes, LibraryProps} from '@/internal/LibraryAPI'; + +import classes from './Picture.module.css'; + +type IntrinsicWidth = `${number}w`; +type DensityDescriptor = `${number}x`; + +type Source = { + /** + * Provide the source image url + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/src + * @see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types + */ + src: string; + /** + * Provide the source image MIME type + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#type + */ + type?: string; + /** + * Provide media condition for the source image + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#media + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries + */ + mediaCondition?: string; + /** + * Provide width of the slot the image will fill when the media condition is true + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#sizes + */ + slotWidth?: string; + /** + * Provide the source image display height in pixels + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#height + */ + width?: number; + /** + * Provide the source image display width in pixels + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#width + */ + height?: number; +}; + +type SourceWidth = Source & { + /** + * Provide the source image width descriptor. Has to be a positive integer directly followed by w. E.g. 480w + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#srcset + * @see https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size + */ + intrinsicWidth?: IntrinsicWidth; + density?: never; +}; + +type SourceDensity = Source & { + intrinsicWidth?: never; + /** + * Provide the source image pixel density descriptor. Has to be a positive floating point number directly followed by x. E.g. 2x + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#srcset + * @see https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size + */ + density?: DensityDescriptor; +}; + +export type Props = DataAttributes & + LibraryProps & { + /** + * Provide default image url + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/src + */ + src: string; + /** + * Set default image width + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/width + */ + width?: number; + /** + * Set default image height + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/height + */ + height?: number; + /** + * Provide alternate text to display when the image is not loaded or for use by assistive devices + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt + */ + alt?: string; + /** + * Provide alternative sources configs array + * @see SourceDensity + * @see SourceWidth + */ + sources?: (SourceDensity | SourceWidth)[]; + /** + * Set image loading behavior + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading + */ + loading?: DetailedHTMLProps, HTMLImageElement>['loading']; + }; + +export const Picture = forwardRef( + ({className, alt, src, sources, width, height, loading = 'lazy', ...nativeProps}, ref) => { + return ( + + {sources?.map( + ({ + src, + mediaCondition, + density = '1x', + intrinsicWidth, + slotWidth = '', + type, + width: srcWidth, + height: srcHeight, + }) => { + const srcParam = intrinsicWidth ?? density; + return ( + + ); + } + )} + {alt} + + ); + } +); + +Picture.displayName = 'Picture'; diff --git a/src/lib/Picture/index.ts b/src/lib/Picture/index.ts new file mode 100644 index 00000000..64d1081f --- /dev/null +++ b/src/lib/Picture/index.ts @@ -0,0 +1 @@ +export {Picture} from './Picture.tsx'; From 37874814cd2160e789e9fe55a547ee9409ac803a Mon Sep 17 00:00:00 2001 From: Dima Vyshniakov Date: Wed, 20 Dec 2023 18:24:27 +0100 Subject: [PATCH 2/4] improve types --- src/lib/Picture/Picture.tsx | 43 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/lib/Picture/Picture.tsx b/src/lib/Picture/Picture.tsx index ccacd573..06a9d0e8 100644 --- a/src/lib/Picture/Picture.tsx +++ b/src/lib/Picture/Picture.tsx @@ -42,27 +42,26 @@ type Source = { * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#width */ height?: number; -}; - -type SourceWidth = Source & { - /** - * Provide the source image width descriptor. Has to be a positive integer directly followed by w. E.g. 480w - * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#srcset - * @see https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size - */ - intrinsicWidth?: IntrinsicWidth; - density?: never; -}; - -type SourceDensity = Source & { - intrinsicWidth?: never; - /** - * Provide the source image pixel density descriptor. Has to be a positive floating point number directly followed by x. E.g. 2x - * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#srcset - * @see https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size - */ - density?: DensityDescriptor; -}; +} & ( + | { + /** + * Provide the source image width descriptor. Has to be a positive integer directly followed by w. E.g. 480w + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#srcset + * @see https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size + */ + intrinsicWidth?: IntrinsicWidth; + density?: never; + } + | { + intrinsicWidth?: never; + /** + * Provide the source image pixel density descriptor. Has to be a positive floating point number directly followed by x. E.g. 2x + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#srcset + * @see https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size + */ + density?: DensityDescriptor; + } +); export type Props = DataAttributes & LibraryProps & { @@ -91,7 +90,7 @@ export type Props = DataAttributes & * @see SourceDensity * @see SourceWidth */ - sources?: (SourceDensity | SourceWidth)[]; + sources?: Source[]; /** * Set image loading behavior * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading From edf357a4e69d5d8ae40ea9e0737a586c13f45ac2 Mon Sep 17 00:00:00 2001 From: Dima Vyshniakov Date: Wed, 20 Dec 2023 19:49:48 +0100 Subject: [PATCH 3/4] add Figure component --- src/lib/Figure/Figure.mdx | 24 ++++ src/lib/Figure/Figure.module.css | 31 +++++ src/lib/Figure/Figure.stories.tsx | 123 +++++++++++++++++++ src/lib/Figure/Figure.tsx | 43 +++++++ src/lib/Figure/index.ts | 1 + src/lib/Picture/Picture.module.css | 4 +- src/lib/Picture/Picture.stories.tsx | 8 +- src/lib/Text/Text.module.css | 8 +- templates/Component/TemplateName.stories.tsx | 12 +- 9 files changed, 246 insertions(+), 8 deletions(-) create mode 100644 src/lib/Figure/Figure.mdx create mode 100644 src/lib/Figure/Figure.module.css create mode 100644 src/lib/Figure/Figure.stories.tsx create mode 100644 src/lib/Figure/Figure.tsx create mode 100644 src/lib/Figure/index.ts diff --git a/src/lib/Figure/Figure.mdx b/src/lib/Figure/Figure.mdx new file mode 100644 index 00000000..39495358 --- /dev/null +++ b/src/lib/Figure/Figure.mdx @@ -0,0 +1,24 @@ +import { Meta, ArgsTable, Story, Canvas, Source, Markdown, Primary } from "@storybook/blocks"; +import {Figure} from './Figure.tsx'; +import * as FigureStories from "./Figure.stories.tsx"; + + + +# Figure + +## Description + +Figure is a React component. + +## Imports + +{` +\`\`\`ts +import {Figure} from 'react-forge-ui'; +\`\`\` +`} + + + + + diff --git a/src/lib/Figure/Figure.module.css b/src/lib/Figure/Figure.module.css new file mode 100644 index 00000000..24d79372 --- /dev/null +++ b/src/lib/Figure/Figure.module.css @@ -0,0 +1,31 @@ +.vars { + --position: center; +} + +.wrapper { + display: flex; + flex-direction: row; + justify-content: var(--position); + margin-bottom: calc(var(--sizeUnit) * 3); +} + +.figure { + background: var(--background000); + border: 3px solid var(--colorMi); + border-radius: 6px; + display: flex; + flex-direction: column; + padding: calc(var(--sizeUnit) * 2) calc(var(--sizeUnit) * 2) var(--sizeUnit); + + &:hover { + border-color: var(--colorRe); + } + + & figcaption { + color: var(--colorFa); + font-size: var(--fontSizeSmall); + font-style: italic; + margin-top: calc(var(--sizeUnit) * 1); + text-align: center; + } +} diff --git a/src/lib/Figure/Figure.stories.tsx b/src/lib/Figure/Figure.stories.tsx new file mode 100644 index 00000000..dfd6b031 --- /dev/null +++ b/src/lib/Figure/Figure.stories.tsx @@ -0,0 +1,123 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import {Picture} from '@/lib/Picture'; +import {Text, Table} from '@/lib/Text'; + +import {Figure} from './Figure.tsx'; + +const TableElement = ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header content 1Header content 2Header content 3
Body content 1Body content 2Body content 3
Body content 1Body content 2Body content 3
Body content 1Body content 2Body content 3
Footer content 1Footer content 2Footer content 3
+); + +const PictureComponent = ; + +const meta = { + title: 'Components/Figure', + component: Figure, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout + layout: 'centered', + }, + args: { + caption: 'This is caption!', + position: 'center', + children: PictureComponent, + }, + argTypes: { + className: { + table: { + disable: true, + }, + }, + id: { + table: { + disable: true, + }, + }, + role: { + table: { + disable: true, + }, + }, + children: { + options: ['picture', 'table'], // An array of serializable values + mapping: { + picture: PictureComponent, + table: TableElement, + }, // Maps serializable option values to complex arg values + control: { + type: 'radio', // Type 'select' is automatically inferred when 'options' is defined + labels: { + // 'labels' maps option values to string labels + picture: 'With Picture component', + table: 'With Table component', + }, + }, + }, + }, +} as Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + render: ({children, ...args}) => { + return
{children}
; + }, + args: {}, +}; + +export const WrappedWithText: Story = { + render: ({children, ...args}) => { + return ( + +

+ It has survived not only five centuries, but also the leap into electronic typesetting, remaining + essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets + containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus + PageMaker including versions of Lorem Ipsum. +

+
{children}
+

+ It has survived not only five centuries, but also the leap into electronic typesetting, remaining + essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets + containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus + PageMaker including versions of Lorem Ipsum. +

+
+ ); + }, + args: {}, +}; diff --git a/src/lib/Figure/Figure.tsx b/src/lib/Figure/Figure.tsx new file mode 100644 index 00000000..0c558c91 --- /dev/null +++ b/src/lib/Figure/Figure.tsx @@ -0,0 +1,43 @@ +import type {ReactElement} from 'react'; +import {forwardRef, useMemo} from 'react'; +import classNames from 'classnames'; +import {useLocalTheme} from 'css-vars-hook'; + +import type {DataAttributes, LibraryProps} from '@/internal/LibraryAPI'; + +import classes from './Figure.module.css'; + +enum Positions { + center = 'center', + left = 'left', + right = 'right', +} + +export type Props = DataAttributes & + LibraryProps & { + children: ReactElement; + caption?: string; + position?: keyof typeof Positions; + }; + +export const Figure = forwardRef( + ({children, className, caption, position = Positions.center, ...nativeProps}, ref) => { + const theme = useMemo( + () => ({ + position, + }), + [position] + ); + const {LocalRoot} = useLocalTheme(); + return ( + +
+ {children} + {caption &&
{caption}
} +
+
+ ); + } +); + +Figure.displayName = 'Figure'; diff --git a/src/lib/Figure/index.ts b/src/lib/Figure/index.ts new file mode 100644 index 00000000..1cdc2cac --- /dev/null +++ b/src/lib/Figure/index.ts @@ -0,0 +1 @@ +export {Figure} from './Figure.tsx'; diff --git a/src/lib/Picture/Picture.module.css b/src/lib/Picture/Picture.module.css index 983e5e08..550e3f09 100644 --- a/src/lib/Picture/Picture.module.css +++ b/src/lib/Picture/Picture.module.css @@ -1,3 +1,5 @@ .picture { - --foo: "bar"; + & img { + display: block; + } } diff --git a/src/lib/Picture/Picture.stories.tsx b/src/lib/Picture/Picture.stories.tsx index 13e0b78c..1c0fe542 100644 --- a/src/lib/Picture/Picture.stories.tsx +++ b/src/lib/Picture/Picture.stories.tsx @@ -38,13 +38,13 @@ export const Primary: Story = { return ; }, args: { - src: 'https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg', - width: 298, - height: 332, + src: 'https://picsum.photos/300/333', + width: 300, + height: 333, alt: 'Image description', sources: [ { - src: 'https://interactive-examples.mdn.mozilla.net/media/cc0-images/surfer-240-200.jpg', + src: 'https://picsum.photos/600/666', mediaCondition: '(orientation: portrait)', }, ], diff --git a/src/lib/Text/Text.module.css b/src/lib/Text/Text.module.css index be8b1913..eaf2d23e 100644 --- a/src/lib/Text/Text.module.css +++ b/src/lib/Text/Text.module.css @@ -272,7 +272,7 @@ .table, .text table { - border: 1px solid gray; + border: 2px solid var(--background000); border-collapse: collapse; color: var(--textColor); font-size: var(--fontSizeSmall); @@ -282,7 +282,7 @@ & > tr:hover td, & > *:not(tfoot) tr:hover td { - background-color: var(--colorMi); + background-color: var(--colorSol); } & th, @@ -300,6 +300,10 @@ letter-spacing: 0.3px; } + & td { + background: var(--background000); + } + & tfoot td { background: var(--colorFa); color: var(--background000); diff --git a/templates/Component/TemplateName.stories.tsx b/templates/Component/TemplateName.stories.tsx index 30a52500..5215ace2 100644 --- a/templates/Component/TemplateName.stories.tsx +++ b/templates/Component/TemplateName.stories.tsx @@ -17,6 +17,16 @@ const meta = { disable: true, }, }, + id: { + table: { + disable: true, + }, + }, + role: { + table: { + disable: true, + }, + }, }, } as Meta; @@ -24,7 +34,7 @@ export default meta; type Story = StoryObj; export const Primary: Story = { - render: function Render(args) { + render: args => { return ; }, args: {}, From a7de0d91d0479db60890eac338a4666618457fe3 Mon Sep 17 00:00:00 2001 From: Dima Vyshniakov Date: Wed, 20 Dec 2023 22:19:20 +0100 Subject: [PATCH 4/4] clean up --- src/lib/Figure/Figure.module.css | 1 - src/lib/Text/Text.module.css | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/Figure/Figure.module.css b/src/lib/Figure/Figure.module.css index 24d79372..9f4df605 100644 --- a/src/lib/Figure/Figure.module.css +++ b/src/lib/Figure/Figure.module.css @@ -12,7 +12,6 @@ .figure { background: var(--background000); border: 3px solid var(--colorMi); - border-radius: 6px; display: flex; flex-direction: column; padding: calc(var(--sizeUnit) * 2) calc(var(--sizeUnit) * 2) var(--sizeUnit); diff --git a/src/lib/Text/Text.module.css b/src/lib/Text/Text.module.css index eaf2d23e..0b2e21b7 100644 --- a/src/lib/Text/Text.module.css +++ b/src/lib/Text/Text.module.css @@ -332,8 +332,9 @@ border-radius: var(--sizeUnit); color: var(--textColor); display: block; - font-family: var(--fontFamilyMonospace); + font-family: var(--fontFamily); font-size: var(--fontSizeSmall); + line-height: 1.5; margin-bottom: calc(var(--sizeUnit) * 2); max-width: 100%; overflow: auto; @@ -345,10 +346,10 @@ border-right: 3px solid var(--colorDo); bottom: 0; color: var(--colorRe); - content: ""; - font-size: 24px; + content: "{x}"; + font-size: 36px; font-style: normal; - font-weight: var(--fontWeightBold); + font-weight: var(--fontWeightNormal); left: 6px; line-height: 1; padding-left: 6px;