From ddb73cb6cfbf6f9ae813b267da8c74993462547b Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Sat, 28 Oct 2023 22:58:32 +0100 Subject: [PATCH] Tighten up editor ui (#2102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR tightens up the editor UI. It removes padding around the editor. ![Kapture 2023-10-28 at 18 27 15](https://github.com/tldraw/tldraw/assets/23072548/18075308-7b62-43a1-8c80-ff4e4136197b) image image ### Change Type - [x] `minor` — New feature ### Release Notes - Small adjustment to editor ui. --- apps/examples/e2e/shared-e2e.ts | 1 + .../e2e/tests/export-snapshots.spec.ts | 46 +- apps/examples/e2e/tests/test-shapes.spec.ts | 17 +- apps/examples/e2e/tests/test-smoke.spec.ts | 3 +- .../src/examples/end-to-end/end-to-end.tsx | 17 +- assets/icons/icon/checkbox-empty.svg | 2 +- assets/translations/main.json | 2 +- packages/editor/editor.css | 61 +- packages/tldraw/api-report.md | 9 +- packages/tldraw/api/api.json | 22 +- packages/tldraw/src/lib/ui.css | 1141 +++++++---------- packages/tldraw/src/lib/ui/TldrawUi.tsx | 1 + .../src/lib/ui/components/ActionsMenu.tsx | 7 +- .../src/lib/ui/components/BackToContent.tsx | 1 + .../src/lib/ui/components/ContextMenu.tsx | 23 +- .../src/lib/ui/components/DebugPanel.tsx | 92 +- .../src/lib/ui/components/DuplicateButton.tsx | 1 + .../src/lib/ui/components/EditLinkDialog.tsx | 2 +- .../src/lib/ui/components/EmbedDialog.tsx | 26 +- .../lib/ui/components/FollowingIndicator.tsx | 2 +- .../tldraw/src/lib/ui/components/HelpMenu.tsx | 17 +- .../src/lib/ui/components/LanguageMenu.tsx | 2 +- .../tldraw/src/lib/ui/components/Menu.tsx | 5 +- .../tldraw/src/lib/ui/components/MenuZone.tsx | 4 +- .../lib/ui/components/MobileStylePanel.tsx | 2 +- .../src/lib/ui/components/MoveToPageMenu.tsx | 8 +- .../NavigationZone/NavigationZone.tsx | 13 +- .../ui/components/NavigationZone/ZoomMenu.tsx | 2 + .../components/PageMenu/PageItemSubmenu.tsx | 12 +- .../lib/ui/components/PageMenu/PageMenu.tsx | 14 +- .../src/lib/ui/components/PenModeToggle.tsx | 1 + .../src/lib/ui/components/RedoButton.tsx | 1 + .../src/lib/ui/components/StopFollowing.tsx | 1 + .../StylePanel/DoubleDropdownPicker.tsx | 175 ++- .../components/StylePanel/DropdownPicker.tsx | 16 +- .../ui/components/StylePanel/StylePanel.tsx | 40 +- .../tldraw/src/lib/ui/components/Toasts.tsx | 24 +- .../Toolbar/ToggleToolLockedButton.tsx | 1 + .../src/lib/ui/components/Toolbar/Toolbar.tsx | 14 +- .../src/lib/ui/components/TrashButton.tsx | 1 + .../src/lib/ui/components/UndoButton.tsx | 1 + .../lib/ui/components/primitives/Button.tsx | 8 +- .../ui/components/primitives/ButtonPicker.tsx | 13 +- .../lib/ui/components/primitives/Dialog.tsx | 6 +- .../ui/components/primitives/DropdownMenu.tsx | 32 +- .../lib/ui/components/primitives/Popover.tsx | 7 +- .../tldraw/src/lib/ui/hooks/useMenuIsOpen.ts | 4 +- .../src/lib/ui/hooks/useToastsProvider.tsx | 5 +- .../useTranslation/defaultTranslation.ts | 2 +- .../hooks/useTranslation/useTranslation.tsx | 4 + 50 files changed, 921 insertions(+), 990 deletions(-) diff --git a/apps/examples/e2e/shared-e2e.ts b/apps/examples/e2e/shared-e2e.ts index d7755945b..7926f7d37 100644 --- a/apps/examples/e2e/shared-e2e.ts +++ b/apps/examples/e2e/shared-e2e.ts @@ -38,6 +38,7 @@ export async function setupPage(page: PlaywrightTestArgs['page']) { await page.evaluate(() => { editor.user.updateUserPreferences({ animationSpeed: 0 }) }) + await page.mouse.move(50, 50) } export async function setupPageWithShapes(page: PlaywrightTestArgs['page']) { diff --git a/apps/examples/e2e/tests/export-snapshots.spec.ts b/apps/examples/e2e/tests/export-snapshots.spec.ts index cc6153421..c10b56f30 100644 --- a/apps/examples/e2e/tests/export-snapshots.spec.ts +++ b/apps/examples/e2e/tests/export-snapshots.spec.ts @@ -221,31 +221,27 @@ test.describe('Export snapshots', () => { }) async function snapshotTest(page: Page) { - const downloadEvent = page.waitForEvent('download') - await page.click('[data-testid="main.menu"]') - await page.click('[data-testid="menu-item.edit"]') - await page.click('[data-testid="menu-item.export-as"]') - await page.click('[data-testid="menu-item.export-as-svg"]') + page.waitForEvent('download').then(async (download) => { + const path = (await download.path()) as string + assert(path) + await rename(path, path + '.svg') + await writeFile( + path + '.html', + ` + + + + + `, + 'utf-8' + ) - const download = await downloadEvent - const path = (await download.path()) as string - assert(path) - await rename(path, path + '.svg') - await writeFile( - path + '.html', - ` - - - - - `, - 'utf-8' - ) - - await page.goto(`file://${path}.html`) - const clip = await page.$eval('img', (img) => img.getBoundingClientRect()) - await expect(page).toHaveScreenshot({ - omitBackground: true, - clip, + await page.goto(`file://${path}.html`) + const clip = await page.$eval('img', (img) => img.getBoundingClientRect()) + await expect(page).toHaveScreenshot({ + omitBackground: true, + clip, + }) }) + await page.evaluate(() => (window as any)['tldraw-export']()) } diff --git a/apps/examples/e2e/tests/test-shapes.spec.ts b/apps/examples/e2e/tests/test-shapes.spec.ts index 8b50a66e0..f1b00c14c 100644 --- a/apps/examples/e2e/tests/test-shapes.spec.ts +++ b/apps/examples/e2e/tests/test-shapes.spec.ts @@ -76,8 +76,14 @@ test.describe('Shape Tools', () => { if (!(await page.getByTestId(`tools.more`).isVisible())) { throw Error(`Tool more is not visible`) } - await page.getByTestId('tools.more').click() + + if (!(await page.getByTestId(`tools.more.${tool}`).isVisible())) { + throw Error(`Tool in more panel is not visible`) + } + await page.getByTestId(`tools.more.${tool}`).click() + + await page.getByTestId(`tools.more`).click() } if (!(await page.getByTestId(`tools.${tool}`).isVisible())) { @@ -106,6 +112,8 @@ test.describe('Shape Tools', () => { // Find and click the button if (!(await page.getByTestId(`tools.${tool}`).isVisible())) { await page.getByTestId('tools.more').click() + await page.getByTestId(`tools.more.${tool}`).click() + await page.getByTestId('tools.more').click() } await page.getByTestId(`tools.${tool}`).click() @@ -124,7 +132,7 @@ test.describe('Shape Tools', () => { expect(await getAllShapeTypes(page)).toEqual([shape]) // Reset for next time - await page.mouse.click(0, 0) // to ensure we're not focused + await page.mouse.click(50, 50) // to ensure we're not focused await page.keyboard.press('v') // go to the select tool await page.keyboard.press('Control+a') await page.keyboard.press('Backspace') @@ -142,7 +150,10 @@ test.describe('Shape Tools', () => { // Find and click the button if (!(await page.getByTestId(`tools.${tool}`).isVisible())) { await page.getByTestId('tools.more').click() + await page.getByTestId(`tools.more.${tool}`).click() + await page.getByTestId('tools.more').click() } + await page.getByTestId(`tools.${tool}`).click() // Button should be selected @@ -163,7 +174,7 @@ test.describe('Shape Tools', () => { expect(await getAllShapeTypes(page)).toEqual([shape]) // Reset for next time - await page.mouse.click(0, 0) // to ensure we're not focused + await page.mouse.click(50, 50) // to ensure we're not focused await page.keyboard.press('v') await page.keyboard.press('Control+a') await page.keyboard.press('Backspace') diff --git a/apps/examples/e2e/tests/test-smoke.spec.ts b/apps/examples/e2e/tests/test-smoke.spec.ts index a5c75b02b..42e138cc1 100644 --- a/apps/examples/e2e/tests/test-smoke.spec.ts +++ b/apps/examples/e2e/tests/test-smoke.spec.ts @@ -71,7 +71,8 @@ test.describe('smoke tests', () => { expect(await getSelectedShapeColor()).toBe('black') // when on a mobile device... - const hasMobileMenu = await page.isVisible('.tlui-toolbar__styles__button') + const mobileStylesButton = page.getByTestId('mobile.styles') + const hasMobileMenu = await mobileStylesButton.isVisible() if (hasMobileMenu) { // open the style menu diff --git a/apps/examples/src/examples/end-to-end/end-to-end.tsx b/apps/examples/src/examples/end-to-end/end-to-end.tsx index 98e4dabfd..22ad0d465 100644 --- a/apps/examples/src/examples/end-to-end/end-to-end.tsx +++ b/apps/examples/src/examples/end-to-end/end-to-end.tsx @@ -1,5 +1,6 @@ -import { Tldraw } from '@tldraw/tldraw' +import { Tldraw, useActions } from '@tldraw/tldraw' import '@tldraw/tldraw/tldraw.css' +import { useEffect } from 'react' ;(window as any).__tldraw_ui_event = { id: 'NOTHING_YET' } ;(window as any).__tldraw_editor_events = [] @@ -15,7 +16,19 @@ export default function EndToEnd() { onUiEvent={(name, data) => { ;(window as any).__tldraw_ui_event = { name, data } }} - /> + > + + ) } + +function SneakyExportButton() { + const actions = useActions() + + useEffect(() => { + ;(window as any)['tldraw-export'] = () => actions['export-as-svg'].onSelect('unknown') + }, [actions]) + + return null +} diff --git a/assets/icons/icon/checkbox-empty.svg b/assets/icons/icon/checkbox-empty.svg index 5ff6485cf..703836424 100644 --- a/assets/icons/icon/checkbox-empty.svg +++ b/assets/icons/icon/checkbox-empty.svg @@ -1,3 +1,3 @@ - + diff --git a/assets/translations/main.json b/assets/translations/main.json index fbcfbde27..a0c97d07a 100644 --- a/assets/translations/main.json +++ b/assets/translations/main.json @@ -295,7 +295,7 @@ "style-panel.align": "Align", "style-panel.vertical-align": "Vertical align", "style-panel.position": "Position", - "style-panel.arrowheads": "Arrowheads", + "style-panel.arrowheads": "Arrows", "style-panel.arrowhead-start": "Start", "style-panel.arrowhead-end": "End", "style-panel.color": "Color", diff --git a/packages/editor/editor.css b/packages/editor/editor.css index d30b72369..af511a198 100644 --- a/packages/editor/editor.css +++ b/packages/editor/editor.css @@ -18,12 +18,15 @@ /* Radius */ --radius-0: 2px; --radius-1: 4px; - --radius-2: 7px; + --radius-2: 6px; --radius-3: 9px; - --radius-4: 12px; - --radius-5: 16px; + --radius-4: 13px; + --layer-background: 100; --layer-grid: 150; --layer-canvas: 200; + --layer-shapes: 300; + --layer-overlays: 400; + --layer-following-indicator: 1000; /* Misc */ --tl-zoom: 1; --tl-dpr-multiple: 100; @@ -98,8 +101,10 @@ --color-brush-fill: rgba(144, 144, 144, 0.102); --color-brush-stroke: rgba(144, 144, 144, 0.251); --color-grid: rgb(109, 109, 109); - --color-low: rgb(237, 240, 242); + --color-low: hsl(204, 16%, 94%); + --color-low-border: hsl(204, 16%, 92%); --color-culled: rgb(235, 238, 240); + --color-muted-none: rgba(0, 0, 0, 0); --color-muted-0: rgba(0, 0, 0, 0.02); --color-muted-1: rgba(0, 0, 0, 0.1); --color-muted-2: rgba(0, 0, 0, 0.042); @@ -116,19 +121,19 @@ --color-selection-stroke: #2f80ed; --color-text-0: #1d1d1d; --color-text-1: #2d2d2d; - --color-text-2: #5f6369; - --color-text-3: #b6b7ba; + --color-text-3: #a4a5a7; + --color-text-shadow: #ffffff; --color-primary: #2f80ed; --color-warn: #d10b0b; --color-text: #000000; --color-laser: #ff0000; - --shadow-1: 0px 1px 2px rgba(0, 0, 0, 0.22), 0px 1px 3px rgba(0, 0, 0, 0.09); - --shadow-2: 0px 0px 2px rgba(0, 0, 0, 0.12), 0px 2px 3px rgba(0, 0, 0, 0.24), + --shadow-1: 0px 1px 2px rgba(0, 0, 0, 0.25), 0px 1px 3px rgba(0, 0, 0, 0.09); + --shadow-2: 0px 0px 2px rgba(0, 0, 0, 0.16), 0px 2px 3px rgba(0, 0, 0, 0.24), 0px 2px 6px rgba(0, 0, 0, 0.1), inset 0px 0px 0px 1px var(--color-panel-contrast); - --shadow-3: 0px 1px 2px rgba(0, 0, 0, 0.25), 0px 2px 6px rgba(0, 0, 0, 0.14), + --shadow-3: 0px 1px 2px rgba(0, 0, 0, 0.28), 0px 2px 6px rgba(0, 0, 0, 0.14), inset 0px 0px 0px 1px var(--color-panel-contrast); - --shadow-4: 0px 0px 3px rgba(0, 0, 0, 0.16), 0px 5px 4px rgba(0, 0, 0, 0.16), + --shadow-4: 0px 0px 3px rgba(0, 0, 0, 0.19), 0px 5px 4px rgba(0, 0, 0, 0.16), 0px 2px 16px rgba(0, 0, 0, 0.06), inset 0px 0px 0px 1px var(--color-panel-contrast); } @@ -139,7 +144,9 @@ --color-brush-stroke: rgba(180, 180, 180, 0.25); --color-grid: #909090; --color-low: #2c3136; - --color-culled: rgb(47, 52, 57); + --color-low-border: #30363b + --color-culled: blue; + --color-muted-none: rgba(255, 255, 255, 0); --color-muted-0: rgba(255, 255, 255, 0.02); --color-muted-1: rgba(255, 255, 255, 0.1); --color-muted-2: rgba(255, 255, 255, 0.05); @@ -156,10 +163,10 @@ --color-selection-stroke: #2f80ed; --color-text-0: #f0eded; --color-text-1: #d9d9d9; - --color-text-2: #8e9094; - --color-text-3: #515a62; + --color-text-3: #6d747b; + --color-text-shadow: #292f35; --color-primary: #2f80ed; - --color-warn: #d10b0b; + --color-warn: #ef6464; --color-text: #f8f9fa; --color-laser: #ff0000; @@ -234,12 +241,12 @@ input, .tl-shapes { position: relative; - z-index: 2; + z-index: var(--layer-shapes); } .tl-overlays { position: relative; - z-index: 3; + z-index: var(--layer-overlays); } .tl-overlays__item { @@ -275,6 +282,7 @@ input, position: absolute; background-color: var(--color-background); inset: 0px; + z-index: var(--layer-background); } /* --------------------- Grid Layer --------------------- */ @@ -287,7 +295,7 @@ input, height: 100%; touch-action: none; pointer-events: none; - z-index: 2; + z-index: var(--layer-grid); contain: strict; } @@ -586,7 +594,7 @@ input, transform-origin: top right; background-color: var(--color-background); padding: 2px 4px; - border-radius: 4px; + border-radius: var(--radius-1); } /* --------------------- Nametag -------------------- */ @@ -967,7 +975,7 @@ input, color: var(--color-text); text-overflow: ellipsis; text-decoration: none; - color: var(--color-text-2); + color: var(--color-text-1); cursor: var(--tl-cursor-pointer); } @@ -1516,17 +1524,18 @@ it from receiving any pointer events or affecting the cursor. */ width: 400px; max-height: 100%; background-color: var(--color-panel); - padding: var(--space-6); - border-radius: var(--radius-4); + padding: 16px; + border-radius: 16px; box-shadow: var(--shadow-2); font-size: 14px; font-weight: 400; display: flex; flex-direction: column; - gap: var(--space-5); overflow: auto; z-index: 600; + gap: 12px; } + .tl-error-boundary__content__expanded { width: 600px; } @@ -1549,7 +1558,7 @@ it from receiving any pointer events or affecting the cursor. */ overflow: auto; font-size: 12px; max-height: 320px; - margin: 0px; + } .tl-error-boundary__content button { @@ -1574,7 +1583,7 @@ it from receiving any pointer events or affecting the cursor. */ text-decoration: none; } .tl-error-boundary__content a:hover { - color: var(--color-text-2); + color: var(--color-text-1); } .tl-error-boundary__content__error { @@ -1594,8 +1603,8 @@ it from receiving any pointer events or affecting the cursor. */ display: flex; justify-content: space-between; gap: var(--space-4); - margin: calc(var(--space-4) * -1); - margin-top: 0px; + margin: 0px; + margin-left: -4px; } .tl-error-boundary__content__actions__group { display: flex; diff --git a/packages/tldraw/api-report.md b/packages/tldraw/api-report.md index cb6077a96..885a06cc4 100644 --- a/packages/tldraw/api-report.md +++ b/packages/tldraw/api-report.md @@ -1024,10 +1024,11 @@ export function parseTldrawJsonFile({ json, schema, }: { function RadioItem({ children, onSelect, ...rest }: DropdownMenuCheckboxItemProps): JSX.Element; // @public (undocumented) -function Root({ id, children, modal, }: { +function Root({ id, children, modal, debugOpen, }: { id: string; children: any; modal?: boolean; + debugOpen?: boolean; }): JSX.Element; // @public (undocumented) @@ -1309,7 +1310,7 @@ export interface TLUiButtonProps extends React_3.HTMLAttributes void; // (undocumented) - type: 'primary' | 'secondary' | 'warn'; + type: 'danger' | 'normal' | 'primary'; } // @public (undocumented) diff --git a/packages/tldraw/api/api.json b/packages/tldraw/api/api.json index 3309cb487..dadb4a2a8 100644 --- a/packages/tldraw/api/api.json +++ b/packages/tldraw/api/api.json @@ -4137,11 +4137,11 @@ "excerptTokens": [ { "kind": "Content", - "text": "export declare function Root({ id, children, modal, }: " + "text": "export declare function Root({ id, children, modal, debugOpen, }: " }, { "kind": "Content", - "text": "{\n id: string;\n children: any;\n modal?: boolean;\n}" + "text": "{\n id: string;\n children: any;\n modal?: boolean;\n debugOpen?: boolean;\n}" }, { "kind": "Content", @@ -4166,7 +4166,7 @@ "overloadIndex": 1, "parameters": [ { - "parameterName": "{ id, children, modal, }", + "parameterName": "{ id, children, modal, debugOpen, }", "parameterTypeTokenRange": { "startIndex": 1, "endIndex": 2 @@ -14545,11 +14545,11 @@ "excerptTokens": [ { "kind": "Content", - "text": "type?: " + "text": "type: " }, { "kind": "Content", - "text": "'danger' | 'normal' | 'primary'" + "text": "'danger' | 'help' | 'icon' | 'low' | 'menu' | 'normal' | 'primary' | 'tool'" }, { "kind": "Content", @@ -14557,7 +14557,7 @@ } ], "isReadonly": false, - "isOptional": true, + "isOptional": false, "releaseTag": "Public", "name": "type", "propertyTypeTokenRange": { @@ -14583,7 +14583,7 @@ "text": "export interface TLUiContextMenuProps " } ], - "fileUrlPath": "packages/tldraw/.tsbuild-api/lib/ui/components/ContextMenu.d.ts", + "fileUrlPath": "packages/tldraw/src/lib/ui/components/ContextMenu.tsx", "releaseTag": "Public", "name": "TLUiContextMenuProps", "preserveMemberOrder": false, @@ -14606,7 +14606,6 @@ "text": ";" } ], - "fileUrlPath": "packages/tldraw/src/lib/ui/components/ContextMenu.tsx", "isReadonly": false, "isOptional": false, "releaseTag": "Public", @@ -16746,8 +16745,9 @@ "text": "icon?: " }, { - "kind": "Content", - "text": "string" + "kind": "Reference", + "text": "TLUiIconType", + "canonicalReference": "@tldraw/tldraw!TLUiIconType:type" }, { "kind": "Content", @@ -16927,7 +16927,7 @@ }, { "kind": "Content", - "text": "'primary' | 'secondary' | 'warn'" + "text": "'danger' | 'normal' | 'primary'" }, { "kind": "Content", diff --git a/packages/tldraw/src/lib/ui.css b/packages/tldraw/src/lib/ui.css index 673d90dfd..65f5bf80d 100644 --- a/packages/tldraw/src/lib/ui.css +++ b/packages/tldraw/src/lib/ui.css @@ -8,6 +8,353 @@ --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); + text-shadow: 1px 1px var(--color-text-shadow); +} + +.tlui-button:disabled { + color: var(--color-text-3); + text-shadow: none; +} + +.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; +} + +@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; +} + +/* Icon button */ + +.tlui-button__icon { + height: 40px; + width: 40px; + min-height: 40px; + min-width: 40px; + padding: 0px; +} + +/* Hinted */ + +.tlui-button__icon[data-state='hinted']::after { + background: var(--color-hint); + opacity: 1; + /* box-shadow: inset 0 0 0 1px var(--color-muted-1); */ +} + +.tlui-button__icon[data-state='hinted']:not(:disabled, :focus-visible):active::after { + background: var(--color-hint); + opacity: 1; + /* box-shadow: inset 0 0 0 1px var(--color-text-3); */ +} + +@media (hover: hover) { + .tlui-button__icon::after { + inset: 4px; + border-radius: var(--radius-2); + } + + .tlui-button__icon[data-state='hinted']:not(:disabled, :focus-visible):hover::after { + background: var(--color-hint); + /* box-shadow: inset 0 0 0 1px var(--color-text-3); */ + } +} + +/* Menu button */ + +.tlui-button__menu { + height: 40px; + min-height: 40px; + min-width: 128px; + 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; +} + +/* 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; + } +} + +/* Icon */ + +.tlui-button__icon-left { + margin-right: var(--space-4); +} + +/* 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; +} + +/* Button Grid */ + +.tlui-buttons__grid { + display: grid; + grid-template-columns: repeat(4, auto); + grid-auto-flow: row; +} +.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; +} + +@media (max-width: 640px) { + .tlui-button__tool { + height: 48px; + width: 44px; + } + + .tlui-button__tool > .tlui-icon { + height: 16px; + width: 16px; + } + + .tlui-kbd { + visibility: hidden; + } + + .tlui-menu__group .tlui-button__icon-left { + display: none; + } +} + /* --------------------- Layout --------------------- */ .tlui-layout { @@ -19,7 +366,6 @@ height: 100%; max-height: 100%; overflow: clip; - padding: var(--space-2); pointer-events: none; user-select: none; contain: strict; @@ -73,18 +419,12 @@ align-items: flex-start; width: min-content; gap: var(--space-3); - margin: var(--space-3) var(--space-2); + margin: var(--space-2) var(--space-3); white-space: nowrap; pointer-events: none; z-index: var(--layer-panels); } -.tlui-helper-buttons > .tlui-button { - pointer-events: all; - background-color: var(--color-low); - border-radius: var(--radius-3); -} - /* ---------------------- Icon ---------------------- */ .tlui-icon { @@ -110,7 +450,7 @@ } .tlui-slider__container { - width: 164px; + width: 100%; padding: 0px var(--space-4); } @@ -129,7 +469,7 @@ height: 3px; width: 100%; background-color: var(--color-muted-1); - border-radius: var(--radius-4); + border-radius: 14px; } .tlui-slider__range { @@ -138,7 +478,7 @@ left: 0px; height: 3px; background-color: var(--color-selected); - border-radius: var(--radius-4); + border-radius: 14px; } .tlui-slider__thumb { @@ -151,12 +491,12 @@ top: -1px; background-color: var(--color-panel); border-radius: 999px; - box-shadow: inset 0px 0px 0px 2px var(--color-text-2); + 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-2), var(--shadow-1); + box-shadow: inset 0px 0px 0px 2px var(--color-text-1), var(--shadow-1); } .tlui-slider__thumb:focus-visible { @@ -176,7 +516,7 @@ grid-auto-columns: minmax(1em, auto); gap: 1px; align-self: bottom; - color: var(--color-text-2); + color: var(--color-text-1); margin-left: var(--space-4); } @@ -193,167 +533,6 @@ margin-right: var(--space-2); } -/* --------------------- Button --------------------- */ - -.tlui-button { - margin: 0px; - position: relative; - z-index: 1; - height: 44px; - display: flex; - align-items: center; - justify-content: center; - font-family: inherit; - font-size: 12px; - font-weight: inherit; - color: var(--color-text-1); - padding: 0px 13px; - cursor: pointer; - border: none; - outline: none; - user-select: none; - white-space: nowrap; - overflow: hidden; - background: transparent; - text-shadow: 1px 1px 0px var(--color-panel); -} - -.tlui-button::after { - content: ''; - z-index: 1; - position: absolute; - right: 4px; - bottom: 4px; - display: block; - width: calc(100% - 8px); - height: calc(100% - 8px); - border-radius: var(--radius-3); - background-color: transparent; - pointer-events: none; -} - -.tlui-button > span { - text-overflow: ellipsis; - overflow: hidden; - display: flex; - align-items: center; -} - -.tlui-button > span:not(:only-child) { - flex-grow: 2; -} - -.tlui-button > span > svg { - margin-left: var(--space-2); -} - -.tlui-button:disabled { - cursor: default; - color: var(--color-text-3); -} - -.tlui-button:not([data-state='selected'], :disabled):active::after { - background: var(--color-muted-2); -} - -@media (hover: hover) { - .tlui-button:not([data-state='selected'], :disabled):hover::after { - background: var(--color-muted-2); - } -} - -.tlui-icon-left { - margin-right: var(--space-4); -} - -.tlui-button > * { - position: relative; - z-index: 100; - color: inherit; -} - -.tlui-button > svg { - width: 18px; - height: 18px; - pointer-events: none; -} - -.tlui-button:not(:disabled, :focus-visible, [data-state='open']):active { - z-index: 2; - color: var(--color-text-0); -} - -.tlui-button:not(:hover, :disabled, [data-state='open']):focus-visible::after { - box-shadow: inset 0 0 0 2px var(--color-focus); -} - -.tlui-button[data-state='selected']:not(:hover, :disabled):focus-visible::after { - box-shadow: inset 0 0 0 2px var(--color-focus); -} - -@media (hover: hover) { - .tlui-button:not(:disabled, :focus-visible):hover { - z-index: 2; - color: var(--color-text-0); - } - - /* - .tlui-button:not(:disabled, :focus-visible):hover::after { - box-shadow: inset 0 0 0 1px var(--color-muted-1); - } */ - - .tlui-button__primary:not(:disabled, :focus-visible):hover { - color: var(--color-primary); - } - - .tlui-button__warning:not(:disabled, :focus-visible):hover { - color: var(--color-warn); - } -} - -.tlui-button:disabled { - color: var(--color-text-3); -} - -/* Selected */ - -.tlui-button[data-state='selected'] { - color: var(--color-selected-contrast); -} - -.tlui-button[data-state='selected']:not(:disabled, :focus-visible):active { - color: var(--color-selected-contrast); -} - -@media (hover: hover) { - .tlui-button[data-state='selected']:not(:disabled, :focus-visible):hover { - color: var(--color-selected-contrast); - } -} - -.tlui-button[data-state='selected']:not(:disabled)::after { - background: var(--color-selected); -} - -/* Hinted */ - -.tlui-button[data-state='hinted']::after { - background: var(--color-hint); - /* box-shadow: inset 0 0 0 1px var(--color-muted-1); */ -} - -.tlui-button[data-state='hinted']:not(:disabled, :focus-visible):active::after { - background: var(--color-hint); - /* box-shadow: inset 0 0 0 1px var(--color-text-3); */ -} - -@media (hover: hover) { - .tlui-button[data-state='hinted']:not(:disabled, :focus-visible):hover::after { - background: var(--color-hint); - /* box-shadow: inset 0 0 0 1px var(--color-text-3); */ - } -} - /* Focus Mode Button */ .tlui-focus-button { @@ -361,30 +540,6 @@ pointer-events: all; } -/* Squished */ - -.tlui-button.squished { - height: 36px; - width: 44px; -} - -.tlui-button.squished { - height: 36px; - width: 44px; -} - -.tlui-button__primary { - color: var(--color-primary); -} - -.tlui-button__warning { - color: var(--color-warn); -} - -.tlui-button__danger { - color: var(--color-warn); -} - /* --------------------- Popover -------------------- */ .tlui-popover { @@ -398,7 +553,7 @@ max-height: 75vh; margin: 0px; border: none; - border-radius: var(--radius-4); + border-radius: var(--radius-3); background-color: var(--color-panel); box-shadow: var(--shadow-3); z-index: var(--layer-menus); @@ -417,7 +572,6 @@ /* ------------------- Status Bar ------------------- */ .tlui-debug-panel { - margin-top: var(--space-2); background-color: var(--color-low); width: 100%; display: grid; @@ -425,7 +579,7 @@ grid-template-columns: 1fr auto auto; justify-content: space-between; padding-left: var(--space-4); - border-radius: var(--radius-1); + border-top: 1px solid var(--color-background); font-size: 12px; color: var(--color-text-1); z-index: var(--layer-panels); @@ -442,17 +596,9 @@ position: relative; z-index: var(--layer-panels); width: fit-content; -} - -.tlui-menu-zone::before { - content: ''; - display: block; - position: absolute; - top: 0px; - left: 0px; - inset: -4px; - border: 4px solid var(--color-background); - border-radius: var(--radius-1) var(--radius-1) var(--radius-5) var(--radius-1); + border-right: 4px solid var(--color-background); + border-bottom: 4px solid var(--color-background); + border-bottom-right-radius: var(--radius-4); background-color: var(--color-low); } @@ -460,61 +606,20 @@ background: linear-gradient(180deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%); } -.tlui-menu-zone__controls { - position: relative; - display: flex; - align-items: center; - grid-row: 1; - grid-column: 1; - width: fit-content; - border-radius: var(--radius-1) var(--radius-1) var(--radius-4) var(--radius-1); - display: flex; - flex-direction: row; - z-index: var(--layer-panels); - pointer-events: all; -} - -.tlui-menu-zone__divider { - width: 1px; - height: 18px; - background-color: var(--color-muted-1); -} - -.tlui-menu-zone__controls > * { - margin: 0px -2px; -} - -.tlui-menu-zone__controls > *:first-child { - margin-left: 0px; -} - -.tlui-menu-zone__controls > *:last-child { - margin-right: 0px; -} - -.tlui-menu-zone__controls > .tlui-menu-zone__divider { - margin: 0px; -} - -.tlui-menu-zone__controls .tlui-icon { - width: 15px; - height: 15px; -} - /* ------------------- Style Panel ------------------ */ .tlui-style-panel__wrapper { box-shadow: var(--shadow-2); - border-radius: var(--radius-4); + border-radius: var(--radius-3); pointer-events: all; background-color: var(--color-panel); height: fit-content; max-height: 100%; - margin: var(--space-2) var(--space-2); - overflow: hidden; + margin: var(--space-3); touch-action: auto; overscroll-behavior: none; overflow-y: auto; + overflow-x: hidden; color: var(--color-text); } @@ -522,6 +627,8 @@ position: relative; z-index: var(--layer-panels); pointer-events: all; + width: 148px; + max-width: 148px; } .tlui-style-panel::-webkit-scrollbar { @@ -554,29 +661,31 @@ .tlui-style-panel__row { display: flex; } -.tlui-style-panel__row > *:nth-child(2) { - margin-left: -4px; +/* Only really used for the alignment picker */ +.tlui-style-panel__row__extra-button { + margin-left: -2px; +} + +.tlui-style-panel__double-select-picker__wrapper { + width: 100%; + max-width: 100%; } .tlui-style-panel__double-select-picker { - display: grid; - grid-template-columns: 1fr auto auto; + display: flex; + grid-template-columns: 1fr auto; align-items: center; padding-left: var(--space-4); + color: var(--color-text-1); font-size: 12px; - width: 164px; -} - -.tlui-style-panel__double-select-picker > .tlui-button { - min-width: 44px; - margin-left: -4px; } .tlui-style-panel__double-select-picker-label { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; - color: var(--color-text-1); + flex-grow: 2; + max-width: 100%; } .tlui-style-panel__section *[data-state='open']::after { @@ -590,8 +699,8 @@ margin: 0px; position: relative; z-index: 1; - height: 44px; - max-height: 44px; + height: 40px; + max-height: 40px; display: flex; align-items: center; justify-content: center; @@ -599,13 +708,14 @@ font-size: 12px; font-weight: inherit; color: var(--color-text-1); - padding: 13px; + 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; } @@ -708,7 +818,7 @@ cursor: default; background-color: var(--color-panel); box-shadow: var(--shadow-3); - border-radius: var(--radius-4); + border-radius: var(--radius-3); font-size: 12px; overflow: hidden; min-width: 300px; @@ -733,7 +843,6 @@ font-size: 12px; margin: 0px; color: var(--color-text-1); - font-weight: 500; } .tlui-dialog__header__close { @@ -741,7 +850,7 @@ } .tlui-dialog__body { - padding: var(--space-4) var(--space-6); + padding: var(--space-4) var(--space-4); flex: 0 1; overflow-y: auto; overflow-x: hidden; @@ -765,84 +874,6 @@ margin-right: -4px; } -.tlui-dialog__scrim { - display: block; - content: ''; - bottom: 0px; - width: 100%; - height: 40px; - position: absolute; - background: linear-gradient(transparent, var(--color-panel)); - border-bottom-left-radius: var(--radius-4); - border-bottom-right-radius: var(--radius-4); - pointer-events: none; -} - -/* ---------------- Shortcuts ---------------- */ - -.tlui-shortcuts-dialog__header { - border-bottom: 1px solid var(--color-divider); -} - -.tlui-shortcuts-dialog__body { - position: relative; - columns: 1; - column-gap: var(--space-9); - pointer-events: all; - touch-action: auto; -} - -@media (min-width: 475px) { - .tlui-shortcuts-dialog__body { - columns: 2; - column-gap: var(--space-9); - } -} - -@media (min-width: 960px) { - .tlui-shortcuts-dialog__body { - columns: 3; - column-gap: var(--space-9); - } -} - -.tlui-shortcuts-dialog__group { - break-inside: avoid-column; - padding-bottom: var(--space-6); -} - -.tlui-shortcuts-dialog__group__title { - font-size: inherit; - font-weight: 500; - margin: 0px; - color: var(--color-text-2); - letter-spacing: 0.5px; - text-transform: uppercase; - font-size: 9px; - 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; -} - /* --------------------- Toolbar -------------------- */ /* Wide container */ @@ -853,7 +884,7 @@ align-items: center; justify-content: center; flex-grow: 2; - padding-bottom: calc(var(--space-2) + var(--sab)); + padding-bottom: calc(var(--space-3) + var(--sab)); } /* Centered Content */ @@ -872,81 +903,32 @@ /* Row of controls + lock button */ .tlui-toolbar__extras { position: relative; + z-index: 1; width: 100%; - height: 44px; pointer-events: none; -} - -.tlui-toolbar__extras__hidden { - display: none; + top: 4px; } .tlui-toolbar__extras__controls { display: flex; - flex-direction: row; - background-color: var(--color-low); - border-top-left-radius: var(--radius-3); - border-top-right-radius: var(--radius-3); position: relative; - bottom: -4px; + 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: 4px solid var(--color-background); margin-left: 8px; margin-right: 0px; pointer-events: all; width: fit-content; } -.tlui-toolbar__extras__controls::before { - content: ''; - display: block; - position: absolute; - z-index: -1; - top: 0px; - left: 0px; - inset: -4px; - border: 4px solid var(--color-background); - border-radius: var(--radius-4); - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; - background-color: var(--color-background); -} - -.tlui-toolbar__extras__controls > .tlui-button, -.tlui-toolbar__extras__controls > .tlui-popover > .tlui-button { - height: 40px; - width: 40px; -} - -.tlui-toolbar__extras__controls .tlui-button::after { - border-radius: var(--radius-2); -} - -.tlui-toolbar__lock-button { - position: absolute; - top: 0px; - right: 0px; - pointer-events: all; - height: 40px; - width: 48px; - right: -4px; -} - -.tlui-toolbar__lock-button::after { - border-radius: 100%; - top: 4px; - left: 8px; - height: 32px; - width: 32px; -} - -.tlui-toolbar__lock-button__mobile { - right: -8px; -} - .tlui-toolbar__tools { display: flex; flex-direction: row; background-color: var(--color-low); - border-radius: var(--radius-4); + border-radius: 11px; z-index: var(--layer-panels); pointer-events: all; position: relative; @@ -955,62 +937,21 @@ box-shadow: var(--shadow-2); } -.tlui-toolbar__tools__button { - height: 48px; - width: 48px; -} - -.tlui-toolbar__tools__button:nth-of-type(n + 2) { - margin-left: -2px; -} - -.tlui-toolbar__tools__button:nth-last-of-type(n + 2) { - margin-right: -2px; -} - -.tlui-toolbar__tools__button { - height: 48px; - width: 48px; -} - -.tlui-layout__mobile .tlui-toolbar__tools__button { - height: 48px; - width: 44px; -} - -.tlui-layout__mobile .tlui-toolbar__tools__button > .tlui-icon { - height: 16px; - width: 16px; -} - .tlui-toolbar__overflow { width: 40px; } -.tlui-layout__mobile .tlui-toolbar__overflow { - width: 32px; - padding: 0px; +@media (max-width: 640px) { + .tlui-toolbar__overflow { + width: 32px; + padding: 0px; + } + + .tlui-toolbar *[data-state='open']::after { + background: linear-gradient(0deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%); + } } -.tlui-toolbar *[data-state='open']::after { - background: linear-gradient(0deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%); -} - -.tlui-toolbar__styles__button { - width: 44px; - height: 44px; -} - -.tlui-layout__mobile .tlui-toolbar__styles__button { - height: 48px; -} - -.tlui-toolbar__divider { - display: block; - background: var(--color-divider); - height: 18px; - width: 1px; -} /* -------------------- Help Zone ------------------- */ .tlui-help-menu { @@ -1018,25 +959,8 @@ position: absolute; bottom: var(--space-2); right: var(--space-2); -} - -.tlui-help-menu__button { - position: relative; - background-color: var(--color-low); - border-radius: 100%; - height: 48px; - width: 48px; - overflow: visible; z-index: var(--layer-panels); border: 4px solid var(--color-background); - display: flex; - align-items: center; - justify-content: center; - pointer-events: all; - z-index: 1; -} - -.tlui-help-menu__button::after { border-radius: 100%; } @@ -1060,7 +984,7 @@ height: fit-content; width: fit-content; max-height: 80vh; - border-radius: var(--radius-4); + border-radius: var(--radius-3); pointer-events: all; touch-action: auto; overflow-y: auto; @@ -1111,102 +1035,6 @@ background: linear-gradient(270deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%); } -.tlui-menu__button { - width: 100%; - justify-content: space-between; -} - -.tlui-menu__button__wide { - max-width: initial; -} - -.tlui-menu__button:nth-child(n + 2) { - margin-top: -8px; -} - -.tlui-menu__button:nth-last-child(n + 2) { - margin-bottom: -8px; -} - -.tlui-menu__button > span:only-child { - text-align: left; - flex-grow: 2; -} - -.tlui-menu__checkbox-item { - padding-left: 28px; -} - -.tlui-menu__checkbox-item__check { - position: absolute; - left: 0px; - width: 24px; - padding-left: 10px; - display: inline-flex; - align-items: center; - justify-content: center; -} - -/* ------------------- Button Grid ------------------ */ - -.tlui-button-grid__button { - width: 44px; - height: 44px; -} - -.tlui-button-grid__four { - display: grid; - grid-template-columns: 40px 40px 40px 44px; -} - -.tlui-button-grid__four > .tlui-button-grid__button:nth-child(n + 5) { - margin-top: -2px; -} - -.tlui-button-grid__four > .tlui-button-grid__button:nth-last-child(n + 5) { - margin-bottom: -2px; -} - -.tlui-button-grid__three { - display: grid; - grid-template-columns: 40px 40px 44px; -} - -.tlui-button-grid__three > .tlui-button-grid__button:nth-child(n + 4) { - margin-top: -2px; -} - -.tlui-button-grid__three > .tlui-button-grid__button:nth-last-child(n + 4) { - margin-bottom: -2px; -} - -.tlui-button-grid__two { - display: grid; - grid-template-columns: 40px 44px; -} - -.tlui-button-grid__two > .tlui-button-grid__button:nth-child(n + 3) { - margin-top: -2px; -} - -.tlui-button-grid__two > .tlui-button-grid__button:nth-last-child(n + 3) { - margin-bottom: -2px; -} - -/* -.tlui-button-grid__button:not(:nth-child(4n - 3)) { - margin-left: -2px; -} - -.tlui-button-grid__button:not(:nth-child(4n)) { - margin-right: -2px; -}*/ -/* - -.tlui-button-grid__button:nth-last-child(1) { - margin-right: 0px; -} */ - /* ------------------ Actions Menu ------------------ */ .tlui-actions-menu { @@ -1236,22 +1064,23 @@ .tlui-toast__icon { padding-top: var(--space-4); padding-left: var(--space-4); + color: var(--color-text-1); } .tlui-toast__container { min-width: 200px; - max-width: 280px; display: flex; flex-direction: row; gap: var(--space-3); background-color: var(--color-panel); box-shadow: var(--shadow-2); - border-radius: var(--radius-4); + border-radius: var(--radius-3); font-size: 12px; } .tlui-toast__main { flex-grow: 2; + max-width: 280px; } .tlui-toast__main:nth-child(1) > .tlui-toast__content { @@ -1272,8 +1101,8 @@ } .tlui-toast__title { - font-weight: 600; - color: var(--color-text); + font-weight: inherit; + color: var(--color-text-1); } .tlui-toast__description { @@ -1287,10 +1116,12 @@ display: flex; flex-direction: row; justify-content: flex-start; + margin-left: -12px; } .tlui-toast__close { align-self: flex-end; + flex-shrink: 0; } @media (prefers-reduced-motion: no-preference) { @@ -1316,22 +1147,6 @@ } } -/* --------------------- Mobile --------------------- */ - -@media (max-width: 640px) { - .tlui-menu__group .tlui-button { - height: 40px; - } - - .tlui-menu__group .tlui-button > .tlui-kbd { - display: none; - } - - .tlui-menu__group .tlui-button > .tlui-icon-left { - display: none; - } -} - /* --------------------- Bottom --------------------- */ .tlui-layout__bottom { @@ -1352,7 +1167,6 @@ display: flex; width: min-content; flex-direction: column; - background-color: var(--color-low); z-index: var(--layer-panels); pointer-events: all; position: absolute; @@ -1365,47 +1179,25 @@ display: block; position: absolute; z-index: -1; - inset: -4px; - border: 4px solid var(--color-background); - border-radius: var(--radius-1); - border-top-right-radius: var(--radius-5); + inset: -4px -4px 0px 0px; + border-radius: 0; + border-top: 4px solid var(--color-background); + border-right: 4px solid var(--color-background); + border-top-right-radius: var(--radius-4); background-color: var(--color-low); } -.tlui-navigation-zone__controls { - display: flex; - flex-direction: row; - width: min-content; - background-color: none; - overflow: hidden; -} - -.tlui-navigation-zone__controls > .tlui-button { - margin-left: -2px; - margin-right: -2px; -} - -.tlui-navigation-zone__controls > .tlui-button:nth-of-type(1) { - margin-left: 0px; -} -.tlui-navigation-zone__controls > .tlui-button:nth-last-of-type(1) { - margin-right: 0px; -} - .tlui-navigation-zone__toggle .tlui-icon { opacity: 0.24; - transition: opacity 0.2s ease-in-out; } .tlui-navigation-zone__toggle:active .tlui-icon { opacity: 1; - transition: opacity 0.12s ease-in-out; } @media (hover: hover) { .tlui-navigation-zone__toggle:hover .tlui-icon { opacity: 1; - transition: opacity 0.12s ease-in-out; } } @@ -1424,11 +1216,6 @@ height: 100%; } -.tlui-zoom-menu__button__pct { - width: 60px; - text-align: center; -} - /* ----------------------- ... ---------------------- */ @keyframes hide { @@ -1484,7 +1271,6 @@ align-items: center; width: 100%; padding-left: var(--space-4); - min-height: 44px; border-bottom: 1px solid var(--color-divider); } @@ -1495,7 +1281,6 @@ .tlui-page-menu__header__title { color: var(--color-text); font-size: 12px; - font-weight: 500; flex-grow: 2; } @@ -1522,14 +1307,16 @@ 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 { +.tlui-page-menu__item__button:not(:only-child) { flex-grow: 2; + margin-right: -2px; } .tlui-page-menu__item__button > span { @@ -1577,10 +1364,6 @@ height: 100%; } -.tlui-page_menu__item__sortable__button { - flex: 0; -} - .tlui-page_menu__item__sortable:focus-within { z-index: 10; } @@ -1588,6 +1371,7 @@ .tlui-page_menu__item__sortable__handle { touch-action: none; width: 32px; + min-width: 0px; height: 40px; cursor: grab; color: var(--color-text-3); @@ -1600,7 +1384,7 @@ } .tlui-page-menu__item__input { - margin-left: 13px; + margin-left: 12px; height: 100%; } @@ -1608,12 +1392,17 @@ /* 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__button + .tlui-page_menu__item__submenu { + background-color: red; +} + .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'] { @@ -1675,8 +1464,9 @@ display: flex; text-align: left; gap: var(--space-3); + margin: 0px -8px; cursor: pointer; - padding: 0; + padding: 0px 4px; align-items: center; color: var(--color-text); font-size: var(--font-size-1); @@ -1684,21 +1474,17 @@ } @media (hover: hover) { - .tlui-embed-dialog__item:hover::after { + .tlui-embed-dialog__item:not(:disabled, :focus-visible):hover::after { display: block; content: ''; position: absolute; - inset: 0px; + inset: 4px; background-color: var(--color-muted-2); - border-radius: var(--radius-4); + border-radius: var(--radius-1); } } .tlui-embed-dialog__item__image { - padding: var(--space-3); -} - -.tlui-embed-dialog__item__image__img { width: 24px; height: 24px; display: flex; @@ -1725,6 +1511,7 @@ .tlui-embed-dialog__warning { color: var(--color-warn); + text-shadow: none; } .tlui-embed-dialog__instruction__link { @@ -1737,13 +1524,13 @@ color: var(--color-text-1); } -.tlui-following { +.tlui-following-indicator { display: block; position: absolute; inset: 0px; border-width: 2px; border-style: solid; - z-index: 9999999; + z-index: var(--layer-following-indicator); pointer-events: none; } @@ -1767,3 +1554,65 @@ 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: 1; + column-gap: var(--space-9); + pointer-events: all; + touch-action: auto; +} + +@media (min-width: 475px) { + .tlui-shortcuts-dialog__body { + columns: 2; + column-gap: var(--space-9); + } +} + +@media (min-width: 960px) { + .tlui-shortcuts-dialog__body { + columns: 3; + column-gap: var(--space-9); + } +} + +.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; +} diff --git a/packages/tldraw/src/lib/ui/TldrawUi.tsx b/packages/tldraw/src/lib/ui/TldrawUi.tsx index fd2bbb207..e1c6b497c 100644 --- a/packages/tldraw/src/lib/ui/TldrawUi.tsx +++ b/packages/tldraw/src/lib/ui/TldrawUi.tsx @@ -141,6 +141,7 @@ const TldrawUiContent = React.memo(function TldrawUI({ {isFocusMode ? (
)} - + diff --git a/packages/tldraw/src/lib/ui/components/DuplicateButton.tsx b/packages/tldraw/src/lib/ui/components/DuplicateButton.tsx index 36334734e..f3c026bfc 100644 --- a/packages/tldraw/src/lib/ui/components/DuplicateButton.tsx +++ b/packages/tldraw/src/lib/ui/components/DuplicateButton.tsx @@ -13,6 +13,7 @@ export const DuplicateButton = track(function DuplicateButton() { return (
- {isRemoving ? ( diff --git a/packages/tldraw/src/lib/ui/components/EmbedDialog.tsx b/packages/tldraw/src/lib/ui/components/EmbedDialog.tsx index 4c0d1d7ee..dc751b80f 100644 --- a/packages/tldraw/src/lib/ui/components/EmbedDialog.tsx +++ b/packages/tldraw/src/lib/ui/components/EmbedDialog.tsx @@ -3,7 +3,7 @@ import { useRef, useState } from 'react' import { TLEmbedResult, getEmbedInfo } from '../../utils/embeds' import { useAssetUrls } from '../hooks/useAssetUrls' import { TLUiDialogProps } from '../hooks/useDialogsProvider' -import { useTranslation } from '../hooks/useTranslation/useTranslation' +import { untranslated, useTranslation } from '../hooks/useTranslation/useTranslation' import { Button } from './primitives/Button' import * as Dialog from './primitives/Dialog' import { Icon } from './primitives/Icon' @@ -88,6 +88,7 @@ export const EmbedDialog = track(function EmbedDialog({ onClose }: TLUiDialogPro +
+ ) })} -
)} diff --git a/packages/tldraw/src/lib/ui/components/FollowingIndicator.tsx b/packages/tldraw/src/lib/ui/components/FollowingIndicator.tsx index 5db2b9699..d197b5058 100644 --- a/packages/tldraw/src/lib/ui/components/FollowingIndicator.tsx +++ b/packages/tldraw/src/lib/ui/components/FollowingIndicator.tsx @@ -10,5 +10,5 @@ export function FollowingIndicator() { function FollowingIndicatorInner({ userId }: { userId: string }) { const presence = usePresence(userId) if (!presence) return null - return
+ return
} diff --git a/packages/tldraw/src/lib/ui/components/HelpMenu.tsx b/packages/tldraw/src/lib/ui/components/HelpMenu.tsx index f3c6edb0d..1d1e0137e 100644 --- a/packages/tldraw/src/lib/ui/components/HelpMenu.tsx +++ b/packages/tldraw/src/lib/ui/components/HelpMenu.tsx @@ -9,8 +9,8 @@ import { TLUiTranslationKey } from '../hooks/useTranslation/TLUiTranslationKey' import { useTranslation } from '../hooks/useTranslation/useTranslation' import { TLUiIconType } from '../icon-types' import { LanguageMenu } from './LanguageMenu' +import { Button } from './primitives/Button' import * as M from './primitives/DropdownMenu' -import { Icon } from './primitives/Icon' interface HelpMenuLink { label: TLUiTranslationKey @@ -32,12 +32,14 @@ export const HelpMenu = React.memo(function HelpMenu() { return (
- - + + @@ -88,8 +89,9 @@ export const MoveToPageMenu = track(function MoveToPageMenu() { asChild > diff --git a/packages/tldraw/src/lib/ui/components/NavigationZone/NavigationZone.tsx b/packages/tldraw/src/lib/ui/components/NavigationZone/NavigationZone.tsx index 85588df3d..fb77f43c2 100644 --- a/packages/tldraw/src/lib/ui/components/NavigationZone/NavigationZone.tsx +++ b/packages/tldraw/src/lib/ui/components/NavigationZone/NavigationZone.tsx @@ -26,23 +26,25 @@ export const NavigationZone = memo(function NavigationZone() { return (
-
+
{breakpoint < 6 ? ( ) : collapsed ? ( <>
)}
- - preventDefault(e)} - > -
- - +
) }) diff --git a/packages/tldraw/src/lib/ui/components/StylePanel/DropdownPicker.tsx b/packages/tldraw/src/lib/ui/components/StylePanel/DropdownPicker.tsx index 19f032186..05b4c7fb4 100644 --- a/packages/tldraw/src/lib/ui/components/StylePanel/DropdownPicker.tsx +++ b/packages/tldraw/src/lib/ui/components/StylePanel/DropdownPicker.tsx @@ -1,11 +1,10 @@ import { Trigger } from '@radix-ui/react-dropdown-menu' import { SharedStyle, StyleProp, preventDefault } from '@tldraw/editor' -import classNames from 'classnames' import * as React from 'react' import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey' import { useTranslation } from '../../hooks/useTranslation/useTranslation' import { TLUiIconType } from '../../icon-types' -import { Button } from '../primitives/Button' +import { Button, TLUiButtonProps } from '../primitives/Button' import * as DropdownMenu from '../primitives/DropdownMenu' import { StyleValuesForUi } from './styles' @@ -16,6 +15,7 @@ interface DropdownPickerProps { style: StyleProp value: SharedStyle items: StyleValuesForUi + type: TLUiButtonProps['type'] onValueChange: (style: StyleProp, value: T, squashing: boolean) => void } @@ -25,6 +25,7 @@ export const DropdownPicker = React.memo(function DropdownPicker) { @@ -43,6 +44,7 @@ export const DropdownPicker = React.memo(function DropdownPicker preventDefault(e)} >
)}
@@ -267,6 +271,7 @@ function GeoStylePickerSet({ styles }: { styles: ReadonlySharedStyleMap }) { return ( {toast.actions.map((action, i) => ( - + ))} - {hasActions && ( - - - - )} + + + )} {!hasActions && ( - + )} diff --git a/packages/tldraw/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx b/packages/tldraw/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx index b12f13934..2f923179b 100644 --- a/packages/tldraw/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +++ b/packages/tldraw/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx @@ -30,6 +30,7 @@ export function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonP return ( diff --git a/packages/tldraw/src/lib/ui/components/primitives/DropdownMenu.tsx b/packages/tldraw/src/lib/ui/components/primitives/DropdownMenu.tsx index bd5781ce8..aa35e2d24 100644 --- a/packages/tldraw/src/lib/ui/components/primitives/DropdownMenu.tsx +++ b/packages/tldraw/src/lib/ui/components/primitives/DropdownMenu.tsx @@ -10,15 +10,17 @@ export function Root({ id, children, modal = false, + debugOpen = false, }: { id: string children: any modal?: boolean + debugOpen?: boolean }) { const [open, onOpenChange] = useMenuIsOpen(id) return ( - + {children} ) @@ -101,7 +103,8 @@ export function SubTrigger({ return (