diff --git a/packages/components-css/card-group/README.md b/packages/components-css/card-group/README.md new file mode 100644 index 00000000..4ad1d3b8 --- /dev/null +++ b/packages/components-css/card-group/README.md @@ -0,0 +1,3 @@ + + +# Frameless CardGroup component diff --git a/packages/components-css/card-group/index.scss b/packages/components-css/card-group/index.scss new file mode 100644 index 00000000..a06db111 --- /dev/null +++ b/packages/components-css/card-group/index.scss @@ -0,0 +1,24 @@ +.frameless-card-group { + container-type: inline-size; + display: grid; + gap: var(--frameless-card-group-gap); + grid-auto-flow: dense; +} + +@media (width >= 600px) { + .frameless-card-group { + grid-template-columns: 1fr 1fr; + } +} + +@media (width <= 900px) { + .frameless-card-group { + grid-template-columns: 1fr; + } +} + +@container (max-width: 400px) { + .frameless-card { + --utrecht-paragraph-font-size: var(--frameless-card-paragraph-font-size); + } +} diff --git a/packages/components-css/card/README.md b/packages/components-css/card/README.md new file mode 100644 index 00000000..6e3e27c4 --- /dev/null +++ b/packages/components-css/card/README.md @@ -0,0 +1,3 @@ + + +# Frameless Card component diff --git a/packages/components-css/card/index.scss b/packages/components-css/card/index.scss new file mode 100644 index 00000000..73bd333b --- /dev/null +++ b/packages/components-css/card/index.scss @@ -0,0 +1,38 @@ +.frameless-card { + background-color: var(--frameless-card-color-background-color); + border-radius: var(--frameless-card-border-border-radius); + font-family: var(--frameless-card-font-font-family); + max-inline-size: var(--frameless-card-spacing-max-width); + padding-block-end: var(--frameless-card-spacing-padding-block-end); + padding-block-start: var(--frameless-card-spacing-padding-block-start); + padding-inline-end: var(--frameless-card-spacing-padding-inline-end); + padding-inline-start: var(--frameless-card-spacing-padding-inline-start); +} + +.frameless-card__content { + --utrecht-paragraph-margin-block-end: var(--frameless-card-paragraph-margin-block-end); + --utrecht-space-around: 1; +} + +@container (max-width: 400px) { + .frameless-card__content { + --utrecht-paragraph-font-size: var(--frameless-card-paragraph-font-size); + } +} + +.frameless-card__heading { + --utrecht-heading-2-font-size: var(--frameless-card-heading-font-size); + --utrecht-heading-3-font-size: var(--frameless-card-heading-font-size); + --utrecht-heading-4-font-size: var(--frameless-card-heading-font-size); + --utrecht-heading-5-font-size: var(--frameless-card-heading-font-size); + --utrecht-heading-6-font-size: var(--frameless-card-heading-font-size); + --utrecht-heading-2-margin-block-end: var(--frameless-card-heading-margin-block-end); + --utrecht-heading-3-margin-block-end: var(--frameless-card-heading-margin-block-end); + --utrecht-heading-4-margin-block-end: var(--frameless-card-heading-margin-block-end); + --utrecht-heading-5-margin-block-end: var(--frameless-card-heading-margin-block-end); + --utrecht-heading-6-margin-block-end: var(--frameless-card-heading-margin-block-end); + --utrecht-heading-4-line-height: var(--frameless-card-line-height); + --utrecht-heading-5-line-height: var(--frameless-card-line-height); + --utrecht-heading-6-line-height: var(--frameless-card-line-height); + --utrecht-space-around: 1; +} diff --git a/packages/components-react/src/Card/index.tsx b/packages/components-react/src/Card/index.tsx new file mode 100644 index 00000000..dde784e3 --- /dev/null +++ b/packages/components-react/src/Card/index.tsx @@ -0,0 +1,26 @@ +import { Heading } from '@utrecht/component-library-react'; +import clsx from 'clsx'; +import { HTMLAttributes, PropsWithChildren } from 'react'; +import '@frameless/components-css/card/index.scss'; + +interface CardProps extends HTMLAttributes { + heading?: string; + headingLevel?: number; +} + +export const Card = ({ + children, + heading, + headingLevel = 2, + className, + ...restProps +}: PropsWithChildren) => ( +
+ {heading && ( + + {heading} + + )} +
{children}
+
+); diff --git a/packages/components-react/src/CardGroup/index.tsx b/packages/components-react/src/CardGroup/index.tsx new file mode 100644 index 00000000..ec62600b --- /dev/null +++ b/packages/components-react/src/CardGroup/index.tsx @@ -0,0 +1,16 @@ +import clsx from 'clsx'; +import { ForwardedRef, forwardRef, HTMLAttributes, PropsWithChildren } from 'react'; +import '@frameless/components-css/card-group/index.scss'; +import '@frameless/components-css/card/index.scss'; + +export type CardGroupProps = HTMLAttributes; + +export const CardGroup = forwardRef( + ({ children, className, ...restProps }: PropsWithChildren, ref: ForwardedRef) => ( +
+ {children} +
+ ), +); + +CardGroup.displayName = 'CardGroup'; diff --git a/packages/components-react/src/index.ts b/packages/components-react/src/index.ts index 956ae7a6..df291207 100644 --- a/packages/components-react/src/index.ts +++ b/packages/components-react/src/index.ts @@ -1 +1,3 @@ export { Heading1 } from '@utrecht/component-library-react'; +export { Card } from './Card'; +export { CardGroup } from './CardGroup'; diff --git a/packages/storybook/src/css-card.stories.tsx b/packages/storybook/src/css-card.stories.tsx new file mode 100644 index 00000000..8bf6306a --- /dev/null +++ b/packages/storybook/src/css-card.stories.tsx @@ -0,0 +1,141 @@ +import '@frameless/components-css/card/index.scss'; +import readme from '@frameless/components-css/card/README.md?raw'; +import { Card } from '@frameless/components-react/src/Card'; +import type { Meta, StoryObj } from '@storybook/react'; +import { Paragraph } from '@utrecht/component-library-react'; + +const meta = { + title: 'CSS Component/Card', + id: 'css-card', + component: Card, + argTypes: { + children: { + name: 'Content', + description: 'Card', + type: { + name: 'string', + required: true, + }, + defaultValue: '', + }, + }, + args: { + children: '', + }, + tags: ['autodocs'], + parameters: { + docs: { + description: { + component: readme, + }, + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; + +export const LongHeading: Story = { + args: { + heading: 'The quick brown fox jumps over the lazy dog', + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; + +export const Empty: Story = { + args: { + children: '', + }, +}; + +export const WithHeading2: Story = { + args: { + heading: 'Design Systems', + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; +export const WithHeading3: Story = { + args: { + heading: 'Design Systems', + headingLevel: 3, + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; +export const WithHeading4: Story = { + args: { + heading: 'Design Systems', + headingLevel: 4, + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; +export const WithHeading5: Story = { + args: { + heading: 'Design Systems', + headingLevel: 5, + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; + +export const WithHeading6: Story = { + args: { + heading: 'Design Systems', + headingLevel: 6, + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; diff --git a/packages/storybook/src/css-cardgroup.stories.tsx b/packages/storybook/src/css-cardgroup.stories.tsx new file mode 100644 index 00000000..c7f84130 --- /dev/null +++ b/packages/storybook/src/css-cardgroup.stories.tsx @@ -0,0 +1,62 @@ +/* @license CC0-1.0 */ + +import '@frameless/components-css/card/index.scss'; +import readme from '@frameless/components-css/card-group/README.md?raw'; +import { Card } from '@frameless/components-react/src/Card'; +import { CardGroup } from '@frameless/components-react/src/CardGroup'; +import type { Meta, StoryObj } from '@storybook/react'; +import { Paragraph } from '@utrecht/component-library-react'; + +const meta = { + title: 'CSS Component/CardGroup', + id: 'css-card-group', + component: CardGroup, + argTypes: { + children: { + name: 'Content', + description: 'CardGroup', + type: { + name: 'string', + required: true, + }, + defaultValue: '', + }, + }, + args: { + children: '', + }, + tags: ['autodocs'], + parameters: { + docs: { + description: { + component: readme, + }, + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + children: ( + <> + + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + + ), + }, + name: 'Frameless CardGroup', +}; diff --git a/packages/storybook/src/css-stories/heading1.stories.tsx b/packages/storybook/src/css-stories/heading1.stories.tsx index e25f5614..46c7a9ed 100644 --- a/packages/storybook/src/css-stories/heading1.stories.tsx +++ b/packages/storybook/src/css-stories/heading1.stories.tsx @@ -1,10 +1,8 @@ /* @license CC0-1.0 */ -// import readme from '@frameless/components-css/heading1/README.md?raw'; import type { Meta, StoryObj } from '@storybook/react'; import { Heading1 } from '@utrecht/component-library-react/dist/css-module'; // import { Heading1 } from '@frameless/components-react'; // TODO: use frameless package instead -// import '@frameless/components-css/heading1/index.scss'; const meta = { title: 'CSS Component/Heading1', diff --git a/packages/storybook/src/react-card.stories.tsx b/packages/storybook/src/react-card.stories.tsx new file mode 100644 index 00000000..a9eb2f52 --- /dev/null +++ b/packages/storybook/src/react-card.stories.tsx @@ -0,0 +1,141 @@ +import '@frameless/components-css/card/index.scss'; +import readme from '@frameless/components-css/card/README.md?raw'; +import { Card } from '@frameless/components-react/src/Card'; +import type { Meta, StoryObj } from '@storybook/react'; +import { Paragraph } from '@utrecht/component-library-react'; + +const meta = { + title: 'React Component/Card', + id: 'react-card', + component: Card, + argTypes: { + children: { + name: 'Content', + description: 'Card', + type: { + name: 'string', + required: true, + }, + defaultValue: '', + }, + }, + args: { + children: '', + }, + tags: ['autodocs'], + parameters: { + docs: { + description: { + component: readme, + }, + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; + +export const LongHeading: Story = { + args: { + heading: 'The quick brown fox jumps over the lazy dog', + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; + +export const Empty: Story = { + args: { + children: '', + }, +}; + +export const WithHeading2: Story = { + args: { + heading: 'Design Systems', + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; +export const WithHeading3: Story = { + args: { + heading: 'Design Systems', + headingLevel: 3, + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; +export const WithHeading4: Story = { + args: { + heading: 'Design Systems', + headingLevel: 4, + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; +export const WithHeading5: Story = { + args: { + heading: 'Design Systems', + headingLevel: 5, + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; + +export const WithHeading6: Story = { + args: { + heading: 'Design Systems', + headingLevel: 6, + children: ( + <> + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + ), + }, +}; diff --git a/packages/storybook/src/react-cardgroup.stories.tsx b/packages/storybook/src/react-cardgroup.stories.tsx new file mode 100644 index 00000000..c0087273 --- /dev/null +++ b/packages/storybook/src/react-cardgroup.stories.tsx @@ -0,0 +1,62 @@ +/* @license CC0-1.0 */ + +import '@frameless/components-css/card/index.scss'; +import readme from '@frameless/components-css/card-group/README.md?raw'; +import { Card } from '@frameless/components-react/src/Card'; +import { CardGroup } from '@frameless/components-react/src/CardGroup'; +import type { Meta, StoryObj } from '@storybook/react'; +import { Paragraph } from '@utrecht/component-library-react'; + +const meta = { + title: 'React Component/CardGroup', + id: 'react-card-group', + component: CardGroup, + argTypes: { + children: { + name: 'Content', + description: 'CardGroup', + type: { + name: 'string', + required: true, + }, + defaultValue: '', + }, + }, + args: { + children: '', + }, + tags: ['autodocs'], + parameters: { + docs: { + description: { + component: readme, + }, + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + children: ( + <> + + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + + + Herbruikbare componenten onafhankelijk van huisstijl, daar mag je ons voor wakker maken! Frameless heeft al + aan meerdere white-label design systems mogen werken en is trots op onze bijdrage aan NL Design System. + + + + ), + }, + name: 'Frameless CardGroup', +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b200f4c..8a6b8fe3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -317,7 +317,11 @@ importers: specifier: 0.0.33 version: 0.0.33 - proprietary/font: {} + proprietary/font: + dependencies: + '@fontsource/fira-sans': + specifier: 5.0.20 + version: 5.0.20 packages: @@ -1302,6 +1306,9 @@ packages: '@fal-works/esbuild-plugin-global-externals@2.1.2': resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} + '@fontsource/fira-sans@5.0.20': + resolution: {integrity: sha512-inmUjoKPrgnO4uUaZTAgP0b6YdhDfA52axHXvdTwgLvwd2kn3ZgK52UZoxD0VnrvTOjLA/iE4oC0tNtz4nyb5g==} + '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -9669,6 +9676,8 @@ snapshots: '@fal-works/esbuild-plugin-global-externals@2.1.2': {} + '@fontsource/fira-sans@5.0.20': {} + '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.2 diff --git a/proprietary/design-tokens/figma/figma.tokens.json b/proprietary/design-tokens/figma/figma.tokens.json index da6021a7..12f1bbaf 100644 --- a/proprietary/design-tokens/figma/figma.tokens.json +++ b/proprietary/design-tokens/figma/figma.tokens.json @@ -62,7 +62,7 @@ }, "font-family": { "primary": { - "value": "Fira Sans, Helvetica, Arial, sans-serif", + "value": "'Fira Sans', Helvetica, Arial, sans-serif", "type": "fontFamilies" }, "secondary": { @@ -647,6 +647,20 @@ "value": "48px", "type": "sizing" } + }, + "max-width": { + "sm": { + "value": "100px", + "type": "sizing" + }, + "md": { + "value": "200px", + "type": "sizing" + }, + "lg": { + "value": "500px", + "type": "sizing" + } } }, "box-shadow": { @@ -2080,6 +2094,43 @@ } } }, + "components/card": { + "frameless": { + "card": { + "heading": { + "font-size": { "value": "{frameless.typography.font-size.xl}" }, + "margin-block-end": { "value": "{frameless.space.block.rat}" } + }, + "font": { + "font-family": { "value": "{frameless.typography.font-family.primary}" } + }, + "color": { + "background-color": { "value": "{frameless.color.petrol.95}" } + }, + "paragraph": { + "font-size": { "value": "{frameless.typography.font-size.sm}" }, + "margin-block-end": { "value": "{frameless.space.block.rat}" } + }, + "border": { + "border-radius": { "value": "{frameless.border-radius.md}" } + }, + "spacing": { + "max-width": { "value": "{frameless.size.max-width.lg}" }, + "padding-block-start": { "value": "{frameless.space.block.snail}" }, + "padding-block-end": { "value": "{frameless.space.block.snail}" }, + "padding-inline-start": { "value": "{frameless.space.inline.rabbit}" }, + "padding-inline-end": { "value": "{frameless.space.inline.rabbit}" } + }, + "group": { + "gap": { "value": "{frameless.space.row.cat}" } + }, + + "line-height": { + "line-height": { "value": "{frameless.typography.line-height.sm}" } + } + } + } + }, "components/checkbox": { "utrecht": { "checkbox": { diff --git a/proprietary/font/package.json b/proprietary/font/package.json index 2fdb21a1..badc6f7d 100644 --- a/proprietary/font/package.json +++ b/proprietary/font/package.json @@ -18,5 +18,8 @@ "repository": { "type": "git+ssh", "url": "git@github.com:frameless/website.git" + }, + "dependencies": { + "@fontsource/fira-sans": "5.0.20" } } diff --git a/proprietary/font/src/index.scss b/proprietary/font/src/index.scss index eefea7c4..97c8ed7d 100644 --- a/proprietary/font/src/index.scss +++ b/proprietary/font/src/index.scss @@ -1,12 +1,16 @@ -/* -You can install your own font files, or install font packages from npm. -FontSource contains many fonts that can installed via npm -so you don't have to use a CDN or hosted files from Google Fonts. - -Here's "Open Sans", for example. -https://fontsource.org/fonts/open-sans -*/ - -/* @import "~@fontsource/open-sans/400.css"; */ - -/* @import "~@fontsource/open-sans/700.css"; */ +@import "@fontsource/fira-sans/200.css"; +@import "@fontsource/fira-sans/200-italic.css"; +@import "@fontsource/fira-sans/300.css"; +@import "@fontsource/fira-sans/300-italic.css"; +@import "@fontsource/fira-sans/400.css"; +@import "@fontsource/fira-sans/400-italic.css"; +@import "@fontsource/fira-sans/500.css"; +@import "@fontsource/fira-sans/500-italic.css"; +@import "@fontsource/fira-sans/600.css"; +@import "@fontsource/fira-sans/600-italic.css"; +@import "@fontsource/fira-sans/700.css"; +@import "@fontsource/fira-sans/700-italic.css"; +@import "@fontsource/fira-sans/800.css"; +@import "@fontsource/fira-sans/800-italic.css"; +@import "@fontsource/fira-sans/900.css"; +@import "@fontsource/fira-sans/900-italic.css";