Skip to content

Breaking: Svelte 5 #295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 47 commits into from
May 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
a972279
breaking: update deps, move svelte to peerdeps
Antosik Dec 14, 2024
4ebc4c2
misc: update vite/svelte configs
Antosik Dec 14, 2024
d2246e6
breaking: auto-migrate to svelte5
Antosik Dec 14, 2024
c05b6e3
fix: update icons to svelte5
Antosik Dec 14, 2024
973c2c9
misc: update scrollIntoViewIfNeeded definition
Antosik Dec 14, 2024
58874df
docs: update contributing
Antosik Dec 14, 2024
25a677e
breaking: update Wiggle & require svelte 5.8
Antosik Dec 14, 2024
7d310e4
breaking: auto-migrate MultiSelect to svelte5 & update slotNames
Antosik Dec 14, 2024
a00872a
breaking: migrate MultiSelect to svelte5, update props & events
Antosik Dec 15, 2024
d111289
fix: update remaining lib components to svelte5
Antosik Dec 15, 2024
0a33a19
fix: remove package-lock
Antosik Dec 15, 2024
7f74032
fix: return option naming for slot
Antosik Dec 15, 2024
b115d83
fix: fix warnings and codestyle
Antosik Dec 15, 2024
ec69382
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 15, 2024
7e99a86
fix: fix Spring usage in Wiggle
Antosik Dec 15, 2024
edb01ae
tests: update unit tests
Antosik Dec 15, 2024
031bc22
fix: remove package-lock
Antosik Dec 15, 2024
ef2b27e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 15, 2024
b786061
fix package.json import in svelte.config.js by updating to 'with' syntax
janosh Dec 15, 2024
52e63cb
deps: update dependencies
Antosik Jan 12, 2025
71cb007
misc: update tsconfig to sveltekit latest
Antosik Jan 13, 2025
1991dcb
fix: update routes & site to svelte5
Antosik Jan 13, 2025
912ae43
fix: lint fixes
Antosik Jan 13, 2025
e666a16
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 13, 2025
d040972
Merge branch 'main' into pr/Antosik/295
janosh Feb 6, 2025
e59fe1c
- fix failing package.json import in svelte.config.js to use 'with' s…
janosh Feb 6, 2025
12efa32
deps: update dependencies
Antosik Feb 8, 2025
0083dcb
misc: ignore test results folder
Antosik Feb 8, 2025
891df75
misc: update tests configs
Antosik Feb 8, 2025
d603863
misc: better props types
Antosik Feb 8, 2025
1cab93d
test: update tests
Antosik Feb 8, 2025
40eeea3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 8, 2025
7392c40
bump package deps, fix eslint errors, remove semicolons
janosh Apr 13, 2025
8ea86e2
fix MultiSelect.svelte.test.ts unit tests
janosh May 14, 2025
10be0ea
refactor imports
janosh May 14, 2025
da239ed
stricter link check with lychee over markdown-link-check
janosh May 14, 2025
cdb62f8
refactor: consolidate utility functions into single utils.ts file
janosh May 14, 2025
89fec56
bum package deps
janosh May 14, 2025
5b00d9c
MultiSelect.svelte remove global CSS scoping
janosh May 14, 2025
8005410
pnpm remove @testing-library/jest-dom @testing-library/svelte @testin…
janosh May 14, 2025
0f2afe5
rename <Name>Slot.svelte to <Name>Snippet.svelte (more terminology ch…
janosh May 14, 2025
ef37bc7
add install-e2e: npx playwright install chromium
janosh May 14, 2025
8f98915
readme migrate slot example to svelte 5 snippets and remove breaking …
janosh May 14, 2025
96ab7f6
fix missing $state() runes in examples
janosh May 15, 2025
8c46e9d
fix vestiges of svelte 4 event props (on:event -> onevent)
janosh May 15, 2025
692f720
MultiSelect.svelte replace :where() with :is() in all CSS selectors
janosh May 15, 2025
fab2711
fix failing playwright tests
janosh May 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .github/workflows/link-check.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
name: Link Check
name: Link check

on:
push:
branches: [main]
pull_request:
branches: [main]
paths: ['**/*.md']
schedule:
- cron: '0 0 1 * *' # monthly

jobs:
markdown-link-check:
uses: janosh/workflows/.github/workflows/markdown-link-check.yml@main
link-check:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4

- name: Discover broken links
uses: lycheeverse/lychee-action@v2
with:
args: --exclude '%7B' --accept 100..=103,200..=299,403,429 -- ./**/*.{md,svelte,ts}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ jobs:
uses: janosh/workflows/.github/workflows/npm-test.yml@main
with:
test-cmd: npm run test:unit
install-e2e: npx playwright install chromium
e2e-test-cmd: npx playwright test tests/*.ts
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@ node_modules
build
dist

# test results
test-results

# test coverage reports
coverage

package-lock.json
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ repos:
exclude: changelog\.md

- repo: https://github.com/pre-commit/mirrors-eslint
rev: v9.19.0
rev: v9.24.0
hooks:
- id: eslint
types: [file]
Expand Down
2 changes: 1 addition & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ All notable changes to this project will be documented in this file. Dates are d
- Move examples to new `src/routes/demos` dir [`#63`](https://github.com/janosh/svelte-multiselect/pull/63)
- make ToC position fixed (closes #64) [`#64`](https://github.com/janosh/svelte-multiselect/issues/64)
- check for undefined (not falsy) value in rawOp processing (fixes #65) [`#65`](https://github.com/janosh/svelte-multiselect/issues/65)
- LanguageSlot change SVG icons src repo to vscode-icons for more coverage [`92390e9`](https://github.com/janosh/svelte-multiselect/commit/92390e937a063b2b0c88e0ac6f9a9d8f3cb1eadd)
- LanguageSnippet change SVG icons src repo to vscode-icons for more coverage [`92390e9`](https://github.com/janosh/svelte-multiselect/commit/92390e937a063b2b0c88e0ac6f9a9d8f3cb1eadd)
- more preselected slots in Examples.svelte [`cd0a01a`](https://github.com/janosh/svelte-multiselect/commit/cd0a01a7a6b319299642b3c24c5caea8dc9dc24d)

#### [v4.0.3](https://github.com/janosh/svelte-multiselect/compare/v4.0.2...v4.0.3)
Expand Down
64 changes: 33 additions & 31 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,47 +15,49 @@
"preview": "vite preview",
"package": "svelte-package",
"serve": "vite build && vite preview",
"check": "svelte-check --ignore dist",
"test": "vitest --run --coverage tests/unit/*.ts && playwright test tests/*.test.ts",
"check": "svelte-check src",
"test": "vitest --run --coverage tests/unit/*.ts && npm run test:e2e",
"test:unit": "vitest tests/unit/*.ts",
"test:e2e": "playwright test tests/*.test.ts",
"changelog": "npx auto-changelog --package --output changelog.md --hide-empty-releases --hide-credit --commit-limit false",
"update-coverage": "vitest tests/unit --run --coverage && npx istanbul-badges-readme"
},
"dependencies": {
"svelte": "4.2.12"
"peerDependencies": {
"svelte": "^5.8.0"
},
"devDependencies": {
"@iconify/svelte": "^4.0.2",
"@playwright/test": "^1.48.1",
"@stylistic/eslint-plugin": "^2.12.1",
"@sveltejs/adapter-static": "^3.0.5",
"@sveltejs/kit": "^2.7.2",
"@sveltejs/package": "2.3.5",
"@sveltejs/vite-plugin-svelte": "3.0.2",
"@vitest/coverage-v8": "^2.1.3",
"eslint": "^9.13.0",
"eslint-plugin-svelte": "^2.46.0",
"globals": "^15.11.0",
"hastscript": "^9.0.0",
"highlight.js": "^11.10.0",
"jsdom": "^25.0.1",
"mdsvex": "^0.12.3",
"mdsvexamples": "^0.4.1",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.7",
"@iconify/svelte": "^5.0.0",
"@playwright/test": "^1.52.0",
"@stylistic/eslint-plugin": "^4.2.0",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.21.0",
"@sveltejs/package": "2.3.11",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@types/node": "^22.15.18",
"@vitest/coverage-v8": "^3.1.3",
"eslint": "^9.26.0",
"eslint-plugin-svelte": "^3.6.0",
"globals": "^16.1.0",
"hastscript": "^9.0.1",
"highlight.js": "^11.11.1",
"jsdom": "^26.1.0",
"mdsvex": "^0.12.6",
"mdsvexamples": "^0.5.0",
"prettier": "^3.5.3",
"prettier-plugin-svelte": "^3.3.3",
"rehype-autolink-headings": "^7.1.0",
"rehype-slug": "^6.0.0",
"svelte-check": "^4.0.5",
"svelte-multiselect": "^10.3.0",
"svelte": "^5.28.6",
"svelte-check": "^4.1.7",
"svelte-multiselect": "11.0.0-rc.1",
"svelte-preprocess": "^6.0.3",
"svelte-toc": "^0.5.9",
"svelte-zoo": "^0.4.13",
"svelte2tsx": "^0.7.22",
"typescript": "5.6.3",
"typescript-eslint": "^8.11.0",
"vite": "^5.4.9",
"vitest": "^2.1.3"
"svelte-toc": "^0.6.0",
"svelte-zoo": "^0.4.18",
"svelte2tsx": "^0.7.37",
"typescript": "5.8.3",
"typescript-eslint": "^8.32.1",
"vite": "^6.3.5",
"vitest": "^3.1.3"
},
"keywords": [
"svelte",
Expand Down
6 changes: 5 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import type { PlaywrightTestConfig } from '@playwright/test'

export default {
webServer: {
command: `vite dev --port 3005`,
command: `npm run build && npm run preview -- --port 3005`,
port: 3005,
reuseExistingServer: true,
},
testDir: `tests`,
testMatch: `tests/*.test.ts`,
timeout: 5000,
} satisfies PlaywrightTestConfig
101 changes: 40 additions & 61 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,34 +40,6 @@
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| ![Statements](https://img.shields.io/badge/statements-97.94%25-brightgreen.svg?style=flat) | ![Branches](https://img.shields.io/badge/branches-79.39%25-red.svg?style=flat) | ![Lines](https://img.shields.io/badge/lines-97.94%25-brightgreen.svg?style=flat) |

## 📜 &thinsp; Breaking changes

- **8.0.0** (2022-10-22)&nbsp;
- Props `selectedLabels` and `selectedValues` were removed. If you were using them, they were equivalent to assigning `bind:selected` to a local variable and then running `selectedLabels = selected.map(option => option.label)` and `selectedValues = selected.map(option => option.value)` if your options were objects with `label` and `value` keys. If they were simple strings/numbers, there was no point in using `selected{Labels,Values}` anyway. [PR 138](https://github.com/janosh/svelte-multiselect/pull/138)
- Prop `noOptionsMsg` was renamed to `noMatchingOptionsMsg`. [PR 133](https://github.com/janosh/svelte-multiselect/pull/133).
- **v8.3.0** (2023-01-25)&nbsp; `addOptionMsg` was renamed to `createOptionMsg` (no major since version since it's rarely used) [sha](https://github.com/janosh/svelte-multiselect/commits).
- **v9.0.0** (2023-06-01)&nbsp; Svelte bumped from v3 to v4. Also, not breaking but noteworthy: MultiSelect received a default slot that functions as both `"option"` and `"selected"`. If you previously had two identical slots for `"option"` and `"selected"`, you can now remove the `name` from one of them and drop the other:

```diff
<MultiSelect
{options}
+ let:option
>
- <SlotComponent let:option {option} slot="selected" />
- <SlotComponent let:option {option} slot="option" />
+ <SlotComponent {option} />
</MultiSelect>
```

- **v10.0.0** (2023-06-23)&nbsp; `duplicateFunc()` renamed to `key` in [#238](https://github.com/janosh/svelte-multiselect/pull/238). Signature changed:

```diff
- duplicateFunc: (op1: T, op2: T) => boolean = (op1, op2) => `${get_label(op1)}`.toLowerCase() === `${get_label(op2)}`.toLowerCase()
+ key: (opt: T) => unknown = (opt) => `${get_label(opt)}`.toLowerCase()
```

Rather than implementing custom equality in `duplicateFunc`, the `key` function is now expected to map options to a unique identifier. `key(op1) === key(op2)` should mean `op1` and `op2` are the same option. `key` can return any type but usually best to return primitives (`string`, `number`, ...) for Svelte keyed each blocks (see [#217](https://github.com/janosh/svelte-multiselect/pull/217)).

## 🔨 &thinsp; Installation

```sh
Expand All @@ -84,7 +56,7 @@ yarn add --dev svelte-multiselect

const ui_libs = [`Svelte`, `React`, `Vue`, `Angular`, `...`]

let selected = []
let selected = $state([])
</script>

Favorite Frontend Tools?
Expand Down Expand Up @@ -257,7 +229,7 @@ Full list of props/bindable variables for this component. The `Option` type you
loading: boolean = false
```

Whether the component should display a spinner to indicate it's in loading state. Use `<slot name='spinner'>` to specify a custom spinner.
Whether the component should display a spinner to indicate it's in loading state. Use `{#snippet spinner()} ... {/snippet}` to specify a custom spinner.

1. ```ts
matchingOptions: Option[] = []
Expand Down Expand Up @@ -423,35 +395,42 @@ Full list of props/bindable variables for this component. The `Option` type you

If `maxSelect={1}`, `value` will be the single item in `selected` (or `null` if `selected` is empty). If `maxSelect != 1`, `maxSelect` and `selected` are equal. Warning: Setting `value` does not rendered state on initial mount, meaning `bind:value` will update local variable `value` whenever internal component state changes but passing a `value` when component first mounts won't be reflected in UI. This is because the source of truth for rendering is `bind:selected`. `selected` is reactive to `value` internally but only on reassignment from initial value. Suggestions for better solutions than [#249](https://github.com/janosh/svelte-multiselect/issues/249) welcome!

## 🎰 &thinsp; Slots
## 🎰 &thinsp; Snippets

`MultiSelect.svelte` accepts the following named slots:
`MultiSelect.svelte` accepts the following named snippets:

1. `slot="option"`: Customize rendering of dropdown options. Receives as props an `option` and the zero-indexed position (`idx`) it has in the dropdown.
1. `slot="selected"`: Customize rendering of selected items. Receives as props an `option` and the zero-indexed position (`idx`) it has in the list of selected items.
1. `slot="spinner"`: Custom spinner component to display when in `loading` state. Receives no props.
1. `slot="disabled-icon"`: Custom icon to display inside the input when in `disabled` state. Receives no props. Use an empty `<span slot="disabled-icon" />` or `div` to remove the default disabled icon.
1. `slot="expand-icon"`: Allows setting a custom icon to indicate to users that the Multiselect text input field is expandable into a dropdown list. Receives prop `open: boolean` which is true if the Multiselect dropdown is visible and false if it's hidden.
1. `slot="remove-icon"`: Custom icon to display as remove button. Will be used both by buttons to remove individual selected options and the 'remove all' button that clears all options at once. Receives no props.
1. `slot="user-msg"`: Displayed like a dropdown item when the list is empty and user is allowed to create custom options based on text input (or if the user's text input clashes with an existing option). Receives props:
1. `#snippet option({ option, idx })`: Customize rendering of dropdown options. Receives as props an `option` and the zero-indexed position (`idx`) it has in the dropdown.
1. `#snippet selectedItem({ option, idx })`: Customize rendering of selected items. Receives as props an `option` and the zero-indexed position (`idx`) it has in the list of selected items.
1. `#snippet spinner()`: Custom spinner component to display when in `loading` state. Receives no props.
1. `#snippet disabledIcon()`: Custom icon to display inside the input when in `disabled` state. Receives no props. Use an empty `{#snippet disabledIcon()}{/snippet}` to remove the default disabled icon.
1. `#snippet expandIcon()`: Allows setting a custom icon to indicate to users that the Multiselect text input field is expandable into a dropdown list. Receives prop `open: boolean` which is true if the Multiselect dropdown is visible and false if it's hidden.
1. `#snippet removeIcon()`: Custom icon to display as remove button. Will be used both by buttons to remove individual selected options and the 'remove all' button that clears all options at once. Receives no props.
1. `#snippet userMsg({ searchText, msgType, msg })`: Displayed like a dropdown item when the list is empty and user is allowed to create custom options based on text input (or if the user's text input clashes with an existing option). Receives props:
- `searchText`: The text user typed into search input.
- `msgType: false | 'create' | 'dupe' | 'no-match'`: `'dupe'` means user input is a duplicate of an existing option. `'create'` means user is allowed to convert their input into a new option not previously in the dropdown. `'no-match'` means user input doesn't match any dropdown items and users are not allowed to create new options. `false` means none of the above.
- `msg`: Will be `duplicateOptionMsg` or `createOptionMsg` (see [props](#🔣-props)) based on whether user input is a duplicate or can be created as new option. Note this slot replaces the default UI for displaying these messages so the slot needs to render them instead (unless purposely not showing a message).
1. `slot='after-input'`: Placed after the search input. For arbitrary content like icons or temporary messages. Receives props `selected: Option[]`, `disabled: boolean`, `invalid: boolean`, `id: string | null`, `placeholder: string`, `open: boolean`, `required: boolean`. Can serve as a more dynamic, more customizable alternative to the `placeholder` prop.
- `msg`: Will be `duplicateOptionMsg` or `createOptionMsg` (see [props](#🔣-props)) based on whether user input is a duplicate or can be created as new option. Note this snippet replaces the default UI for displaying these messages so the snippet needs to render them instead (unless purposely not showing a message).
1. `snippet='after-input'`: Placed after the search input. For arbitrary content like icons or temporary messages. Receives props `selected: Option[]`, `disabled: boolean`, `invalid: boolean`, `id: string | null`, `placeholder: string`, `open: boolean`, `required: boolean`. Can serve as a more dynamic, more customizable alternative to the `placeholder` prop.

Example using several slots:
Example using several snippets:

```svelte
<MultiSelect options={[`Red`, `Green`, `Blue`, `Yellow`, `Purple`]} let:idx let:option>
<!-- default slot overrides rendering of both dropdown-listed and selected options -->
<span>
{idx + 1}
{option.label}
<span style:background={option.label} style=" width: 1em; height: 1em;" />
</span>

<CustomSpinner slot="spinner">
<strong slot="remove-icon">X</strong>
<MultiSelect options={[`Red`, `Green`, `Blue`, `Yellow`, `Purple`]}>
{#snippet children({ idx, option })}
<span style="display: flex; align-items: center; gap: 6pt;">
<span
style:background={`${option}`}
style="border-radius: 50%; width: 1em; height: 1em;"
></span>
{idx + 1}
{option}
</span>
{/snippet}
{#snippet spinner()}
<CustomSpinner />
{/snippet}
{#snippet removeIcon()}
<strong>X</strong>
{/snippet}
</MultiSelect>
```

Expand All @@ -460,37 +439,37 @@ Example using several slots:
`MultiSelect.svelte` dispatches the following events:

1. ```ts
on:add={(event) => console.log(event.detail.option)}
onadd={(event) => console.log(event.detail.option)}
```

Triggers when a new option is selected. The newly selected option is provided as `event.detail.option`.

1. ```ts
on:remove={(event) => console.log(event.detail.option)}`
onremove={(event) => console.log(event.detail.option)}`
```

Triggers when a single selected option is removed. The removed option is provided as `event.detail.option`.

1. ```ts
on:removeAll={(event) => console.log(event.detail.options)}`
onremoveAll={(event) => console.log(event.detail.options)}`
```

Triggers when all selected options are removed. The payload `event.detail.options` gives the options that were previously selected.

1. ```ts
on:change={(event) => console.log(`${event.detail.type}: '${event.detail.option}'`)}
onchange={(event) => console.log(`${event.detail.type}: '${event.detail.option}'`)}
```

Triggers when an option is either added (selected) or removed from selected, or all selected options are removed at once. `type` is one of `'add' | 'remove' | 'removeAll'` and payload will be `option: Option` or `options: Option[]`, respectively.

1. ```ts
on:open={(event) => console.log(`Multiselect dropdown was opened by ${event}`)}
onopen={(event) => console.log(`Multiselect dropdown was opened by ${event}`)}
```

Triggers when the dropdown list of options appears. Event is the DOM's `FocusEvent`,`KeyboardEvent` or `ClickEvent` that initiated this Svelte `dispatch` event.

1. ```ts
on:close={(event) => console.log(`Multiselect dropdown was closed by ${event}`)}
onclose={(event) => console.log(`Multiselect dropdown was closed by ${event}`)}
```

Triggers when the dropdown list of options disappears. Event is the DOM's `FocusEvent`, `KeyboardEvent` or `ClickEvent` that initiated this Svelte `dispatch` event.
Expand All @@ -499,7 +478,7 @@ For example, here's how you might annoy your users with an alert every time one

```svelte
<MultiSelect
on:change={(e) => {
onchange={(e) => {
if (e.detail.type === 'add') alert(`You added ${e.detail.option}`)
if (e.detail.type === 'remove') alert(`You removed ${e.detail.option}`)
if (e.detail.type === 'removeAll') alert(`You removed ${e.detail.options}`)
Expand All @@ -514,7 +493,7 @@ The above list of events are [Svelte `dispatch` events](https://svelte.dev/tutor
```svelte
<MultiSelect
options={[1, 2, 3]}
on:keyup={(event) => console.log('key', event.target.value)}
onkeyup={(event) => console.log('key', event.target.value)}
/>
```

Expand All @@ -534,7 +513,7 @@ const options = [42, 69]
// type Option = number
```

The inferred type of `Option` is used to enforce type-safety on derived props like `selected` as well as slot components. E.g. you'll get an error when trying to use a slot component that expects a string if your options are objects (see [this comment](https://github.com/janosh/svelte-multiselect/pull/189/files#r1058853697) for example screenshots).
The inferred type of `Option` is used to enforce type-safety on derived props like `selected` as well as snippets. E.g. you'll get an error when trying to use a snippet that expects a string if your options are objects (see [this comment](https://github.com/janosh/svelte-multiselect/pull/189/files#r1058853697) for example screenshots).

You can also import [the types this component uses](https://github.com/janosh/svelte-multiselect/blob/main/src/lib/index.ts) for downstream applications:

Expand Down
12 changes: 3 additions & 9 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,10 @@
--sms-li-disabled-bg: black;
--sms-placeholder-color: lightgray;

--toc-mobile-bg: #1c0e3e;
--toc-li-padding: 3pt 1ex;
--toc-mobile-btn-color: white;
--toc-desktop-nav-margin: 0 0 0 1em;
--toc-active-bg: teal;

--zoo-github-corner-color: var(--night);
--zoo-github-corner-bg: white;
--zoo-example-margin: 1em auto;
--zoo-example-btn-bg: none;
}
body {
background: var(--night);
Expand All @@ -41,14 +36,13 @@ a.btn {
cursor: pointer;
border: none;
border-radius: 3pt;
background-color: teal;
padding: 2pt 4pt;
font-size: 12pt;
line-height: initial;
transition: background-color 0.2s;
background-color: rgba(31, 182, 205, 0.425);
}
:is(button, a.btn):hover {
background-color: teal;
color: white;
}
a {
Expand Down Expand Up @@ -90,7 +84,7 @@ table {
border-collapse: collapse;
}
table :is(td, th) {
border: 1px dashed teal;
border: 1px dashed rgba(255, 255, 255, 0.2);
padding: 5pt 9pt;
}
table img {
Expand Down
Loading
Loading