Add custom admonition for code sandbox (#95)

This commit is contained in:
a.nvlkv
2024-05-11 22:12:35 +03:00
committed by GitHub
parent cde438d67b
commit 40774ab8b5
24 changed files with 303 additions and 27 deletions

View File

@@ -0,0 +1,3 @@
<svg width="600" height="600" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M150 150L449.832 150V450H150V150ZM419.168 180.682V419.318H180.665V180.682H419.168Z" fill="#151515"/>
</svg>

After

Width:  |  Height:  |  Size: 257 B

View File

@@ -1,5 +1,10 @@
[output.html]
additional-css = ["./mdbook-admonish.css"]
additional-css = [
"./mdbook-admonish.css",
"./mdbook-admonish-custom.css",
"./sandbox.css",
]
additional-js = ["./sandbox.js"]
git-repository-url = "https://github.com/leptos-rs/book"
edit-url-template = "https://github.com/leptos-rs/book/edit/main/{path}"
[output.html.playground]
@@ -10,3 +15,8 @@ runnable = false
[preprocessor.admonish]
command = "mdbook-admonish"
assets_version = "3.0.1" # do not edit: managed by `mdbook-admonish install`
[[preprocessor.admonish.custom]]
directive = "sandbox"
color = "#DCFF50"
icon = "./CodeSandbox-Square-Logo.svg"

View File

@@ -0,0 +1,20 @@
:root {
--md-admonition-icon--admonish-sandbox: url("data:image/svg+xml;charset=utf-8,<svg width='600' height='600' viewBox='0 0 600 600' fill='none' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M150 150L449.832 150V450H150V150ZM419.168 180.682V419.318H180.665V180.682H419.168Z' fill='%23151515'/></svg>");
}
:is(.admonition):is(.admonish-sandbox) {
border-color: #dcff50;
}
:is(.admonish-sandbox) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(220, 255, 80, 0.1);
}
:is(.admonish-sandbox) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #dcff50;
mask-image: var(--md-admonition-icon--admonish-sandbox);
-webkit-mask-image: var(--md-admonition-icon--admonish-sandbox);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}

43
sandbox.css Normal file
View File

@@ -0,0 +1,43 @@
:is(.admonition):is(.admonish-sandbox) {
transition-property: width, margin-left;
transition-duration: 300ms;
transition-timing-function: ease-out;
margin-left: 0;
position: relative;
box-sizing: border-box;
max-width: 1380px;
}
@media only screen and (min-width: 1081px) {
:is(.admonition):is(.admonish-sandbox):is([open]) {
--sandbox-width: calc(
100vw - var(--sidebar-width) - calc(var(--page-padding) + 1.2rem) *
2 - 6px - 4px
);
width: var(--sandbox-width);
margin-left: calc(calc(min(var(--sandbox-width), 1380px) - 100%) / 2 * -1 + 4px);
z-index: 10;
}
body.sidebar-hidden :is(.admonition):is(.admonish-sandbox):is([open]) {
--sandbox-width: calc(
100vw - calc(var(--page-padding) + 1.2rem) * 2 - 4px
);
}
}
@media only screen and (min-width: 1380px) {
:is(.admonition):is(.admonish-sandbox):is([open]) {
--sandbox-width: calc(
100vw - var(--sidebar-width) -
calc(var(--page-padding) + 1.2rem + 90px) * 2 - 6px - 4px
);
}
body.sidebar-hidden :is(.admonition):is(.admonish-sandbox):is([open]) {
--sandbox-width: calc(
100vw - calc(var(--page-padding) + 1.2rem + 90px) * 2 - 4px
);
}
}

13
sandbox.js Normal file
View File

@@ -0,0 +1,13 @@
(() => {
const boxes = document.querySelectorAll("details.admonish-sandbox");
boxes.forEach((box) => {
const once = () => {
const template = box.querySelector("template");
const sandbox = template.content.cloneNode(true);
template.after(sandbox);
box.removeEventListener("toggle", once);
};
box.addEventListener("toggle", once);
});
})();

View File

