Merge pull request #307 from reuters-graphics/feature/headpile
Feature/headpile
This commit is contained in:
commit
a0ff39be8a
9 changed files with 310 additions and 0 deletions
5
.changeset/slimy-cities-swim.md
Normal file
5
.changeset/slimy-cities-swim.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@reuters-graphics/graphics-components': patch
|
||||
---
|
||||
|
||||
Adds new Headpile component.
|
||||
37
src/components/Headpile/Headpile.mdx
Normal file
37
src/components/Headpile/Headpile.mdx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { Meta, Canvas } from '@storybook/blocks';
|
||||
|
||||
import * as HeadpileStories from './Headpile.stories.svelte';
|
||||
|
||||
<Meta of={HeadpileStories} />
|
||||
|
||||
# Headpile
|
||||
|
||||
The `Headpile` component is a headshot-bulleted list of people, identifying them with their names, roles and a short description of their significance to a story.
|
||||
|
||||
It's designed to be used with headshots that have had their background removed, which can be done in the [Preview app](https://support.apple.com/en-gb/guide/preview/prvw15636/mac?#apd320b3b1b750a4) on macOS.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Headpile } from '@reuters-graphics/graphics-components';
|
||||
import { assets } from '$app/paths'; // 👈 If using in the graphics kit...
|
||||
</script>
|
||||
|
||||
<Headpile
|
||||
figures={[
|
||||
{
|
||||
img: `${assets}/images/person-A.jpg`,
|
||||
name: 'General Abdel Fattah al-Burhan',
|
||||
role: "Sudan's Sovereign Council Chief and military commander",
|
||||
text: 'Burhan was little known in public life until taking part in the coup ...',
|
||||
},
|
||||
{
|
||||
img: `${assets}/images/person-B.jpg`,
|
||||
name: 'General Mohamed Hamdan Dagalo',
|
||||
role: 'Leader of the Sudanese paramilitary Rapid Support Forces (RSF)',
|
||||
text: 'Popularly known as Hemedti, Dagalo rose from lowly beginnings ...',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
```
|
||||
|
||||
<Canvas of={HeadpileStories.Demo} />
|
||||
37
src/components/Headpile/Headpile.stories.svelte
Normal file
37
src/components/Headpile/Headpile.stories.svelte
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<script module lang="ts">
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import Headpile from './Headpile.svelte';
|
||||
|
||||
import hed1 from './images/abdel.png';
|
||||
import hed2 from './images/hemedti.png';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Components/Text elements/Headpile',
|
||||
component: Headpile,
|
||||
argTypes: {},
|
||||
});
|
||||
|
||||
const defaultArgs = [
|
||||
{
|
||||
name: 'General Abdel Fattah al-Burhan',
|
||||
role: "Sudan's Sovereign Council Chief and military commander",
|
||||
img: hed1,
|
||||
text: 'Burhan was little known in public life until taking part in the coup against Bashir in 2019 after a popular uprising against his rule. In August 2019, his role as de facto head of state was affirmed when he became head of the Sovereign Council, a body comprising civilian and military leaders formed to oversee the transition towards elections.',
|
||||
// colour: '#957caa',
|
||||
},
|
||||
{
|
||||
name: 'General Mohamed Hamdan Dagalo',
|
||||
role: 'Leader of the Sudanese paramilitary Rapid Support Forces (RSF)',
|
||||
img: hed2,
|
||||
text: "Popularly known as Hemedti, Dagalo rose from lowly beginnings as a camel trader to head a widely feared Arab militia that crushed a revolt in Darfur, winning him influence and eventually a role as Sudan's former deputy head of state.\r\n\r\nOver the past decade, he has been a key figure in Sudanese politics, aiding in the ousting of Bashir in 2019 and suppressing pro-democracy protests. As the country limped from one economic crisis to another, Hemedti became one of Sudan’s richest men, exporting gold from mines in Darfur seized by his fighters.",
|
||||
colour: '#afb776',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<Story
|
||||
name="Demo"
|
||||
args={{
|
||||
figures: defaultArgs,
|
||||
}}
|
||||
/>
|
||||
81
src/components/Headpile/Headpile.svelte
Normal file
81
src/components/Headpile/Headpile.svelte
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<script lang="ts">
|
||||
import type { ContainerWidth } from '../@types/global';
|
||||
import Block from '../Block/Block.svelte';
|
||||
import KeyFigure from './KeyFigure.svelte';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* Add classes to target with custom CSS.
|
||||
*/
|
||||
class: string;
|
||||
/**
|
||||
* Add an id to target with custom CSS.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Width of the container.
|
||||
*/
|
||||
width: Extract<ContainerWidth, 'normal' | 'wide'>;
|
||||
/**
|
||||
* Default background colour to be used as a mount behind the headshot.
|
||||
*/
|
||||
colour: string;
|
||||
/**
|
||||
* Individual figures -- i.e., people -- for the headpile.
|
||||
*/
|
||||
figures: {
|
||||
/**
|
||||
* Headshot image src. Be sure to prefix the image
|
||||
*
|
||||
* ```typescript
|
||||
* import { assets } from '$app/paths';
|
||||
*
|
||||
* const imgSrc = `${assets}/images/my-image.jpg`;
|
||||
* ```
|
||||
*/
|
||||
img: string;
|
||||
/**
|
||||
* Figure name.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Figure role or title.
|
||||
*/
|
||||
role?: string;
|
||||
/**
|
||||
* Text describing the person.
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
* Background colour to be used as a mount behind the headshot.
|
||||
*/
|
||||
colour?: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
let {
|
||||
figures,
|
||||
class: cls,
|
||||
id,
|
||||
width = 'normal',
|
||||
colour = '#cccccc',
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<Block class="fmy-6 {cls} {id} {width}">
|
||||
<div class="figures">
|
||||
{#each figures as figure}
|
||||
<KeyFigure {...{ ...figure, colour: figure.colour ?? colour }} />
|
||||
{/each}
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<style lang="scss">
|
||||
@use '../../scss/mixins' as mixins;
|
||||
|
||||
div.figures {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2.75rem;
|
||||
}
|
||||
</style>
|
||||
41
src/components/Headpile/Headshot.svelte
Normal file
41
src/components/Headpile/Headshot.svelte
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<script lang="ts">
|
||||
let { img = '', colour = 'var(--theme-colour-accent)' } = $props();
|
||||
</script>
|
||||
|
||||
<div class="headshot-wrapper">
|
||||
<div class="background" style="background-color: {colour};"></div>
|
||||
<div class="headshot" style="background-image: url({img}); "></div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.headshot-wrapper {
|
||||
width: 7rem;
|
||||
height: 6.75rem;
|
||||
position: relative;
|
||||
margin-block-start: -1.75rem;
|
||||
margin-block-end: -1.75rem;
|
||||
border-radius: 0.25rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
.background {
|
||||
position: absolute;
|
||||
inset-block-end: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 7rem;
|
||||
height: 4.75rem;
|
||||
display: inline-block;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
.headshot {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: 106%;
|
||||
background-position: center bottom;
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
inset-block-end: 0;
|
||||
inset-inline-start: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
108
src/components/Headpile/KeyFigure.svelte
Normal file
108
src/components/Headpile/KeyFigure.svelte
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
<script lang="ts">
|
||||
import { Markdown } from '@reuters-graphics/svelte-markdown';
|
||||
import Headshot from './Headshot.svelte';
|
||||
import { MediaQuery } from 'svelte/reactivity';
|
||||
|
||||
interface Props {
|
||||
img: string;
|
||||
name: string;
|
||||
role?: string;
|
||||
text: string;
|
||||
colour?: string;
|
||||
}
|
||||
|
||||
let { name, role, img, text, colour }: Props = $props();
|
||||
|
||||
const mobile = new MediaQuery('max-width: 600px');
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="wrapper-profile">
|
||||
<div>
|
||||
<Headshot {img} {colour} />
|
||||
</div>
|
||||
<div class="text">
|
||||
<div class="title">{name}</div>
|
||||
<div class="role">
|
||||
{role || ''}
|
||||
</div>
|
||||
{#if !mobile.current}
|
||||
<div class="description desktop">
|
||||
<Markdown source={text} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if mobile.current}
|
||||
<div class="description mobile">
|
||||
<Markdown source={text} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use '../../scss/mixins' as mixins;
|
||||
|
||||
.wrapper-profile {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: start;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
min-height: 5.5rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include mixins.font-bold;
|
||||
@include mixins.text-base;
|
||||
@include mixins.leading-none;
|
||||
|
||||
@media (max-width: 450px) {
|
||||
font-size: calc(0.9 * var(--theme-font-size-base, 1rem));
|
||||
}
|
||||
}
|
||||
|
||||
.role {
|
||||
border-block-start: 0.5px solid var(--tr-muted-grey);
|
||||
margin-inline-start: -0.75rem;
|
||||
padding-inline-start: 0.75rem;
|
||||
margin-block-start: 0.25rem;
|
||||
padding-block-start: 0.25rem;
|
||||
|
||||
@include mixins.font-note;
|
||||
@include mixins.text-secondary;
|
||||
@include mixins.text-sm;
|
||||
@include mixins.font-light;
|
||||
@include mixins.leading-tighter;
|
||||
@include mixins.fmb-4;
|
||||
|
||||
@media (max-width: 450px) {
|
||||
@include mixins.text-xs;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
:global(p) {
|
||||
@include mixins.font-note;
|
||||
font-size: calc(0.9 * var(--theme-font-size-base, 1rem));
|
||||
font-weight: 300;
|
||||
@include mixins.fmb-0;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
&.desktop {
|
||||
display: block;
|
||||
}
|
||||
&.mobile {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
&.desktop {
|
||||
display: none;
|
||||
}
|
||||
&.mobile {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
BIN
src/components/Headpile/images/abdel.png
Normal file
BIN
src/components/Headpile/images/abdel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 304 KiB |
BIN
src/components/Headpile/images/hemedti.png
Normal file
BIN
src/components/Headpile/images/hemedti.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 407 KiB |
|
|
@ -20,6 +20,7 @@ export { default as FeaturePhoto } from './components/FeaturePhoto/FeaturePhoto.
|
|||
export { default as Framer } from './components/Framer/Framer.svelte';
|
||||
export { default as GraphicBlock } from './components/GraphicBlock/GraphicBlock.svelte';
|
||||
export { default as Headline } from './components/Headline/Headline.svelte';
|
||||
export { default as Headpile } from './components/Headpile/Headpile.svelte';
|
||||
export { default as HeroHeadline } from './components/HeroHeadline/HeroHeadline.svelte';
|
||||
export { default as EndNotes } from './components/EndNotes/EndNotes.svelte';
|
||||
export { default as InfoBox } from './components/InfoBox/InfoBox.svelte';
|
||||
|
|
|
|||
Loading…
Reference in a new issue