Merge pull request #241 from reuters-graphics/mf-block

Updates Block
This commit is contained in:
MinamiFunakoshiTR 2025-04-07 10:19:49 -05:00 committed by GitHub
commit 3de2b2a982
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 200 additions and 164 deletions

View file

@ -0,0 +1,99 @@
import { Meta, Canvas } from '@storybook/blocks';
import * as BlockStories from './Block.stories.svelte';
<Meta of={BlockStories} />
# Block
The `Block` component is the basic building block of pages, a responsive container that wraps around each section of your piece.
Blocks are stacked vertically within the well created by the [Article](./?path=/docs/components-page-layout-article--docs) component. They can have different widths on larger screens depending on the `width` prop.
> 📌 Many of our other components already use the `Block` component internally. You'll usually only need to use it yourself if you're making something custom.
```svelte
<script>
import { Block } from '@reuters-graphics/graphics-components';
</script>
<Block>
<!-- Contents for this block goes here -->
</Block>
```
<Canvas of={BlockStories.Demo} />
## Custom layouts
Our article well is designed to provide a basic responsive layout for you, but it also lets you customise.
The radical but easiest way to do this is to create a `Block` with a `fluid` width -- which basically cancels out the article well dimensions -- and then code whatever you need from scratch or with another framework.
The demo below does exactly that to create an edge-to-edge grid with [flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).
```svelte
<Block width="fluid">
<div class="my-radical-container">
<!-- Now, you have full control over layout! -->
</div>
</Block>
```
<Canvas of={BlockStories.CustomLayout} />
## Snap widths
Normally, `Block` containers resize fluidly below the original `width`. Sometimes, though, you may want the container to snap to the next breakpoint -- for example, if you have a static graphic that looks fine at the set block breakpoints, but isn't so great at widths inbetween.
You can use the `snap` prop to force the container to snap to each block width successively as the window sizes down.
```svelte
<Block width="wider" snap={true}>
<!-- Contents for this block -->
</Block>
```
<Canvas of={BlockStories.SnapWidthsBasic} />
If you want to skip certain block widths entirely, you can add one or more class of `skip-{block width class}` to the `Block`.
> **NOTE:** The snap width breakpoints only work on `Block` components with widths `wider` and below. `widest` and `fluid` are both **always** fluid, since they go edge-to-edge.
```svelte
<!-- Will skip wide and go straight to normal column width on resize. -->
<Block width="wider" snap={true} class="skip-wide">
<!-- Contents for this block -->
</Block>
```
This is probably easier to see in action than explain in words, so [resize the demo](./?path=/docs/components-page-layout-block--snap-skip-widths) to get a better picture of how it all works.
## Using with custom column widths
Snap width breakpoints are hard-coded to the default article well column widths, so if you set custom `columnWidths` on the [Article](./?path=/docs/components-page-layout-article--docs) component (**rare!**), you need to do a littie work to use this functionality.
Luckily, it's still pretty easy. Just add a `cls` or `id` to your `Block` so you can target it with some custom SCSS. Then define a few SCSS variables corresponding to your custom column widths, and use the `block-snap-widths` SCSS mixin to get the same functionality at your custom breakpoints.
```svelte
<Block width="wider" snap={true} class="custom-blocks">
<!-- Contents for this block -->
</Block>
<style lang="scss">
// Define custom column widths
$column-width-narrower: 310px;
$column-width-narrow: 450px;
$column-width-normal: 600px;
$column-width-wide: 860px;
$column-width-wider: 1400px;
@use '@reuters-graphics/graphics-components/scss/mixins' as mixins;
:global {
div.custom-blocks {
@include mixins.block-snap-widths; // Use the `block-snap-widths` mixin
}
}
</style>
```

View file