@@ -180,9 +180,19 @@ data flow and of fine-grained reactive updates.
> **Note**: There are some significant drawbacks to this approach. Both signals and memos need to own their values, so a memo will need to clone the fields value on every change. The most natural way to manage state in a framework like Leptos is always to provide signals that are as locally-scoped and fine-grained as they can be, not to hoist everything up into global state. But when you _do_ need some kind of global state, `create_slice` can be a useful tool.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/15-global-state-0-5-8c2ff6?file=%2Fsrc%2Fmain.rs%3A1%2C2)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/15-global-state-0-5-8c2ff6?file=%2Fsrc%2Fmain.rs%3A1%2C2" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -47,9 +47,19 @@ view! {
Resources also provide a `refetch()` method that allows you to manually reload the data (for example, in response to a button click) and a `loading()` method that returns a `ReadSignal<bool>` indicating whether the resource is currently loading or not.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/10-resources-0-5-x6h5j6?file=%2Fsrc%2Fmain.rs%3A2%2C3)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/10-resources-0-5-9jq86q?file=%2Fsrc%2Fmain.rs%3A2%2C3" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -97,9 +97,19 @@ view! {
}
```
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/11-suspense-0-5-qzpgqs?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/11-suspense-0-5-qzpgqs?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -6,9 +6,19 @@ Youll notice in the `<Suspense/>` example that if you keep reloading the data
This example shows how you can create a simple tabbed contact list with `<Transition/>`. When you select a new tab, it continues showing the current contact until the new data loads. This can be a much better user experience than constantly falling back to a loading message.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/12-transition-0-5-2jg5lz?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/12-transition-0-5-2jg5lz?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -91,9 +91,19 @@ view! {
Now, theres a chance this all seems a little over-complicated, or maybe too restricted. I wanted to include actions here, alongside resources, as the missing piece of the puzzle. In a real Leptos app, youll actually most often use actions alongside server functions, [`create_server_action`](https://docs.rs/leptos/latest/leptos/fn.create_server_action.html), and the [`<ActionForm/>`](https://docs.rs/leptos_router/latest/leptos_router/fn.ActionForm.html) component to create really powerful progressively-enhanced forms. So if this primitive seems useless to you... Dont worry! Maybe it will make sense later. (Or check out our [`todo_app_sqlite`](https://github.com/leptos-rs/leptos/blob/main/examples/todo_app_sqlite/src/todo.rs) example now.)
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/13-actions-0-5-8xk35v?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/13-actions-0-5-8xk35v?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -149,9 +149,19 @@ stop(); // stop watching
set_num.set(2); // (nothing happens)
```
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/14-effect-0-5-d6hkch?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/14-effect-0-5-d6hkch?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -204,9 +204,19 @@ In fact, in this case, we dont even need to rerender the `<Contact/>` compone
> This sandbox includes a couple features (like nested routing) discussed in this section and the previous one, and a couple well cover in the rest of this chapter. The router is such an integrated system that it makes sense to provide a single example, so dont be surprised if theres anything you dont understand.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/16-router-0-5-4xp4zz?file=%2Fsrc%2Fmain.rs%3A102%2C2)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/16-router-0-5-4xp4zz?file=%2Fsrc%2Fmain.rs%3A102%2C2" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -82,9 +82,19 @@ This can get a little messy: deriving a signal that wraps an `Option<_>` or `Res
> This is the same example from the previous section. The router is such an integrated system that it makes sense to provide a single example highlighting multiple features, even if we havent explained them all yet.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/16-router-0-5-4xp4zz?file=%2Fsrc%2Fmain.rs%3A102%2C2)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/16-router-0-5-4xp4zz?file=%2Fsrc%2Fmain.rs%3A102%2C2" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -35,9 +35,18 @@ The second argument here is a set of [`NavigateOptions`](https://docs.rs/leptos_
> Once again, this is the same example. Check out the relative `<A/>` components, and take a look at the CSS in `index.html` to see the ARIA-based styling.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/16-router-0-5-4xp4zz?file=%2Fsrc%2Fmain.rs%3A102%2C2)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/16-router-0-5-4xp4zz?file=%2Fsrc%2Fmain.rs%3A102%2C2" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -62,9 +62,19 @@ view! {
Youll notice that this version drops the `Submit` button. Instead, we add an `oninput` attribute to the input. Note that this is _not_ `on:input`, which would listen for the `input` event and run some Rust code. Without the colon, `oninput` is the plain HTML attribute. So the string is actually a JavaScript string. `this.form` gives us the form the input is attached to. `requestSubmit()` fires the `submit` event on the `<form>`, which is caught by `<Form/>` just as if we had clicked a `Submit` button. Now the form will “navigate” on every keystroke or input to keep the URL (and therefore the search) perfectly in sync with the users input as they type.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/20-form-0-5-9g7v9p?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/20-form-0-5-9g7v9p?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -152,14 +152,26 @@ move |_| {
You can see here that while `set_count` just sets the value, `set_count.update()` gives us a mutable reference and mutates the value in place. Either one will trigger a reactive update in our UI.
> Throughout this tutorial, well use CodeSandbox to show interactive examples. To
> show the browser in the sandbox, you may need to click `Add DevTools >
Other Previews > 8080.` Hover over any of the variables to show Rust-Analyzer details
> Throughout this tutorial, well use CodeSandbox to show interactive examples.
> Hover over any of the variables to show Rust-Analyzer details
> and docs for whats going on. Feel free to fork the examples to play with them yourself!
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/1-basic-component-3d74p3?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
> To show the browser in the sandbox, you may need to click `Add DevTools >
Other Previews > 8080.`
<template>
<iframe src="https://codesandbox.io/p/sandbox/1-basic-component-3d74p3?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -186,9 +186,19 @@ for expensive calculations.
>
> [Click here for the full `view` macros docs](https://docs.rs/leptos/latest/leptos/macro.view.html).
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/2-dynamic-attributes-0-5-lwdrpm?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/2-dynamic-attributes-0-5-lwdrpm?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -420,9 +420,19 @@ and see the power of the `#[component]` macro combined with rust-analyzer here.
> In general, you should not need to use transparent components unless you are
> creating custom wrapping components that fall into one of these two categories.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/3-components-0-5-5vvl69?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/3-components-0-5-5vvl69?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -104,9 +104,19 @@ it is generated, and using that as an ID for the key function.
Check out the `<DynamicList/>` component below for an example.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/4-iteration-0-5-pwdn2y?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/4-iteration-0-5-pwdn2y?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -236,11 +236,19 @@ pub fn SelectOption(is: &'static str, value: ReadSignal<String>) -> impl IntoVie
> This is expected to be made consistent in the next major version of Leptos; see [this issue](https://github.com/leptos-rs/leptos/issues/2196)
> for more details.
**Controlled vs uncontrolled forms CodeSandbox:**
```admonish sandbox title="Controlled vs uncontrolled forms CodeSandbox" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/5-forms-0-5-rf2t7c?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/5-forms-0-5-rf2t7c?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -283,9 +283,19 @@ view! {
}
```
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/6-control-flow-0-5-4yn7qz?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/6-control-flow-0-5-4yn7qz?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -110,9 +110,18 @@ Not a number! Errors:
If you fix the error, the error message will disappear and the content youre wrapping in
an `<ErrorBoundary/>` will appear again.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/7-errors-0-5-5mptv9?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/7-errors-0-5-5mptv9?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -130,7 +130,6 @@ closure might require some cloning compared to using a `Callback`.
> confused, look back at the [generic props](./03_components.html#generic-props) section
> of the chapter on components.
## 3. Use an Event Listener
You can actually write Option 2 in a slightly different way. If the callback maps directly onto
@@ -320,9 +319,19 @@ in `<ButtonD/>` and a single text node in `<App/>`. Its as if the components
themselves dont exist at all. And, well... at runtime, they dont. Its just
signals and effects, all the way down.
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/8-parent-child-0-5-7rz7qd?file=%2Fsrc%2Fmain.rs%3A1%2C2)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/8-parent-child-0-5-7rz7qd?file=%2Fsrc%2Fmain.rs%3A1%2C2" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>

View File

@@ -122,9 +122,19 @@ view! {
}
```
```admonish sandbox title="Live example" collapsible=true
[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/9-component-children-0-5-m4jwhp?file=%2Fsrc%2Fmain.rs%3A1%2C1)
<noscript>
Please enable JavaScript to view examples.
</noscript>
<template>
<iframe src="https://codesandbox.io/p/sandbox/9-component-children-0-5-m4jwhp?file=%2Fsrc%2Fmain.rs%3A1%2C1" width="100%" height="1000px" style="max-height: 100vh"></iframe>
</template>
```
<details>
<summary>CodeSandbox Source</summary>