commit
9ea5dfe266
10 changed files with 242 additions and 207 deletions
164
src/components/Theme/Theme.mdx
Normal file
164
src/components/Theme/Theme.mdx
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
import { Meta, Canvas } from '@storybook/blocks';
|
||||
|
||||
import * as ThemeStories from './Theme.stories.svelte';
|
||||
|
||||
<Meta of={ThemeStories} />
|
||||
|
||||
# Theme
|
||||
|
||||
The `Theme` component wraps your page content and uses [CSS variables](../?path=/docs/scss-css-variables--page) to set major colour and typography styles for your page. All the components from this library that are added to your page will use the CSS variables set by `Theme`.
|
||||
|
||||
Use the [theme builder](?path=/docs/components-theming-theme-builder--docs) to test custom themes.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Theme } from '@reuters-graphics/graphics-components';
|
||||
</script>
|
||||
|
||||
<Theme base="light">
|
||||
<!-- Page content, now styled according to your theme! -->
|
||||
</Theme>
|
||||
```
|
||||
|
||||
> In Graphics Kit, the `Theme` is set in both `pages/+page.svelte` and in `App.svelte`.
|
||||
|
||||
<Canvas of={ThemeStories.Demo} />
|
||||
|
||||
## Custom theme
|
||||
|
||||
You can customise your page's theme in two ways:
|
||||
|
||||
- Choose the `base` theme, either `light` or `dark`
|
||||
- Pass a custom theme object to the `theme` prop, which will override styles in the `base` theme.
|
||||
|
||||
Use the [theme builder](?path=/docs/components-theming-theme-builder--docs) to see what properties you can customise.
|
||||
|
||||
```svelte
|
||||
<Theme
|
||||
base="dark"
|
||||
theme={{
|
||||
colour: { accent: 'var(--tr-light-orange)' },
|
||||
font: { family: { hed: 'FreightText, serif' } },
|
||||
}}
|
||||
>
|
||||
<!-- Page content -->
|
||||
</Theme>
|
||||
```
|
||||
|
||||
> **Note:** The `Theme` component only styles child components or elements, so if you're changing the background colour of your page, make sure to also set the `background-color` on your `body` element in global SCSS.
|
||||
>
|
||||
> ```scss
|
||||
> // global.scss
|
||||
> body {
|
||||
> background-color: #2e3440;
|
||||
> }
|
||||
> ```
|
||||
|
||||
<Canvas of={ThemeStories.CustomTheme} />
|
||||
|
||||
## Custom font
|
||||
|
||||
To use typefaces other than the defaults provided by the Graphics Kit, download the font files from services such as [Google Fonts](https://fonts.google.com/) or [Adobe Typekit](https://fonts.adobe.com/). Make a folder called `fonts` inside `statics/` and put the font file -- for example, `IndieFlower-Regular.ttf` downloaded from [Google Fonts](https://fonts.google.com/share?selection.family=Indie+Flower) -- in `statics/fonts/`.
|
||||
|
||||
Then, declare it as a `@font-face` in `global.scss`:
|
||||
|
||||
```scss
|
||||
/* global.scss in Graphics Kit */
|
||||
@font-face {
|
||||
// If you're unsure of the font-family name,
|
||||
// click on "Get embed code" on the Google font page and check the CSS class.
|
||||
font-family: 'Indie Flower';
|
||||
|
||||
// Path to the font file. Change format depending on the font file type.
|
||||
src: url('/fonts/IndieFlower-Regular.ttf') format('truetype');
|
||||
font-weight: normal; // Optional
|
||||
font-style: normal; // Optional
|
||||
}
|
||||
```
|
||||
|
||||
Finally, pass the font to the appropriate text type in `Theme`:
|
||||
|
||||
```svelte
|
||||
<Theme
|
||||
base="light"
|
||||
theme={{
|
||||
font: {
|
||||
family: {
|
||||
hed: 'IndieFlower', // Set header text font to `IndieFlower`
|
||||
body: 'IndieFlower', // Set body text font to `IndieFlower`
|
||||
// etc...
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<!-- Page content -->
|
||||
</Theme>
|
||||
```
|
||||
|
||||
<Canvas of={ThemeStories.CustomFont} />
|
||||
|
||||
## Background patterns
|
||||
|
||||
To use a background pattern or image, set the background colour property in `Theme` to `transparent`:
|
||||
|
||||
```svelte
|
||||
<Theme
|
||||
base="dark"
|
||||
theme={{
|
||||
colour: { background: 'transparent' },
|
||||
}}
|
||||
>
|
||||
<!-- Page content -->
|
||||
</Theme>
|
||||
```
|
||||
|
||||
Then in `global.scss`, set your image, which should be stored in `statics/images/`, as `background-image`:
|
||||
|
||||
```scss
|
||||
/* global.scss */
|
||||
body {
|
||||
background-image: url('/images/my-pattern.png');
|
||||
}
|
||||
```
|
||||
|
||||
You may also want to override the background on the header nav if it conflicts with your background, especially the dropdown menu:
|
||||
|
||||
```scss
|
||||
/* global.scss
|
||||
Main nav container */
|
||||
.nav-container .inner {
|
||||
background: darkblue !important;
|
||||
/* Dropdown menu */
|
||||
.dropdown {
|
||||
background: darkblue !important;
|
||||
}
|
||||
}
|
||||
/* Mobile nav overlay */
|
||||
header + .overlay {
|
||||
background: darkblue !important;
|
||||
}
|
||||
```
|
||||
|
||||
<Canvas of={ThemeStories.BackgroundPatterns} />
|
||||
|
||||
## Inheritance
|
||||
|
||||
Styles that use `Theme`'s CSS variables will always use those set by the nearest parent `Theme`. That lets you change the theme for parts of your page by simply wrapping that bit in a new `Theme` with different styles.
|
||||
|
||||
The demo below shows a more complex example of nesting themes, but more likely you'll so something like this:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Theme } from '@reuters-graphics/graphics-components';
|
||||
</script>
|
||||
|
||||
<Theme>
|
||||
<!-- Page content styled with the default light theme. -->
|
||||
<Theme theme={{ colour: { background: 'lightgrey' } }}>
|
||||
<!-- A darker background for this section. -->
|
||||
</Theme>
|
||||
<!-- Back to normal here... -->
|
||||
</Theme>
|
||||
```
|
||||
|
||||
<Canvas of={ThemeStories.Inheritance} />
|
||||
|
|
@ -1,64 +1,38 @@
|
|||
<script module lang="ts">
|
||||
// @ts-ignore raw
|
||||
import componentDocs from './stories/docs/component.md?raw';
|
||||
// @ts-ignore raw
|
||||
import customiseDocs from './stories/docs/customise.md?raw';
|
||||
// @ts-ignore raw
|
||||
import customiseFontDocs from './stories/docs/customise-font.md?raw';
|
||||
// @ts-ignore raw
|
||||
import patternDocs from './stories/docs/pattern.md?raw';
|
||||
// @ts-ignore raw
|
||||
import inheritanceDocs from './stories/docs/inheritance.md?raw';
|
||||
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import Theme, { themes } from './Theme.svelte';
|
||||
|
||||
import {
|
||||
withComponentDocs,
|
||||
withStoryDocs,
|
||||
} from '../../docs/utils/withParams.js';
|
||||
|
||||
export const meta = {
|
||||
const { Story } = defineMeta({
|
||||
title: 'Components/Theming/Theme',
|
||||
component: Theme,
|
||||
...withComponentDocs(componentDocs),
|
||||
argTypes: {
|
||||
base: {
|
||||
control: 'select',
|
||||
options: ['light', 'dark'],
|
||||
},
|
||||
themes: { control: false },
|
||||
theme: {
|
||||
control: { expanded: true },
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||
|
||||
import ThemedPage from './stories/ThemedPage.svelte';
|
||||
import ThemedPage from './demo/ThemedPage.svelte';
|
||||
import SiteHeader from '../SiteHeader/SiteHeader.svelte';
|
||||
|
||||
import Headline from './../Headline/Headline.svelte';
|
||||
import BodyText from '../BodyText/BodyText.svelte';
|
||||
</script>
|
||||
|
||||
<Template>
|
||||
{#snippet children({ args })}
|
||||
<div class="reset-article">
|
||||
<Theme {...args}>
|
||||
<ThemedPage />
|
||||
</Theme>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Template>
|
||||
<Story name="Demo">
|
||||
<div class="reset-article">
|
||||
<Theme theme={themes.light} base="light">
|
||||
<ThemedPage />
|
||||
</Theme>
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Default"
|
||||
args={{
|
||||
theme: themes.light,
|
||||
base: 'light',
|
||||
}}
|
||||
/>
|
||||
|
||||
<Story name="Custom theme" {...withStoryDocs(customiseDocs)}>
|
||||
<Story name="Custom theme" exportName="CustomTheme">
|
||||
<Theme
|
||||
base="dark"
|
||||
theme={{
|
||||
|
|
@ -70,11 +44,11 @@
|
|||
</Theme>
|
||||
</Story>
|
||||
|
||||
<Story name="Custom Google font" {...withStoryDocs(customiseFontDocs)}>
|
||||
<Story name="Custom font" exportName="CustomFont">
|
||||
<Theme
|
||||
base="light"
|
||||
theme={{
|
||||
font: { family: { hed: 'Bebas Neue, sans-serif' } },
|
||||
font: { family: { hed: 'Indie Flower', body: 'Indie Flower' } },
|
||||
}}
|
||||
>
|
||||
<div class="gfont">
|
||||
|
|
@ -83,11 +57,14 @@
|
|||
dek={'The beginning of a beautiful page'}
|
||||
section={'Global news'}
|
||||
/>
|
||||
<BodyText
|
||||
text={'Bacon ipsum dolor amet cupim porchetta chuck buffalo sirloin beef. Biltong ham brisket tenderloin hamburger doner.'}
|
||||
/>
|
||||
</div>
|
||||
</Theme>
|
||||
</Story>
|
||||
|
||||
<Story name="Background patterns" {...withStoryDocs(patternDocs)}>
|
||||
<Story name="Background patterns" exportName="BackgroundPatterns">
|
||||
<div id="pattern-bg">
|
||||
<Theme
|
||||
base="dark"
|
||||
|
|
@ -96,12 +73,19 @@
|
|||
}}
|
||||
>
|
||||
<SiteHeader />
|
||||
<ThemedPage />
|
||||
<Headline
|
||||
hed={'Reuters Graphics Interactive'}
|
||||
dek={'The beginning of a beautiful page'}
|
||||
section={'Global news'}
|
||||
/>
|
||||
<BodyText
|
||||
text={'Bacon ipsum dolor amet cupim porchetta chuck buffalo sirloin beef. Biltong ham brisket tenderloin hamburger doner.'}
|
||||
/>
|
||||
</Theme>
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Inheritance" {...withStoryDocs(inheritanceDocs)}>
|
||||
<Story name="Inheritance" tags={['!autodocs', '!dev']}>
|
||||
<Theme theme={themes.light}>
|
||||
<div class="themed">
|
||||
<p>Theme</p>
|
||||
|
|
@ -131,7 +115,7 @@
|
|||
</Story>
|
||||
|
||||
<style lang="scss">
|
||||
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Indie+Flower&display=swap');
|
||||
|
||||
div.themed {
|
||||
background-color: var(--theme-colour-background);
|
||||
|
|
|
|||
|
|
@ -10,12 +10,15 @@
|
|||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import type { CustomTheme } from './@types/component';
|
||||
|
||||
type Base = 'light' | 'dark';
|
||||
|
||||
// Utils
|
||||
import flatten from './utils/flatten';
|
||||
import mergeThemes from './utils/merge';
|
||||
|
||||
// Types
|
||||
import type { CustomTheme } from './@types/component';
|
||||
import type { Snippet } from 'svelte';
|
||||
type Base = 'light' | 'dark';
|
||||
|
||||
interface Props {
|
||||
/** Custom theme object. Can be a partial theme with just
|
||||
* what you want to change.
|
||||
|
|
@ -27,12 +30,12 @@
|
|||
* explicitly set.
|
||||
*/
|
||||
base?: Base;
|
||||
children?: import('svelte').Snippet;
|
||||
/** Content wrapped inside `Theme` */
|
||||
children: Snippet;
|
||||
}
|
||||
|
||||
let { theme = {}, base = 'light', children }: Props = $props();
|
||||
|
||||
/** @type {Theme} */
|
||||
let mergedTheme = $derived(
|
||||
mergeThemes({}, themes[base] || themes.light, theme)
|
||||
);
|
||||
|
|
@ -48,6 +51,6 @@
|
|||
<!-- Clients can override the theme above by attaching custom properties to this element. -->
|
||||
<div class="theme-client-override" style="display: contents;">
|
||||
<!-- Themed content -->
|
||||
{@render children?.()}
|
||||
{@render children()}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
36
src/components/Theme/demo/ThemedPage.svelte
Normal file
36
src/components/Theme/demo/ThemedPage.svelte
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<script>
|
||||
import Article from '../../Article/Article.svelte';
|
||||
import Headline from '../../Headline/Headline.svelte';
|
||||
import BodyText from '../../BodyText/BodyText.svelte';
|
||||
import GraphicBlock from '../../GraphicBlock/GraphicBlock.svelte';
|
||||
</script>
|
||||
|
||||
<Article>
|
||||
<Headline
|
||||
hed={'Reuters Graphics Interactive'}
|
||||
dek={'The beginning of a beautiful page'}
|
||||
section={'Global news'}
|
||||
authors={['Jon McClure', 'Prasanta Kumar Dutta']}
|
||||
publishTime={new Date('2021-09-12').toISOString()}
|
||||
/>
|
||||
<BodyText
|
||||
text={`Bacon ipsum dolor amet cupim porchetta chuck buffalo sirloin beef. Biltong ham brisket tenderloin hamburger doner.`}
|
||||
/>
|
||||
<GraphicBlock
|
||||
title="Steak tar-tar"
|
||||
description="Andouille pork loin cow buffalo pork chop shoulder."
|
||||
notes="Source: U.S. FDA"
|
||||
>
|
||||
<div class="fake-graphic"></div>
|
||||
</GraphicBlock>
|
||||
<BodyText
|
||||
text={'Bacon ipsum dolor amet cupim porchetta chuck buffalo sirloin beef. Biltong ham brisket tenderloin hamburger doner.'}
|
||||
/>
|
||||
</Article>
|
||||
|
||||
<style>
|
||||
div.fake-graphic {
|
||||
height: 200px;
|
||||
border: 1px solid var(--theme-colour-accent);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
The `Theme` component wraps your page content and uses [CSS variables](../?path=/docs/scss-css-variables--page) to set major colour and typography styles for your page. All of the components in this library will use those CSS variables for styling by default.
|
||||
|
||||
Use our [theme builder](../?path=/docs/theming-theme-builder--docs) to customise your page's theme.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Theme } from '@reuters-graphics/graphics-components';
|
||||
</script>
|
||||
|
||||
<Theme base="light">
|
||||
<!-- ...page stuff, now styled according to your theme! -->
|
||||
</Theme>
|
||||
```
|
||||
|
||||
> For Graphics Kit users, the `Theme` is set for you in your graphics homepage (`pages/+page.svelte`). You can customise it there for the whole page.
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
For some projects, you may need to use typefaces other than the defaults provided by the GraphicsKit.
|
||||
|
||||
You will need to:
|
||||
|
||||
- Import the fonts in your code.
|
||||
- Declare the `font-family` in the corresponding CSS variables in the Theme.
|
||||
|
||||
There are many ways to load fonts, but care should be taken that the font files load first before page render, to avoid layout shifts during font swapping after the font is downloaded. For this reason, we will use `<link>` method in the page `head` instead of CSS imports.
|
||||
|
||||
> ##### Importing custom fonts
|
||||
|
||||
> In this sample from [Google Fonts](https://fonts.google.com/specimen/Bebas+Neue), once we have selected the font family, copy the `<link>` code.
|
||||
|
||||
> ```html
|
||||
> <link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
> <link
|
||||
> href="https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap"
|
||||
> rel="stylesheet"
|
||||
> />
|
||||
> ```
|
||||
|
||||
> In your project, navigate to `src` > `template.html` and add the copied code in `head` section :
|
||||
|
||||
> ```svelte
|
||||
> <head>
|
||||
> <!-- HTML meta -->
|
||||
> <link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
> <link
|
||||
> href="https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap"
|
||||
> rel="stylesheet"
|
||||
> />
|
||||
>
|
||||
> %sveltekit.head%
|
||||
> </head>
|
||||
> ```
|
||||
|
||||
> Similarly, you can add fonts from [Adobe Typekit](https://fonts.adobe.com/) or custom local fonts with the correct paths to the URL.
|
||||
|
||||
You can customise one or more of the pre-defined font families in the Theme. Do not directly apply the font family in your CSS. Always use the CSS variables defined in the Theme so that it configures and reflects across the page design.
|
||||
|
||||
```svelte
|
||||
<Theme
|
||||
base="light"
|
||||
theme="{{
|
||||
font: { family: { hed: 'Bebas Neue, sans-serif' } },
|
||||
}}"
|
||||
>
|
||||
<!-- Page content -->
|
||||
</Theme>
|
||||
```
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
You can customise the theme of your page in two ways:
|
||||
|
||||
First, you can choose the `base` theme, either `light` or `dark`.
|
||||
|
||||
From there, you can pass a custom theme object to the `theme` prop. Any custom styles you pass to `theme` will override styles in the `base` theme.
|
||||
|
||||
Check out the "Control" column for `theme` in the properties table above to see what properties you can customise.
|
||||
|
||||
> **Pro tip:** The `Theme` component only styles child components or elements, so if you're changing the background colour of your page, it's still a good idea to set a `background-color` on your `body` element in global SCSS.
|
||||
>
|
||||
> ```scss
|
||||
> // global.scss
|
||||
> body {
|
||||
> background-color: #2e3440;
|
||||
> }
|
||||
> ```
|
||||
|
||||
```svelte
|
||||
<Theme
|
||||
base="dark"
|
||||
theme="{{
|
||||
colour: { accent: 'var(--tr-light-orange)' },
|
||||
font: { family: { hed: 'FreightText, serif' } },
|
||||
}}"
|
||||
>
|
||||
<!-- Page content -->
|
||||
</Theme>
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 481 KiB |
|
|
@ -1,17 +0,0 @@
|
|||
Styles that use `Theme`'s CSS variables will always use those set by the nearest parent `Theme`. That lets you change the theme for parts of your page by simply wrapping that bit in a _new_ `Theme` with different styles.
|
||||
|
||||
The demo below shows a more complex example of nesting themes, but more likely you'll so something like this:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Theme } from '@reuters-graphics/graphics-components';
|
||||
</script>
|
||||
|
||||
<Theme>
|
||||
<!-- Page content styled with the default light theme. -->
|
||||
<Theme theme="{{ colour: { background: 'lightgrey' } }}">
|
||||
<!-- A darker background for this section. -->
|
||||
</Theme>
|
||||
<!-- Back to normal here... -->
|
||||
</Theme>
|
||||
```
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
To use a background pattern or image, set the background colour property in your custom theme to `transparent`...
|
||||
|
||||
```svelte
|
||||
<Theme
|
||||
base="dark"
|
||||
theme="{{
|
||||
colour: { background: 'transparent' },
|
||||
}}"
|
||||
>
|
||||
<!-- Page content -->
|
||||
</Theme>
|
||||
```
|
||||
|
||||
... then set your background image in global SCSS:
|
||||
|
||||
```scss
|
||||
/* global.scss */
|
||||
body {
|
||||
background-color: darkblue;
|
||||
background-image: url('$assets/images/my-pattern.png');
|
||||
}
|
||||
```
|
||||
|
||||
You may also want to override the background on the header nav if it conflicts with your background, especially the dropdown menu:
|
||||
|
||||
```scss
|
||||
/* global.scss
|
||||
Main nav container */
|
||||
.nav-container .inner {
|
||||
background: darkblue !important;
|
||||
/* Dropdown menu */
|
||||
.dropdown {
|
||||
background: darkblue !important;
|
||||
}
|
||||
}
|
||||
/* Mobile nav overlay */
|
||||
header + .overlay {
|
||||
background: darkblue !important;
|
||||
}
|
||||
```
|
||||
Loading…
Reference in a new issue