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..9f4df605 --- /dev/null +++ b/src/lib/Figure/Figure.module.css @@ -0,0 +1,30 @@ +.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); + 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.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..550e3f09 --- /dev/null +++ b/src/lib/Picture/Picture.module.css @@ -0,0 +1,5 @@ +.picture { + & img { + display: block; + } +} diff --git a/src/lib/Picture/Picture.stories.tsx b/src/lib/Picture/Picture.stories.tsx new file mode 100644 index 00000000..1c0fe542 --- /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://picsum.photos/300/333', + width: 300, + height: 333, + alt: 'Image description', + sources: [ + { + src: 'https://picsum.photos/600/666', + 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..06a9d0e8 --- /dev/null +++ b/src/lib/Picture/Picture.tsx @@ -0,0 +1,135 @@ +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; +} & ( + | { + /** + * 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 & { + /** + * 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?: Source[]; + /** + * 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'; diff --git a/src/lib/Text/Text.module.css b/src/lib/Text/Text.module.css index be8b1913..0b2e21b7 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); @@ -328,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; @@ -341,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; 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: {},