Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Use react-aria-components #371

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
compressionLevel: mixed

enableGlobalCache: false

logFilters:
- code: YN0002
level: discard
Expand Down
1 change: 1 addition & 0 deletions apps/dev/src/schema/example/RichTextFields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const RichTextFields = Config.document('Rich text fields', {
}),
makeRO: Field.check('Make read-only'),
nested: Field.richText('With nested blocks', {
enableTables: true,
schema: {
Inner: Config.type('Inner', {
fields: {
Expand Down
7 changes: 6 additions & 1 deletion build.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,12 @@ function jsEntry({watch, test, report}) {
'lib0/webcrypto': `data:text/javascript,
import {crypto} from '@alinea/iso'
export const subtle = crypto.subtle
export const getRandomValues = crypto.getRandomValues.bind(crypto)`
export const getRandomValues = crypto.getRandomValues.bind(crypto)`,

// Used in react-aria-components, not ESM
'use-sync-external-store/shim/index.js': `data:text/javascript,
export {useSyncExternalStore} from 'react'
`
},
define: {
// See https://github.com/pmndrs/jotai/blob/2188d7557500e59c10415a9e74bb5cfc8a3f9c31/src/react/useSetAtom.ts#L33
Expand Down
109 changes: 53 additions & 56 deletions src/dashboard/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {SuspenseBoundary} from './util/SuspenseBoundary.js'
import {ErrorBoundary} from './view/ErrorBoundary.js'
import {Modal} from './view/Modal.js'
import {Sidebar} from './view/Sidebar.js'
import {Toolbar} from './view/Toolbar.js'
import {Viewport} from './view/Viewport.js'
import {SidebarSettings} from './view/sidebar/SidebarSettings.js'

Expand Down Expand Up @@ -86,61 +85,59 @@ function AppAuthenticated() {
</Modal>
)}
<Statusbar.Provider>
<Toolbar.Provider>
<Sidebar.Provider>
<Head>
<FavIcon color={color} />
</Head>
<div
style={{
flex: '1',
display: 'flex',
minHeight: 0,
position: 'relative'
}}
>
<Sidebar.Nav>
{Object.entries(roots).map(([key, root], i) => {
const isSelected = key === currentRoot
const {id, ...location} = entryLocation
const link =
location.root === key
? nav.entry(location)
: nav.root({
workspace,
root: key,
locale: preferredLanguage
})
const {label, icon} = Root.data(root)
return (
<Sidebar.Nav.Item
key={key}
selected={isEntry && isSelected}
href={link}
aria-label={label}
>
<Icon icon={icon ?? IcRoundDescription} />
</Sidebar.Nav.Item>
)
})}
{/*<DraftsButton />*/}
<SidebarSettings />
</Sidebar.Nav>
<ErrorBoundary>
<SuspenseBoundary name="main" fallback={<Loader absolute />}>
<RouteView fallback={null} />
</SuspenseBoundary>
</ErrorBoundary>
</div>
{alineaDev && (
<Statusbar.Root>
<Statusbar.Status icon={MaterialSymbolsDatabase}>
{meta.contentHash}
</Statusbar.Status>
</Statusbar.Root>
)}
</Sidebar.Provider>
</Toolbar.Provider>
<Sidebar.Provider>
<Head>
<FavIcon color={color} />
</Head>
<div
style={{
flex: '1',
display: 'flex',
minHeight: 0,
position: 'relative'
}}
>
<Sidebar.Nav>
{Object.entries(roots).map(([key, root], i) => {
const isSelected = key === currentRoot
const {id, ...location} = entryLocation
const link =
location.root === key
? nav.entry(location)
: nav.root({
workspace,
root: key,
locale: preferredLanguage
})
const {label, icon} = Root.data(root)
return (
<Sidebar.Nav.Item
key={key}
selected={isEntry && isSelected}
href={link}
aria-label={label}
>
<Icon icon={icon ?? IcRoundDescription} />
</Sidebar.Nav.Item>
)
})}
{/*<DraftsButton />*/}
<SidebarSettings />
</Sidebar.Nav>
<ErrorBoundary>
<SuspenseBoundary name="main" fallback={<Loader absolute />}>
<RouteView fallback={null} />
</SuspenseBoundary>
</ErrorBoundary>
</div>
{alineaDev && (
<Statusbar.Root>
<Statusbar.Status icon={MaterialSymbolsDatabase}>
{meta.contentHash}
</Statusbar.Status>
</Statusbar.Root>
)}
</Sidebar.Provider>
</Statusbar.Provider>
</>
)
Expand Down
2 changes: 1 addition & 1 deletion src/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"@dnd-kit/core": "^3.1.1",
"@dnd-kit/sortable": "^4.0.0",
"@dnd-kit/utilities": "^2.0.0",
"@floating-ui/react-dom": "^0.7.1",
"@headless-tree/core": "^0.0.8",
"@headless-tree/react": "^0.0.7",
"@headlessui/react": "^2.1.10",
Expand All @@ -21,6 +20,7 @@
"lib0": "^0.2.88",
"p-limit": "^4.0.0",
"pretty-bytes": "^6.0.0",
"react-aria-components": "^1.0.1",
"react-query": "^3.39.1",
"react-tiny-virtual-list": "^2.2.0",
"smartcrop": "^2.0.5",
Expand Down
20 changes: 14 additions & 6 deletions src/dashboard/view/EntryEdit.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@
flex-direction: column;

&-tabs {
margin: auto;
padding: 0 calc(var(--alinea-main-padding-x) - 8px);
padding-bottom: 2px;
max-width: var(--alinea-main-width);
display: flex;
flex-direction: column;
width: 100%;
flex-grow: 1;
min-width: 0;

@include ml {
margin-top: -16px;
&-header {
margin: auto;
padding: 0 calc(var(--alinea-main-padding-x) - 8px);
padding-bottom: 2px;
max-width: var(--alinea-main-width);

@include ml {
margin-top: -16px;
}
}
}
}
112 changes: 59 additions & 53 deletions src/dashboard/view/EntryEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {TabsHeader} from 'alinea/field/tabs/Tabs.view'
import {Button, HStack, Stack, VStack} from 'alinea/ui'
import {Main} from 'alinea/ui/Main'
import {Statusbar} from 'alinea/ui/Statusbar'
import {Tabs} from 'alinea/ui/Tabs'
import {TabPanel, Tabs} from 'alinea/ui/Tabs'
import {IcOutlineTableRows} from 'alinea/ui/icons/IcOutlineTableRows'
import {IcRoundInsertDriveFile} from 'alinea/ui/icons/IcRoundInsertDriveFile'
import {IcRoundTranslate} from 'alinea/ui/icons/IcRoundTranslate'
Expand Down Expand Up @@ -200,63 +200,69 @@ export function EntryEdit({editor}: EntryEditProps) {
<FieldToolbar.Provider>
<EntryHeader editor={editor} />
{showHistory && <EntryHistory editor={editor} />}
<Tabs.Root style={{flex: 1}}>
<EntryTitle
editor={editor}
backLink={
editor.activeVersion.parentId
? nav.entry({
id: editor.activeVersion.parentId,
workspace: editor.activeVersion.workspace
})
: nav.entry({id: undefined})
}
>
{hasRootTabs && (
<div className={styles.root.tabs()}>
<TabsHeader backdrop={false} section={sections[0]} />
</div>
)}
</EntryTitle>
<Main.Container>
{untranslated && (
<div>
<EntryNotice
icon={IcRoundTranslate}
title="Untranslated"
variant="untranslated"
>
{editor.parentNeedsTranslation
? 'Translate the parent page first.'
: 'Enter the details below and save to start translating.'}
</EntryNotice>
</div>
)}
<EntryEditorProvider editor={editor}>
<SuspenseBoundary name="input form">
{mode === EditMode.Diff ? (
<ShowChanges editor={editor} />
) : hasRootTabs && visibleTypes ? (
<Tabs.Panels>
{visibleTypes.map((type, i) => {
<div className={styles.root.tabs()}>
<Tabs>
<EntryTitle
editor={editor}
backLink={
editor.activeVersion.parentId
? nav.entry({
id: editor.activeVersion.parentId,
workspace: editor.activeVersion.workspace
})
: nav.entry({id: undefined})
}
>
{hasRootTabs && (
<div className={styles.root.tabs.header()}>
<TabsHeader
id="entry"
backdrop={false}
section={sections[0]}
/>
</div>
)}
</EntryTitle>
<Main.Container>
{untranslated && (
<div>
<EntryNotice
icon={IcRoundTranslate}
title="Untranslated"
variant="untranslated"
>
This page has not yet been translated to this language,
<br />
{editor.parentNeedsTranslation
? 'Translate the parent page first.'
: 'Enter the details below and save to start translating.'}
</EntryNotice>
</div>
)}
<EntryEditorProvider editor={editor}>
<SuspenseBoundary name="input form">
{mode === EditMode.Diff ? (
<ShowChanges editor={editor} />
) : hasRootTabs && visibleTypes ? (
visibleTypes.map((type, i) => {
return (
<FormProvider form={form} key={i}>
<Tabs.Panel unmount={false} tabIndex={i}>
<TabPanel id={`entry+${i}`}>
<InputForm type={type} />
</Tabs.Panel>
</TabPanel>
</FormProvider>
)
})}
</Tabs.Panels>
) : (
<VStack gap={18}>
<InputForm form={form} />
</VStack>
)}
</SuspenseBoundary>
</EntryEditorProvider>
</Main.Container>
</Tabs.Root>
})
) : (
<VStack gap={18}>
<InputForm form={form} />
</VStack>
)}
</SuspenseBoundary>
</EntryEditorProvider>
</Main.Container>
</Tabs>
</div>
<FieldToolbar.Root />
</FieldToolbar.Provider>
</Main>
Expand Down
6 changes: 3 additions & 3 deletions src/dashboard/view/SearchBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {HStack, Stack} from 'alinea/ui'
import {IcOutlineGridView} from 'alinea/ui/icons/IcOutlineGridView'
import {IcOutlineList} from 'alinea/ui/icons/IcOutlineList'
import {IcRoundSearch} from 'alinea/ui/icons/IcRoundSearch'
import {useLayoutEffect, useMemo, useState} from 'react'
import {memo, useLayoutEffect, useMemo, useState} from 'react'
import {useFocusList} from '../hook/UseFocusList.js'
import {useLocale} from '../hook/UseLocale.js'
import {useNav} from '../hook/UseNav.js'
Expand All @@ -17,7 +17,7 @@ import {Explorer, ExporerItemSelect} from './explorer/Explorer.js'

const styles = styler(css)

export function SearchBox() {
export const SearchBox = memo(function SearchBox() {
const nav = useNav()
const navigate = useNavigate()
const location = useLocation()
Expand Down Expand Up @@ -102,4 +102,4 @@ export function SearchBox() {
</list.Container>
</div>
)
}
})
2 changes: 2 additions & 0 deletions src/dashboard/view/Sidebar.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,9 @@
padding: 6px 12px 6px 6px;

&:focus,
&:focus-visible,
&:hover {
outline: none;
background: var(--alinea-highlight);
}
}
Expand Down
Loading
Loading