@ -1,19 +1,11 @@
<script module lang="ts">
// @ts-ignore raw
import componentDocs from './stories/docs/component.md?raw';
// @ts-ignore raw
import customLayoutsDocs from './stories/docs/customLayouts.md?raw';
// @ts-ignore raw
import snapWidthsDocs from './stories/docs/snapWidths.md?raw';
import { defineMeta } from '@storybook/addon-svelte-csf';
import Block from './Block.svelte';
import { withComponentDocs, withStoryDocs } from '$docs/utils/withParams.js';
export const meta = {
const { Story } = defineMeta({
title: 'Components/Page layout/Block',
component: Block,
...withComponentDocs(componentDocs),
tags: ['autodocs'],
argTypes: {
width: {
control: 'select',
@ -28,35 +20,27 @@
],
},
},
};
});
</script>
<script>
import { Template, Story } from '@storybook/addon-svelte-csf';
import Article from '../Article/Article.svelte';
</script>
<Template >
{#snippet children({ args })}
<Article id="block-demo-article">
<div class="article-boundaries">
<div class="label">Article</div>
<Block {...args}>
<div class="label">Block</div>
</Block>
</div>
</Article>
{/snippet}
</Template>
{#snippet template()}
<Article id="block-demo-article">
<div class="article-boundaries">
<div class="label">Article</div>
<Block>
<div class="label">Block</div>
</Block>
</div>
</Article>
{/snippet}
<Story
name="Default"
args="{{
width: 'normal',
}}"
/>
<Story name="Demo" children={template} />
<Story name="Custom layouts" {...withStoryDocs(customLayoutsDocs)}>
<Story name="Custom layout" exportName="CustomLayout">
<Block width="fluid">
<!-- Enter bootstrap grid! -->
<div id="block-flex-example">
@ -73,53 +57,76 @@
</Block>
</Story>
<Story name="Snap widths" {...withStoryDocs(snapWidthsDocs)}>
<Story name="Snap widths" exportName="SnapWidthsBasic">
<Article id="block-demo-article">
<div class="article-boundaries">
<div class="label">Article</div>
<Block width="narrower" snap="{true}" class="block-snap-widths-demo"
>narrower</Block
>
<Block width="narrow" snap="{true}" class="block-snap-widths-demo"
>narrow</Block
>
<Block width="normal" snap="{true}" class="block-snap-widths-demo"
>normal</Block
>
<Block width="wide" snap="{true}" class="block-snap-widths-demo"
>wide</Block
>
<Block width="wider" snap="{true}" class="block-snap-widths-demo"
>wider</Block
>
<Block width="narrower" snap="{true}" class="block-snap-widths-demo even"
>narrower</Block
>
<Block width="narrow" snap="{true}" class="block-snap-widths-demo even"
>narrow</Block
>
<h4>snap widths</h4>
<Block snap={true}>
<div class="label">Block</div>
</Block>
</div>
</Article>
</Story>
<Story name="Snap and skip widths" exportName="SnapSkipWidths">
<Article id="block-demo-article">
<div class="article-boundaries">
<div class="label">Article</div>
<h4>Regular layout</h4>
<Block width="narrower" snap={true} class="block-snap-widths-demo">
narrower
</Block>
<Block width="narrow" snap={true} class="block-snap-widths-demo">
narrow
</Block>
<Block width="normal" snap={true} class="block-snap-widths-demo">
normal
</Block>
<Block width="wide" snap={true} class="block-snap-widths-demo">
wide
</Block>
<Block width="wider" snap={true} class="block-snap-widths-demo">
wider
</Block>
<h4>with snap and skip</h4>
<Block width="narrower" snap={true} class="block-snap-widths-demo even">
narrower
</Block>
<Block width="narrow" snap={true} class="block-snap-widths-demo even">
narrow
</Block>
<Block
width="normal"
snap="{true}"
snap={true}
class="block-snap-widths-demo even skip-narrow"
>normal.skip-narrow</Block
>
normal.skip-narrow
</Block>
<Block
width="wide"
snap="{true}"
snap={true}
class="block-snap-widths-demo even skip-normal skip-narrow"
>wide.skip-normal.skip-narrow</Block
>
wide.skip-normal.skip-narrow
</Block>
<Block
width="wider"
snap="{true}"
class="block-snap-widths-demo even skip-wide">wider.skip-wide</Block
snap={true}
class="block-snap-widths-demo even skip-wide"
>
wider.skip-wide
</Block>
</div>
</Article>
</Story>
<style lang="scss">
h4 {
text-align: center;
}
:global(#block-demo-article) {
background-color: #ddd;
position: relative;
@ -145,11 +152,12 @@
background: rgb(211, 132, 123);
}
:global(
#block-demo-article .label,
#block-demo-article div.article-block.block-snap-widths-demo
) {
#block-demo-article .label,
#block-demo-article div.article-block.block-snap-widths-demo
) {
padding-left: 3px;
color: white;
font-weight: 500;
}
div#block-flex-example {

View file

