diff --git a/README.md b/README.md index 210d8409c..a43340fb6 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,3 @@ -
- - - tldraw - -
- # tldraw Welcome to the public monorepo for [tldraw](https://github.com/tldraw/tldraw). tldraw is a library for creating infinite canvas experiences in React. It's the software behind the digital whiteboard [tldraw.com](https://tldraw.com). @@ -12,6 +5,29 @@ Welcome to the public monorepo for [tldraw](https://github.com/tldraw/tldraw). t - Read the docs and learn more at [tldraw.dev](https://tldraw.dev). - Learn about [our license](https://github.com/tldraw/tldraw#License). +## Installation + +```bash +npm i tldraw +``` + +## Usage + +```tsx +import { Tldraw } from 'tldraw' +import 'tldraw/tldraw.css' + +export default function App() { + return ( +
+ +
+ ) +} +``` + +Learn more at [tldraw.dev](https://tldraw.dev). + ## Local development The local development server will run our examples app. The basic example will show any changes you've made to the codebase. @@ -21,22 +37,22 @@ To run the local development server, first clone this repo. Install dependencies: ```bash -yarn +yarn i ``` Start the local development server: ```bash -yarn dev +yarn run dev ``` Open the example project at `localhost:5420`. ## License -tldraw's source code and distributed packages are provided under the non-commercial [tldraw license](https://github.com/tldraw/tldraw/blob/master/LICENSE.md). +tldraw's source code and distributed packages are provided under the non-commercial [tldraw license](https://github.com/tldraw/tldraw/blob/main/LICENSE.md). -This license does not permit commercial use. If you wish to use tldraw in a commercial product or enterprise, you will need to purchase a commercial license. To obtain a commercial license, please contact us at [hello@tldraw.com](mailto:hello@tldraw.com). +This license does not permit commercial use. If you wish to use tldraw in a commercial product or enterprise, you will need to purchase a commercial license. To obtain a commercial license, please contact us at [sales@tldraw.com](mailto:sales@tldraw.com). To learn more, see our [license](https://tldraw.dev/community/license) page. @@ -53,6 +69,7 @@ Have questions, comments or feedback? [Join our discord](https://discord.gg/rhsy Please see our [contributing guide](https://github.com/tldraw/tldraw/blob/main/CONTRIBUTING.md). Found a bug? Please [submit an issue](https://github.com/tldraw/tldraw/issues/new). ## Contributors + diff --git a/apps/docs/content/community/license.mdx b/apps/docs/content/community/license.mdx index cf1c5badd..e56fdc80f 100644 --- a/apps/docs/content/community/license.mdx +++ b/apps/docs/content/community/license.mdx @@ -6,13 +6,9 @@ date: 11/7/2023 order: 2 --- -tldraw uses a dual licensing model to support the development of the project. +tldraw's source code and distributed packages are provided under the non-commercial [tldraw license](https://github.com/tldraw/tldraw/blob/main/LICENSE.md). -The project's source code, libraries, and distributions are provided under the [tldraw licence](https://github.com/tldraw/tldraw/blob/master/LICENSE.md). - -This license does not permit commercial use. If you wish to use this project in a commercial product or enterprise, you need to purchase a commercial license. - -To purchase a commercial license, or for more information, please contact us at [sales@tldraw.com](mailto:sales@tldraw.com). +This license does not permit commercial use. If you wish to use tldraw in a commercial product or enterprise, you will need to purchase a commercial license. To obtain a commercial license, please contact us at [sales@tldraw.com](mailto:sales@tldraw.com). ## Trademarks diff --git a/apps/docs/content/getting-started/installation.mdx b/apps/docs/content/getting-started/installation.mdx index c519dc130..ad8adfd1a 100644 --- a/apps/docs/content/getting-started/installation.mdx +++ b/apps/docs/content/getting-started/installation.mdx @@ -6,19 +6,13 @@ date: 3/22/2023 order: 1 --- -At the moment the `tldraw` package is in beta. We also ship a canary version which is always up to date with the main branch of tldraw [repository](https://github.com/tldraw/tldraw). +## Installation -## Beta +First, install the `tldraw` package: -First, install the `tldraw` package using `@beta` for the latest beta release. - - - -## Canary - -To get the very latest version, use the [latest canary release](https://www.npmjs.com/package/tldraw?activeTab=versions). Docs for the very latest version are also available at [canary.tldraw.dev](https://canary.tldraw.dev). - - +```bash +npm i tldraw +``` ## Usage @@ -105,7 +99,7 @@ In order to use the [Tldraw](?) component, the app must be able to find certain ### Using a public CDN -By default we serve these assets from a [public CDN called unpkg](https://unpkg.com/browse/@tldraw/assets@2.0.0-alpha.12/), so everything should work out of the box and is a good way to get started. +By default we serve these assets from a public CDN. Everything should work out of the box and is a good way to get started. If you would like to customize some of the assets you can pass the customizations to our [Tldraw](?) component. For example, to use a custom icon for the `hand` tool you can do the following: diff --git a/apps/docs/content/getting-started/quick-start.mdx b/apps/docs/content/getting-started/quick-start.mdx index 649f15c12..a85c3a1a9 100644 --- a/apps/docs/content/getting-started/quick-start.mdx +++ b/apps/docs/content/getting-started/quick-start.mdx @@ -8,7 +8,7 @@ order: 0

Add a tldraw canvas to your React app in just 5 minutes.

-The tldraw SDK provides a really simple way to craft infinite canvas experiences for the web. It's perfect for collaborative applications, productivity tools, interfacing with multi-modal AI, and more. +You can use the tldraw SDK to craft infinite canvas experiences for the web. It's perfect for collaborative whiteboards but you can use it for lots of other things, too. By the end of this guide you will have made something that looks like this: @@ -20,7 +20,7 @@ By the end of this guide you will have made something that looks like this: - Install the tldraw library using this command: ```bash -npm install @tldraw/tldraw@beta +npm install tldraw ``` ### 2. Import Styles @@ -32,7 +32,7 @@ To import fonts and CSS for tldraw: ```CSS @import url("https://fonts.googleapis.com/css2?family=Inter:wght@500;700;&display=swap"); -@import url("@tldraw/tldraw/tldraw.css"); +@import url("tldraw/tldraw.css"); body { font-family: "Inter"; @@ -43,14 +43,14 @@ body { To render the Tldraw component -- Import the `` component from `@tldraw/tldraw` +- Import the `` component from the tldraw` package - Import the `index.css` CSS file from earlier - Wrap the Tldraw component in a `
` element with the style attribute set to: `{ position: 'fixed', inset: 0 }` This will render a full screen canvas: ```javascript -import { Tldraw } from "@tldraw/tldraw"; +import { Tldraw } from "tldraw"; import "./index.css"; export default function App() { diff --git a/apps/docs/content/sections.json b/apps/docs/content/sections.json index 9e7508e23..8dbb2266f 100644 --- a/apps/docs/content/sections.json +++ b/apps/docs/content/sections.json @@ -99,7 +99,7 @@ }, { "id": "tldraw", - "title": "tldraw", + "title": "@tldraw/tldraw", "description": "", "groups": [ { diff --git a/apps/docs/styles/globals.css b/apps/docs/styles/globals.css index ee5b92121..fd3f99cee 100644 --- a/apps/docs/styles/globals.css +++ b/apps/docs/styles/globals.css @@ -505,6 +505,7 @@ body { } .article p code, +.article li code, .article td code { background-color: var(--color-tint-0); font-size: 15px; diff --git a/packages/namespaced-tldraw/tldraw.css b/packages/namespaced-tldraw/tldraw.css new file mode 100644 index 000000000..107ed6606 --- /dev/null +++ b/packages/namespaced-tldraw/tldraw.css @@ -0,0 +1,3091 @@ +/* THIS CSS FILE IS GENERATED! DO NOT EDIT. OR EDIT. I'M A COMMENT NOT A COP */ +/* This file is created by the copy-css-files.mjs script in packages/tldraw. */ +/* It combines @tldraw/editor's editor.css and tldraw's ui.css */ + +/* @tldraw/editor */ + +.tl-container { + width: 100%; + height: 100%; + font-size: 12px; + /* Spacing */ + --space-1: 2px; + --space-2: 4px; + --space-3: 8px; + --space-4: 12px; + --space-5: 16px; + --space-6: 20px; + --space-7: 28px; + --space-8: 32px; + --space-9: 64px; + --space-10: 72px; + /* Radius */ + --radius-0: 2px; + --radius-1: 4px; + --radius-2: 6px; + --radius-3: 9px; + --radius-4: 11px; + /* Z Index */ + --layer-background: 100; + --layer-grid: 150; + --layer-canvas: 200; + --layer-shapes: 300; + --layer-overlays: 400; + --layer-following-indicator: 1000; + /* Misc */ + --tl-zoom: 1; + + /* Cursor SVGs */ + --tl-cursor-none: none; + --tl-cursor-default: url("data:image/svg+xml,") + 12 8, + default; + --tl-cursor-pointer: url("data:image/svg+xml,") + 14 10, + pointer; + --tl-cursor-cross: url("data:image/svg+xml,") + 16 16, + crosshair; + --tl-cursor-move: url("data:image/svg+xml,") + 16 16, + move; + --tl-cursor-grab: url("data:image/svg+xml,") + 16 16, + grab; + --tl-cursor-grabbing: url("data:image/svg+xml,") + 16 16, + grabbing; + --tl-cursor-text: url("data:image/svg+xml,") + 4 10, + text; + --tl-cursor-zoom-in: url("data:image/svg+xml,") + 16 16, + zoom-in; + --tl-cursor-zoom-out: url("data:image/svg+xml,") + 16 16, + zoom-out; + + /* These cursor values get programmatically overridden */ + /* They're just here to help your editor autocomplete */ + --tl-cursor: var(--tl-cursor-default); + --tl-cursor-resize-edge: ew-resize; + --tl-cursor-resize-corner: nesw-resize; + --tl-cursor-ew-resize: ew-resize; + --tl-cursor-ns-resize: ns-resize; + --tl-cursor-nesw-resize: nesw-resize; + --tl-cursor-nwse-resize: nwse-resize; + --tl-cursor-rotate: pointer; + --tl-cursor-nwse-rotate: pointer; + --tl-cursor-nesw-rotate: pointer; + --tl-cursor-senw-rotate: pointer; + --tl-cursor-swne-rotate: pointer; + --tl-scale: calc(1 / var(--tl-zoom)); + /* fonts */ + --tl-font-draw: 'tldraw_draw', sans-serif; + --tl-font-sans: 'tldraw_sans', sans-serif; + --tl-font-serif: 'tldraw_serif', serif; + --tl-font-mono: 'tldraw_mono', monospace; + /* fext outline */ + --a: calc(min(0.5, 1 / var(--tl-zoom)) * 2px); + --b: calc(min(0.5, 1 / var(--tl-zoom)) * -2px); + --tl-text-outline: 0 var(--b) 0 var(--color-background), 0 var(--a) 0 var(--color-background), + var(--b) var(--b) 0 var(--color-background), var(--a) var(--b) 0 var(--color-background), + var(--a) var(--a) 0 var(--color-background), var(--b) var(--a) 0 var(--color-background); + /* own properties */ + position: relative; + inset: 0px; + height: 100%; + width: 100%; + overflow: clip; +} + +.tl-theme__light { + --color-accent: hsl(0, 76%, 60%); + --color-background: hsl(210, 20%, 98%); + --color-brush-fill: hsl(0, 0%, 56%, 10.2%); + --color-brush-stroke: hsl(0, 0%, 56%, 25.1%); + --color-grid: hsl(0, 0%, 43%); + --color-low: hsl(204, 16%, 94%); + --color-low-border: hsl(204, 16%, 92%); + --color-culled: hsl(204, 14%, 93%); + --color-muted-none: hsl(0, 0%, 0%, 0%); + --color-muted-0: hsl(0, 0%, 0%, 2%); + --color-muted-1: hsl(0, 0%, 0%, 10%); + --color-muted-2: hsl(0, 0%, 0%, 4.3%); + --color-hint: hsl(0, 0%, 0%, 5.5%); + --color-overlay: hsl(0, 0%, 0%, 20%); + --color-divider: hsl(0, 0%, 91%); + --color-panel-contrast: hsl(0, 0%, 100%); + --color-panel-overlay: hsl(0, 0%, 100%, 82%); + --color-panel: hsl(0, 0%, 99%); + --color-focus: hsl(214, 100%, 29%); + --color-selected: hsl(214, 84%, 56%); + --color-selected-contrast: hsl(0, 0%, 100%); + --color-selection-fill: hsl(210, 100%, 56%, 24%); + --color-selection-stroke: hsl(214, 84%, 56%); + --color-text-0: hsl(0, 0%, 11%); + --color-text-1: hsl(0, 0%, 18%); + --color-text-3: hsl(220, 2%, 65%); + --color-text-shadow: hsl(0, 0%, 100%); + --color-primary: hsl(214, 84%, 56%); + --color-warn: hsl(0, 90%, 43%); + --color-text: hsl(0, 0%, 0%); + --color-laser: hsl(0, 100%, 50%); + /* Shadows */ + --shadow-1: 0px 1px 2px hsl(0, 0%, 0%, 25%), 0px 1px 3px hsl(0, 0%, 0%, 9%); + --shadow-2: 0px 0px 2px hsl(0, 0%, 0%, 16%), 0px 2px 3px hsl(0, 0%, 0%, 24%), + 0px 2px 6px hsl(0, 0%, 0%, 0.1), inset 0px 0px 0px 1px var(--color-panel-contrast); + --shadow-3: 0px 1px 2px hsl(0, 0%, 0%, 28%), 0px 2px 6px hsl(0, 0%, 0%, 14%), + inset 0px 0px 0px 1px var(--color-panel-contrast); + --shadow-4: 0px 0px 3px hsl(0, 0%, 0%, 19%), 0px 5px 4px hsl(0, 0%, 0%, 16%), + 0px 2px 16px hsl(0, 0%, 0%, 6%), inset 0px 0px 0px 1px var(--color-panel-contrast); +} + +.tl-theme__dark { + --color-accent: hsl(0, 76%, 60%); + --color-background: hsl(240, 5%, 8%); + --color-brush-fill: hsl(0, 0%, 71%, 5.1%); + --color-brush-stroke: hsl(0, 0%, 71%, 25.1%); + --color-grid: hsl(0, 0%, 56%); + --color-low: hsl(260, 5%, 12.5%); + --color-low-border: hsl(207, 10%, 10%); + --color-culled: hsl(210, 11%, 19%); + --color-muted-none: hsl(0, 0%, 100%, 0%); + --color-muted-0: hsl(0, 0%, 100%, 2%); + --color-muted-1: hsl(0, 0%, 100%, 10%); + --color-muted-2: hsl(0, 0%, 100%, 5%); + --color-hint: hsl(0, 0%, 100%, 7%); + --color-overlay: hsl(0, 0%, 0%, 50%); + --color-divider: hsl(240, 9%, 25%); + --color-panel-contrast: hsl(240, 13%, 22%); + --color-panel: hsl(220, 8%, 15%); + --color-panel-overlay: hsl(210, 11%, 24%, 82%); + --color-focus: hsl(217, 76%, 80%); + --color-selected: hsl(217, 89%, 61%); + --color-selected-contrast: hsl(0, 0%, 100%); + --color-selection-fill: hsl(209, 100%, 57%, 20%); + --color-selection-stroke: hsl(214, 84%, 56%); + --color-text-0: hsl(0, 9%, 94%); + --color-text-1: hsl(0, 0%, 85%); + --color-text-3: hsl(210, 6%, 45%); + --color-text-shadow: hsl(210, 13%, 18%); + --color-primary: hsl(214, 84%, 56%); + --color-warn: hsl(0, 81%, 66%); + --color-text: hsl(210, 17%, 98%); + --color-laser: hsl(0, 100%, 50%); + /* Shadows */ + --shadow-1: 0px 1px 2px hsl(0, 0%, 0%, 16.1%), 0px 1px 3px hsl(0, 0%, 0%, 22%), + inset 0px 0px 0px 1px var(--color-panel-contrast); + --shadow-2: 0px 1px 3px hsl(0, 0%, 0%, 66.6%), 0px 2px 6px hsl(0, 0%, 0%, 33%), + inset 0px 0px 0px 1px var(--color-panel-contrast); + --shadow-3: 0px 1px 3px hsl(0, 0%, 0%, 50%), 0px 2px 12px hsl(0, 0%, 0%, 50%), + inset 0px 0px 0px 1px var(--color-panel-contrast); +} + +.tl-counter-scaled { + transform: scale(var(--tl-scale)); + transform-origin: top left; + width: calc(100% * var(--tl-zoom)); + height: calc(100% * var(--tl-zoom)); +} + +.tl-container, +.tl-container * { + -webkit-touch-callout: none; + -webkit-tap-highlight-color: transparent; + scrollbar-highlight-color: transparent; + -webkit-user-select: none; + user-select: none; + box-sizing: border-box; + outline: none; +} + +.tl-container a { + -webkit-touch-callout: initial; +} + +.tl-container:focus-within { + outline: 1px solid var(--color-low); +} + +input, +*[contenteditable], +*[contenteditable] * { + -webkit-user-select: text; +} + +/* -------------------------------------------------- */ +/* Canvas */ +/* -------------------------------------------------- */ + +.tl-canvas { + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + color: var(--color-text); + z-index: var(--layer-canvas); + cursor: var(--tl-cursor); + overflow: clip; + content-visibility: auto; + touch-action: none; + contain: strict; +} + +.tl-shapes { + position: relative; + z-index: var(--layer-shapes); +} + +.tl-overlays { + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + contain: strict; + pointer-events: none; + z-index: var(--layer-overlays); +} + +.tl-overlays__item { + position: absolute; + top: 0px; + left: 0px; + overflow: visible; + pointer-events: none; + transform-origin: top left; +} + +.tl-svg-context { + position: absolute; + top: 0px; + left: 0px; + pointer-events: none; +} + +/* ------------------- Background ------------------- */ + +.tl-background { + position: absolute; + background-color: var(--color-background); + inset: 0px; + height: 100%; + width: 100%; + z-index: var(--layer-background); +} + +/* --------------------- Grid Layer --------------------- */ + +.tl-grid { + position: absolute; + inset: 0px; + width: 100%; + height: 100%; + touch-action: none; + pointer-events: none; + z-index: var(--layer-grid); + contain: strict; +} + +.tl-grid-dot { + fill: var(--color-grid); +} + +/* --------------------- Layers --------------------- */ + +.tl-html-layer { + position: absolute; + top: 0px; + left: 0px; + width: 1px; + height: 1px; + contain: layout style size; +} + +/* ---------------------- Brush --------------------- */ + +.tl-brush { + stroke-width: calc(var(--tl-scale) * 1px); + contain: size layout; +} + +.tl-brush__default { + stroke: var(--color-brush-stroke); + fill: var(--color-brush-fill); +} + +/* -------------------- Scribble -------------------- */ + +.tl-scribble { + stroke-linejoin: round; + stroke-linecap: round; + pointer-events: none; + contain: size layout; +} + +/* ---------------------- Shape --------------------- */ + +.tl-shape { + position: absolute; + pointer-events: none; + overflow: visible; + transform-origin: top left; + contain: size layout; +} + +.tl-shape__culled { + position: relative; + background-color: var(--color-culled); +} + +/* ---------------- Shape Containers ---------------- */ + +.tl-svg-container { + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + pointer-events: none; + stroke-linecap: round; + stroke-linejoin: round; + transform-origin: top left; + overflow: visible; +} + +.tl-html-container { + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + pointer-events: none; + stroke-linecap: round; + stroke-linejoin: round; + /* content-visibility: auto; */ + transform-origin: top left; + color: inherit; +} + +/* --------------- Overlay Stack --------------- */ + +/* back of the stack, behind user's stuff */ +.tl-collaborator__scribble { + z-index: 10; +} + +.tl-collaborator__brush { + z-index: 20; +} + +.tl-collaborator__shape-indicator { + z-index: 30; +} + +.tl-user-scribble { + z-index: 40; +} + +.tl-user-brush { + z-index: 50; +} + +.tl-user-indicator__selected { + z-index: 60; +} + +.tl-user-indicator__hovered { + z-index: 70; +} + +.tl-user-handles { + z-index: 80; +} + +.tl-user-snapline { + z-index: 90; +} + +.tl-selection__fg { + pointer-events: none; + z-index: 100; +} + +.tl-user-indicator__hint { + z-index: 110; + stroke-width: calc(2.5px * var(--tl-scale)); +} + +/* behind collaborator cursor */ +.tl-collaborator__cursor-hint { + z-index: 120; +} + +.tl-collaborator__cursor { + z-index: 130; +} + +.tl-cursor { + overflow: visible; +} + +/* -------------------- Indicator ------------------- */ + +.tl-shape-indicator { + transform-origin: top left; + fill: none; + stroke-width: calc(1.5px * var(--tl-scale)); + contain: size; +} + +/* ------------------ SelectionBox ------------------ */ + +.tl-selection__bg { + position: absolute; + top: 0px; + left: 0px; + transform-origin: top left; + background-color: transparent; + pointer-events: all; +} + +.tl-selection__fg__outline { + fill: none; + pointer-events: none; + stroke: var(--color-selection-stroke); + stroke-width: calc(1.5px * var(--tl-scale)); +} + +.tl-corner-handle { + pointer-events: none; + stroke: var(--color-selection-stroke); + fill: var(--color-background); + stroke-width: calc(1.5px * var(--tl-scale)); +} + +.tl-text-handle { + pointer-events: none; + fill: var(--color-selection-stroke); +} + +.tl-corner-crop-handle { + pointer-events: none; + fill: none; + stroke: var(--color-selection-stroke); +} + +.tl-corner-crop-edge-handle { + pointer-events: none; + fill: none; + stroke: var(--color-selection-stroke); +} + +.tl-mobile-rotate__bg { + pointer-events: all; + cursor: var(--tl-cursor-grab); +} + +.tl-mobile-rotate__fg { + pointer-events: none; + stroke: var(--color-selection-stroke); + fill: var(--color-background); + stroke-width: calc(1.5px * var(--tl-scale)); +} + +.tl-transparent { + fill: transparent; + stroke: transparent; +} + +/* --------------------- Handles -------------------- */ + +.tl-handle { + pointer-events: all; +} + +.tl-handle__bg { + fill: transparent; + stroke: transparent; + pointer-events: all; +} + +.tl-handle__fg { + fill: var(--color-selected-contrast); + stroke: var(--color-selection-stroke); + stroke-width: calc(1.5px * var(--tl-scale)); + pointer-events: none; +} + +.tl-handle__create { + opacity: 0; +} +.tl-handle__create:hover { + opacity: 1; +} + +.tl-handle__bg:active { + fill: none; +} + +.tl-handle__bg:hover { + cursor: var(--tl-cursor-grab); + fill: var(--color-selection-fill); +} + +@media (pointer: coarse) { + .tl-handle__bg:active { + fill: var(--color-selection-fill); + } + + .tl-handle__create { + opacity: 1; + } +} + +/* ------------------ Bounds Detail ----------------- */ + +.tl-image, +.tl-video { + object-fit: cover; + background-size: cover; + width: 100%; + height: 100%; +} + +.tl-image-container, +.tl-embed-container { + width: 100%; + height: 100%; + pointer-events: all; + /* background-color: var(--color-background); */ + + display: flex; + justify-content: center; + align-items: center; +} + +.tl-image__tg { + --scale: calc(min(2, var(--tl-scale))); + position: absolute; + top: calc(var(--scale) * 8px); + right: calc(var(--scale) * 8px); + font-size: 10px; + transform-origin: top right; + background-color: var(--color-background); + padding: 2px 4px; + border-radius: var(--radius-1); +} + +/* --------------------- Nametag -------------------- */ + +.tl-collaborator-cursor { + position: absolute; +} + +.tl-nametag { + position: absolute; + top: 16px; + left: 13px; + width: fit-content; + height: fit-content; + max-width: 120px; + padding: 3px 6px; + white-space: nowrap; + position: absolute; + overflow: hidden; + text-overflow: ellipsis; + font-size: 12px; + font-family: var(--font-body); + border-radius: var(--radius-2); + color: var(--color-selected-contrast); +} + +.tl-nametag-title { + position: absolute; + top: -2px; + left: 13px; + width: fit-content; + height: fit-content; + padding: 0px 6px; + max-width: 120px; + white-space: nowrap; + position: absolute; + overflow: hidden; + text-overflow: ellipsis; + font-size: 12px; + font-family: var(--font-body); + text-shadow: var(--tl-text-outline); + color: var(--color-selected-contrast); +} + +.tl-nametag-chat { + position: absolute; + top: 16px; + left: 13px; + width: fit-content; + height: fit-content; + color: var(--color-selected-contrast); + white-space: nowrap; + position: absolute; + padding: 3px 6px; + font-size: 12px; + font-family: var(--font-body); + opacity: 1; + border-radius: var(--radius-2); +} + +.tl-cursor-chat { + position: absolute; + color: var(--color-selected-contrast); + white-space: nowrap; + padding: 3px 6px; + font-size: 12px; + font-family: var(--font-body); + pointer-events: none; + z-index: var(--layer-cursor); + margin-top: 16px; + margin-left: 13px; + opacity: 1; + border: none; + user-select: text; + border-radius: var(--radius-2); +} + +.tl-cursor-chat .tl-cursor-chat__bubble { + padding-right: 12px; +} + +.tl-cursor-chat::selection { + background: var(--color-selected); + color: var(--color-selected-contrast); + text-shadow: none; +} + +.tl-cursor-chat-fade { + /* Setting to zero causes it to immediately disappear */ + /* Setting to near-zero causes it to fade out gradually */ + opacity: 0.0001; + transition: opacity 5s ease-in-out; +} + +.tl-cursor-chat::placeholder { + color: var(--color-selected-contrast); + opacity: 0.7; +} + +/* -------------------------------------------------- */ +/* Spinner */ +/* -------------------------------------------------- */ + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} + +/* ------------------- Text Shape ------------------- */ + +.tl-text-shape__wrapper { + position: relative; + font-weight: normal; + min-width: 1px; + padding: 0px; + margin: 0px; + border: none; + height: 100%; + font-variant: normal; + font-style: normal; + pointer-events: all; + white-space: pre-wrap; + overflow-wrap: break-word; + text-shadow: var(--tl-text-outline); +} + +.tl-text-shape__wrapper[data-align='start'] { + text-align: left; +} + +.tl-text-shape__wrapper[data-align='middle'] { + text-align: center; +} + +.tl-text-shape__wrapper[data-align='end'] { + text-align: right; +} + +.tl-text-shape__wrapper[data-font='draw'] { + font-family: var(--tl-font-draw); +} + +.tl-text-shape__wrapper[data-font='sans'] { + font-family: var(--tl-font-sans); +} + +.tl-text-shape__wrapper[data-font='serif'] { + font-family: var(--tl-font-serif); +} + +.tl-text-shape__wrapper[data-font='mono'] { + font-family: var(--tl-font-mono); +} + +.tl-text-shape__wrapper[data-isediting='true'] .tl-text-content { + opacity: 0; +} + +.tl-text { + /* remove overflow from textarea on windows */ + margin: 0px; + padding: 0px; + border: 0px; + color: inherit; + caret-color: var(--color-text); + background: none; + border-image: none; + font-size: inherit; + font-family: inherit; + font-weight: inherit; + line-height: inherit; + font-variant: inherit; + font-style: inherit; + text-align: inherit; + letter-spacing: inherit; + text-shadow: inherit; + outline: none; + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; + pointer-events: all; + text-rendering: auto; + text-transform: none; + text-indent: 0px; + display: inline-block; + appearance: auto; + column-count: initial !important; + writing-mode: horizontal-tb !important; + word-spacing: 0px; +} + +.tl-text-measure { + position: absolute; + z-index: -999999; + top: 0px; + left: 0px; + opacity: 0; + width: max-content; + box-sizing: border-box; + pointer-events: none; + line-break: normal; + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; + resize: none; + border: none; + user-select: none; + contain: style paint; + -webkit-user-select: none; +} + +.tl-text-input, +.tl-text-content { + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + min-width: 1px; + min-height: 1px; + overflow: visible; + outline: none; +} + +.tl-text-content { + pointer-events: none; +} + +.tl-text-input { + resize: none; + user-select: all; + -webkit-user-select: text; + overflow: hidden; + cursor: var(--tl-cursor-text); +} + +.tl-text-input::selection { + background: var(--color-selected); + color: var(--color-selected-contrast); + text-shadow: none; +} + +/* ------------------- Snap Lines ------------------- */ + +.tl-snap-indicator { + stroke: var(--color-accent); + stroke-width: calc(1px * var(--tl-scale)); + fill: none; +} + +.tl-snap-point { + stroke: var(--color-accent); + stroke-width: calc(1px * var(--tl-scale)); + fill: none; +} + +/* -------------------- Groups ------------------ */ + +.tl-group { + stroke: var(--color-text); + stroke-width: calc(1px * var(--tl-scale)); + opacity: 0.5; +} + +/* ------------------- Bookmark Shape ------------------- */ + +.tl-bookmark__container { + width: 100%; + height: 100%; + position: relative; + border: 1px solid var(--color-panel-contrast); + background-color: var(--color-panel); + border-radius: var(--radius-2); + display: flex; + flex-direction: column; + overflow: hidden; +} + +.tl-bookmark__image_container { + flex: 1; + overflow: hidden; + border-top-left-radius: var(--radius-1); + border-top-right-radius: var(--radius-1); + width: 100%; + height: 100%; + display: flex; + justify-content: flex-end; + align-items: flex-start; +} + +.tl-bookmark__image_container > .tl-hyperlink-button::after { + background-color: var(--color-panel); +} + +.tl-bookmark__placeholder { + width: 100%; + height: 100%; + background-color: var(--color-muted-2); + border-bottom: 1px solid var(--color-muted-2); +} + +.tl-bookmark__image { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; +} + +.tl-bookmark__copy_container { + background-color: var(--color-muted); + padding: var(--space-4); + pointer-events: all; +} + +.tl-bookmark__heading, +.tl-bookmark__description, +.tl-bookmark__link { + margin: 0px; + width: 100%; + font-family: inherit; +} + +.tl-bookmark__heading { + font-size: 16px; + font-weight: bold; + padding-bottom: var(--space-2); + margin: 8px 0px; +} + +.tl-bookmark__description { + font-size: 12px; + padding-bottom: var(--space-4); +} + +.tl-bookmark__link { + font-size: 14px; + pointer-events: all; + z-index: 999; + overflow: hidden; + display: block; + color: var(--color-text); + text-overflow: ellipsis; + text-decoration: none; + color: var(--color-text-1); + cursor: var(--tl-cursor-pointer); +} + +.tl-bookmark__link:hover { + color: var(--color-selected); +} + +/* ---------------- Hyperlink Button ---------------- */ + +.tl-hyperlink-button { + background: none; + margin: 0px; + position: absolute; + top: 0px; + right: 0px; + height: 44px; + width: 44px; + display: flex; + align-items: center; + justify-content: center; + z-index: 200; + font-size: 12px; + font-weight: 400; + color: var(--color-text-1); + padding: 13px; + cursor: var(--tl-cursor-pointer); + border: none; + outline: none; + pointer-events: all; +} + +.tl-hyperlink-button::after { + content: ''; + z-index: -1; + position: absolute; + right: 6px; + bottom: 6px; + display: block; + width: calc(100% - 12px); + height: calc(100% - 12px); + border-radius: var(--radius-1); + background-color: var(--color-background); + pointer-events: none; +} + +.tl-hyperlink-button:hover { + color: var(--color-selected); +} + +.tl-hyperlink-button:focus-visible { + color: var(--color-selected); +} + +.tl-hyperlink-button__icon { + width: 18px; + height: 18px; + background-color: currentColor; + pointer-events: none; +} + +.tl-hyperlink-button__hidden { + display: none; +} + +/* ---------------- Geo shape ---------------- */ + +.tl-text-label { + display: flex; + justify-content: center; + align-items: center; + color: var(--color-text); + text-shadow: var(--tl-text-outline); + line-height: inherit; + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + z-index: 10; +} + +.tl-text-label[data-isediting='true'] .tl-text-content { + opacity: 0; +} + +.tl-text-label[data-hastext='false'][data-isediting='false'] > .tl-text-label__inner { + width: 40px; + height: 40px; +} + +.tl-text-label[data-hastext='true'][data-isediting='false'] .tl-text-content { + pointer-events: all; +} + +.tl-text-label__inner { + position: relative; + width: fit-content; + height: fit-content; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; + min-height: auto; +} + +.tl-text-label__inner > .tl-text-content { + position: relative; + top: 0px; + left: 0px; + padding: 16px; + height: fit-content; + width: fit-content; + border-radius: var(--radius-1); + max-width: 100%; + z-index: 3; +} + +.tl-text-label__inner > .tl-text-input { + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + padding: 16px; + z-index: 4; +} + +.tl-text-label[data-textwrap='true'] > .tl-text-label__inner { + max-width: 100%; +} + +.tl-text-label[data-isediting='true'] { + background-color: transparent; + min-height: auto; +} + +.tl-text-label[data-isediting='true'] p { + opacity: 0; +} + +.tl-text-label[data-align='start'], +.tl-text-label[data-align='start-legacy'] { + text-align: left; +} + +.tl-text-label[data-align='middle'], +.tl-text-label[data-align='middle-legacy'] { + text-align: center; +} + +.tl-text-label[data-align='end'], +.tl-text-label[data-align='end-legacy'] { + text-align: right; +} + +.tl-arrow-hint { + stroke: var(--color-text-1); + fill: none; + stroke-linecap: round; + overflow: visible; +} + +.tl-arrow-label[data-font='draw'], +.tl-text-label[data-font='draw'] { + font-family: var(--tl-font-draw); +} + +.tl-arrow-label[data-font='sans'], +.tl-text-label[data-font='sans'] { + font-family: var(--tl-font-sans); +} + +.tl-arrow-label[data-font='serif'], +.tl-text-label[data-font='serif'] { + font-family: var(--tl-font-serif); +} + +.tl-arrow-label[data-font='mono'], +.tl-text-label[data-font='mono'] { + font-family: var(--tl-font-mono); +} + +/* ------------------- Arrow Shape ------------------ */ + +.tl-arrow-label { + position: absolute; + top: -1px; + left: -1px; + width: 2px; + height: 2px; + padding: 0px; + display: flex; + justify-content: center; + align-items: center; + color: var(--color-text); + text-shadow: var(--tl-text-outline); +} + +.tl-arrow-label[data-isediting='true'] p { + opacity: 0; +} + +.tl-arrow-label[data-isediting='true'] > .tl-arrow-label__inner { + background-color: var(--color-background); +} + +.tl-arrow-label__inner { + border-radius: var(--radius-1); + box-sizing: content-box; + position: relative; + height: max-content; + width: max-content; + pointer-events: all; + display: flex; + justify-content: center; + align-items: center; +} + +.tl-arrow-label p, +.tl-arrow-label textarea { + margin: 0px; + padding: 0px; + border: 0px; + color: inherit; + caret-color: var(--color-text); + background: none; + border-image: none; + font-size: inherit; + font-family: inherit; + font-weight: inherit; + line-height: inherit; + font-variant: inherit; + font-style: inherit; + text-align: inherit; + letter-spacing: inherit; + text-shadow: inherit; + outline: none; + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; + pointer-events: all; + text-rendering: auto; + text-transform: none; + text-indent: 0px; + display: inline-block; + appearance: auto; + column-count: initial !important; + writing-mode: horizontal-tb !important; + word-spacing: 0px; +} + +.tl-arrow-label p { + position: relative; + height: max-content; + z-index: 2; + padding: 4px; + overflow: visible; +} + +.tl-arrow-label textarea { + z-index: 3; + margin: 0px; + padding: 4px; + height: 100%; + width: 100%; + position: absolute; + resize: none; + border: 0px; + user-select: all; + -webkit-user-select: text; + caret-color: var(--color-text); + border-image: none; + /* Don't allow textarea to be zero width */ + min-width: 4px; +} + +/* -------------------- NoteShape ------------------- */ + +.tl-note__container { + position: relative; + width: 100%; + height: 100%; + border-radius: var(--radius-2); + box-shadow: var(--shadow-1); + overflow: hidden; + border-color: currentColor; + border-style: solid; + border-width: 1px; +} + +.tl-note__container .tl-text-label { + text-shadow: none; +} + +.tl-note__scrim { + position: absolute; + z-index: 1; + inset: 0px; + height: 100%; + width: 100%; + background-color: var(--color-background); + opacity: 0.28; +} + +.tl-loading { + background-color: var(--color-background); + color: var(--color-text-1); + height: 100%; + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: var(--space-2); + font-size: 14px; + font-weight: 500; + opacity: 0; + animation: fade-in 0.2s ease-in-out forwards; + animation-delay: 0.2s; +} + +@keyframes fade-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +/* -------------------- FrameShape ------------------- */ + +.tl-frame__body { + stroke-width: calc(1px * var(--tl-scale)); +} + +.tl-frame__creating { + stroke: var(--color-selected); + fill: none; +} + +.tl-frame-heading { + display: flex; + align-items: center; + position: absolute; + transform-origin: 0% 100%; + overflow: hidden; + max-width: 100%; + min-width: 32px; + height: auto; + font-size: 12px; + padding-bottom: 4px; + pointer-events: all; +} + +.tl-frame-heading-hit-area { + pointer-events: all; + /* scale from bottom left corner so we can pin it to the top left corner of the frame */ + transform-origin: 0% 100%; + display: flex; + height: 100%; + width: 100%; + align-items: center; + border-radius: var(--radius-1); + background-color: var(--color-background); +} + +.tl-frame-label { + pointer-events: all; + overflow: hidden; + text-overflow: ellipsis; + padding: var(--space-3) var(--space-3); + position: relative; + font-size: inherit; + white-space: pre; + border: 1px solid transparent; +} + +.tl-frame-label__editing { + color: transparent; + white-space: pre; + width: auto; + overflow: visible; + background-color: var(--color-panel); + border-radius: var(--radius-1); + border-color: var(--color-selected); +} + +.tl-frame-name-input { + position: absolute; + border: none; + background: none; + outline: none; + padding: var(--space-3) var(--space-3); + inset: 0px; + height: 100%; + width: 100%; + font-size: inherit; + font-family: inherit; + font-weight: inherit; + width: 100%; + color: var(--color-text-1); + border-radius: var(--radius-1); + user-select: all; + -webkit-user-select: text; + white-space: pre; + cursor: var(--tl-cursor-text); +} + +/* If mobile use 16px as font size */ +/* On iOS, font size under 16px in an input will make the page zoom into the input 🤦‍♂️ */ +/* https://css-tricks.com/16px-or-larger-text-prevents-ios-form-zoom/ */ +@media (max-width: 600px) { + .tl-frame-heading { + font-size: 16px; + } +} + +/* ------------------ iFrames Detail ----------------- */ + +.tl-embed { + border: none; + border-radius: var(--radius-2); +} + +/* -------------- Shape Error Boundary -------------- */ + +.tl-shape-error-boundary { + width: 100%; + height: 100%; + background-color: var(--color-muted-1); + border-width: calc(1px * var(--tl-scale)); + border-color: var(--color-muted-1); + border-style: solid; + border-radius: calc(var(--radius-1) * var(--tl-scale)); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: left; + position: relative; + pointer-events: all; + overflow: hidden; + padding: var(--space-2); +} + +.tl-shape-error-boundary::before { + transform: scale(var(--tl-scale)); + content: 'Error'; + font-size: 12px; + font-family: inherit; + color: var(--color-text-0); +} + +/* ----------------- Error Boundary ----------------- */ + +.tl-error-boundary { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + padding: var(--space-4); + background-color: var(--color-background); + color: var(--color-text-1); + position: absolute; + z-index: 600; +} + +.tl-error-boundary__overlay { + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + z-index: 500; + background-color: var(--color-overlay); +} + +.tl-error-boundary__content * { + user-select: all; + -webkit-user-select: text; + pointer-events: all; +} + +.tl-error-boundary__canvas { + pointer-events: none; + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + z-index: -1; +} +/* some browsers seem to have some weird interactions between stacking contexts +and pointer-events. this ::after pseudo element covers the canvas and prevents +it from receiving any pointer events or affecting the cursor. */ +.tl-error-boundary__canvas::after { + content: ' '; + display: block; + position: absolute; + inset: 0px; + height: 100%; + width: 100%; + z-index: 600; + pointer-events: all; +} + +.tl-error-boundary__content { + width: fit-content; + height: fit-content; + max-width: 100%; + width: 400px; + max-height: 100%; + background-color: var(--color-panel); + padding: 16px; + border-radius: 16px; + box-shadow: var(--shadow-2); + font-size: 14px; + font-weight: 400; + display: flex; + flex-direction: column; + overflow: auto; + z-index: 600; + gap: 12px; +} + +.tl-error-boundary__content__expanded { + width: 600px; +} + +.tl-error-boundary__content h2 { + font-size: 16px; + margin: 0px; + font-weight: 500; +} + +.tl-error-boundary__content h4 { + border: 1px solid var(--color-low-border); + margin: -6px 0 0 0; + padding: var(--space-5); + border-radius: var(--radius-2); + font-weight: normal; +} + +.tl-error-boundary__content p { + line-height: 1.5; + margin: 0px; +} + +.tl-error-boundary__content pre { + background-color: var(--color-muted-2); + margin-top: 0; + padding: var(--space-5); + border-radius: var(--radius-2); + overflow: auto; + font-size: 12px; + max-height: 320px; +} + +.tl-error-boundary__content button { + background: none; + border: none; + font-family: inherit; + font-size: 14px; + font-weight: 500; + padding: var(--space-4); + border-radius: var(--radius-3); + cursor: var(--tl-cursor-pointer); + color: inherit; + background-color: transparent; +} +.tl-error-boundary__content button:hover { + background-color: var(--color-low); +} + +.tl-error-boundary__content a { + color: var(--color-text-1); + font-weight: 500; + text-decoration: none; +} +.tl-error-boundary__content a:hover { + color: var(--color-text-1); +} + +.tl-error-boundary__content__error { + position: relative; + margin: -6px 0 0 0; +} + +.tl-error-boundary__content__error button { + position: absolute; + top: var(--space-2); + right: var(--space-2); + font-size: 12px; + padding: var(--space-2) var(--space-3); + background-color: var(--color-panel); + border-radius: var(--radius-1); +} + +.tl-error-boundary__content__actions { + display: flex; + justify-content: space-between; + gap: var(--space-4); + margin: 0px; + margin-left: -4px; +} +.tl-error-boundary__content__actions__group { + display: flex; + gap: var(--space-4); +} +.tl-error-boundary__content .tl-error-boundary__reset { + color: var(--color-warn); +} +.tl-error-boundary__content .tl-error-boundary__refresh { + background-color: var(--color-primary); + color: var(--color-selected-contrast); +} +.tl-error-boundary__content .tl-error-boundary__refresh:hover { + background-color: var(--color-primary); + opacity: 0.9; +} + +/* --------------------- Coarse --------------------- */ + +.tl-hidden { + opacity: 0; + pointer-events: none; +} + +.debug__ui-logger { + position: absolute; + top: 62px; + left: 16px; + color: #555; + font-size: 12px; + font-family: monospace; +} + +/* @tldraw/ui */ + +.tl-container { + --layer-panels: 300; + --layer-menus: 400; + --layer-overlays: 500; + --layer-toasts: 650; + --layer-cursor: 700; +} + +/* -------------------------------------------------- */ +/* UI Refresh */ +/* -------------------------------------------------- */ + +/* Button */ + +.tlui-button { + position: relative; + height: 40px; + min-width: 40px; + padding: 0px 12px; + display: flex; + align-items: center; + justify-content: center; + background-color: transparent; + border: transparent; + color: currentColor; + cursor: pointer; + pointer-events: all; + font-weight: inherit; + font-family: inherit; + text-rendering: optimizeLegibility; + font-size: 12px; + gap: 0px; + color: var(--color-text-1); +} + +.tlui-button:disabled { + color: var(--color-text-3); + text-shadow: none; + cursor: default; +} + +.tlui-button:disabled .tlui-kbd { + color: var(--color-text-3); +} + +.tlui-button > * { + position: relative; + z-index: 1; +} + +.tlui-button__label { + flex-grow: 2; + text-align: left; +} + +.tlui-button:focus-visible:not(:hover) { + outline: 1px solid var(--color-selected); + outline-offset: -4px; + border-radius: var(--radius-3); +} + +.tlui-button::after { + display: block; + content: ''; + position: absolute; + inset: 4px; + background-color: transparent; + border-radius: var(--radius-2); +} + +.tlui-button[aria-expanded='true']::after { + background-color: var(--color-muted-0); + opacity: 1; +} + +.tlui-button__icon + .tlui-button__label { + margin-left: var(--space-2); +} + +.tlui-button[data-state='hinted']::after { + background-color: var(--color-hint); + opacity: 1; +} + +.tlui-button[data-state='hinted']:not(:disabled, :focus-visible):active:after { + background: var(--color-hint); + opacity: 1; +} + +@media (hover: hover) { + .tlui-button::after { + background-color: var(--color-muted-2); + opacity: 0; + } + + .tlui-button:not(:disabled):hover::after { + opacity: 1; + } +} + +/* Low button */ + +.tlui-button__low { + border-radius: var(--radius-3); + background-color: var(--color-low); +} + +@media (hover: hover) { + .tlui-button__low::after { + background-color: var(--color-muted-2); + } +} + +/* Primary / danger buttons */ + +.tlui-button__primary { + color: var(--color-primary); +} + +.tlui-button__danger { + color: var(--color-warn); + text-shadow: none; +} + +@media (hover: hover) { + .tlui-button__primary:not(:disabled, :focus-visible):hover { + color: var(--color-primary); + } + + .tlui-button__danger:not(:disabled, :focus-visible):hover { + color: var(--color-warn); + text-shadow: none; + } +} + +/* Panel button */ + +.tlui-button__panel { + position: relative; +} + +/* Menu button */ + +.tlui-button__menu { + height: 40px; + min-height: 40px; + width: 100%; + gap: 8px; + margin: -4px 0px; +} + +.tlui-button__menu:nth-child(1) { + margin-top: 0px; +} + +.tlui-button__menu:nth-last-child(1) { + margin-bottom: 0px; +} + +@media (hover: hover) { + .tlui-button__menu::after { + inset: 4px; + border-radius: var(--radius-2); + } +} + +/* Menu checkbox button */ + +.tlui-button__checkbox { + padding-left: 8px; +} + +.tlui-button__checkbox__indicator { + width: 15px; + height: 15px; +} + +/* Tool lock button */ + +.tlui-toolbar__lock-button { + position: absolute; + top: 4px; + right: 0px; + pointer-events: all; + height: 40px; + width: 40px; + min-width: 0px; + border-radius: var(--radius-2); +} + +.tlui-toolbar__lock-button::after { + top: 4px; + left: 8px; + inset: 4px; +} + +/* Tool button */ + +.tlui-button__tool { + position: relative; + height: 48px; + width: 48px; + margin-left: -2px; + margin-right: -2px; +} + +.tlui-button__tool:nth-of-type(1) { + margin-left: 0px; +} + +.tlui-button__tool:nth-last-of-type(1) { + margin-right: 0px; +} + +@media (hover: hover) { + .tlui-button__tool::after { + inset: 4px; + border-radius: 8px; + } + + .tlui-button__tool[data-state='selected']:not(:disabled, :focus-visible):hover { + color: var(--color-selected-contrast); + } +} + +.tlui-button__tool[data-state='selected'] { + color: var(--color-selected-contrast); +} + +.tlui-button__tool[data-state='selected']:not(:disabled, :focus-visible):active { + color: var(--color-selected-contrast); +} + +.tlui-button__tool[data-state='selected']:not(:disabled)::after { + background: var(--color-selected); + opacity: 1; +} + +.tlui-layout__mobile .tlui-button__tool { + height: 48px; + width: 44px; +} + +.tlui-layout__mobile .tlui-button__tool > .tlui-icon { + height: 16px; + width: 16px; +} + +/* Help */ + +.tlui-button__help { + height: 32px; + width: 32px; + padding: 0px; + min-width: 32px; + border-radius: 100%; + background-color: var(--color-low); + border: 1px solid var(--color-low-border); +} + +@media (hover: hover) { + .tlui-button__help::after { + background-color: var(--color-muted-2); + border-radius: 100%; + inset: 4px; + } +} + +/* Button Row */ + +.tlui-buttons__horizontal { + display: flex; + flex-direction: row; +} +.tlui-buttons__horizontal > * { + margin-left: -2px; + margin-right: -2px; +} +.tlui-buttons__horizontal > *:nth-child(1) { + margin-left: 0px; +} +.tlui-buttons__horizontal > *:nth-last-child(1) { + margin-right: 0px; +} +.tlui-buttons__horizontal > *:only-child { + width: 56px; +} + +/* Button Grid */ + +.tlui-buttons__grid { + display: grid; + grid-template-columns: repeat(4, auto); + grid-auto-flow: row; + overflow: hidden; +} +.tlui-buttons__grid > .tlui-button { + margin: -2px; +} +.tlui-buttons__grid > .tlui-button:nth-of-type(4n) { + margin-right: 0px; +} +.tlui-buttons__grid > .tlui-button:nth-of-type(4n - 3) { + margin-left: 0px; +} +.tlui-buttons__grid > .tlui-button:nth-of-type(-n + 4) { + margin-top: 0px; +} +.tlui-buttons__grid > .tlui-button:nth-last-of-type(-n + 4) { + margin-bottom: 0px; +} + +/* Zoom button */ + +.tlui-zoom-menu__button__pct { + width: 60px; + min-width: 60px; + text-align: center; +} + +/* --------------------- Layout --------------------- */ + +.tlui-layout { + position: relative; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: minmax(0px, 1fr) auto; + grid-auto-rows: auto; + height: 100%; + max-height: 100%; + overflow: clip; + pointer-events: none; + user-select: none; + contain: strict; + z-index: var(--layer-panels); + -webkit-transform: translate3d(0, 0, 0); + --sab: env(safe-area-inset-bottom); +} + +.tlui-layout__top { + grid-column: 1; + grid-row: 1; + display: flex; + min-width: 0px; + justify-content: space-between; +} + +.tlui-layout__top__left { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + width: 100%; + height: 100%; + flex: 0 1 0; +} + +.tlui-layout__top__right { + display: flex; + flex-direction: column; + align-items: flex-end; + justify-content: flex-start; + height: 100%; + flex: 0 0 auto; + min-width: 0px; +} + +.scrollable, +.scrollable * { + pointer-events: all; + touch-action: auto; + overscroll-behavior: none; +} + +/* ----------------- Helper Buttons ---------------- */ + +.tlui-helper-buttons { + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + width: min-content; + gap: var(--space-3); + margin: var(--space-2) var(--space-3); + white-space: nowrap; + pointer-events: none; + z-index: var(--layer-panels); +} + +/* ---------------------- Icon ---------------------- */ + +.tlui-icon { + flex-shrink: 0; + width: 18px; + height: 18px; + background-color: currentColor; +} + +.tlui-icon__small { + width: 15px; + height: 15px; +} + +/* --------------------- Slider --------------------- */ + +.tlui-slider { + position: relative; + display: flex; + align-items: center; + user-select: none; + touch-action: none; +} + +.tlui-slider__container { + width: 100%; + padding: 0px var(--space-4); +} + +.tlui-slider__track { + position: relative; + flex-grow: 1; + height: 44px; + cursor: pointer; +} + +.tlui-slider__track::after { + display: block; + position: absolute; + top: calc(50% - 2px); + content: ''; + height: 3px; + width: 100%; + background-color: var(--color-muted-1); + border-radius: 14px; +} + +.tlui-slider__range { + position: absolute; + top: calc(50% - 2px); + left: 0px; + height: 3px; + background-color: var(--color-selected); + border-radius: 14px; +} + +.tlui-slider__thumb { + all: unset; + cursor: grab; + display: block; + width: 18px; + height: 18px; + position: relative; + top: -1px; + background-color: var(--color-panel); + border-radius: 999px; + box-shadow: inset 0px 0px 0px 2px var(--color-text-1); +} + +.tlui-slider__thumb:active { + cursor: grabbing; + box-shadow: + inset 0px 0px 0px 2px var(--color-text-1), + var(--shadow-1); +} + +.tlui-slider__thumb:focus-visible { + box-shadow: inset 0 0 0 2px var(--color-focus); +} + +/* ----------------------- Kbd ---------------------- */ + +.tlui-kbd { + font-family: inherit; + font-size: 11px; + line-height: 11px; + display: grid; + justify-items: center; + grid-auto-flow: column; + grid-template-columns: auto; + grid-auto-columns: minmax(1em, auto); + align-self: bottom; + color: var(--color-text-1); + margin-left: var(--space-4); +} + +.tlui-kbd > span { + width: 100%; + text-align: center; + display: inline; + margin: 0px; + padding: 2px; + border-radius: 2px; +} + +.tlui-kbd > span:last-child { + padding-right: 0; +} + +.tlui-kbd:not(:last-child) { + margin-right: var(--space-2); +} + +/* Focus Mode Button */ + +.tlui-focus-button { + z-index: var(--layer-panels); + pointer-events: all; +} + +/* --------------------- Popover -------------------- */ + +.tlui-popover { + position: relative; + display: flex; + align-content: stretch; +} + +.tlui-popover__content { + position: relative; + max-height: 75vh; + margin: 0px; + border: none; + border-radius: var(--radius-3); + background-color: var(--color-panel); + box-shadow: var(--shadow-3); + z-index: var(--layer-menus); + overflow: hidden; + overflow-y: auto; + touch-action: auto; + overscroll-behavior: none; + scrollbar-width: none; + -ms-overflow-style: none; +} + +/* -------------------------------------------------- */ +/* Zones */ +/* -------------------------------------------------- */ + +/* ------------------- Status Bar ------------------- */ + +.tlui-debug-panel { + background-color: var(--color-low); + width: 100%; + display: grid; + align-items: center; + grid-template-columns: 1fr auto auto auto; + justify-content: space-between; + padding-left: var(--space-4); + border-top: 1px solid var(--color-background); + font-size: 12px; + color: var(--color-text-1); + z-index: var(--layer-panels); + pointer-events: all; +} + +.tlui-debug-panel__current-state { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.tlui-debug-panel__fps { + margin-right: 8px; +} + +.tlui-debug-panel__fps__slow { + font-weight: bold; + color: var(--color-warn); +} + +/* -------------------- Menu Zone ------------------- */ + +.tlui-menu-zone { + position: relative; + z-index: var(--layer-panels); + width: fit-content; + border-right: 2px solid var(--color-background); + border-bottom: 2px solid var(--color-background); + border-bottom-right-radius: var(--radius-4); + background-color: var(--color-low); +} + +.tlui-menu-zone *[data-state='open']::after { + background: linear-gradient(180deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%); +} + +/* ------------------- Style Panel ------------------ */ + +.tlui-style-panel__wrapper { + box-shadow: var(--shadow-2); + border-radius: var(--radius-3); + pointer-events: all; + background-color: var(--color-panel); + height: fit-content; + max-height: 100%; + margin: 8px; + touch-action: auto; + overscroll-behavior: none; + overflow-y: auto; + overflow-x: hidden; + color: var(--color-text); +} + +.tlui-style-panel { + position: relative; + z-index: var(--layer-panels); + pointer-events: all; + width: 148px; + max-width: 148px; +} + +.tlui-style-panel::-webkit-scrollbar { + display: none; +} + +.tlui-style-panel .tlui-button.select { + width: 100%; +} + +.tlui-style-panel__section { + display: flex; + position: relative; + flex-direction: column; +} + +.tlui-style-panel__section:nth-of-type(n + 2):not(:last-child) { + border-bottom: 1px solid var(--color-divider); +} + +.tlui-style-panel__section:empty { + display: none; +} + +.tlui-style-panel__section__common:not(:only-child) { + margin-bottom: 7px; + border-bottom: 1px solid var(--color-divider); +} + +.tlui-style-panel__row { + display: flex; +} +/* Only really used for the alignment picker */ +.tlui-style-panel__row__extra-button { + margin-left: -2px; +} + +.tlui-style-panel__double-select-picker { + display: flex; + grid-template-columns: 1fr auto; + align-items: center; + padding-left: var(--space-4); + color: var(--color-text-1); + font-size: 12px; +} + +.tlui-style-panel__double-select-picker-label { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + flex-grow: 2; + max-width: 100%; +} + +.tlui-style-panel__section *[data-state='open']::after { + background: var(--color-muted-0); +} + +/* ---------------------- Input --------------------- */ + +.tlui-input { + background: none; + margin: 0px; + position: relative; + z-index: 1; + height: 40px; + max-height: 40px; + display: flex; + align-items: center; + justify-content: center; + font-family: inherit; + font-size: 12px; + font-weight: inherit; + color: var(--color-text-1); + padding: var(--space-4); + padding-left: 0px; + border: none; + outline: none; + text-overflow: ellipsis; + width: 100%; + user-select: all; + text-rendering: optimizeLegibility; + -webkit-user-select: auto !important; +} + +.tlui-input__wrapper { + width: 100%; + height: 44px; + display: flex; + align-items: center; + gap: var(--space-4); + color: var(--color-text); +} + +.tlui-input__wrapper > .tlui-icon { + flex-shrink: 0; +} + +/* If mobile use 16px as font size */ +/* On iOS, font size under 16px in an input will make the page zoom into the input 🤦‍♂️ */ +/* https://css-tricks.com/16px-or-larger-text-prevents-ios-form-zoom/ */ +@media (max-width: 600px) { + @supports (-webkit-touch-callout: none) { + /* CSS specific to iOS devices */ + .tlui-input { + font-size: 16px; + } + } +} + +/* ---------------- Dialog ---------------- */ + +.tlui-dialog__overlay { + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + z-index: var(--layer-overlays); + background-color: var(--color-overlay); + pointer-events: all; + animation: fadeIn 0.12s ease-out; + display: grid; + place-items: center; + overflow-y: auto; +} + +.tlui-dialog__content { + display: flex; + flex-direction: column; + position: relative; + cursor: default; + background-color: var(--color-panel); + box-shadow: var(--shadow-3); + border-radius: var(--radius-3); + font-size: 12px; + overflow: hidden; + min-width: 300px; + max-width: 80%; + max-height: 80%; +} + +.tlui-dialog__header { + position: relative; + display: flex; + align-items: center; + flex: 0; + z-index: 999; + padding-left: var(--space-4); + color: var(--color-text); + height: 44px; +} + +.tlui-dialog__header__title { + flex: 1; + font-weight: inherit; + font-size: 12px; + margin: 0px; + color: var(--color-text-1); +} + +.tlui-dialog__header__close { + justify-self: flex-end; +} + +.tlui-dialog__body { + padding: var(--space-4) var(--space-4); + flex: 0 1; + overflow-y: auto; + overflow-x: hidden; + color: var(--color-text-1); + user-select: all; + -webkit-user-select: text; +} + +.tlui-dialog__footer { + position: relative; + z-index: 999; +} + +.tlui-dialog__footer__actions { + display: flex; + align-items: center; + justify-content: flex-end; +} + +.tlui-dialog__footer__actions > .tlui-button:nth-last-child(n + 2) { + margin-right: -4px; +} + +/* --------------------- Toolbar -------------------- */ + +/* Wide container */ +.tlui-toolbar { + grid-column: 1 / span 3; + grid-row: 1; + display: flex; + align-items: center; + justify-content: center; + flex-grow: 2; + padding-bottom: calc(var(--space-3) + var(--sab)); +} + +/* Centered Content */ +.tlui-toolbar__inner { + position: relative; + width: fit-content; + display: flex; + gap: var(--space-3); + align-items: flex-end; +} + +.tlui-toolbar__left { + width: fit-content; +} + +/* Row of controls + lock button */ +.tlui-toolbar__extras { + position: relative; + z-index: 1; + width: 100%; + pointer-events: none; + top: 6px; + height: 48px; +} + +.tlui-toolbar__extras:empty { + display: none; +} + +.tlui-toolbar__extras__controls { + display: flex; + position: relative; + flex-direction: row; + z-index: 1; + background-color: var(--color-low); + border-top-left-radius: var(--radius-4); + border-top-right-radius: var(--radius-4); + border: 2px solid var(--color-background); + margin-left: 8px; + margin-right: 0px; + pointer-events: all; + width: fit-content; +} + +.tlui-toolbar__tools { + display: flex; + flex-direction: row; + background-color: var(--color-low); + border-radius: var(--radius-4); + z-index: var(--layer-panels); + pointer-events: all; + position: relative; + align-items: center; + background: var(--color-panel); + box-shadow: var(--shadow-2); +} + +.tlui-toolbar__overflow { + width: 40px; +} + +.tlui-layout__mobile .tlui-toolbar__overflow { + width: 32px; + padding: 0px; +} + +.tlui-layout__mobile .tlui-toolbar *[data-state='open']::after { + background: linear-gradient(0deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%); +} + +/* -------------------- Help Zone ------------------- */ + +.tlui-help-menu { + pointer-events: all; + position: absolute; + bottom: var(--space-2); + right: var(--space-2); + z-index: var(--layer-panels); + border: 2px solid var(--color-background); + border-radius: 100%; +} + +/* ------------------ Context Menu ------------------ */ + +.tlui-context-menu__move-to-page__name { + max-width: calc(min(300px, 35vw)); + overflow: hidden; + text-overflow: ellipsis; +} + +.tlui-context-menu__move-to-page__name[data-disabled] { + color: var(--color-text-3); + pointer-events: none; +} + +/* ---------------------- Menu ---------------------- */ + +.tlui-menu:empty { + display: none; +} + +.tlui-menu { + z-index: var(--layer-menus); + height: fit-content; + width: fit-content; + max-height: 80vh; + border-radius: var(--radius-3); + pointer-events: all; + touch-action: auto; + overflow-y: auto; + overscroll-behavior: none; + background-color: var(--color-panel); + box-shadow: var(--shadow-3); +} + +.tlui-menu::-webkit-scrollbar { + display: none; +} + +.tlui-menu__arrow { + position: relative; + top: -1px; + fill: var(--color-panel); + stroke: var(--color-panel-contrast); + stroke-width: 1px; +} + +.tlui-menu__group { + width: 100%; +} + +.tlui-menu__group:empty { + display: none; +} + +.tlui-menu__group { + border-bottom: 1px solid var(--color-divider); +} +.tlui-menu__group:nth-last-of-type(1) { + border-bottom: none; +} + +.tlui-menu__submenu__trigger[data-state='open']:not(:hover)::after { + border-radius: var(--radius-1); + background: linear-gradient(90deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%); +} + +.tlui-menu__submenu__trigger[data-direction='left'][data-state='open']:not(:hover)::after { + border-radius: var(--radius-1); + background: linear-gradient(270deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%); +} + +/* Menu Sizes */ + +.tlui-menu[data-size='large'] > .tlui-menu__group { + min-width: initial; +} + +.tlui-menu[data-size='medium'] > .tlui-menu__group { + min-width: 144px; +} + +.tlui-menu[data-size='small'] > .tlui-menu__group { + min-width: 96px; +} + +.tlui-menu[data-size='tiny'] > .tlui-menu__group { + min-width: 0px; +} + +/* ------------------ Actions Menu ------------------ */ + +.tlui-actions-menu { + max-height: calc(100vh - 150px); +} + +/* --------------------- Toasts --------------------- */ + +.tlui-toast__viewport { + position: absolute; + inset: 0px; + margin: 0px; + display: flex; + align-items: flex-end; + justify-content: flex-end; + flex-direction: column; + gap: var(--space-3); + pointer-events: none; + padding: 0px var(--space-3) 64px 0px; + z-index: var(--layer-toasts); +} + +.tlui-toast__viewport > * { + pointer-events: all; +} + +.tlui-toast__icon { + padding-top: var(--space-4); + padding-left: var(--space-4); + color: var(--color-text-1); +} + +.tlui-toast__container { + min-width: 200px; + display: flex; + flex-direction: row; + background-color: var(--color-panel); + box-shadow: var(--shadow-2); + border-radius: var(--radius-3); + font-size: 12px; +} + +.tlui-toast__main { + flex-grow: 2; + max-width: 280px; +} + +.tlui-toast__content { + padding: var(--space-4); + display: flex; + flex-direction: column; + gap: var(--space-3); +} + +.tlui-toast__title { + font-weight: bold; + color: var(--color-text-1); +} + +.tlui-toast__description { + color: var(--color-text-1); + padding: var(--space-3); + margin: 0px; + padding: 0px; +} + +.tlui-toast__icon + .tlui-toast__main > .tlui-toast__actions { + padding-left: 0px; +} + +.tlui-toast__actions { + display: flex; + flex-direction: row; + justify-content: flex-start; + margin-left: 0; +} + +.tlui-toast__close { + align-self: flex-end; + flex-shrink: 0; +} + +@media (prefers-reduced-motion: no-preference) { + .tlui-toast__container[data-state='open'] { + animation: slide-in 200ms cubic-bezier(0.785, 0.135, 0.15, 0.86); + } + + .tlui-toast__container[data-state='closed'] { + animation: hide 100ms ease-in; + } + + .tlui-toast__container[data-swipe='move'] { + transform: translateX(var(--radix-toast-swipe-move-x)); + } + + .tlui-toast__container[data-swipe='cancel'] { + transform: translateX(0); + transition: transform 200ms ease-out; + } + + .tlui-toast__container[data-swipe='end'] { + animation: swipe-out 100ms ease-out; + } +} + +/* --------------------- Bottom --------------------- */ + +.tlui-layout__bottom { + grid-row: 2; +} + +.tlui-layout__bottom__main { + width: 100%; + position: relative; + display: flex; + align-items: flex-end; + justify-content: center; +} + +/* ------------------- Navigation ------------------- */ + +.tlui-navigation-panel { + display: flex; + width: min-content; + flex-direction: column; + z-index: var(--layer-panels); + pointer-events: all; + position: absolute; + left: 0px; + bottom: 0px; +} + +.tlui-navigation-panel::before { + content: ''; + display: block; + position: absolute; + z-index: -1; + inset: -2px -2px 0px 0px; + border-radius: 0; + border-top: 2px solid var(--color-background); + border-right: 2px solid var(--color-background); + border-top-right-radius: var(--radius-4); + background-color: var(--color-low); +} + +.tlui-navigation-panel__toggle .tlui-icon { + opacity: 0.24; +} + +.tlui-navigation-panel__toggle:active .tlui-icon { + opacity: 1; +} + +@media (hover: hover) { + .tlui-navigation-panel__toggle:hover .tlui-icon { + opacity: 1; + } +} + +.tlui-minimap { + width: 100%; + height: 96px; + min-height: 96px; + overflow: hidden; + padding: var(--space-3); + padding-top: 0px; +} + +.tlui-minimap__canvas { + position: relative; + width: 100%; + height: 100%; +} + +/* ----------------------- ... ---------------------- */ + +@keyframes hide { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} + +@keyframes slide-in { + from { + transform: translateX(calc(100% + var(--space-3))); + } + to { + transform: translateX(0px); + } +} + +@keyframes swipe-out { + from { + transform: translateX(var(--radix-toast-swipe-end-x)); + } + to { + transform: translateX(calc(100% + var(--space-3))); + } +} + +/* ------------------- Page Select ------------------ */ + +.tlui-page-menu__wrapper { + position: relative; + display: flex; + flex-direction: column; + width: 220px; + height: fit-content; + max-height: 50vh; +} + +.tlui-page-menu__trigger { + width: 128px; +} + +.tlui-page-menu__header { + display: flex; + flex-direction: row; + align-items: center; + width: 100%; + height: 40px; + padding-left: var(--space-4); + border-bottom: 1px solid var(--color-divider); +} + +.tlui-page-menu__header > .tlui-button:nth-of-type(1) { + margin-right: -4px; +} + +.tlui-page-menu__header__title { + color: var(--color-text); + font-size: 12px; + flex-grow: 2; +} + +.tlui-page-menu__name { + flex-grow: 2; + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.tlui-page-menu__list { + position: relative; + touch-action: auto; + flex-direction: column; + max-height: 100%; + overflow-x: hidden; + overflow-y: auto; + touch-action: auto; +} + +.tlui-page-menu__item { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 0px; +} + +.tlui-page-menu__item:nth-of-type(n + 2) { + margin-top: -4px; +} + +.tlui-page-menu__item__button { + width: 100%; +} + +.tlui-page-menu__item__button:not(:only-child) { + flex-grow: 2; + margin-right: -2px; +} + +.tlui-page-menu__item__button > span { + display: block; + flex-grow: 2; + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.tlui-page-menu__item__button__checkbox { + padding-left: 35px; +} + +.tlui-page-menu__item__button__check { + position: absolute; + left: 0px; + width: 24px; + padding-left: 10px; + display: inline-flex; + align-items: center; + justify-content: center; + color: var(--color-text); +} + +.tlui-page_menu__item__sortable { + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: fit-content; + display: flex; + flex-direction: row; + align-items: center; + overflow: hidden; + z-index: 1; +} + +.tlui-page_menu__item__sortable__title { + flex: 1; +} + +.tlui-page_menu__item__sortable__title > .tlui-input__wrapper { + height: 100%; +} + +.tlui-page_menu__item__sortable:focus-within { + z-index: 10; +} + +.tlui-page_menu__item__sortable__handle { + touch-action: none; + width: 32px; + min-width: 0px; + height: 40px; + cursor: grab; + color: var(--color-text-3); + flex-shrink: 0; + margin-right: -9px; +} + +.tlui-page_menu__item__sortable__handle:active { + cursor: grabbing; +} + +.tlui-page-menu__item__input { + margin-left: 12px; + height: 100%; +} + +/* The more menu has complex CSS here: */ +/* If the user can hover, then visible but opacity zero until hover */ +/* If the user cannot hover, then not displayed unless editing, and then opacity 1 */ + +.tlui-page_menu__item__submenu { + pointer-events: all; + flex: 0; + cursor: pointer; + margin: 0px; + display: none; + margin-left: -2px; +} + +.tlui-page_menu__item__submenu[data-isediting='true'] { + display: block; + opacity: 1; +} + +.tlui-page_menu__item__submenu > .tlui-button { + opacity: 0; +} + +@media (any-pointer: coarse) { + .tlui-page_menu__item__submenu > .tlui-button { + opacity: 1; + } +} + +.tlui-page-menu__item__button .tlui-button__icon { + margin-right: 4px; +} + +@media (hover: hover) { + .tlui-page_menu__item__submenu { + display: block; + } + + .tlui-page_menu__item__submenu[data-isediting='true'] > .tlui-button { + opacity: 0; + } + + .tlui-page_menu__item__submenu > .tlui-button[data-state='open'], + .tlui-page_menu__item__submenu:hover > .tlui-button, + .tlui-page_menu__item__sortable:focus-within > .tlui-page_menu__item__submenu > .tlui-button { + opacity: 1; + } +} + +/* --------------------- Dialogs -------------------- */ + +/* Edit Link Dialog */ + +.tlui-edit-link-dialog { + display: flex; + flex-direction: column; + gap: var(--space-4); + color: var(--color-text); +} + +.tlui-edit-link-dialog__input { + background-color: var(--color-muted-2); + flex-grow: 2; + border-radius: var(--radius-2); + padding: 0px var(--space-4); +} + +/* Embed Dialog */ + +.tlui-embed__spacer { + flex-grow: 2; + min-height: 0px; + margin-left: calc(-1 * var(--space-4)); + margin-top: calc(-1 * var(--space-4)); + pointer-events: none; +} + +.tlui-embed-dialog__list { + display: flex; + flex-direction: column; + padding-bottom: var(--space-5); +} + +.tlui-embed-dialog__item__image { + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + background-size: contain; + background-repeat: no-repeat; + background-position: center center; +} + +.tlui-embed-dialog__enter { + display: flex; + flex-direction: column; + gap: var(--space-4); + color: var(--color-text-1); +} + +.tlui-embed-dialog__input { + background-color: var(--color-muted-2); + flex-grow: 2; + border-radius: var(--radius-2); + padding: 0px var(--space-4); +} + +.tlui-embed-dialog__warning { + color: var(--color-warn); + text-shadow: none; +} + +.tlui-embed-dialog__instruction__link { + display: flex; + gap: var(--space-1); + margin-top: var(--space-4); +} + +.tlui-embed-dialog__enter a { + color: var(--color-text-1); +} + +.tlui-following-indicator { + display: block; + position: absolute; + inset: 0px; + border-width: 2px; + border-style: solid; + z-index: var(--layer-following-indicator); + pointer-events: none; +} + +/* ---------------- Offline Indicator --------------- */ + +.tlui-offline-indicator { + display: flex; + flex-direction: row; + gap: var(--space-3); + color: var(--color-text); + background-color: var(--color-low); + border: 3px solid var(--color-background); + padding: 0px var(--space-5); + height: 42px; + align-items: center; + justify-content: center; + border-radius: 99px; + opacity: 0; + animation: fade-in; + animation-duration: 0.12s; + animation-delay: 2s; + animation-fill-mode: forwards; +} + +/* --------------- Keyboard shortcuts --------------- */ + +.tlui-shortcuts-dialog__header { + border-bottom: 1px solid var(--color-divider); +} + +.tlui-shortcuts-dialog__body { + position: relative; + columns: 3; + column-gap: var(--space-9); + pointer-events: all; + touch-action: auto; +} + +.tlui-shortcuts-dialog__body__tablet { + columns: 2; +} + +.tlui-shortcuts-dialog__body__mobile { + columns: 1; +} + +.tlui-shortcuts-dialog__group { + break-inside: avoid-column; + padding-bottom: var(--space-6); +} + +.tlui-shortcuts-dialog__group__title { + font-size: inherit; + font-weight: inherit; + margin: 0px; + color: var(--color-text-3); + height: 32px; + display: flex; + align-items: center; +} + +.tlui-shortcuts-dialog__group__content { + display: flex; + flex-direction: column; + color: var(--color-text-1); +} + +.tlui-shortcuts-dialog__key-pair { + display: flex; + gap: var(--space-4); + align-items: center; + justify-content: space-between; + height: 32px; +} + +.tlui-shortcuts-dialog__key-pair__key { + flex: 1; + font-size: 12px; +} +