mirror of
https://github.com/LukeHagar/sveltesociety.dev.git
synced 2025-12-06 12:47:44 +00:00
Merge pull request #301 from MacFJA/pass-data
[New Recipe] Passing data between components
This commit is contained in:
27
src/lib/Mermaid.svelte
Normal file
27
src/lib/Mermaid.svelte
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
let graph = null;
|
||||||
|
let png = null;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
png =
|
||||||
|
'https://mermaid.ink/img/' +
|
||||||
|
btoa(JSON.stringify({ code: graph.textContent }))
|
||||||
|
.replaceAll('+', '-')
|
||||||
|
.replaceAll('/', '_')
|
||||||
|
.replaceAll('=', '');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<pre bind:this={graph}><slot /></pre>
|
||||||
|
<img src={png} alt="Mermaid graph" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
pre {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,545 @@
|
|||||||
|
---
|
||||||
|
title: Passing data between components
|
||||||
|
layout: recipe
|
||||||
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Mermaid from "$lib/Mermaid.svelte"; import {HighlightSvelte} from "svelte-highlight";
|
||||||
|
import {HighlightAuto} from "svelte-highlight";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
## Stores
|
||||||
|
|
||||||
|
| In Component | In Javascript/TypeScript | Reactive | Bi-directional | Direction |
|
||||||
|
| :----------: | :----------------------: | :------: | :------------: | :-------: |
|
||||||
|
| ✅ | ✅ | ✅ | ✅ | Any |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Stores allow components to "react" when the content of the store is changed.
|
||||||
|
|
||||||
|
If the store is declared _"globally"_ (not in a components) any scripts can access it and interact with it.
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<header>Globally declared store</header>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart BT
|
||||||
|
subgraph External file
|
||||||
|
Store["store"]
|
||||||
|
end
|
||||||
|
C1[Component1.svelte] <-- "$store" --> Store
|
||||||
|
C2[Component2.svelte] <-- "$store" --> Store
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Component1.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import { store } from "./my-store.ts"
|
||||||
|
</script>
|
||||||
|
<input bind:value={$store} />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Component2.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import { store } from "./my-store.ts"
|
||||||
|
</script>
|
||||||
|
The store value is: <var>{$store}</var>`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>my-store.ts</summary>
|
||||||
|
<HighlightAuto
|
||||||
|
code={`import { writable } from "svelte/store"
|
||||||
|
export const store = writable("hello")`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<header>
|
||||||
|
<em>In component</em> declared store
|
||||||
|
</header>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart BT
|
||||||
|
C1[Component1.svelte] <-- "$store" --> C1
|
||||||
|
C2[Component2.svelte] <-- "$store" --> C1
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Component1.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script context="module">
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
export const store = writable("hello")
|
||||||
|
</script>
|
||||||
|
<input bind:value={$store} />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Component2.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import { store } from "./Component1.svelte"
|
||||||
|
</script>
|
||||||
|
The store value is: <var>{$store}</var>`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
<footer>
|
||||||
|
You are creating a hard/direct dependency between <code>Component1.svelte</code> and{' '}
|
||||||
|
<code>Component2.svelte</code>.<br />
|
||||||
|
<code>Component2.svelte</code> can't exist without <code>Component1.svelte</code>
|
||||||
|
</footer>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
## Global variable
|
||||||
|
|
||||||
|
| In Component | In Javascript/TypeScript | Reactive | Bi-directional | Direction |
|
||||||
|
| :----------: | :----------------------: | :------: | :------------: | :-------: |
|
||||||
|
| ✅ | ✅ | ❌ | ✅ | Any |
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Similar to store, a global variable act as a central point of storage.
|
||||||
|
But global variable are not reactive, so you have to implement yourself a method to update the component.
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart BT
|
||||||
|
subgraph External file
|
||||||
|
Store["myVar"]
|
||||||
|
end
|
||||||
|
C1[Component1.svelte] <-- "myVar" --> Store
|
||||||
|
C2[Component2.svelte] <-- "myVar" --> Store
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Component1.svelte</summary>
|
||||||
|
<HighlightSvelte code={`<script>
|
||||||
|
import { variable } from "./data.js"
|
||||||
|
</script>
|
||||||
|
In component1: <var>{variable}</var>`} />
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Component2.svelte</summary>
|
||||||
|
<HighlightSvelte code={`<script>
|
||||||
|
import { variable } from "./data.js"
|
||||||
|
</script>
|
||||||
|
In component2: <var>{variable}</var>`} />
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>data.js</summary>
|
||||||
|
<HighlightAuto language="javascript" code={`export let variable = 2
|
||||||
|
export function updateVariable(value) {
|
||||||
|
variable = value
|
||||||
|
}`} />
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>App.svelte</summary>
|
||||||
|
<HighlightSvelte code={`<script>
|
||||||
|
import Component2 from "./Component2.svelte"
|
||||||
|
import Component1 from "./Component1.svelte"
|
||||||
|
import { variable, updateVariable } from "./data.js"
|
||||||
|
let v = variable
|
||||||
|
$: updateVariable(v)
|
||||||
|
</script>
|
||||||
|
<input bind:value={v} />
|
||||||
|
<hr />
|
||||||
|
<!-- Forcing reactivity -->
|
||||||
|
{#key v}
|
||||||
|
<Component1 />
|
||||||
|
<br>
|
||||||
|
<Component2 />
|
||||||
|
{/key}`} />
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
## Svelte event
|
||||||
|
|
||||||
|
| In Component | In Javascript/TypeScript | Reactive | Bi-directional | Direction |
|
||||||
|
| :----------: | :----------------------: | :------: | :------------: | :-----------------: |
|
||||||
|
| ✅ | ❌ | ✅ | ❌ | Child → Parent |
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
The data sharing only works in the direction child to parent.
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart BT
|
||||||
|
Child[Child.svelte] -->|on:myEvent| Parent[Parent.svelte]
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Child.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
let value = 'hello'
|
||||||
|
</script>
|
||||||
|
<input bind:value />
|
||||||
|
<button on:click={() => dispatch('validate', value}}>Validate data</button>
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Parent.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import Child from "./Child.svelte"
|
||||||
|
</script>
|
||||||
|
<Child on:validate={(e) => console.log(e.detail)} />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
## get/setContext
|
||||||
|
|
||||||
|
| In Component | In Javascript/TypeScript | Reactive | Bi-directional | Direction |
|
||||||
|
| :----------: | :----------------------: | :------: | :------------: | :--------------------: |
|
||||||
|
| ✅ | ❌ | ❌ | ❌ | Parent → Children |
|
||||||
|
|
||||||
|
_(Can be bi-directional and reactive, see below)_
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
The data sharing only works in the direction parent to children (and children of children).
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<header>Context with normal variable</header>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart TB
|
||||||
|
Parent[Parent.svelte]
|
||||||
|
Child[Child.svelte]
|
||||||
|
GrandChild[GrandChild.svelte]
|
||||||
|
Parent -.->|context| Child
|
||||||
|
Child -.->|inherit context| GrandChild
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Parent.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import { setContext } from "svelte"
|
||||||
|
import Child from "./Child.svelte"
|
||||||
|
setContext("name", "John Doe")
|
||||||
|
</script>
|
||||||
|
<Child />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Child.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
import GrandChild from "./GrandChild.svelte"
|
||||||
|
const name = getContext("name")
|
||||||
|
</script>
|
||||||
|
<p>Hello, my parent name is <var>{name}</var></p>
|
||||||
|
<GrandChild />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>GrandChild.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
const name = getContext("name")
|
||||||
|
</script>
|
||||||
|
<p>Hello, one of my parent have the name <var>{name}</var></p>`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<header>
|
||||||
|
Context with store
|
||||||
|
<div><small>Bi-directional and reactive</small></div>
|
||||||
|
</header>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart TB
|
||||||
|
Parent[Parent.svelte]
|
||||||
|
Child[Child.svelte]
|
||||||
|
GrandChild[GrandChild.svelte]
|
||||||
|
Parent -.->|context| Child
|
||||||
|
Child -.->|inherit context| GrandChild
|
||||||
|
Child --> Parent
|
||||||
|
GrandChild --> Parent
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Parent.svelte</summary>
|
||||||
|
<HighlightSvelte code={`<script>
|
||||||
|
import { setContext } from "svelte"
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import Child from "./Child.svelte"
|
||||||
|
const minAge = writable(80)
|
||||||
|
setContext("min-age", minAge)
|
||||||
|
</script>
|
||||||
|
<p>The youngest of the family is {$minAge} year old.</p>
|
||||||
|
<Child />`} />
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Child.svelte</summary>
|
||||||
|
<HighlightSvelte code={`<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
import GrandChild from "./GrandChild.svelte"
|
||||||
|
const minAge = getContext("min-age")
|
||||||
|
$minAge = 50 // Override the age (Parent is updated)
|
||||||
|
</script>
|
||||||
|
<GrandChild />`} />
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>GrandChild.svelte</summary>
|
||||||
|
<HighlightSvelte code={`<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
const age = getContext("min-age")
|
||||||
|
$age = 25 // Override the age (Parents are updated), initial value
|
||||||
|
</script>
|
||||||
|
<div>
|
||||||
|
<!-- The age can be edited, all parents will be updated thanks to the store contract -->
|
||||||
|
<label>I'm the youngest, and my age is: <input type="number" bind:value={$age} /></label>
|
||||||
|
</div>`} />
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
### One-way binding (down)
|
||||||
|
|
||||||
|
| In Component | In Javascript/TypeScript | Reactive | Bi-directional | Direction |
|
||||||
|
| :----------: | :----------------------: | :------: | :------------: | :-----------------: |
|
||||||
|
| ✅ | ❌ | ✅ | ❌ | Parent → Child |
|
||||||
|
|
||||||
|
<br>
|
||||||
|
The parent is providing the value to its child.
|
||||||
|
Changing the value in the parent will be reflected in the child.
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart TB
|
||||||
|
Parent[Parent.svelte]
|
||||||
|
Child[Child.svelte]
|
||||||
|
Parent -->|"myVar=#123;myVar}"| Child
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Parent.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import Child from "./Child.svelte"
|
||||||
|
let name="Joe"
|
||||||
|
</script>
|
||||||
|
My child name is <input bind:value={name} />
|
||||||
|
<hr />
|
||||||
|
<Child {name} />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Child.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
export let name="Rich"
|
||||||
|
</script>
|
||||||
|
My name is <var>{name}</var>`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
### Two-way binding
|
||||||
|
|
||||||
|
| In Component | In Javascript/TypeScript | Reactive | Bi-directional | Direction |
|
||||||
|
| :----------: | :----------------------: | :------: | :------------: | :-----------------: |
|
||||||
|
| ✅ | ❌ | ✅ | ✅ | Parent ↔ Child |
|
||||||
|
|
||||||
|
<br>
|
||||||
|
The parent is providing a variable that can be written by the child.
|
||||||
|
Changes made in the parent will be reflected and the child, changes made in children will be send to its parent
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart TB
|
||||||
|
Parent[Parent.svelte]
|
||||||
|
Child[Child.svelte]
|
||||||
|
Parent <-->|bind:myVar| Child
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Parent.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import Child from "./Child.svelte"
|
||||||
|
let name="Joe"
|
||||||
|
</script>
|
||||||
|
My child name is <input bind:value={name} />
|
||||||
|
<hr />
|
||||||
|
<Child bind:name={name} />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Child.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
export let name="Rich"
|
||||||
|
</script>
|
||||||
|
My name is <input bind:value={name} />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
### One-way binding (up)
|
||||||
|
|
||||||
|
| In Component | In Javascript/TypeScript | Reactive | Bi-directional | Direction |
|
||||||
|
| :----------: | :----------------------: | :------: | :------------: | :-----------------: |
|
||||||
|
| ✅ | ❌ | ✅ | ❌ | Child → Parent |
|
||||||
|
|
||||||
|
<br>
|
||||||
|
The parent is providing a function that will update the parent scope from its children
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart TB
|
||||||
|
Parent[Parent.svelte]
|
||||||
|
Child[Child.svelte]
|
||||||
|
Parent -->|"myFunc=#123;myFunc}"| Child
|
||||||
|
Child -->|"myFunc()"| Parent
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Parent.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import Child from "./Child.svelte"
|
||||||
|
let name="Joe"
|
||||||
|
function setName(value) {
|
||||||
|
name = value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
My child name is <var>{name}</var>
|
||||||
|
<hr />
|
||||||
|
<Child set={setName} />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Child.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
export let set
|
||||||
|
let myName
|
||||||
|
</script>
|
||||||
|
My name is <input bind:value={myName} />
|
||||||
|
<button on:click={() => set(myName)}>Send</button>`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
## DOM event
|
||||||
|
|
||||||
|
| In Component | In Javascript/TypeScript | Reactive | Bi-directional | Direction |
|
||||||
|
| :----------: | :----------------------: | :------: | :------------: | :------------------: |
|
||||||
|
| ✅ | ❌ | ✅ | ❌ | Child → Parents |
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Use native DOMEvent to bubble up data from a child to any parent willing to listen to it.
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<aside>
|
||||||
|
<Mermaid>{`
|
||||||
|
flowchart BT
|
||||||
|
Window
|
||||||
|
Body
|
||||||
|
Parent[Parent.svelte]
|
||||||
|
Child[Child.svelte]
|
||||||
|
Body -.- Window
|
||||||
|
Parent -.- Body
|
||||||
|
Child -->|on:myEvent| Parent
|
||||||
|
Child -->|on:myEvent| Body
|
||||||
|
Child -->|on:myEvent| Window
|
||||||
|
`}</Mermaid>
|
||||||
|
</aside>
|
||||||
|
<nav>
|
||||||
|
<details>
|
||||||
|
<summary>Parent.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
import Child from "./Child.svelte"
|
||||||
|
</script>
|
||||||
|
<svelte:window on:my-custom-event={(e) => console.log('The choice is '+e.detail)} />
|
||||||
|
<Child />`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Child.svelte</summary>
|
||||||
|
<HighlightSvelte
|
||||||
|
code={`<script>
|
||||||
|
function triggerEvent(choice) {
|
||||||
|
const event = new CustomEvent('my-custom-event', {detail: choice});
|
||||||
|
window.dispatchEvent(event)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<button on:click={() => triggerEvent('A')}>Select A</button>
|
||||||
|
<button on:click={() => triggerEvent('B')}>Select B</button>`}
|
||||||
|
/>
|
||||||
|
</details>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
article {
|
||||||
|
border: 3px solid var(--primary-color);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
padding: 1ex;
|
||||||
|
margin: 1ex 0;
|
||||||
|
}
|
||||||
|
article header {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 1ex;
|
||||||
|
margin-bottom: 1ex;
|
||||||
|
border-bottom: 1px solid var(--primary-color);
|
||||||
|
grid-column: 1/3
|
||||||
|
}
|
||||||
|
article footer {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding-top: 1ex;
|
||||||
|
margin-top: 1px;
|
||||||
|
border-top: 1px solid var(--primary-color);
|
||||||
|
grid-column: 1/3
|
||||||
|
}
|
||||||
|
article details :global(pre) {
|
||||||
|
font-size: 0.8em
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user