From 40774ab8b5e563253380e23e3c73761cff07fc1c Mon Sep 17 00:00:00 2001 From: "a.nvlkv" <2813794+anvlkv@users.noreply.github.com> Date: Sat, 11 May 2024 22:12:35 +0300 Subject: [PATCH] Add custom admonition for code sandbox (#95) --- CodeSandbox-Square-Logo.svg | 3 ++ book.toml | 14 ++++++++-- mdbook-admonish-custom.css | 20 ++++++++++++++ sandbox.css | 43 +++++++++++++++++++++++++++++ sandbox.js | 13 +++++++++ src/15_global_state.md | 12 +++++++- src/async/10_resources.md | 12 +++++++- src/async/11_suspense.md | 12 +++++++- src/async/12_transition.md | 12 +++++++- src/async/13_actions.md | 12 +++++++- src/reactivity/14_create_effect.md | 12 +++++++- src/router/17_nested_routing.md | 12 +++++++- src/router/18_params_and_queries.md | 12 +++++++- src/router/19_a.md | 11 +++++++- src/router/20_form.md | 12 +++++++- src/view/01_basic_component.md | 20 +++++++++++--- src/view/02_dynamic_attributes.md | 12 +++++++- src/view/03_components.md | 12 +++++++- src/view/04_iteration.md | 12 +++++++- src/view/05_forms.md | 12 ++++++-- src/view/06_control_flow.md | 12 +++++++- src/view/07_errors.md | 11 +++++++- src/view/08_parent_child.md | 15 ++++++++-- src/view/09_component_children.md | 12 +++++++- 24 files changed, 303 insertions(+), 27 deletions(-) create mode 100644 CodeSandbox-Square-Logo.svg create mode 100644 mdbook-admonish-custom.css create mode 100644 sandbox.css create mode 100644 sandbox.js diff --git a/CodeSandbox-Square-Logo.svg b/CodeSandbox-Square-Logo.svg new file mode 100644 index 0000000..7ac3d39 --- /dev/null +++ b/CodeSandbox-Square-Logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/book.toml b/book.toml index d3ab98c..c9a854f 100644 --- a/book.toml +++ b/book.toml @@ -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] @@ -9,4 +14,9 @@ runnable = false [preprocessor.admonish] command = "mdbook-admonish" -assets_version = "3.0.1" # do not edit: managed by `mdbook-admonish install` +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" diff --git a/mdbook-admonish-custom.css b/mdbook-admonish-custom.css new file mode 100644 index 0000000..77c1473 --- /dev/null +++ b/mdbook-admonish-custom.css @@ -0,0 +1,20 @@ +:root { + --md-admonition-icon--admonish-sandbox: url("data:image/svg+xml;charset=utf-8,"); +} + +: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; +} diff --git a/sandbox.css b/sandbox.css new file mode 100644 index 0000000..c0e3405 --- /dev/null +++ b/sandbox.css @@ -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 + ); + } +} diff --git a/sandbox.js b/sandbox.js new file mode 100644 index 0000000..6206ee9 --- /dev/null +++ b/sandbox.js @@ -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); + }); +})(); diff --git a/src/15_global_state.md b/src/15_global_state.md index b106d2e..0017e19 100644 --- a/src/15_global_state.md +++ b/src/15_global_state.md @@ -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 field’s 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) - + + + + +```
CodeSandbox Source diff --git a/src/async/10_resources.md b/src/async/10_resources.md index 08a6ad3..073befa 100644 --- a/src/async/10_resources.md +++ b/src/async/10_resources.md @@ -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` 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) - + + + + +```
CodeSandbox Source diff --git a/src/async/11_suspense.md b/src/async/11_suspense.md index e880e52..c991be2 100644 --- a/src/async/11_suspense.md +++ b/src/async/11_suspense.md @@ -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) - + + + + +```
CodeSandbox Source diff --git a/src/async/12_transition.md b/src/async/12_transition.md index 85db85b..f62202e 100644 --- a/src/async/12_transition.md +++ b/src/async/12_transition.md @@ -6,9 +6,19 @@ You’ll notice in the `` example that if you keep reloading the data This example shows how you can create a simple tabbed contact list with ``. 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) - + + + + +```
CodeSandbox Source diff --git a/src/async/13_actions.md b/src/async/13_actions.md index 625dc33..ff55c6e 100644 --- a/src/async/13_actions.md +++ b/src/async/13_actions.md @@ -91,9 +91,19 @@ view! { Now, there’s 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, you’ll actually most often use actions alongside server functions, [`create_server_action`](https://docs.rs/leptos/latest/leptos/fn.create_server_action.html), and the [``](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... Don’t 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) - + + + + +```
CodeSandbox Source diff --git a/src/reactivity/14_create_effect.md b/src/reactivity/14_create_effect.md index ed21475..8f86a58 100644 --- a/src/reactivity/14_create_effect.md +++ b/src/reactivity/14_create_effect.md @@ -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) - + + + + +```
CodeSandbox Source diff --git a/src/router/17_nested_routing.md b/src/router/17_nested_routing.md index 88444cc..7610b37 100644 --- a/src/router/17_nested_routing.md +++ b/src/router/17_nested_routing.md @@ -204,9 +204,19 @@ In fact, in this case, we don’t even need to rerender the `` compone > This sandbox includes a couple features (like nested routing) discussed in this section and the previous one, and a couple we’ll cover in the rest of this chapter. The router is such an integrated system that it makes sense to provide a single example, so don’t be surprised if there’s anything you don’t 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) - + + + + +```
CodeSandbox Source diff --git a/src/router/18_params_and_queries.md b/src/router/18_params_and_queries.md index a783fff..acf2195 100644 --- a/src/router/18_params_and_queries.md +++ b/src/router/18_params_and_queries.md @@ -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 haven’t 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) - + + + + +```
CodeSandbox Source diff --git a/src/router/19_a.md b/src/router/19_a.md index ea38438..ecbe834 100644 --- a/src/router/19_a.md +++ b/src/router/19_a.md @@ -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 `` 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) - + + + +```
CodeSandbox Source diff --git a/src/router/20_form.md b/src/router/20_form.md index 58e2b4e..dfaeb82 100644 --- a/src/router/20_form.md +++ b/src/router/20_form.md @@ -62,9 +62,19 @@ view! { You’ll 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 `
`, which is caught by `` 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 user’s 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) - + + + + +```
CodeSandbox Source diff --git a/src/view/01_basic_component.md b/src/view/01_basic_component.md index 0d917b0..be210c7 100644 --- a/src/view/01_basic_component.md +++ b/src/view/01_basic_component.md @@ -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, we’ll 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, we’ll use CodeSandbox to show interactive examples. +> Hover over any of the variables to show Rust-Analyzer details > and docs for what’s 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) - + + +> To show the browser in the sandbox, you may need to click `Add DevTools > +Other Previews > 8080.` + + + +```
CodeSandbox Source diff --git a/src/view/02_dynamic_attributes.md b/src/view/02_dynamic_attributes.md index 7478f2c..c522744 100644 --- a/src/view/02_dynamic_attributes.md +++ b/src/view/02_dynamic_attributes.md @@ -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) - + + + + +```
CodeSandbox Source diff --git a/src/view/03_components.md b/src/view/03_components.md index 5807711..bcc16cc 100644 --- a/src/view/03_components.md +++ b/src/view/03_components.md @@ -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) - + + + + +```
CodeSandbox Source diff --git a/src/view/04_iteration.md b/src/view/04_iteration.md index 4756500..f08d07e 100644 --- a/src/view/04_iteration.md +++ b/src/view/04_iteration.md @@ -104,9 +104,19 @@ it is generated, and using that as an ID for the key function. Check out the `` 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) - + + + + +```
CodeSandbox Source diff --git a/src/view/05_forms.md b/src/view/05_forms.md index 8f40279..7de39f1 100644 --- a/src/view/05_forms.md +++ b/src/view/05_forms.md @@ -236,11 +236,19 @@ pub fn SelectOption(is: &'static str, value: ReadSignal) -> 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) - + + + + +```
CodeSandbox Source diff --git a/src/view/06_control_flow.md b/src/view/06_control_flow.md index b3f1af6..45ab480 100644 --- a/src/view/06_control_flow.md +++ b/src/view/06_control_flow.md @@ -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) - + + + + +```
CodeSandbox Source diff --git a/src/view/07_errors.md b/src/view/07_errors.md index 61575a7..e26ea73 100644 --- a/src/view/07_errors.md +++ b/src/view/07_errors.md @@ -110,9 +110,18 @@ Not a number! Errors: If you fix the error, the error message will disappear and the content you’re wrapping in an `` 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) - + + + +```
CodeSandbox Source diff --git a/src/view/08_parent_child.md b/src/view/08_parent_child.md index b9c7789..f0a4fae 100644 --- a/src/view/08_parent_child.md +++ b/src/view/08_parent_child.md @@ -91,7 +91,7 @@ are real trade-offs, not a simple right-or-wrong choice. > Note the way we use the `Callback` type. This is basically a > wrapper around a closure `Fn(In) -> Out` that is also `Copy` and makes it > easy to pass around. -> +> > We also used the `#[prop(into)]` attribute so we can pass a normal closure into > `on_click`. Please see the [chapter "`into` Props"](./03_components.md#into-props) for more details. @@ -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 `` and a single text node in ``. It’s as if the components themselves don’t exist at all. And, well... at runtime, they don’t. It’s 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) - + + + + +```
CodeSandbox Source diff --git a/src/view/09_component_children.md b/src/view/09_component_children.md index 0da9e64..3875d98 100644 --- a/src/view/09_component_children.md +++ b/src/view/09_component_children.md @@ -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) - + + + + +```
CodeSandbox Source