ui: make toasts look more toasty (#2988)

<img width="449" alt="Screenshot 2024-03-11 at 14 03 44"
src="https://github.com/tldraw/tldraw/assets/469604/5b00dafc-abf1-44a3-b6c6-1d16db74b1be">


### Change Type

- [x] `patch` — Bug fix

### Release Notes

- UI: Add severity to toasts.
This commit is contained in:
Mime Čuvalo 2024-03-27 09:41:13 +00:00 committed by GitHub
parent d76d53db95
commit 6def201da2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 167 additions and 11 deletions

View file

@ -16,6 +16,7 @@ export function SneakyOnDropOverride({ isMultiplayer }: { isMultiplayer: boolean
addToast({ addToast({
title: msg('file-system.shared-document-file-open-error.title'), title: msg('file-system.shared-document-file-open-error.title'),
description: msg('file-system.shared-document-file-open-error.description'), description: msg('file-system.shared-document-file-open-error.description'),
severity: 'error',
}) })
} else { } else {
const shouldOverride = await shouldOverrideDocument(addDialog) const shouldOverride = await shouldOverrideDocument(addDialog)

View file

@ -147,6 +147,7 @@ export function useSharing(): TLUiOverrides {
addToast({ addToast({
title: 'Error', title: 'Error',
description: msg('share-menu.upload-failed'), description: msg('share-menu.upload-failed'),
severity: 'error',
}) })
} }
}, },
@ -242,6 +243,7 @@ async function getRoomData(
addToast({ addToast({
title: 'Too big!', title: 'Too big!',
description: msg('share-menu.project-too-large'), description: msg('share-menu.project-too-large'),
severity: 'warning',
}) })
trackAnalyticsEvent('shared-fail-too-big', { trackAnalyticsEvent('shared-fail-too-big', {

View file

@ -44,6 +44,7 @@ export function useFileSystem({ isMultiplayer }: { isMultiplayer: boolean }): TL
addToast({ addToast({
title: msg('file-system.shared-document-file-open-error.title'), title: msg('file-system.shared-document-file-open-error.title'),
description: msg('file-system.shared-document-file-open-error.description'), description: msg('file-system.shared-document-file-open-error.description'),
severity: 'error',
}) })
return return
} }

View file

@ -0,0 +1 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.49991 0.877045C3.84222 0.877045 0.877075 3.84219 0.877075 7.49988C0.877075 11.1575 3.84222 14.1227 7.49991 14.1227C11.1576 14.1227 14.1227 11.1575 14.1227 7.49988C14.1227 3.84219 11.1576 0.877045 7.49991 0.877045ZM1.82708 7.49988C1.82708 4.36686 4.36689 1.82704 7.49991 1.82704C10.6329 1.82704 13.1727 4.36686 13.1727 7.49988C13.1727 10.6329 10.6329 13.1727 7.49991 13.1727C4.36689 13.1727 1.82708 10.6329 1.82708 7.49988ZM10.1589 5.53774C10.3178 5.31191 10.2636 5.00001 10.0378 4.84109C9.81194 4.68217 9.50004 4.73642 9.34112 4.96225L6.51977 8.97154L5.35681 7.78706C5.16334 7.59002 4.84677 7.58711 4.64973 7.78058C4.45268 7.97404 4.44978 8.29061 4.64325 8.48765L6.22658 10.1003C6.33054 10.2062 6.47617 10.2604 6.62407 10.2483C6.77197 10.2363 6.90686 10.1591 6.99226 10.0377L10.1589 5.53774Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>

After

Width:  |  Height:  |  Size: 973 B

View file

@ -0,0 +1 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.877075 7.49988C0.877075 3.84219 3.84222 0.877045 7.49991 0.877045C11.1576 0.877045 14.1227 3.84219 14.1227 7.49988C14.1227 11.1575 11.1576 14.1227 7.49991 14.1227C3.84222 14.1227 0.877075 11.1575 0.877075 7.49988ZM7.49991 1.82704C4.36689 1.82704 1.82708 4.36686 1.82708 7.49988C1.82708 10.6329 4.36689 13.1727 7.49991 13.1727C10.6329 13.1727 13.1727 10.6329 13.1727 7.49988C13.1727 4.36686 10.6329 1.82704 7.49991 1.82704ZM9.85358 5.14644C10.0488 5.3417 10.0488 5.65829 9.85358 5.85355L8.20713 7.49999L9.85358 9.14644C10.0488 9.3417 10.0488 9.65829 9.85358 9.85355C9.65832 10.0488 9.34173 10.0488 9.14647 9.85355L7.50002 8.2071L5.85358 9.85355C5.65832 10.0488 5.34173 10.0488 5.14647 9.85355C4.95121 9.65829 4.95121 9.3417 5.14647 9.14644L6.79292 7.49999L5.14647 5.85355C4.95121 5.65829 4.95121 5.3417 5.14647 5.14644C5.34173 4.95118 5.65832 4.95118 5.85358 5.14644L7.50002 6.79289L9.14647 5.14644C9.34173 4.95118 9.65832 4.95118 9.85358 5.14644Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,4 @@
<!-- MUI, MIT License: https://github.com/mui/material-ui/blob/master/LICENSE -->
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path>
</svg>

After

Width:  |  Height:  |  Size: 337 B

View file

@ -55,6 +55,7 @@ import iconsAvatar from './icons/icon/avatar.svg'
import iconsBlob from './icons/icon/blob.svg' import iconsBlob from './icons/icon/blob.svg'
import iconsBringForward from './icons/icon/bring-forward.svg' import iconsBringForward from './icons/icon/bring-forward.svg'
import iconsBringToFront from './icons/icon/bring-to-front.svg' import iconsBringToFront from './icons/icon/bring-to-front.svg'
import iconsCheckCircle from './icons/icon/check-circle.svg'
import iconsCheck from './icons/icon/check.svg' import iconsCheck from './icons/icon/check.svg'
import iconsCheckboxChecked from './icons/icon/checkbox-checked.svg' import iconsCheckboxChecked from './icons/icon/checkbox-checked.svg'
import iconsCheckboxEmpty from './icons/icon/checkbox-empty.svg' import iconsCheckboxEmpty from './icons/icon/checkbox-empty.svg'
@ -71,6 +72,7 @@ import iconsCollab from './icons/icon/collab.svg'
import iconsColor from './icons/icon/color.svg' import iconsColor from './icons/icon/color.svg'
import iconsComment from './icons/icon/comment.svg' import iconsComment from './icons/icon/comment.svg'
import iconsCross2 from './icons/icon/cross-2.svg' import iconsCross2 from './icons/icon/cross-2.svg'
import iconsCrossCircle from './icons/icon/cross-circle.svg'
import iconsCross from './icons/icon/cross.svg' import iconsCross from './icons/icon/cross.svg'
import iconsDashDashed from './icons/icon/dash-dashed.svg' import iconsDashDashed from './icons/icon/dash-dashed.svg'
import iconsDashDotted from './icons/icon/dash-dotted.svg' import iconsDashDotted from './icons/icon/dash-dotted.svg'
@ -85,6 +87,7 @@ import iconsDotsVertical from './icons/icon/dots-vertical.svg'
import iconsDragHandleDots from './icons/icon/drag-handle-dots.svg' import iconsDragHandleDots from './icons/icon/drag-handle-dots.svg'
import iconsDuplicate from './icons/icon/duplicate.svg' import iconsDuplicate from './icons/icon/duplicate.svg'
import iconsEdit from './icons/icon/edit.svg' import iconsEdit from './icons/icon/edit.svg'
import iconsError from './icons/icon/error.svg'
import iconsExternalLink from './icons/icon/external-link.svg' import iconsExternalLink from './icons/icon/external-link.svg'
import iconsFile from './icons/icon/file.svg' import iconsFile from './icons/icon/file.svg'
import iconsFillNone from './icons/icon/fill-none.svg' import iconsFillNone from './icons/icon/fill-none.svg'
@ -271,6 +274,7 @@ export function getAssetUrlsByImport(opts) {
blob: formatAssetUrl(iconsBlob, opts), blob: formatAssetUrl(iconsBlob, opts),
'bring-forward': formatAssetUrl(iconsBringForward, opts), 'bring-forward': formatAssetUrl(iconsBringForward, opts),
'bring-to-front': formatAssetUrl(iconsBringToFront, opts), 'bring-to-front': formatAssetUrl(iconsBringToFront, opts),
'check-circle': formatAssetUrl(iconsCheckCircle, opts),
check: formatAssetUrl(iconsCheck, opts), check: formatAssetUrl(iconsCheck, opts),
'checkbox-checked': formatAssetUrl(iconsCheckboxChecked, opts), 'checkbox-checked': formatAssetUrl(iconsCheckboxChecked, opts),
'checkbox-empty': formatAssetUrl(iconsCheckboxEmpty, opts), 'checkbox-empty': formatAssetUrl(iconsCheckboxEmpty, opts),
@ -287,6 +291,7 @@ export function getAssetUrlsByImport(opts) {
color: formatAssetUrl(iconsColor, opts), color: formatAssetUrl(iconsColor, opts),
comment: formatAssetUrl(iconsComment, opts), comment: formatAssetUrl(iconsComment, opts),
'cross-2': formatAssetUrl(iconsCross2, opts), 'cross-2': formatAssetUrl(iconsCross2, opts),
'cross-circle': formatAssetUrl(iconsCrossCircle, opts),
cross: formatAssetUrl(iconsCross, opts), cross: formatAssetUrl(iconsCross, opts),
'dash-dashed': formatAssetUrl(iconsDashDashed, opts), 'dash-dashed': formatAssetUrl(iconsDashDashed, opts),
'dash-dotted': formatAssetUrl(iconsDashDotted, opts), 'dash-dotted': formatAssetUrl(iconsDashDotted, opts),
@ -301,6 +306,7 @@ export function getAssetUrlsByImport(opts) {
'drag-handle-dots': formatAssetUrl(iconsDragHandleDots, opts), 'drag-handle-dots': formatAssetUrl(iconsDragHandleDots, opts),
duplicate: formatAssetUrl(iconsDuplicate, opts), duplicate: formatAssetUrl(iconsDuplicate, opts),
edit: formatAssetUrl(iconsEdit, opts), edit: formatAssetUrl(iconsEdit, opts),
error: formatAssetUrl(iconsError, opts),
'external-link': formatAssetUrl(iconsExternalLink, opts), 'external-link': formatAssetUrl(iconsExternalLink, opts),
file: formatAssetUrl(iconsFile, opts), file: formatAssetUrl(iconsFile, opts),
'fill-none': formatAssetUrl(iconsFillNone, opts), 'fill-none': formatAssetUrl(iconsFillNone, opts),

View file

@ -55,6 +55,7 @@ import iconsAvatar from './icons/icon/avatar.svg?url'
import iconsBlob from './icons/icon/blob.svg?url' import iconsBlob from './icons/icon/blob.svg?url'
import iconsBringForward from './icons/icon/bring-forward.svg?url' import iconsBringForward from './icons/icon/bring-forward.svg?url'
import iconsBringToFront from './icons/icon/bring-to-front.svg?url' import iconsBringToFront from './icons/icon/bring-to-front.svg?url'
import iconsCheckCircle from './icons/icon/check-circle.svg?url'
import iconsCheck from './icons/icon/check.svg?url' import iconsCheck from './icons/icon/check.svg?url'
import iconsCheckboxChecked from './icons/icon/checkbox-checked.svg?url' import iconsCheckboxChecked from './icons/icon/checkbox-checked.svg?url'
import iconsCheckboxEmpty from './icons/icon/checkbox-empty.svg?url' import iconsCheckboxEmpty from './icons/icon/checkbox-empty.svg?url'
@ -71,6 +72,7 @@ import iconsCollab from './icons/icon/collab.svg?url'
import iconsColor from './icons/icon/color.svg?url' import iconsColor from './icons/icon/color.svg?url'
import iconsComment from './icons/icon/comment.svg?url' import iconsComment from './icons/icon/comment.svg?url'
import iconsCross2 from './icons/icon/cross-2.svg?url' import iconsCross2 from './icons/icon/cross-2.svg?url'
import iconsCrossCircle from './icons/icon/cross-circle.svg?url'
import iconsCross from './icons/icon/cross.svg?url' import iconsCross from './icons/icon/cross.svg?url'
import iconsDashDashed from './icons/icon/dash-dashed.svg?url' import iconsDashDashed from './icons/icon/dash-dashed.svg?url'
import iconsDashDotted from './icons/icon/dash-dotted.svg?url' import iconsDashDotted from './icons/icon/dash-dotted.svg?url'
@ -85,6 +87,7 @@ import iconsDotsVertical from './icons/icon/dots-vertical.svg?url'
import iconsDragHandleDots from './icons/icon/drag-handle-dots.svg?url' import iconsDragHandleDots from './icons/icon/drag-handle-dots.svg?url'
import iconsDuplicate from './icons/icon/duplicate.svg?url' import iconsDuplicate from './icons/icon/duplicate.svg?url'
import iconsEdit from './icons/icon/edit.svg?url' import iconsEdit from './icons/icon/edit.svg?url'
import iconsError from './icons/icon/error.svg?url'
import iconsExternalLink from './icons/icon/external-link.svg?url' import iconsExternalLink from './icons/icon/external-link.svg?url'
import iconsFile from './icons/icon/file.svg?url' import iconsFile from './icons/icon/file.svg?url'
import iconsFillNone from './icons/icon/fill-none.svg?url' import iconsFillNone from './icons/icon/fill-none.svg?url'
@ -271,6 +274,7 @@ export function getAssetUrlsByImport(opts) {
blob: formatAssetUrl(iconsBlob, opts), blob: formatAssetUrl(iconsBlob, opts),
'bring-forward': formatAssetUrl(iconsBringForward, opts), 'bring-forward': formatAssetUrl(iconsBringForward, opts),
'bring-to-front': formatAssetUrl(iconsBringToFront, opts), 'bring-to-front': formatAssetUrl(iconsBringToFront, opts),
'check-circle': formatAssetUrl(iconsCheckCircle, opts),
check: formatAssetUrl(iconsCheck, opts), check: formatAssetUrl(iconsCheck, opts),
'checkbox-checked': formatAssetUrl(iconsCheckboxChecked, opts), 'checkbox-checked': formatAssetUrl(iconsCheckboxChecked, opts),
'checkbox-empty': formatAssetUrl(iconsCheckboxEmpty, opts), 'checkbox-empty': formatAssetUrl(iconsCheckboxEmpty, opts),
@ -287,6 +291,7 @@ export function getAssetUrlsByImport(opts) {
color: formatAssetUrl(iconsColor, opts), color: formatAssetUrl(iconsColor, opts),
comment: formatAssetUrl(iconsComment, opts), comment: formatAssetUrl(iconsComment, opts),
'cross-2': formatAssetUrl(iconsCross2, opts), 'cross-2': formatAssetUrl(iconsCross2, opts),
'cross-circle': formatAssetUrl(iconsCrossCircle, opts),
cross: formatAssetUrl(iconsCross, opts), cross: formatAssetUrl(iconsCross, opts),
'dash-dashed': formatAssetUrl(iconsDashDashed, opts), 'dash-dashed': formatAssetUrl(iconsDashDashed, opts),
'dash-dotted': formatAssetUrl(iconsDashDotted, opts), 'dash-dotted': formatAssetUrl(iconsDashDotted, opts),
@ -301,6 +306,7 @@ export function getAssetUrlsByImport(opts) {
'drag-handle-dots': formatAssetUrl(iconsDragHandleDots, opts), 'drag-handle-dots': formatAssetUrl(iconsDragHandleDots, opts),
duplicate: formatAssetUrl(iconsDuplicate, opts), duplicate: formatAssetUrl(iconsDuplicate, opts),
edit: formatAssetUrl(iconsEdit, opts), edit: formatAssetUrl(iconsEdit, opts),
error: formatAssetUrl(iconsError, opts),
'external-link': formatAssetUrl(iconsExternalLink, opts), 'external-link': formatAssetUrl(iconsExternalLink, opts),
file: formatAssetUrl(iconsFile, opts), file: formatAssetUrl(iconsFile, opts),
'fill-none': formatAssetUrl(iconsFillNone, opts), 'fill-none': formatAssetUrl(iconsFillNone, opts),

View file

@ -50,6 +50,7 @@ export function getAssetUrls(opts) {
blob: formatAssetUrl('./icons/icon/blob.svg', opts), blob: formatAssetUrl('./icons/icon/blob.svg', opts),
'bring-forward': formatAssetUrl('./icons/icon/bring-forward.svg', opts), 'bring-forward': formatAssetUrl('./icons/icon/bring-forward.svg', opts),
'bring-to-front': formatAssetUrl('./icons/icon/bring-to-front.svg', opts), 'bring-to-front': formatAssetUrl('./icons/icon/bring-to-front.svg', opts),
'check-circle': formatAssetUrl('./icons/icon/check-circle.svg', opts),
check: formatAssetUrl('./icons/icon/check.svg', opts), check: formatAssetUrl('./icons/icon/check.svg', opts),
'checkbox-checked': formatAssetUrl('./icons/icon/checkbox-checked.svg', opts), 'checkbox-checked': formatAssetUrl('./icons/icon/checkbox-checked.svg', opts),
'checkbox-empty': formatAssetUrl('./icons/icon/checkbox-empty.svg', opts), 'checkbox-empty': formatAssetUrl('./icons/icon/checkbox-empty.svg', opts),
@ -66,6 +67,7 @@ export function getAssetUrls(opts) {
color: formatAssetUrl('./icons/icon/color.svg', opts), color: formatAssetUrl('./icons/icon/color.svg', opts),
comment: formatAssetUrl('./icons/icon/comment.svg', opts), comment: formatAssetUrl('./icons/icon/comment.svg', opts),
'cross-2': formatAssetUrl('./icons/icon/cross-2.svg', opts), 'cross-2': formatAssetUrl('./icons/icon/cross-2.svg', opts),
'cross-circle': formatAssetUrl('./icons/icon/cross-circle.svg', opts),
cross: formatAssetUrl('./icons/icon/cross.svg', opts), cross: formatAssetUrl('./icons/icon/cross.svg', opts),
'dash-dashed': formatAssetUrl('./icons/icon/dash-dashed.svg', opts), 'dash-dashed': formatAssetUrl('./icons/icon/dash-dashed.svg', opts),
'dash-dotted': formatAssetUrl('./icons/icon/dash-dotted.svg', opts), 'dash-dotted': formatAssetUrl('./icons/icon/dash-dotted.svg', opts),
@ -80,6 +82,7 @@ export function getAssetUrls(opts) {
'drag-handle-dots': formatAssetUrl('./icons/icon/drag-handle-dots.svg', opts), 'drag-handle-dots': formatAssetUrl('./icons/icon/drag-handle-dots.svg', opts),
duplicate: formatAssetUrl('./icons/icon/duplicate.svg', opts), duplicate: formatAssetUrl('./icons/icon/duplicate.svg', opts),
edit: formatAssetUrl('./icons/icon/edit.svg', opts), edit: formatAssetUrl('./icons/icon/edit.svg', opts),
error: formatAssetUrl('./icons/icon/error.svg', opts),
'external-link': formatAssetUrl('./icons/icon/external-link.svg', opts), 'external-link': formatAssetUrl('./icons/icon/external-link.svg', opts),
file: formatAssetUrl('./icons/icon/file.svg', opts), file: formatAssetUrl('./icons/icon/file.svg', opts),
'fill-none': formatAssetUrl('./icons/icon/fill-none.svg', opts), 'fill-none': formatAssetUrl('./icons/icon/fill-none.svg', opts),

View file

@ -40,6 +40,7 @@ export type AssetUrls = {
blob: string blob: string
'bring-forward': string 'bring-forward': string
'bring-to-front': string 'bring-to-front': string
'check-circle': string
check: string check: string
'checkbox-checked': string 'checkbox-checked': string
'checkbox-empty': string 'checkbox-empty': string
@ -56,6 +57,7 @@ export type AssetUrls = {
color: string color: string
comment: string comment: string
'cross-2': string 'cross-2': string
'cross-circle': string
cross: string cross: string
'dash-dashed': string 'dash-dashed': string
'dash-dotted': string 'dash-dotted': string
@ -70,6 +72,7 @@ export type AssetUrls = {
'drag-handle-dots': string 'drag-handle-dots': string
duplicate: string duplicate: string
edit: string edit: string
error: string
'external-link': string 'external-link': string
file: string file: string
'fill-none': string 'fill-none': string

View file

@ -140,6 +140,10 @@ export function getAssetUrlsByMetaUrl(opts) {
new URL('./icons/icon/bring-to-front.svg', import.meta.url).href, new URL('./icons/icon/bring-to-front.svg', import.meta.url).href,
opts opts
), ),
'check-circle': formatAssetUrl(
new URL('./icons/icon/check-circle.svg', import.meta.url).href,
opts
),
check: formatAssetUrl(new URL('./icons/icon/check.svg', import.meta.url).href, opts), check: formatAssetUrl(new URL('./icons/icon/check.svg', import.meta.url).href, opts),
'checkbox-checked': formatAssetUrl( 'checkbox-checked': formatAssetUrl(
new URL('./icons/icon/checkbox-checked.svg', import.meta.url).href, new URL('./icons/icon/checkbox-checked.svg', import.meta.url).href,
@ -186,6 +190,10 @@ export function getAssetUrlsByMetaUrl(opts) {
color: formatAssetUrl(new URL('./icons/icon/color.svg', import.meta.url).href, opts), color: formatAssetUrl(new URL('./icons/icon/color.svg', import.meta.url).href, opts),
comment: formatAssetUrl(new URL('./icons/icon/comment.svg', import.meta.url).href, opts), comment: formatAssetUrl(new URL('./icons/icon/comment.svg', import.meta.url).href, opts),
'cross-2': formatAssetUrl(new URL('./icons/icon/cross-2.svg', import.meta.url).href, opts), 'cross-2': formatAssetUrl(new URL('./icons/icon/cross-2.svg', import.meta.url).href, opts),
'cross-circle': formatAssetUrl(
new URL('./icons/icon/cross-circle.svg', import.meta.url).href,
opts
),
cross: formatAssetUrl(new URL('./icons/icon/cross.svg', import.meta.url).href, opts), cross: formatAssetUrl(new URL('./icons/icon/cross.svg', import.meta.url).href, opts),
'dash-dashed': formatAssetUrl( 'dash-dashed': formatAssetUrl(
new URL('./icons/icon/dash-dashed.svg', import.meta.url).href, new URL('./icons/icon/dash-dashed.svg', import.meta.url).href,
@ -227,6 +235,7 @@ export function getAssetUrlsByMetaUrl(opts) {
), ),
duplicate: formatAssetUrl(new URL('./icons/icon/duplicate.svg', import.meta.url).href, opts), duplicate: formatAssetUrl(new URL('./icons/icon/duplicate.svg', import.meta.url).href, opts),
edit: formatAssetUrl(new URL('./icons/icon/edit.svg', import.meta.url).href, opts), edit: formatAssetUrl(new URL('./icons/icon/edit.svg', import.meta.url).href, opts),
error: formatAssetUrl(new URL('./icons/icon/error.svg', import.meta.url).href, opts),
'external-link': formatAssetUrl( 'external-link': formatAssetUrl(
new URL('./icons/icon/external-link.svg', import.meta.url).href, new URL('./icons/icon/external-link.svg', import.meta.url).href,
opts opts

View file

@ -124,6 +124,10 @@
--color-text-3: hsl(220, 2%, 65%); --color-text-3: hsl(220, 2%, 65%);
--color-text-shadow: hsl(0, 0%, 100%); --color-text-shadow: hsl(0, 0%, 100%);
--color-primary: hsl(214, 84%, 56%); --color-primary: hsl(214, 84%, 56%);
--color-success: hsl(123, 46%, 34%);
--color-info: hsl(201, 98%, 41%);
--color-warning: hsl(27, 98%, 47%);
--color-error: hsl(0, 65%, 51%);
--color-warn: hsl(0, 90%, 43%); --color-warn: hsl(0, 90%, 43%);
--color-text: hsl(0, 0%, 0%); --color-text: hsl(0, 0%, 0%);
--color-laser: hsl(0, 100%, 50%); --color-laser: hsl(0, 100%, 50%);
@ -166,6 +170,10 @@
--color-text-3: hsl(210, 6%, 45%); --color-text-3: hsl(210, 6%, 45%);
--color-text-shadow: hsl(210, 13%, 18%); --color-text-shadow: hsl(210, 13%, 18%);
--color-primary: hsl(214, 84%, 56%); --color-primary: hsl(214, 84%, 56%);
--color-success: hsl(123, 38%, 57%);
--color-info: hsl(199, 92%, 56%);
--color-warning: hsl(36, 100%, 57%);
--color-error: hsl(4, 90%, 58%);
--color-warn: hsl(0, 81%, 66%); --color-warn: hsl(0, 81%, 66%);
--color-text: hsl(210, 17%, 98%); --color-text: hsl(210, 17%, 98%);
--color-laser: hsl(0, 100%, 50%); --color-laser: hsl(0, 100%, 50%);

View file

@ -128,6 +128,9 @@ import { Vec } from '@tldraw/editor';
import { VecLike } from '@tldraw/editor'; import { VecLike } from '@tldraw/editor';
import { VecModel } from '@tldraw/editor'; import { VecModel } from '@tldraw/editor';
// @public (undocumented)
export type AlertSeverity = 'error' | 'info' | 'success' | 'warning';
// @public (undocumented) // @public (undocumented)
export function AlignMenuItems(): JSX_2.Element; export function AlignMenuItems(): JSX_2.Element;
@ -2134,7 +2137,7 @@ export interface TLUiIconProps extends React.HTMLProps<HTMLDivElement> {
} }
// @public (undocumented) // @public (undocumented)
export type TLUiIconType = 'align-bottom-center' | 'align-bottom-left' | 'align-bottom-right' | 'align-bottom' | 'align-center-center' | 'align-center-horizontal' | 'align-center-left' | 'align-center-right' | 'align-center-vertical' | 'align-left' | 'align-right' | 'align-top-center' | 'align-top-left' | 'align-top-right' | 'align-top' | 'arrow-left' | 'arrowhead-arrow' | 'arrowhead-bar' | 'arrowhead-diamond' | 'arrowhead-dot' | 'arrowhead-none' | 'arrowhead-square' | 'arrowhead-triangle-inverted' | 'arrowhead-triangle' | 'aspect-ratio' | 'avatar' | 'blob' | 'bring-forward' | 'bring-to-front' | 'check' | 'checkbox-checked' | 'checkbox-empty' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'chevrons-ne' | 'chevrons-sw' | 'clipboard-copied' | 'clipboard-copy' | 'code' | 'collab' | 'color' | 'comment' | 'cross-2' | 'cross' | 'dash-dashed' | 'dash-dotted' | 'dash-draw' | 'dash-solid' | 'discord' | 'distribute-horizontal' | 'distribute-vertical' | 'dot' | 'dots-horizontal' | 'dots-vertical' | 'drag-handle-dots' | 'duplicate' | 'edit' | 'external-link' | 'file' | 'fill-none' | 'fill-pattern' | 'fill-semi' | 'fill-solid' | 'follow' | 'following' | 'font-draw' | 'font-mono' | 'font-sans' | 'font-serif' | 'geo-arrow-down' | 'geo-arrow-left' | 'geo-arrow-right' | 'geo-arrow-up' | 'geo-check-box' | 'geo-cloud' | 'geo-diamond' | 'geo-ellipse' | 'geo-hexagon' | 'geo-octagon' | 'geo-oval' | 'geo-pentagon' | 'geo-rectangle' | 'geo-rhombus-2' | 'geo-rhombus' | 'geo-star' | 'geo-trapezoid' | 'geo-triangle' | 'geo-x-box' | 'github' | 'group' | 'hidden' | 'image' | 'info-circle' | 'leading' | 'link' | 'lock-small' | 'lock' | 'menu' | 'minus' | 'mixed' | 'pack' | 'page' | 'plus' | 'question-mark-circle' | 'question-mark' | 'redo' | 'reset-zoom' | 'rotate-ccw' | 'rotate-cw' | 'ruler' | 'search' | 'send-backward' | 'send-to-back' | 'settings-horizontal' | 'settings-vertical-1' | 'settings-vertical' | 'share-1' | 'share-2' | 'size-extra-large' | 'size-large' | 'size-medium' | 'size-small' | 'spline-cubic' | 'spline-line' | 'stack-horizontal' | 'stack-vertical' | 'status-offline' | 'status-online' | 'stretch-horizontal' | 'stretch-vertical' | 'text-align-center' | 'text-align-justify' | 'text-align-left' | 'text-align-right' | 'tool-arrow' | 'tool-embed' | 'tool-eraser' | 'tool-frame' | 'tool-hand' | 'tool-highlight' | 'tool-laser' | 'tool-line' | 'tool-media' | 'tool-note' | 'tool-pencil' | 'tool-pointer' | 'tool-text' | 'trash' | 'triangle-down' | 'triangle-up' | 'twitter' | 'undo' | 'ungroup' | 'unlock-small' | 'unlock' | 'vertical-align-center' | 'vertical-align-end' | 'vertical-align-start' | 'visible' | 'warning-triangle' | 'zoom-in' | 'zoom-out'; export type TLUiIconType = 'align-bottom-center' | 'align-bottom-left' | 'align-bottom-right' | 'align-bottom' | 'align-center-center' | 'align-center-horizontal' | 'align-center-left' | 'align-center-right' | 'align-center-vertical' | 'align-left' | 'align-right' | 'align-top-center' | 'align-top-left' | 'align-top-right' | 'align-top' | 'arrow-left' | 'arrowhead-arrow' | 'arrowhead-bar' | 'arrowhead-diamond' | 'arrowhead-dot' | 'arrowhead-none' | 'arrowhead-square' | 'arrowhead-triangle-inverted' | 'arrowhead-triangle' | 'aspect-ratio' | 'avatar' | 'blob' | 'bring-forward' | 'bring-to-front' | 'check-circle' | 'check' | 'checkbox-checked' | 'checkbox-empty' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'chevrons-ne' | 'chevrons-sw' | 'clipboard-copied' | 'clipboard-copy' | 'code' | 'collab' | 'color' | 'comment' | 'cross-2' | 'cross-circle' | 'cross' | 'dash-dashed' | 'dash-dotted' | 'dash-draw' | 'dash-solid' | 'discord' | 'distribute-horizontal' | 'distribute-vertical' | 'dot' | 'dots-horizontal' | 'dots-vertical' | 'drag-handle-dots' | 'duplicate' | 'edit' | 'error' | 'external-link' | 'file' | 'fill-none' | 'fill-pattern' | 'fill-semi' | 'fill-solid' | 'follow' | 'following' | 'font-draw' | 'font-mono' | 'font-sans' | 'font-serif' | 'geo-arrow-down' | 'geo-arrow-left' | 'geo-arrow-right' | 'geo-arrow-up' | 'geo-check-box' | 'geo-cloud' | 'geo-diamond' | 'geo-ellipse' | 'geo-hexagon' | 'geo-octagon' | 'geo-oval' | 'geo-pentagon' | 'geo-rectangle' | 'geo-rhombus-2' | 'geo-rhombus' | 'geo-star' | 'geo-trapezoid' | 'geo-triangle' | 'geo-x-box' | 'github' | 'group' | 'hidden' | 'image' | 'info-circle' | 'leading' | 'link' | 'lock-small' | 'lock' | 'menu' | 'minus' | 'mixed' | 'pack' | 'page' | 'plus' | 'question-mark-circle' | 'question-mark' | 'redo' | 'reset-zoom' | 'rotate-ccw' | 'rotate-cw' | 'ruler' | 'search' | 'send-backward' | 'send-to-back' | 'settings-horizontal' | 'settings-vertical-1' | 'settings-vertical' | 'share-1' | 'share-2' | 'size-extra-large' | 'size-large' | 'size-medium' | 'size-small' | 'spline-cubic' | 'spline-line' | 'stack-horizontal' | 'stack-vertical' | 'status-offline' | 'status-online' | 'stretch-horizontal' | 'stretch-vertical' | 'text-align-center' | 'text-align-justify' | 'text-align-left' | 'text-align-right' | 'tool-arrow' | 'tool-embed' | 'tool-eraser' | 'tool-frame' | 'tool-hand' | 'tool-highlight' | 'tool-laser' | 'tool-line' | 'tool-media' | 'tool-note' | 'tool-pencil' | 'tool-pointer' | 'tool-text' | 'trash' | 'triangle-down' | 'triangle-up' | 'twitter' | 'undo' | 'ungroup' | 'unlock-small' | 'unlock' | 'vertical-align-center' | 'vertical-align-end' | 'vertical-align-start' | 'visible' | 'warning-triangle' | 'zoom-in' | 'zoom-out';
// @public (undocumented) // @public (undocumented)
export interface TLUiInputProps { export interface TLUiInputProps {
@ -2326,6 +2329,8 @@ export interface TLUiToast {
// (undocumented) // (undocumented)
keepOpen?: boolean; keepOpen?: boolean;
// (undocumented) // (undocumented)
severity?: AlertSeverity;
// (undocumented)
title?: string; title?: string;
} }

View file

@ -172,6 +172,32 @@
"name": "", "name": "",
"preserveMemberOrder": false, "preserveMemberOrder": false,
"members": [ "members": [
{
"kind": "TypeAlias",
"canonicalReference": "tldraw!AlertSeverity:type",
"docComment": "/**\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "export type AlertSeverity = "
},
{
"kind": "Content",
"text": "'error' | 'info' | 'success' | 'warning'"
},
{
"kind": "Content",
"text": ";"
}
],
"fileUrlPath": "packages/tldraw/src/lib/ui/context/toasts.tsx",
"releaseTag": "Public",
"name": "AlertSeverity",
"typeTokenRange": {
"startIndex": 1,
"endIndex": 2
}
},
{ {
"kind": "Function", "kind": "Function",
"canonicalReference": "tldraw!AlignMenuItems:function(1)", "canonicalReference": "tldraw!AlignMenuItems:function(1)",
@ -24086,7 +24112,7 @@
}, },
{ {
"kind": "Content", "kind": "Content",
"text": "'align-bottom-center' | 'align-bottom-left' | 'align-bottom-right' | 'align-bottom' | 'align-center-center' | 'align-center-horizontal' | 'align-center-left' | 'align-center-right' | 'align-center-vertical' | 'align-left' | 'align-right' | 'align-top-center' | 'align-top-left' | 'align-top-right' | 'align-top' | 'arrow-left' | 'arrowhead-arrow' | 'arrowhead-bar' | 'arrowhead-diamond' | 'arrowhead-dot' | 'arrowhead-none' | 'arrowhead-square' | 'arrowhead-triangle-inverted' | 'arrowhead-triangle' | 'aspect-ratio' | 'avatar' | 'blob' | 'bring-forward' | 'bring-to-front' | 'check' | 'checkbox-checked' | 'checkbox-empty' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'chevrons-ne' | 'chevrons-sw' | 'clipboard-copied' | 'clipboard-copy' | 'code' | 'collab' | 'color' | 'comment' | 'cross-2' | 'cross' | 'dash-dashed' | 'dash-dotted' | 'dash-draw' | 'dash-solid' | 'discord' | 'distribute-horizontal' | 'distribute-vertical' | 'dot' | 'dots-horizontal' | 'dots-vertical' | 'drag-handle-dots' | 'duplicate' | 'edit' | 'external-link' | 'file' | 'fill-none' | 'fill-pattern' | 'fill-semi' | 'fill-solid' | 'follow' | 'following' | 'font-draw' | 'font-mono' | 'font-sans' | 'font-serif' | 'geo-arrow-down' | 'geo-arrow-left' | 'geo-arrow-right' | 'geo-arrow-up' | 'geo-check-box' | 'geo-cloud' | 'geo-diamond' | 'geo-ellipse' | 'geo-hexagon' | 'geo-octagon' | 'geo-oval' | 'geo-pentagon' | 'geo-rectangle' | 'geo-rhombus-2' | 'geo-rhombus' | 'geo-star' | 'geo-trapezoid' | 'geo-triangle' | 'geo-x-box' | 'github' | 'group' | 'hidden' | 'image' | 'info-circle' | 'leading' | 'link' | 'lock-small' | 'lock' | 'menu' | 'minus' | 'mixed' | 'pack' | 'page' | 'plus' | 'question-mark-circle' | 'question-mark' | 'redo' | 'reset-zoom' | 'rotate-ccw' | 'rotate-cw' | 'ruler' | 'search' | 'send-backward' | 'send-to-back' | 'settings-horizontal' | 'settings-vertical-1' | 'settings-vertical' | 'share-1' | 'share-2' | 'size-extra-large' | 'size-large' | 'size-medium' | 'size-small' | 'spline-cubic' | 'spline-line' | 'stack-horizontal' | 'stack-vertical' | 'status-offline' | 'status-online' | 'stretch-horizontal' | 'stretch-vertical' | 'text-align-center' | 'text-align-justify' | 'text-align-left' | 'text-align-right' | 'tool-arrow' | 'tool-embed' | 'tool-eraser' | 'tool-frame' | 'tool-hand' | 'tool-highlight' | 'tool-laser' | 'tool-line' | 'tool-media' | 'tool-note' | 'tool-pencil' | 'tool-pointer' | 'tool-text' | 'trash' | 'triangle-down' | 'triangle-up' | 'twitter' | 'undo' | 'ungroup' | 'unlock-small' | 'unlock' | 'vertical-align-center' | 'vertical-align-end' | 'vertical-align-start' | 'visible' | 'warning-triangle' | 'zoom-in' | 'zoom-out'" "text": "'align-bottom-center' | 'align-bottom-left' | 'align-bottom-right' | 'align-bottom' | 'align-center-center' | 'align-center-horizontal' | 'align-center-left' | 'align-center-right' | 'align-center-vertical' | 'align-left' | 'align-right' | 'align-top-center' | 'align-top-left' | 'align-top-right' | 'align-top' | 'arrow-left' | 'arrowhead-arrow' | 'arrowhead-bar' | 'arrowhead-diamond' | 'arrowhead-dot' | 'arrowhead-none' | 'arrowhead-square' | 'arrowhead-triangle-inverted' | 'arrowhead-triangle' | 'aspect-ratio' | 'avatar' | 'blob' | 'bring-forward' | 'bring-to-front' | 'check-circle' | 'check' | 'checkbox-checked' | 'checkbox-empty' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'chevrons-ne' | 'chevrons-sw' | 'clipboard-copied' | 'clipboard-copy' | 'code' | 'collab' | 'color' | 'comment' | 'cross-2' | 'cross-circle' | 'cross' | 'dash-dashed' | 'dash-dotted' | 'dash-draw' | 'dash-solid' | 'discord' | 'distribute-horizontal' | 'distribute-vertical' | 'dot' | 'dots-horizontal' | 'dots-vertical' | 'drag-handle-dots' | 'duplicate' | 'edit' | 'error' | 'external-link' | 'file' | 'fill-none' | 'fill-pattern' | 'fill-semi' | 'fill-solid' | 'follow' | 'following' | 'font-draw' | 'font-mono' | 'font-sans' | 'font-serif' | 'geo-arrow-down' | 'geo-arrow-left' | 'geo-arrow-right' | 'geo-arrow-up' | 'geo-check-box' | 'geo-cloud' | 'geo-diamond' | 'geo-ellipse' | 'geo-hexagon' | 'geo-octagon' | 'geo-oval' | 'geo-pentagon' | 'geo-rectangle' | 'geo-rhombus-2' | 'geo-rhombus' | 'geo-star' | 'geo-trapezoid' | 'geo-triangle' | 'geo-x-box' | 'github' | 'group' | 'hidden' | 'image' | 'info-circle' | 'leading' | 'link' | 'lock-small' | 'lock' | 'menu' | 'minus' | 'mixed' | 'pack' | 'page' | 'plus' | 'question-mark-circle' | 'question-mark' | 'redo' | 'reset-zoom' | 'rotate-ccw' | 'rotate-cw' | 'ruler' | 'search' | 'send-backward' | 'send-to-back' | 'settings-horizontal' | 'settings-vertical-1' | 'settings-vertical' | 'share-1' | 'share-2' | 'size-extra-large' | 'size-large' | 'size-medium' | 'size-small' | 'spline-cubic' | 'spline-line' | 'stack-horizontal' | 'stack-vertical' | 'status-offline' | 'status-online' | 'stretch-horizontal' | 'stretch-vertical' | 'text-align-center' | 'text-align-justify' | 'text-align-left' | 'text-align-right' | 'tool-arrow' | 'tool-embed' | 'tool-eraser' | 'tool-frame' | 'tool-hand' | 'tool-highlight' | 'tool-laser' | 'tool-line' | 'tool-media' | 'tool-note' | 'tool-pencil' | 'tool-pointer' | 'tool-text' | 'trash' | 'triangle-down' | 'triangle-up' | 'twitter' | 'undo' | 'ungroup' | 'unlock-small' | 'unlock' | 'vertical-align-center' | 'vertical-align-end' | 'vertical-align-start' | 'visible' | 'warning-triangle' | 'zoom-in' | 'zoom-out'"
}, },
{ {
"kind": "Content", "kind": "Content",
@ -25682,6 +25708,34 @@
"endIndex": 2 "endIndex": 2
} }
}, },
{
"kind": "PropertySignature",
"canonicalReference": "tldraw!TLUiToast#severity:member",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "severity?: "
},
{
"kind": "Reference",
"text": "AlertSeverity",
"canonicalReference": "tldraw!AlertSeverity:type"
},
{
"kind": "Content",
"text": ";"
}
],
"isReadonly": false,
"isOptional": true,
"releaseTag": "Public",
"name": "severity",
"propertyTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
}
},
{ {
"kind": "PropertySignature", "kind": "PropertySignature",
"canonicalReference": "tldraw!TLUiToast#title:member", "canonicalReference": "tldraw!TLUiToast#title:member",

View file

@ -76,6 +76,7 @@ export {
} from './lib/ui/context/events' } from './lib/ui/context/events'
export { export {
useToasts, useToasts,
type AlertSeverity,
type TLUiToast, type TLUiToast,
type TLUiToastAction, type TLUiToastAction,
type TLUiToastsContextType, type TLUiToastsContextType,

View file

@ -128,6 +128,7 @@ export function registerDefaultExternalContentHandlers(
console.error(error) console.error(error)
toasts.addToast({ toasts.addToast({
title: msg('assets.url.failed'), title: msg('assets.url.failed'),
severity: 'error',
}) })
meta = { image: '', title: truncateStringWithEllipsis(url, 32), description: '' } meta = { image: '', title: truncateStringWithEllipsis(url, 32), description: '' }
} }
@ -250,6 +251,7 @@ export function registerDefaultExternalContentHandlers(
} catch (error) { } catch (error) {
toasts.addToast({ toasts.addToast({
title: msg('assets.files.upload-failed'), title: msg('assets.files.upload-failed'),
severity: 'error',
}) })
console.error(error) console.error(error)
return null return null
@ -369,6 +371,7 @@ export function registerDefaultExternalContentHandlers(
} catch (e) { } catch (e) {
toasts.addToast({ toasts.addToast({
title: msg('assets.url.failed'), title: msg('assets.url.failed'),
severity: 'error',
}) })
return return
} }

View file

@ -1013,7 +1013,7 @@
} }
.tlui-toast__icon { .tlui-toast__icon {
padding-top: var(--space-4); padding-top: 11px;
padding-left: var(--space-4); padding-left: var(--space-4);
color: var(--color-text-1); color: var(--color-text-1);
} }
@ -1028,6 +1028,22 @@
font-size: 12px; font-size: 12px;
} }
.tlui-toast__container[data-severity='success'] .tlui-icon {
color: var(--color-success);
}
.tlui-toast__container[data-severity='info'] .tlui-icon {
color: var(--color-info);
}
.tlui-toast__container[data-severity='warning'] .tlui-icon {
color: var(--color-warning);
}
.tlui-toast__container[data-severity='error'] .tlui-icon {
color: var(--color-error);
}
.tlui-toast__main { .tlui-toast__main {
flex-grow: 2; flex-grow: 2;
max-width: 280px; max-width: 280px;
@ -1043,6 +1059,8 @@
.tlui-toast__title { .tlui-toast__title {
font-weight: bold; font-weight: bold;
color: var(--color-text-1); color: var(--color-text-1);
/* this makes the default toast look better */
line-height: 16px;
} }
.tlui-toast__description { .tlui-toast__description {

View file

@ -44,9 +44,10 @@ export function DefaultDebugMenuContent() {
onSelect={() => { onSelect={() => {
addToast({ addToast({
id: uniqueId(), id: uniqueId(),
title: 'Something happened', title: 'Something good happened',
description: 'Hey, attend to this thing over here. It might be important!', description: 'Hey, attend to this thing over here. It might be important!',
keepOpen: true, keepOpen: true,
severity: 'success',
// icon?: string // icon?: string
// title?: string // title?: string
// description?: string // description?: string
@ -57,6 +58,7 @@ export function DefaultDebugMenuContent() {
title: 'Something happened', title: 'Something happened',
description: 'Hey, attend to this thing over here. It might be important!', description: 'Hey, attend to this thing over here. It might be important!',
keepOpen: true, keepOpen: true,
severity: 'info',
actions: [ actions: [
{ {
label: 'Primary', label: 'Primary',
@ -87,10 +89,10 @@ export function DefaultDebugMenuContent() {
}) })
addToast({ addToast({
id: uniqueId(), id: uniqueId(),
title: 'Something happened', title: 'Something maybe bad happened',
description: 'Hey, attend to this thing over here. It might be important!', description: 'Hey, attend to this thing over here. It might be important!',
keepOpen: true, keepOpen: true,
icon: 'twitter', severity: 'warning',
actions: [ actions: [
{ {
label: 'Primary', label: 'Primary',
@ -115,6 +117,12 @@ export function DefaultDebugMenuContent() {
}, },
], ],
}) })
addToast({
id: uniqueId(),
title: 'Something bad happened',
severity: 'error',
keepOpen: true,
})
}} }}
label={untranslated('Show toast')} label={untranslated('Show toast')}
/> />

View file

@ -1,12 +1,19 @@
import * as T from '@radix-ui/react-toast' import * as T from '@radix-ui/react-toast'
import * as React from 'react' import * as React from 'react'
import { TLUiToast, useToasts } from '../context/toasts' import { AlertSeverity, TLUiToast, useToasts } from '../context/toasts'
import { useTranslation } from '../hooks/useTranslation/useTranslation' import { useTranslation } from '../hooks/useTranslation/useTranslation'
import { TLUiIconType } from '../icon-types' import { TLUiIconType } from '../icon-types'
import { TldrawUiButton } from './primitives/Button/TldrawUiButton' import { TldrawUiButton } from './primitives/Button/TldrawUiButton'
import { TldrawUiButtonLabel } from './primitives/Button/TldrawUiButtonLabel' import { TldrawUiButtonLabel } from './primitives/Button/TldrawUiButtonLabel'
import { TldrawUiIcon } from './primitives/TldrawUiIcon' import { TldrawUiIcon } from './primitives/TldrawUiIcon'
const SEVERITY_TO_ICON: { [msg in AlertSeverity]: TLUiIconType } = {
success: 'check-circle',
warning: 'warning-triangle',
error: 'cross-circle',
info: 'info-circle',
}
function Toast({ toast }: { toast: TLUiToast }) { function Toast({ toast }: { toast: TLUiToast }) {
const { removeToast } = useToasts() const { removeToast } = useToasts()
const msg = useTranslation() const msg = useTranslation()
@ -19,15 +26,18 @@ function Toast({ toast }: { toast: TLUiToast }) {
const hasActions = toast.actions && toast.actions.length > 0 const hasActions = toast.actions && toast.actions.length > 0
const icon = toast.icon || (toast.severity && SEVERITY_TO_ICON[toast.severity])
return ( return (
<T.Root <T.Root
onOpenChange={onOpenChange} onOpenChange={onOpenChange}
className="tlui-toast__container" className="tlui-toast__container"
duration={toast.keepOpen ? Infinity : 5000} duration={toast.keepOpen ? Infinity : 5000}
data-severity={toast.severity}
> >
{toast.icon && ( {icon && (
<div className="tlui-toast__icon"> <div className="tlui-toast__icon">
<TldrawUiIcon icon={toast.icon as TLUiIconType} /> <TldrawUiIcon icon={icon} />
</div> </div>
)} )}
<div className="tlui-toast__main"> <div className="tlui-toast__main">

View file

@ -2,10 +2,14 @@ import { Editor, uniqueId } from '@tldraw/editor'
import { ReactNode, createContext, useCallback, useContext, useState } from 'react' import { ReactNode, createContext, useCallback, useContext, useState } from 'react'
import { TLUiIconType } from '../icon-types' import { TLUiIconType } from '../icon-types'
/** @public */
export type AlertSeverity = 'success' | 'info' | 'warning' | 'error'
/** @public */ /** @public */
export interface TLUiToast { export interface TLUiToast {
id: string id: string
icon?: TLUiIconType icon?: TLUiIconType
severity?: AlertSeverity
title?: string title?: string
description?: string description?: string
actions?: TLUiToastAction[] actions?: TLUiToastAction[]

View file

@ -15,7 +15,7 @@ export function useCopyAs() {
copyAs(editor, ids, format).catch(() => { copyAs(editor, ids, format).catch(() => {
addToast({ addToast({
id: 'copy-fail', id: 'copy-fail',
icon: 'warning-triangle', severity: 'warning',
title: msg('toast.error.copy-fail.title'), title: msg('toast.error.copy-fail.title'),
description: msg('toast.error.copy-fail.desc'), description: msg('toast.error.copy-fail.desc'),
}) })

View file

@ -12,6 +12,7 @@ export function useEditorEvents() {
addToast({ addToast({
title: 'Maximum Shapes Reached', title: 'Maximum Shapes Reached',
description: `You've reached the maximum number of shapes allowed on ${name} (${count}). Please delete some shapes or move to a different page to continue.`, description: `You've reached the maximum number of shapes allowed on ${name} (${count}). Please delete some shapes or move to a different page to continue.`,
severity: 'warning',
}) })
} }

View file

@ -19,9 +19,9 @@ export function useExportAs() {
console.error(e.message) console.error(e.message)
addToast({ addToast({
id: 'export-fail', id: 'export-fail',
// icon: 'error',
title: msg('toast.error.export-fail.title'), title: msg('toast.error.export-fail.title'),
description: msg('toast.error.export-fail.desc'), description: msg('toast.error.export-fail.desc'),
severity: 'error',
}) })
}) })
}, },

View file

@ -32,6 +32,7 @@ export type TLUiIconType =
| 'blob' | 'blob'
| 'bring-forward' | 'bring-forward'
| 'bring-to-front' | 'bring-to-front'
| 'check-circle'
| 'check' | 'check'
| 'checkbox-checked' | 'checkbox-checked'
| 'checkbox-empty' | 'checkbox-empty'
@ -48,6 +49,7 @@ export type TLUiIconType =
| 'color' | 'color'
| 'comment' | 'comment'
| 'cross-2' | 'cross-2'
| 'cross-circle'
| 'cross' | 'cross'
| 'dash-dashed' | 'dash-dashed'
| 'dash-dotted' | 'dash-dotted'
@ -62,6 +64,7 @@ export type TLUiIconType =
| 'drag-handle-dots' | 'drag-handle-dots'
| 'duplicate' | 'duplicate'
| 'edit' | 'edit'
| 'error'
| 'external-link' | 'external-link'
| 'file' | 'file'
| 'fill-none' | 'fill-none'
@ -199,6 +202,7 @@ export const iconTypes = [
'blob', 'blob',
'bring-forward', 'bring-forward',
'bring-to-front', 'bring-to-front',
'check-circle',
'check', 'check',
'checkbox-checked', 'checkbox-checked',
'checkbox-empty', 'checkbox-empty',
@ -215,6 +219,7 @@ export const iconTypes = [
'color', 'color',
'comment', 'comment',
'cross-2', 'cross-2',
'cross-circle',
'cross', 'cross',
'dash-dashed', 'dash-dashed',
'dash-dotted', 'dash-dotted',
@ -229,6 +234,7 @@ export const iconTypes = [
'drag-handle-dots', 'drag-handle-dots',
'duplicate', 'duplicate',
'edit', 'edit',
'error',
'external-link', 'external-link',
'file', 'file',
'fill-none', 'fill-none',

View file

@ -267,6 +267,7 @@ export async function parseAndLoadDocument(
addToast({ addToast({
title: msg('file-system.file-open-error.title'), title: msg('file-system.file-open-error.title'),
description, description,
severity: 'error',
}) })
return return