feat: update mobile design (#1526)
This commit is contained in:
@@ -66,6 +66,7 @@ const startApplication: StartApplication = async function startApplication(
|
||||
root = createRoot(appendedRootNode)
|
||||
|
||||
disableIosTextFieldZoom()
|
||||
document.documentElement.style.setProperty('--viewport-height', `${window.innerHeight}px`)
|
||||
|
||||
root.render(
|
||||
<ApplicationGroupView
|
||||
|
||||
@@ -68,7 +68,7 @@ const ContentList: FunctionComponent<Props> = ({
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'infinite-scroll max-h-[75vh] overflow-y-auto overflow-x-hidden focus:shadow-none focus:outline-none',
|
||||
'infinite-scroll overflow-y-auto overflow-x-hidden focus:shadow-none focus:outline-none',
|
||||
'md:max-h-full md:overflow-y-hidden md:hover:overflow-y-auto',
|
||||
'md:hover:[overflow-y:_overlay]',
|
||||
)}
|
||||
|
||||
@@ -185,13 +185,13 @@ const ContentListView: FunctionComponent<Props> = ({
|
||||
<div
|
||||
id="items-column"
|
||||
className={classNames(
|
||||
'sn-component section app-column flex flex-col border-b border-solid border-border ',
|
||||
'sn-component section app-column flex h-screen flex-col md:h-full',
|
||||
'xl:w-87.5 xsm-only:!w-full sm-only:!w-full pointer-coarse:md-only:!w-52 pointer-coarse:lg-only:!w-52',
|
||||
)}
|
||||
aria-label={'Notes & Files'}
|
||||
ref={itemsViewPanelRef}
|
||||
>
|
||||
<ResponsivePaneContent paneId={AppPaneId.Items} contentClassName="min-h-[85vh]">
|
||||
<ResponsivePaneContent paneId={AppPaneId.Items} className="min-h-[85vh]">
|
||||
<div id="items-title-bar" className="section-title-bar border-b border-solid border-border">
|
||||
<div id="items-title-bar-container">
|
||||
<input
|
||||
|
||||
@@ -4,6 +4,7 @@ import Icon from '../../Icon/Icon'
|
||||
import { classNames } from '@/Utils/ConcatenateClassNames'
|
||||
import Popover from '@/Components/Popover/Popover'
|
||||
import DisplayOptionsMenu from './DisplayOptionsMenu'
|
||||
import { NavigationMenuButton } from '@/Components/NavigationMenu/NavigationMenu'
|
||||
|
||||
type Props = {
|
||||
application: {
|
||||
@@ -35,7 +36,8 @@ const ContentListHeader = ({
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="section-title-bar-header gap-1">
|
||||
<div className="section-title-bar-header items-start gap-1">
|
||||
<NavigationMenuButton />
|
||||
<div className="flex flex-grow flex-col">
|
||||
<div className="text-lg font-semibold text-text">{panelTitle}</div>
|
||||
{optionsSubtitle && <div className="text-xs text-passive-0">{optionsSubtitle}</div>}
|
||||
|
||||
@@ -60,7 +60,7 @@ const FileViewWithoutProtection = ({ application, viewControllerManager, file }:
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex min-h-screen flex-col md:min-h-full md:flex-grow">
|
||||
<div className="flex min-h-0 flex-grow flex-col">
|
||||
<FilePreview file={file} application={application} key={file.uuid} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,11 +30,11 @@ const AccountMenuButton = ({
|
||||
onClick={toggleMenu}
|
||||
className={classNames(
|
||||
isOpen ? 'bg-border' : '',
|
||||
'flex h-full w-12 cursor-pointer items-center justify-center rounded-full md:w-8',
|
||||
'flex h-full w-8 cursor-pointer items-center justify-center rounded-full',
|
||||
)}
|
||||
>
|
||||
<div className={hasError ? 'text-danger' : user ? 'text-info' : 'text-neutral'}>
|
||||
<Icon type="account-circle" className="h-6 w-6 hover:text-info md:h-5 md:w-5" />
|
||||
<Icon type="account-circle" className="h-5 w-5 hover:text-info" />
|
||||
</div>
|
||||
</button>
|
||||
<Popover anchorElement={buttonRef.current} open={isOpen} togglePopover={toggleMenu} side="top" className="py-2">
|
||||
|
||||
@@ -341,7 +341,7 @@ class Footer extends PureComponent<Props, State> {
|
||||
<div className="sn-component">
|
||||
<footer
|
||||
id="footer-bar"
|
||||
className="z-footer-bar flex h-12 w-full select-none items-center justify-between border-t border-border bg-contrast pl-3.5 pr-6 text-text md:h-8 md:px-3"
|
||||
className="z-footer-bar hidden h-8 w-full select-none items-center justify-between border-t border-border bg-contrast px-3 text-text md:flex"
|
||||
>
|
||||
<div className="left flex h-full">
|
||||
<div className="sk-app-bar-item relative z-footer-bar-item ml-0 select-none">
|
||||
|
||||
@@ -28,7 +28,7 @@ const QuickSettingsButton = ({
|
||||
<>
|
||||
<button
|
||||
onClick={toggleMenu}
|
||||
className="flex h-full w-12 cursor-pointer items-center justify-center md:w-8"
|
||||
className="flex h-full w-8 cursor-pointer items-center justify-center"
|
||||
ref={buttonRef}
|
||||
>
|
||||
<div className="h-5">
|
||||
|
||||
@@ -11,6 +11,7 @@ export const ICONS = {
|
||||
'check-bold': icons.CheckBoldIcon,
|
||||
'check-circle': icons.CheckCircleIcon,
|
||||
'chevron-down': icons.ChevronDownIcon,
|
||||
'chevron-left': icons.ChevronLeftIcon,
|
||||
'chevron-right': icons.ChevronRightIcon,
|
||||
'clear-circle-filled': icons.ClearCircleFilledIcon,
|
||||
'cloud-off': icons.CloudOffIcon,
|
||||
@@ -33,6 +34,7 @@ export const ICONS = {
|
||||
'menu-arrow-down': icons.MenuArrowDownIcon,
|
||||
'menu-arrow-right': icons.MenuArrowRightIcon,
|
||||
'menu-close': icons.MenuCloseIcon,
|
||||
'menu-variant': icons.MenuVariantIcon,
|
||||
'notes-filled': icons.NotesFilledIcon,
|
||||
'pencil-filled': icons.PencilFilledIcon,
|
||||
'pencil-off': icons.PencilOffIcon,
|
||||
|
||||
@@ -9,6 +9,8 @@ import PanelResizer, { PanelSide, ResizeFinishCallback, PanelResizeType } from '
|
||||
import ResponsivePaneContent from '@/Components/ResponsivePane/ResponsivePaneContent'
|
||||
import { AppPaneId } from '@/Components/ResponsivePane/AppPaneMetadata'
|
||||
import { classNames } from '@/Utils/ConcatenateClassNames'
|
||||
import Icon from '../Icon/Icon'
|
||||
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
|
||||
|
||||
type Props = {
|
||||
application: WebApplication
|
||||
@@ -18,6 +20,7 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
|
||||
const viewControllerManager = useMemo(() => application.getViewControllerManager(), [application])
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const [panelWidth, setPanelWidth] = useState<number>(0)
|
||||
const { toggleAppPane } = useResponsiveAppPane()
|
||||
|
||||
useEffect(() => {
|
||||
const removeObserver = application.addEventObserver(async () => {
|
||||
@@ -48,31 +51,58 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
|
||||
return (
|
||||
<div
|
||||
id="navigation"
|
||||
className={'sn-component section app-column w-[220px] xsm-only:!w-full sm-only:!w-full'}
|
||||
className="sn-component section app-column h-screen max-h-screen w-[220px] overflow-hidden pb-8 md:h-full md:min-h-0 md:py-0 xsm-only:!w-full sm-only:!w-full"
|
||||
ref={ref}
|
||||
>
|
||||
<ResponsivePaneContent
|
||||
paneId={AppPaneId.Navigation}
|
||||
contentElementId="navigation-content"
|
||||
contentClassName="min-h-[85vh]"
|
||||
>
|
||||
<div className={'section-title-bar'}>
|
||||
<div className="section-title-bar-header">
|
||||
<div className="title text-sm">
|
||||
<span className="font-bold">Views</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ResponsivePaneContent paneId={AppPaneId.Navigation} contentElementId="navigation-content">
|
||||
<div
|
||||
className={classNames(
|
||||
'h-full overflow-y-auto overflow-x-hidden',
|
||||
'md:overflow-y-hidden md:hover:overflow-y-auto',
|
||||
'flex-grow overflow-y-auto overflow-x-hidden md:overflow-y-hidden md:hover:overflow-y-auto',
|
||||
'md:hover:[overflow-y:_overlay]',
|
||||
)}
|
||||
>
|
||||
<div className={'section-title-bar'}>
|
||||
<div className="section-title-bar-header">
|
||||
<div className="title text-sm">
|
||||
<span className="font-bold">Views</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<SmartViewsSection viewControllerManager={viewControllerManager} />
|
||||
<TagsSection viewControllerManager={viewControllerManager} />
|
||||
</div>
|
||||
<div className="flex items-center border-t border-border px-3.5 pt-2.5 md:hidden">
|
||||
<button
|
||||
className="flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border bg-default text-neutral hover:bg-contrast focus:bg-contrast"
|
||||
onClick={() => {
|
||||
toggleAppPane(AppPaneId.Items)
|
||||
}}
|
||||
title="Go to items list"
|
||||
aria-label="Go to items list"
|
||||
>
|
||||
<Icon type="chevron-left" />
|
||||
</button>
|
||||
<button
|
||||
className="ml-auto flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border bg-default text-neutral hover:bg-contrast focus:bg-contrast"
|
||||
onClick={() => {
|
||||
viewControllerManager.accountMenuController.toggleShow()
|
||||
}}
|
||||
title="Go to items list"
|
||||
aria-label="Go to items list"
|
||||
>
|
||||
<Icon type="account-circle" />
|
||||
</button>
|
||||
<button
|
||||
className="ml-2.5 flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border bg-default text-neutral hover:bg-contrast focus:bg-contrast"
|
||||
onClick={() => {
|
||||
viewControllerManager.quickSettingsMenuController.toggle()
|
||||
}}
|
||||
title="Go to items list"
|
||||
aria-label="Go to items list"
|
||||
>
|
||||
<Icon type="tune" />
|
||||
</button>
|
||||
</div>
|
||||
</ResponsivePaneContent>
|
||||
{ref.current && (
|
||||
<PanelResizer
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import Icon from '../Icon/Icon'
|
||||
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
|
||||
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
|
||||
|
||||
export const NavigationMenuButton = () => {
|
||||
const { toggleAppPane } = useResponsiveAppPane()
|
||||
|
||||
return (
|
||||
<button
|
||||
className="bg-text-padding mr-3 inline-flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border align-middle text-neutral hover:bg-contrast focus:bg-contrast md:hidden"
|
||||
onClick={() => {
|
||||
toggleAppPane(AppPaneId.Navigation)
|
||||
}}
|
||||
title="Navigation menu"
|
||||
aria-label="Navigation menu"
|
||||
>
|
||||
<Icon type="menu-variant" />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
@@ -9,6 +9,27 @@ import FileView from '@/Components/FileView/FileView'
|
||||
import { FileDnDContext } from '@/Components/FileDragNDropProvider/FileDragNDropProvider'
|
||||
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
|
||||
import ResponsivePaneContent from '../ResponsivePane/ResponsivePaneContent'
|
||||
import Icon from '../Icon/Icon'
|
||||
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
|
||||
|
||||
const MobileItemsListButton = () => {
|
||||
const { toggleAppPane } = useResponsiveAppPane()
|
||||
|
||||
return (
|
||||
<div className="px-3.5 pt-2.5 md:hidden">
|
||||
<button
|
||||
className="bg-text-padding flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border text-neutral hover:bg-contrast focus:bg-contrast"
|
||||
onClick={() => {
|
||||
toggleAppPane(AppPaneId.Items)
|
||||
}}
|
||||
title="Go to items list"
|
||||
aria-label="Go to items list"
|
||||
>
|
||||
<Icon type="chevron-left" />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type State = {
|
||||
showMultipleSelectedNotes: boolean
|
||||
@@ -89,8 +110,12 @@ class NoteGroupView extends PureComponent<Props, State> {
|
||||
!this.state.showMultipleSelectedNotes && !this.state.showMultipleSelectedFiles
|
||||
|
||||
return (
|
||||
<div id={ElementIds.EditorColumn} className="app-column app-column-third h-full">
|
||||
<ResponsivePaneContent paneId={AppPaneId.Editor}>
|
||||
<div
|
||||
id={ElementIds.EditorColumn}
|
||||
className="app-column app-column-third flex min-h-screen flex-col md:h-full md:min-h-0"
|
||||
>
|
||||
<ResponsivePaneContent paneId={AppPaneId.Editor} className="flex-grow">
|
||||
<MobileItemsListButton />
|
||||
{this.state.showMultipleSelectedNotes && (
|
||||
<MultipleSelectedNotes
|
||||
application={this.application}
|
||||
|
||||
@@ -890,207 +890,201 @@ class NoteView extends PureComponent<NoteViewProps, State> {
|
||||
|
||||
return (
|
||||
<div aria-label="Note" className="section editor sn-component">
|
||||
<div className="flex-grow flex-col md:flex">
|
||||
{this.state.noteLocked && (
|
||||
<EditingDisabledBanner
|
||||
onMouseLeave={() => {
|
||||
this.setState({
|
||||
lockText: NOTE_EDITING_DISABLED_TEXT,
|
||||
showLockedIcon: true,
|
||||
})
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
this.setState({
|
||||
lockText: 'Enable editing',
|
||||
showLockedIcon: false,
|
||||
})
|
||||
}}
|
||||
onClick={() => this.viewControllerManager.notesController.setLockSelectedNotes(!this.state.noteLocked)}
|
||||
showLockedIcon={this.state.showLockedIcon}
|
||||
lockText={this.state.lockText}
|
||||
{this.state.noteLocked && (
|
||||
<EditingDisabledBanner
|
||||
onMouseLeave={() => {
|
||||
this.setState({
|
||||
lockText: NOTE_EDITING_DISABLED_TEXT,
|
||||
showLockedIcon: true,
|
||||
})
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
this.setState({
|
||||
lockText: 'Enable editing',
|
||||
showLockedIcon: false,
|
||||
})
|
||||
}}
|
||||
onClick={() => this.viewControllerManager.notesController.setLockSelectedNotes(!this.state.noteLocked)}
|
||||
showLockedIcon={this.state.showLockedIcon}
|
||||
lockText={this.state.lockText}
|
||||
/>
|
||||
)}
|
||||
|
||||
{this.note && (
|
||||
<div id="editor-title-bar" className="content-title-bar section-title-bar z-editor-title-bar w-full">
|
||||
<div className="mb-2 flex flex-wrap items-start justify-between gap-2 md:mb-0 md:flex-nowrap md:gap-0 xl:items-center">
|
||||
<div className={(this.state.noteLocked ? 'locked' : '') + ' flex-grow'}>
|
||||
<div className="title overflow-auto">
|
||||
<input
|
||||
className="input text-lg"
|
||||
disabled={this.state.noteLocked}
|
||||
id={ElementIds.NoteTitleEditor}
|
||||
onChange={this.onTitleChange}
|
||||
onFocus={(event) => {
|
||||
event.target.select()
|
||||
}}
|
||||
onKeyUp={this.onTitleEnter}
|
||||
spellCheck={false}
|
||||
value={this.state.editorTitle}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(
|
||||
'flex flex-col flex-wrap items-start gap-3 md:flex-col-reverse md:items-end',
|
||||
'xl:flex-row xl:flex-nowrap xl:items-center',
|
||||
)}
|
||||
>
|
||||
{this.state.noteStatus?.message?.length && (
|
||||
<div id="save-status-container" className={'xl:mr-5 xl:max-w-[16ch]'}>
|
||||
<div id="save-status">
|
||||
<div
|
||||
className={
|
||||
(this.state.syncTakingTooLong ? 'font-bold text-warning ' : '') +
|
||||
(this.state.saveError ? 'font-bold text-danger ' : '') +
|
||||
'message text-xs'
|
||||
}
|
||||
>
|
||||
{this.state.noteStatus?.message}
|
||||
</div>
|
||||
{this.state.noteStatus?.desc && <div className="desc text-xs">{this.state.noteStatus.desc}</div>}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-3">
|
||||
<AttachedFilesButton
|
||||
application={this.application}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
featuresController={this.viewControllerManager.featuresController}
|
||||
filePreviewModalController={this.viewControllerManager.filePreviewModalController}
|
||||
filesController={this.viewControllerManager.filesController}
|
||||
navigationController={this.viewControllerManager.navigationController}
|
||||
notesController={this.viewControllerManager.notesController}
|
||||
selectionController={this.viewControllerManager.selectionController}
|
||||
/>
|
||||
<ChangeEditorButton
|
||||
application={this.application}
|
||||
viewControllerManager={this.viewControllerManager}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<PinNoteButton
|
||||
notesController={this.viewControllerManager.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<NotesOptionsPanel
|
||||
application={this.application}
|
||||
navigationController={this.viewControllerManager.navigationController}
|
||||
notesController={this.viewControllerManager.notesController}
|
||||
noteTagsController={this.viewControllerManager.noteTagsController}
|
||||
historyModalController={this.viewControllerManager.historyModalController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NoteTagsContainer viewControllerManager={this.viewControllerManager} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
id={ElementIds.EditorContent}
|
||||
className={`${ElementIds.EditorContent} z-editor-content`}
|
||||
ref={this.editorContentRef}
|
||||
>
|
||||
{this.state.marginResizersEnabled && this.editorContentRef.current ? (
|
||||
<PanelResizer
|
||||
minWidth={300}
|
||||
hoverable={true}
|
||||
collapsable={false}
|
||||
panel={this.editorContentRef.current}
|
||||
side={PanelSide.Left}
|
||||
type={PanelResizeType.OffsetAndWidth}
|
||||
left={this.state.leftResizerOffset}
|
||||
width={this.state.leftResizerWidth}
|
||||
resizeFinishCallback={this.onPanelResizeFinish}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{this.state.editorComponentViewer && (
|
||||
<div className="component-view">
|
||||
<ComponentView
|
||||
key={this.state.editorComponentViewer.identifier}
|
||||
componentViewer={this.state.editorComponentViewer}
|
||||
onLoad={this.onEditorComponentLoad}
|
||||
requestReload={this.editorComponentViewerRequestsReload}
|
||||
application={this.application}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{this.state.editorStateDidLoad && !this.state.editorComponentViewer && !this.state.textareaUnloading && (
|
||||
<AutoresizingNoteViewTextarea
|
||||
autoComplete="off"
|
||||
dir="auto"
|
||||
id={ElementIds.NoteTextEditor}
|
||||
onChange={this.onTextAreaChange}
|
||||
value={this.state.editorText}
|
||||
readOnly={this.state.noteLocked}
|
||||
onFocus={this.onContentFocus}
|
||||
spellCheck={this.state.spellcheck}
|
||||
ref={(ref) => ref && this.onSystemEditorLoad(ref)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{this.note && (
|
||||
<div id="editor-title-bar" className="content-title-bar section-title-bar z-editor-title-bar w-full">
|
||||
<div className="mb-2 flex flex-wrap items-start justify-between gap-2 md:mb-0 md:flex-nowrap md:gap-0 xl:items-center">
|
||||
<div className={(this.state.noteLocked ? 'locked' : '') + ' flex-grow'}>
|
||||
<div className="title overflow-auto">
|
||||
<input
|
||||
className="input text-lg"
|
||||
disabled={this.state.noteLocked}
|
||||
id={ElementIds.NoteTitleEditor}
|
||||
onChange={this.onTitleChange}
|
||||
onFocus={(event) => {
|
||||
event.target.select()
|
||||
{this.state.marginResizersEnabled && this.editorContentRef.current ? (
|
||||
<PanelResizer
|
||||
minWidth={300}
|
||||
hoverable={true}
|
||||
collapsable={false}
|
||||
panel={this.editorContentRef.current}
|
||||
side={PanelSide.Right}
|
||||
type={PanelResizeType.OffsetAndWidth}
|
||||
left={this.state.rightResizerOffset}
|
||||
width={this.state.rightResizerWidth}
|
||||
resizeFinishCallback={this.onPanelResizeFinish}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div id="editor-pane-component-stack">
|
||||
{this.state.availableStackComponents.length > 0 && (
|
||||
<div
|
||||
id="component-stack-menu-bar"
|
||||
className="flex h-6 w-full items-center justify-between border-t border-solid border-border bg-contrast px-2 py-0 text-text"
|
||||
>
|
||||
<div className="flex h-full">
|
||||
{this.state.availableStackComponents.map((component) => {
|
||||
return (
|
||||
<div
|
||||
key={component.uuid}
|
||||
onClick={() => {
|
||||
this.toggleStackComponent(component).catch(console.error)
|
||||
}}
|
||||
onKeyUp={this.onTitleEnter}
|
||||
spellCheck={false}
|
||||
value={this.state.editorTitle}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(
|
||||
'flex flex-col flex-wrap items-start gap-3 md:flex-col-reverse md:items-end',
|
||||
'xl:flex-row xl:flex-nowrap xl:items-center',
|
||||
)}
|
||||
>
|
||||
{this.state.noteStatus?.message?.length && (
|
||||
<div id="save-status-container" className={'xl:mr-5 xl:max-w-[16ch]'}>
|
||||
<div id="save-status">
|
||||
<div
|
||||
className={
|
||||
(this.state.syncTakingTooLong ? 'font-bold text-warning ' : '') +
|
||||
(this.state.saveError ? 'font-bold text-danger ' : '') +
|
||||
'message text-xs'
|
||||
}
|
||||
>
|
||||
{this.state.noteStatus?.message}
|
||||
</div>
|
||||
{this.state.noteStatus?.desc && (
|
||||
<div className="desc text-xs">{this.state.noteStatus.desc}</div>
|
||||
)}
|
||||
className="flex flex-grow cursor-pointer items-center justify-center [&:not(:first-child)]:ml-3"
|
||||
>
|
||||
<div className="flex h-full items-center [&:not(:first-child)]:ml-2">
|
||||
{this.stackComponentExpanded(component) && component.active && <IndicatorCircle style="info" />}
|
||||
{!this.stackComponentExpanded(component) && <IndicatorCircle style="neutral" />}
|
||||
</div>
|
||||
<div className="flex h-full items-center [&:not(:first-child)]:ml-2">
|
||||
<div className="whitespace-nowrap text-xs font-bold">{component.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-3">
|
||||
<AttachedFilesButton
|
||||
application={this.application}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
featuresController={this.viewControllerManager.featuresController}
|
||||
filePreviewModalController={this.viewControllerManager.filePreviewModalController}
|
||||
filesController={this.viewControllerManager.filesController}
|
||||
navigationController={this.viewControllerManager.navigationController}
|
||||
notesController={this.viewControllerManager.notesController}
|
||||
selectionController={this.viewControllerManager.selectionController}
|
||||
/>
|
||||
<ChangeEditorButton
|
||||
application={this.application}
|
||||
viewControllerManager={this.viewControllerManager}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<PinNoteButton
|
||||
notesController={this.viewControllerManager.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<NotesOptionsPanel
|
||||
application={this.application}
|
||||
navigationController={this.viewControllerManager.navigationController}
|
||||
notesController={this.viewControllerManager.notesController}
|
||||
noteTagsController={this.viewControllerManager.noteTagsController}
|
||||
historyModalController={this.viewControllerManager.historyModalController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<NoteTagsContainer viewControllerManager={this.viewControllerManager} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
id={ElementIds.EditorContent}
|
||||
className={`${ElementIds.EditorContent} z-editor-content`}
|
||||
ref={this.editorContentRef}
|
||||
>
|
||||
{this.state.marginResizersEnabled && this.editorContentRef.current ? (
|
||||
<PanelResizer
|
||||
minWidth={300}
|
||||
hoverable={true}
|
||||
collapsable={false}
|
||||
panel={this.editorContentRef.current}
|
||||
side={PanelSide.Left}
|
||||
type={PanelResizeType.OffsetAndWidth}
|
||||
left={this.state.leftResizerOffset}
|
||||
width={this.state.leftResizerWidth}
|
||||
resizeFinishCallback={this.onPanelResizeFinish}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{this.state.editorComponentViewer && (
|
||||
<div className="component-view">
|
||||
<ComponentView
|
||||
key={this.state.editorComponentViewer.identifier}
|
||||
componentViewer={this.state.editorComponentViewer}
|
||||
onLoad={this.onEditorComponentLoad}
|
||||
requestReload={this.editorComponentViewerRequestsReload}
|
||||
application={this.application}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{this.state.editorStateDidLoad && !this.state.editorComponentViewer && !this.state.textareaUnloading && (
|
||||
<AutoresizingNoteViewTextarea
|
||||
autoComplete="off"
|
||||
dir="auto"
|
||||
id={ElementIds.NoteTextEditor}
|
||||
onChange={this.onTextAreaChange}
|
||||
value={this.state.editorText}
|
||||
readOnly={this.state.noteLocked}
|
||||
onFocus={this.onContentFocus}
|
||||
spellCheck={this.state.spellcheck}
|
||||
ref={(ref) => ref && this.onSystemEditorLoad(ref)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{this.state.marginResizersEnabled && this.editorContentRef.current ? (
|
||||
<PanelResizer
|
||||
minWidth={300}
|
||||
hoverable={true}
|
||||
collapsable={false}
|
||||
panel={this.editorContentRef.current}
|
||||
side={PanelSide.Right}
|
||||
type={PanelResizeType.OffsetAndWidth}
|
||||
left={this.state.rightResizerOffset}
|
||||
width={this.state.rightResizerWidth}
|
||||
resizeFinishCallback={this.onPanelResizeFinish}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div id="editor-pane-component-stack">
|
||||
{this.state.availableStackComponents.length > 0 && (
|
||||
<div
|
||||
id="component-stack-menu-bar"
|
||||
className="flex h-6 w-full items-center justify-between border-t border-solid border-border bg-contrast px-2 py-0 text-text"
|
||||
>
|
||||
<div className="flex h-full">
|
||||
{this.state.availableStackComponents.map((component) => {
|
||||
return (
|
||||
<div
|
||||
key={component.uuid}
|
||||
onClick={() => {
|
||||
this.toggleStackComponent(component).catch(console.error)
|
||||
}}
|
||||
className="flex flex-grow cursor-pointer items-center justify-center [&:not(:first-child)]:ml-3"
|
||||
>
|
||||
<div className="flex h-full items-center [&:not(:first-child)]:ml-2">
|
||||
{this.stackComponentExpanded(component) && component.active && (
|
||||
<IndicatorCircle style="info" />
|
||||
)}
|
||||
{!this.stackComponentExpanded(component) && <IndicatorCircle style="neutral" />}
|
||||
</div>
|
||||
<div className="flex h-full items-center [&:not(:first-child)]:ml-2">
|
||||
<div className="whitespace-nowrap text-xs font-bold">{component.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<div className="sn-component">
|
||||
{this.state.stackComponentViewers.map((viewer) => {
|
||||
return (
|
||||
<div className="component-view component-stack-item" key={viewer.identifier}>
|
||||
<ComponentView key={viewer.identifier} componentViewer={viewer} application={this.application} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="sn-component">
|
||||
{this.state.stackComponentViewers.map((viewer) => {
|
||||
return (
|
||||
<div className="component-view component-stack-item" key={viewer.identifier}>
|
||||
<ComponentView key={viewer.identifier} componentViewer={viewer} application={this.application} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,43 +1,27 @@
|
||||
import { useMemo, ReactNode } from 'react'
|
||||
import Icon from '@/Components/Icon/Icon'
|
||||
import { AppPaneIcons, AppPaneId, AppPaneTitles } from './AppPaneMetadata'
|
||||
import { AppPaneId } from './AppPaneMetadata'
|
||||
import { classNames } from '@/Utils/ConcatenateClassNames'
|
||||
import { useResponsiveAppPane } from './ResponsivePaneProvider'
|
||||
|
||||
type Props = {
|
||||
children: ReactNode
|
||||
contentClassName?: string
|
||||
className?: string
|
||||
contentElementId?: string
|
||||
paneId: AppPaneId
|
||||
}
|
||||
|
||||
const ResponsivePaneContent = ({ children, contentClassName, contentElementId, paneId }: Props) => {
|
||||
const { selectedPane, toggleAppPane: togglePane } = useResponsiveAppPane()
|
||||
const ResponsivePaneContent = ({ children, className, contentElementId, paneId }: Props) => {
|
||||
const { selectedPane } = useResponsiveAppPane()
|
||||
|
||||
const isSelectedPane = useMemo(() => selectedPane === paneId, [paneId, selectedPane])
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
className={classNames(
|
||||
'flex w-full items-center justify-between border-b border-solid border-border px-4 py-2 focus:shadow-none focus:outline-none md:hidden',
|
||||
isSelectedPane ? 'bg-contrast' : 'bg-default',
|
||||
)}
|
||||
onClick={() => togglePane(paneId)}
|
||||
>
|
||||
<div className="flex items-center gap-2 font-semibold">
|
||||
<Icon type={AppPaneIcons[paneId]} />
|
||||
<span>{AppPaneTitles[paneId]}</span>
|
||||
</div>
|
||||
<Icon type="chevron-down" />
|
||||
</button>
|
||||
<div
|
||||
id={contentElementId}
|
||||
className={classNames('content flex flex-col', isSelectedPane ? 'h-full' : 'hidden md:flex', contentClassName)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</>
|
||||
<div
|
||||
id={contentElementId}
|
||||
className={classNames('content flex flex-col', isSelectedPane ? 'h-full' : 'hidden md:flex', className)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState }) => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={classNames('tag', isSelected && 'selected', isFaded && 'opacity-50')}
|
||||
className={classNames('tag py-2 px-3.5 md:py-1', isSelected && 'selected', isFaded && 'opacity-50')}
|
||||
onClick={selectCurrentTag}
|
||||
style={{
|
||||
paddingLeft: `${level * PADDING_PER_LEVEL_PX + PADDING_BASE_PX}px`,
|
||||
|
||||
@@ -22,6 +22,7 @@ import { useDrag, useDrop } from 'react-dnd'
|
||||
import { DropItem, DropProps, ItemTypes } from './DragNDrop'
|
||||
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
|
||||
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
|
||||
import { classNames } from '@/Utils/ConcatenateClassNames'
|
||||
|
||||
type Props = {
|
||||
tag: SNTag
|
||||
@@ -202,7 +203,11 @@ export const TagsListItem: FunctionComponent<Props> = observer(({ tag, features,
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
className={`tag focus:shadow-inner ${isSelected ? 'selected' : ''} ${readyToDrop ? 'is-drag-over' : ''}`}
|
||||
className={classNames(
|
||||
'tag py-2 px-3.5 focus:shadow-inner md:py-1',
|
||||
isSelected && 'selected',
|
||||
readyToDrop && 'is-drag-over',
|
||||
)}
|
||||
onClick={selectCurrentTag}
|
||||
ref={dragRef}
|
||||
style={{
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
}
|
||||
|
||||
&:not(.selected) {
|
||||
min-height: 0;
|
||||
height: auto;
|
||||
border-bottom: 1px solid var(--sn-stylekit-border-color);
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,16 +150,9 @@ $footer-height: 2rem;
|
||||
width: 100%;
|
||||
|
||||
.section {
|
||||
padding-bottom: 0px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
> .content {
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.section-title-bar {
|
||||
.add-button {
|
||||
font-size: 12px;
|
||||
@@ -168,7 +161,6 @@ $footer-height: 2rem;
|
||||
.section-title-bar-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
// This was causing problems with tags + button cutting off on right when the panel is a certain size
|
||||
// overflow: hidden;
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ $content-horizontal-padding: 16px;
|
||||
.tag,
|
||||
.root-drop {
|
||||
font-size: 14px;
|
||||
padding: 4px 14px;
|
||||
cursor: pointer;
|
||||
transition: height 0.1s ease-in-out;
|
||||
width: 100%;
|
||||
|
||||
@@ -42,12 +42,17 @@ module.exports = {
|
||||
89: '22.25rem',
|
||||
125: '31.25rem',
|
||||
},
|
||||
height: {
|
||||
screen: 'var(--viewport-height)',
|
||||
},
|
||||
minHeight: {
|
||||
1: '0.25rem',
|
||||
2: '0.5rem',
|
||||
screen: 'var(--viewport-height)',
|
||||
},
|
||||
maxHeight: {
|
||||
110: '27.5rem',
|
||||
screen: 'var(--viewport-height)',
|
||||
},
|
||||
zIndex: {
|
||||
'editor-content': 'var(--z-index-editor-content)',
|
||||
|
||||
Reference in New Issue
Block a user