@ -1,37 +1,44 @@
<!-- @migration-task Error while migrating Svelte code: Cannot set properties of undefined (setting 'next') -->
<!-- @component `Block` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-page-layout-block--docs) -->
<script lang="ts">
import type { Snippet } from 'svelte';
import type { ContainerWidth } from '../@types/global';
/** Width of the block within the article well. */
export let width: ContainerWidth = 'normal';
interface Props {
/** Content that goes inside `<Block>`*/
children: Snippet;
/** Width of the block within the article well. */
width?: ContainerWidth;
/** Add an id to the block tag to target it with custom CSS. */
id?: string;
/** Add custom classes to the block tag to target it with custom CSS. */
class?: string;
/** Snap block to column widths, rather than fluidly resizing them. */
snap?: boolean;
/** ARIA [role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles) for the block */
role?: string;
/** ARIA [label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) for the block */
ariaLabel?: string;
}
/** Add an id to the block tag to target it with custom CSS. */
export let id: string = '';
/** Add extra classes to the block tag to target it with custom CSS. */
let cls: string = '';
export { cls as class };
/** Snap block to column widths, rather than fluidly resizing them. */
export let snap: boolean = false;
/** ARIA [role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles) for the block */
export let role: string | null = null;
/** ARIA [label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) for the block */
export let ariaLabel: string | null = null;
let {
children,
width = 'normal',
id = '',
class: cls = '',
snap = false,
role,
ariaLabel,
}: Props = $props();
</script>
<div
{id}
class="article-block fmx-auto {width} {cls}"
class:snap="{snap && width !== 'fluid' && width !== 'widest'}"
class:snap={snap && width !== 'fluid' && width !== 'widest'}
{role}
aria-label="{ariaLabel}"
aria-label={ariaLabel}
>
<!-- block content -->
<slot />
{@render children()}
</div>
<style lang="scss">
@ -66,7 +73,7 @@
max-width: none;
}
// Only setup for the default column widths, b/c can't use
// Only setup for the default column widths, b/c we can't use
// CSS vars in media queries.
&.snap {
@include mixins.block-snap-widths;

View file

@ -1,15 +0,0 @@
The `Block` component is the basic building block of stories, a responsive container that wraps each section of your piece.
Blocks are stacked vertically within the well created by the [`Article`](./?path=/docs/layout-article) component. They can have different widths on larger screens depending on the `width` prop.
> 📌 Many of our other components already use the `Block` component, internally. You'll usually only need to use it yourself if you're making something custom.
```svelte
<script>
import { Block } from '@reuters-graphics/graphics-components';
</script>
<Block width="normal">
<!-- Your stuff for this block -->
</Block>
```

View file

@ -1,13 +0,0 @@
Our article well is designed to provide a basic responsive layout for you, but it's also made to get out of the way quickly when you need to do something custom.
If you need to get really radical, the easiest way is to create a `Block` with a `fluid` width -- which basically cancels out the article well dimensions -- and then code whatever you need from scratch or with another framework.
```svelte
<Block width="fluid">
<div class="my-radical-container">
<!-- Now, you have full control! -->
</div>
</Block>
```
The demo below does exactly that to create an edge-to-edge grid with [flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).

View file

@ -1,50 +0,0 @@
Normally, `Block` containers resize fluidly below the original `width`. Sometimes, though, you may want the container to snap to the next breakpoint -- for example, if you have a static graphic that looks fine at the set block breakpoints, but isn't so great at widths inbetween.
You can use the `snap` prop to force the container to snap to each block width successively as the window sizes down.
```svelte
<Block width="wider" snap="{true}">
<!-- Your stuff for this block -->
</Block>
```
If you want to skip certain block widths entirely, you can add one or more class of `skip-{block width class}` to the `Block`.
```svelte
<!-- Will skip wide and go straight to normal column width on resize. -->
<Block width="wider" snap="{true}" class="skip-wide">
<!-- Your stuff for this block -->
</Block>
```
This is probably easier to see in action than explain in words, so resize the window to get a better picture of how it all works.
> **NOTE:** The snap width breakpoints only work on `Block` components with widths `wider` and below. `widest` and `fluid` are both **always** fluid, since they go edge-to-edge.
#### Using with custom column widths
Snap width breakpoints are hard-coded to the default article well column widths, so if you set custom `columnWidths` on the `Article` tag (**rare!**), you can't use this functionality without a little extra work.
Luckily, it's still pretty easy. Just add a `cls` or `id` to your `Block` so you can target it with some custom SCSS. Now, defined a few SCSS variables corresponding to your custom column widths and use the `block-snap-widths` SCSS mixin to get the same functionality at your custom breakpoints.
```svelte
<Block width="wider" snap="{true}" class="custom-blocks">
<!-- Your stuff for this block -->
</Block>
<style lang="scss">
$column-width-narrower: 310px;
$column-width-narrow: 450px;
$column-width-normal: 600px;
$column-width-wide: 860px;
$column-width-wider: 1400px;
@use '@reuters-graphics/graphics-components/scss/mixins' as mixins;
:global {
div.custom-blocks {
@include mixins.block-snap-widths;
}
}
</style>
```