tldraw/apps/examples/src/index.tsx
Gabriel Lee 260a31db81
feat: add new prop to force mobile mode layout (#1734)
Adds a new prop to force mobile mode layout, similar to how the
?layout=mobile query param works.

An alternative of having the prop accept a breakpoint number was
considered, but while that provides more flexibility, it's best if
usages of tldraw don't need to know about the internal workings of
tldraw. (e.g. someone might use breakpoint 7 to get the "desktop" mode,
but that won't be reliable when in the future more breakpoints are
added)


![licecap-output-1](https://github.com/tldraw/tldraw/assets/5616556/b08fa239-be4f-46c2-9a78-c53b453e4d1a)

![licecap-output-2](https://github.com/tldraw/tldraw/assets/5616556/9be55807-adc7-4253-8b20-757a07a8b157)

Closes #1709 

### Change Type

- [ ] `patch` — Bug fix
- [x] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [ ] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

1. `<Tldraw persistenceKey="tldraw_example" autoFocus
forceMobileModeLayout />`
2. notice that the layout stays in mobile mode no matter the width of
the screen

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- add new prop to force mobile mode layout

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2023-11-11 14:11:59 +00:00

241 lines
5.9 KiB
TypeScript

import { getAssetUrlsByMetaUrl } from '@tldraw/assets/urls'
import {
DefaultErrorFallback,
ErrorBoundary,
setDefaultEditorAssetUrls,
setDefaultUiAssetUrls,
} from '@tldraw/tldraw'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider, createBrowserRouter } from 'react-router-dom'
import ExamplesTldrawLogo from './components/ExamplesTldrawLogo'
import { ListLink } from './components/ListLink'
import BasicExample from './BasicExample'
import APIExample from './examples/APIExample'
import AssetPropsExample from './examples/AssetOptionsExample'
import CanvasEventsExample from './examples/CanvasEventsExample'
import CustomComponentsExample from './examples/CustomComponentsExample'
import CustomConfigExample from './examples/CustomConfigExample/CustomConfigExample'
import CustomStylesExample from './examples/CustomStylesExample/CustomStylesExample'
import CustomUiExample from './examples/CustomUiExample/CustomUiExample'
import ErrorBoundaryExample from './examples/ErrorBoundaryExample/ErrorBoundaryExample'
import ExplodedExample from './examples/ExplodedExample'
import ExternalContentSourcesExample from './examples/ExternalContentSourcesExample'
import ForceMobileExample from './examples/ForceBreakpointExample'
import HideUiExample from './examples/HideUiExample'
import MetaExample from './examples/MetaExample'
import MultipleExample from './examples/MultipleExample'
import OnTheCanvasExample from './examples/OnTheCanvas'
import PersistenceExample from './examples/PersistenceExample'
import ReadOnlyExample from './examples/ReadOnlyExample'
import ScrollExample from './examples/ScrollExample'
import ShapeMetaExample from './examples/ShapeMetaExample'
import SnapshotExample from './examples/SnapshotExample/SnapshotExample'
import StoreEventsExample from './examples/StoreEventsExample'
import UiEventsExample from './examples/UiEventsExample'
import UserPresenceExample from './examples/UserPresenceExample'
import ZonesExample from './examples/ZonesExample'
import EndToEnd from './examples/end-to-end/end-to-end'
import OnlyEditorExample from './examples/only-editor/OnlyEditor'
import YjsExample from './examples/yjs/YjsExample'
// This example is only used for end to end tests
// we use secret internal `setDefaultAssetUrls` functions to set these at the
// top-level so assets don't need to be passed down in every single example.
const assetUrls = getAssetUrlsByMetaUrl()
setDefaultEditorAssetUrls(assetUrls)
setDefaultUiAssetUrls(assetUrls)
type Example = {
path: string
title?: string
element: JSX.Element
}
export const allExamples: Example[] = [
{
title: 'Basic (development)',
path: 'develop',
element: <BasicExample />,
},
{
title: 'Collaboration (with Yjs)',
path: 'yjs',
element: <YjsExample />,
},
{
title: 'Editor API',
path: 'api',
element: <APIExample />,
},
{
title: 'Multiple editors',
path: 'multiple',
element: <MultipleExample />,
},
{
title: 'Meta Example',
path: 'meta',
element: <MetaExample />,
},
{
title: 'Readonly Example',
path: 'readonly',
element: <ReadOnlyExample />,
},
{
title: 'Things on the canvas',
path: 'things-on-the-canvas',
element: <OnTheCanvasExample />,
},
{
title: 'Scroll example',
path: 'scroll',
element: <ScrollExample />,
},
{
title: 'Custom shapes / tools',
path: 'custom-config',
element: <CustomConfigExample />,
},
{
title: 'Sublibraries',
path: 'exploded',
element: <ExplodedExample />,
},
{
title: 'Error boundary',
path: 'error-boundary',
element: <ErrorBoundaryExample />,
},
{
title: 'Custom UI',
path: 'custom-ui',
element: <CustomUiExample />,
},
{
title: 'Hide UI',
path: 'hide-ui',
element: <HideUiExample />,
},
{
title: 'UI components',
path: 'custom-components',
element: <CustomComponentsExample />,
},
{
title: 'UI events',
path: 'ui-events',
element: <UiEventsExample />,
},
{
title: 'Canvas events',
path: 'canvas-events',
element: <CanvasEventsExample />,
},
{
title: 'Store events',
path: 'store-events',
element: <StoreEventsExample />,
},
{
title: 'User presence',
path: 'user-presence',
element: <UserPresenceExample />,
},
{
title: 'UI zones',
path: 'zones',
element: <ZonesExample />,
},
{
title: 'Persistence',
path: 'persistence',
element: <PersistenceExample />,
},
{
title: 'Snapshots',
path: 'snapshots',
element: <SnapshotExample />,
},
{
title: 'Force mobile breakpoint',
path: 'force-mobile',
element: <ForceMobileExample />,
},
{
title: 'Custom styles',
path: 'custom-styles',
element: <CustomStylesExample />,
},
{
title: 'Shape meta property',
path: 'shape-meta',
element: <ShapeMetaExample />,
},
{
title: 'Only editor',
path: 'only-editor',
element: <OnlyEditorExample />,
},
{
title: 'Asset props',
path: 'asset-props',
element: <AssetPropsExample />,
},
{
title: 'External content sources',
path: 'external-content-sources',
element: <ExternalContentSourcesExample />,
},
// not listed
{
path: 'end-to-end',
element: <EndToEnd />,
},
]
function App() {
return (
<div className="examples">
<div className="examples__header">
<ExamplesTldrawLogo />
<p>
See docs at <a href="https://tldraw.dev">tldraw.dev</a>
</p>
</div>
<ul className="examples__list">
{allExamples
.filter((example) => example.title)
.map((example) => (
<ListLink key={example.path} title={example.title!} route={example.path} />
))}
</ul>
</div>
)
}
const router = createBrowserRouter([
{
path: '/',
element: <App />,
},
...allExamples,
])
const rootElement = document.getElementById('root')
const root = createRoot(rootElement!)
root.render(
<StrictMode>
<ErrorBoundary
fallback={(error) => <DefaultErrorFallback error={error} />}
onError={(error) => console.error(error)}
>
<RouterProvider router={router} />
</ErrorBoundary>
</StrictMode>
)