fix: remove tablet specific responsive UI (#1411)

* fix: revert tablet responsiveness UI

* fix: don't let the "Saving..." text container hide the note title on tablets

* chore: better visibility of css classes list

* fix: fixed width of notes container column on Tablets
This commit is contained in:
Vardan Hakobyan
2022-08-17 15:39:56 +04:00
committed by GitHub
parent f14f105703
commit a25923f084
13 changed files with 291 additions and 372 deletions

View File

@@ -21,6 +21,7 @@ import ResponsivePaneContent from '../ResponsivePane/ResponsivePaneContent'
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata' import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider' import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
import { StreamingFileReader } from '@standardnotes/filepicker' import { StreamingFileReader } from '@standardnotes/filepicker'
import { classNames } from '@/Utils/ConcatenateClassNames'
type Props = { type Props = {
accountMenuController: AccountMenuController accountMenuController: AccountMenuController
@@ -179,7 +180,10 @@ const ContentListView: FunctionComponent<Props> = ({
return ( return (
<div <div
id="items-column" id="items-column"
className="sn-component section app-column flex flex-col border-b border-solid border-border xl:w-87.5 xsm-only:!w-full sm-only:!w-full md-only:!w-52 lg-only:!w-52" className={classNames(
'sn-component section app-column flex flex-col border-b border-solid border-border ',
'xl:w-87.5 xsm-only:!w-full sm-only:!w-full md-only:!w-52 lg-only:!w-52',
)}
aria-label={'Notes & Files'} aria-label={'Notes & Files'}
ref={itemsViewPanelRef} ref={itemsViewPanelRef}
> >

View File

@@ -10,7 +10,6 @@ import SearchBar from '@/Components/SearchBar/SearchBar'
import ResponsivePaneContent from '@/Components/ResponsivePane/ResponsivePaneContent' import ResponsivePaneContent from '@/Components/ResponsivePane/ResponsivePaneContent'
import { AppPaneId } from '@/Components/ResponsivePane/AppPaneMetadata' import { AppPaneId } from '@/Components/ResponsivePane/AppPaneMetadata'
import { classNames } from '@/Utils/ConcatenateClassNames' import { classNames } from '@/Utils/ConcatenateClassNames'
import Icon from '@/Components/Icon/Icon'
type Props = { type Props = {
application: WebApplication application: WebApplication
@@ -20,7 +19,6 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
const viewControllerManager = useMemo(() => application.getViewControllerManager(), [application]) const viewControllerManager = useMemo(() => application.getViewControllerManager(), [application])
const ref = useRef<HTMLDivElement>(null) const ref = useRef<HTMLDivElement>(null)
const [panelWidth, setPanelWidth] = useState<number>(0) const [panelWidth, setPanelWidth] = useState<number>(0)
const [isPanelExpanded, setIsPanelExpanded] = useState(true)
useEffect(() => { useEffect(() => {
const removeObserver = application.addEventObserver(async () => { const removeObserver = application.addEventObserver(async () => {
@@ -51,38 +49,22 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
return ( return (
<div <div
id="navigation" id="navigation"
className={classNames( className={'sn-component section app-column w-[220px] xsm-only:!w-full sm-only:!w-full'}
'sn-component section app-column xl:w-[220px] xsm-only:!w-full sm-only:!w-full md-only:transition-width lg-only:transition-width',
isPanelExpanded ? 'md-only:!w-[220px] lg-only:!w-[220px]' : 'md-only:!w-18 lg-only:!w-18',
)}
ref={ref} ref={ref}
> >
<ResponsivePaneContent paneId={AppPaneId.Navigation} contentElementId="navigation-content"> <ResponsivePaneContent paneId={AppPaneId.Navigation} contentElementId="navigation-content">
{isPanelExpanded && (
<SearchBar <SearchBar
itemListController={viewControllerManager.itemListController} itemListController={viewControllerManager.itemListController}
searchOptionsController={viewControllerManager.searchOptionsController} searchOptionsController={viewControllerManager.searchOptionsController}
selectedViewTitle={viewControllerManager.navigationController.selected?.title} selectedViewTitle={viewControllerManager.navigationController.selected?.title}
/> />
)} <div className={'section-title-bar'}>
<div className={'flex justify-end'}>
<div className={classNames('section-title-bar block w-full xl:block', !isPanelExpanded && 'hidden')}>
<div className="section-title-bar-header"> <div className="section-title-bar-header">
<div className="title text-sm"> <div className="title text-sm">
<span className="font-bold">Views</span> <span className="font-bold">Views</span>
</div> </div>
</div> </div>
</div> </div>
<div
className={classNames(
'hidden items-end self-end rounded-full rounded-tr-none rounded-br-none bg-default p-1 text-foreground md:flex xl:hidden',
isPanelExpanded ? 'mb-1 w-fit' : 'mt-4.5 mb-3 ml-3 w-full',
)}
onClick={() => setIsPanelExpanded(!isPanelExpanded)}
>
<Icon type="chevron-down" className={isPanelExpanded ? 'rotate-90' : '-rotate-90'} />
</div>
</div>
<div <div
className={classNames( className={classNames(
'h-full overflow-y-auto overflow-x-hidden', 'h-full overflow-y-auto overflow-x-hidden',
@@ -90,8 +72,8 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
'md:hover:[overflow-y:_overlay]', 'md:hover:[overflow-y:_overlay]',
)} )}
> >
<SmartViewsSection viewControllerManager={viewControllerManager} isCollapsed={!isPanelExpanded} /> <SmartViewsSection viewControllerManager={viewControllerManager} />
<TagsSection viewControllerManager={viewControllerManager} isCollapsed={!isPanelExpanded} /> <TagsSection viewControllerManager={viewControllerManager} />
</div> </div>
</ResponsivePaneContent> </ResponsivePaneContent>
{ref.current && ( {ref.current && (

View File

@@ -36,6 +36,7 @@ import {
import { reloadFont } from './FontFunctions' import { reloadFont } from './FontFunctions'
import { NoteViewProps } from './NoteViewProps' import { NoteViewProps } from './NoteViewProps'
import IndicatorCircle from '../IndicatorCircle/IndicatorCircle' import IndicatorCircle from '../IndicatorCircle/IndicatorCircle'
import { classNames } from '@/Utils/ConcatenateClassNames'
const MINIMUM_STATUS_DURATION = 400 const MINIMUM_STATUS_DURATION = 400
const TEXTAREA_DEBOUNCE = 100 const TEXTAREA_DEBOUNCE = 100
@@ -911,7 +912,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
{this.note && ( {this.note && (
<div id="editor-title-bar" className="content-title-bar section-title-bar z-editor-title-bar w-full"> <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-center justify-between gap-2 md:mb-0 md:flex-nowrap md:gap-0"> <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={(this.state.noteLocked ? 'locked' : '') + ' flex-grow'}>
<div className="title overflow-auto"> <div className="title overflow-auto">
<input <input
@@ -929,9 +930,14 @@ class NoteView extends PureComponent<NoteViewProps, State> {
/> />
</div> </div>
</div> </div>
<div className="flex flex-col flex-wrap items-start gap-3 md:flex-row md:flex-nowrap md:items-center"> <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 && ( {this.state.noteStatus?.message?.length && (
<div id="save-status-container"> <div id="save-status-container" className={'xl:mr-5 xl:max-w-[16ch]'}>
<div id="save-status"> <div id="save-status">
<div <div
className={ className={

View File

@@ -5,10 +5,9 @@ import SmartViewsListItem from './SmartViewsListItem'
type Props = { type Props = {
viewControllerManager: ViewControllerManager viewControllerManager: ViewControllerManager
isCollapsed: boolean
} }
const SmartViewsList: FunctionComponent<Props> = ({ viewControllerManager, isCollapsed }: Props) => { const SmartViewsList: FunctionComponent<Props> = ({ viewControllerManager }: Props) => {
const allViews = viewControllerManager.navigationController.smartViews const allViews = viewControllerManager.navigationController.smartViews
return ( return (
@@ -20,7 +19,6 @@ const SmartViewsList: FunctionComponent<Props> = ({ viewControllerManager, isCol
view={view} view={view}
tagsState={viewControllerManager.navigationController} tagsState={viewControllerManager.navigationController}
features={viewControllerManager.featuresController} features={viewControllerManager.featuresController}
isCollapsed={isCollapsed}
/> />
) )
})} })}

View File

@@ -21,7 +21,6 @@ type Props = {
view: SmartView view: SmartView
tagsState: NavigationController tagsState: NavigationController
features: FeaturesController features: FeaturesController
isCollapsed: boolean
} }
const PADDING_BASE_PX = 14 const PADDING_BASE_PX = 14
@@ -47,7 +46,7 @@ const smartViewIconType = (view: SmartView, isSelected: boolean): IconType => {
return 'hashtag' return 'hashtag'
} }
const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState, isCollapsed }) => { const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState }) => {
const { toggleAppPane } = useResponsiveAppPane() const { toggleAppPane } = useResponsiveAppPane()
const [title, setTitle] = useState(view.title || '') const [title, setTitle] = useState(view.title || '')
@@ -113,31 +112,19 @@ const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState, isColla
return ( return (
<> <>
<div <div
className={classNames( className={classNames('tag', isSelected && 'selected', isFaded && 'opacity-50')}
'tag',
isSelected && 'selected',
isFaded && 'opacity-50',
isCollapsed && '!bg-transparent',
)}
onClick={selectCurrentTag} onClick={selectCurrentTag}
style={{ style={{
paddingLeft: `${level * PADDING_PER_LEVEL_PX + PADDING_BASE_PX}px`, paddingLeft: `${level * PADDING_PER_LEVEL_PX + PADDING_BASE_PX}px`,
}} }}
> >
<div className="tag-info relative"> <div className="tag-info">
<div <div className={'tag-icon mr-2'}>
className={classNames(
isCollapsed
? `relative flex h-[40px] w-[40px] items-center justify-center
${isSelected ? 'transparent-info-color-background' : 'transparent-info-color-background-hover'}`
: 'tag-icon mr-2',
)}
>
<Icon type={iconType} className={isSelected ? 'text-info' : 'text-neutral'} /> <Icon type={iconType} className={isSelected ? 'text-info' : 'text-neutral'} />
</div> </div>
{isEditing ? ( {isEditing ? (
<input <input
className={classNames('title editing', isCollapsed ? 'hidden' : 'block')} className={'title editing'}
id={`react-tag-${view.uuid}`} id={`react-tag-${view.uuid}`}
onBlur={onBlur} onBlur={onBlur}
onInput={onInput} onInput={onInput}
@@ -147,19 +134,14 @@ const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState, isColla
ref={inputRef} ref={inputRef}
/> />
) : ( ) : (
<div <div className={'title overflow-hidden text-left'} id={`react-tag-${view.uuid}`}>
className={classNames('title overflow-hidden text-left', isCollapsed ? 'hidden' : 'block')}
id={`react-tag-${view.uuid}`}
>
{title} {title}
</div> </div>
)} )}
<div className={classNames('count', isCollapsed ? 'absolute top-0 right-0' : '')}> <div className={'count'}>{view.uuid === SystemViewId.AllNotes && tagsState.allNotesCount}</div>
{view.uuid === SystemViewId.AllNotes && tagsState.allNotesCount}
</div>
</div> </div>
{!isSystemView(view) && !isCollapsed && ( {!isSystemView(view) && (
<div className="meta"> <div className="meta">
{view.conflictOf && ( {view.conflictOf && (
<div className="danger text-[0.625rem] font-bold">Conflicted Copy {view.conflictOf}</div> <div className="danger text-[0.625rem] font-bold">Conflicted Copy {view.conflictOf}</div>

View File

@@ -5,13 +5,12 @@ import SmartViewsList from './SmartViewsList'
type Props = { type Props = {
viewControllerManager: ViewControllerManager viewControllerManager: ViewControllerManager
isCollapsed: boolean
} }
const SmartViewsSection: FunctionComponent<Props> = ({ viewControllerManager, isCollapsed }) => { const SmartViewsSection: FunctionComponent<Props> = ({ viewControllerManager }) => {
return ( return (
<section> <section>
<SmartViewsList viewControllerManager={viewControllerManager} isCollapsed={isCollapsed} /> <SmartViewsList viewControllerManager={viewControllerManager} />
</section> </section>
) )
} }

View File

@@ -9,10 +9,9 @@ import { TagsListItem } from './TagsListItem'
type Props = { type Props = {
viewControllerManager: ViewControllerManager viewControllerManager: ViewControllerManager
isCollapsed: boolean
} }
const TagsList: FunctionComponent<Props> = ({ viewControllerManager, isCollapsed }: Props) => { const TagsList: FunctionComponent<Props> = ({ viewControllerManager }: Props) => {
const tagsState = viewControllerManager.navigationController const tagsState = viewControllerManager.navigationController
const allTags = tagsState.allLocalRootTags const allTags = tagsState.allLocalRootTags
@@ -53,7 +52,6 @@ const TagsList: FunctionComponent<Props> = ({ viewControllerManager, isCollapsed
tagsState={tagsState} tagsState={tagsState}
features={viewControllerManager.featuresController} features={viewControllerManager.featuresController}
onContextMenu={onContextMenu} onContextMenu={onContextMenu}
isCollapsed={isCollapsed}
/> />
) )
})} })}

View File

@@ -22,7 +22,6 @@ import { useDrag, useDrop } from 'react-dnd'
import { DropItem, DropProps, ItemTypes } from './DragNDrop' import { DropItem, DropProps, ItemTypes } from './DragNDrop'
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider' import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata' import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
import { classNames } from '@/Utils/ConcatenateClassNames'
type Props = { type Props = {
tag: SNTag tag: SNTag
@@ -30,16 +29,12 @@ type Props = {
features: FeaturesController features: FeaturesController
level: number level: number
onContextMenu: (tag: SNTag, posX: number, posY: number) => void onContextMenu: (tag: SNTag, posX: number, posY: number) => void
isCollapsed: boolean
} }
const PADDING_BASE_PX = 14 const PADDING_BASE_PX = 14
const PADDING_BASE_WHEN_COLLAPSED_PX = 6
const PADDING_PER_LEVEL_PX = 21 const PADDING_PER_LEVEL_PX = 21
const PADDING_PER_LEVEL_WHEN_COLLAPSED_PX = 10
export const TagsListItem: FunctionComponent<Props> = observer( export const TagsListItem: FunctionComponent<Props> = observer(({ tag, features, tagsState, level, onContextMenu }) => {
({ tag, features, tagsState, level, onContextMenu, isCollapsed }) => {
const { toggleAppPane } = useResponsiveAppPane() const { toggleAppPane } = useResponsiveAppPane()
const [title, setTitle] = useState(tag.title || '') const [title, setTitle] = useState(tag.title || '')
@@ -211,11 +206,7 @@ export const TagsListItem: FunctionComponent<Props> = observer(
onClick={selectCurrentTag} onClick={selectCurrentTag}
ref={dragRef} ref={dragRef}
style={{ style={{
paddingLeft: `${ paddingLeft: `${level * PADDING_PER_LEVEL_PX + PADDING_BASE_PX}px`,
isCollapsed
? level * PADDING_PER_LEVEL_WHEN_COLLAPSED_PX + PADDING_BASE_WHEN_COLLAPSED_PX
: level * PADDING_PER_LEVEL_PX + PADDING_BASE_PX
}px`,
}} }}
onContextMenu={(e) => { onContextMenu={(e) => {
e.preventDefault() e.preventDefault()
@@ -236,18 +227,12 @@ export const TagsListItem: FunctionComponent<Props> = observer(
</a> </a>
</div> </div>
)} )}
<div <div className={'tag-icon draggable mr-2'} ref={dragRef}>
className={classNames('tag-icon draggable mr-2', isCollapsed ? 'md-only:!hidden lg-only:!hidden' : '')}
ref={dragRef}
>
<Icon type="hashtag" className={`${isSelected ? 'text-info' : 'text-neutral'}`} /> <Icon type="hashtag" className={`${isSelected ? 'text-info' : 'text-neutral'}`} />
</div> </div>
{isEditing ? ( {isEditing ? (
<input <input
className={classNames( className={'title editing focus:shadow-none focus:outline-none'}
'title editing focus:shadow-none focus:outline-none',
isCollapsed ? 'md-only:!w-min lg-only:!w-min' : '',
)}
id={`react-tag-${tag.uuid}`} id={`react-tag-${tag.uuid}`}
onBlur={onBlur} onBlur={onBlur}
onInput={onInput} onInput={onInput}
@@ -258,10 +243,7 @@ export const TagsListItem: FunctionComponent<Props> = observer(
/> />
) : ( ) : (
<div <div
className={classNames( className={'title overflow-hidden text-left focus:shadow-none focus:outline-none'}
'title overflow-hidden text-left focus:shadow-none focus:outline-none',
isCollapsed ? 'md-only:!w-min lg-only:!w-min' : '',
)}
id={`react-tag-${tag.uuid}`} id={`react-tag-${tag.uuid}`}
> >
{title} {title}
@@ -321,7 +303,6 @@ export const TagsListItem: FunctionComponent<Props> = observer(
tagsState={tagsState} tagsState={tagsState}
features={features} features={features}
onContextMenu={onContextMenu} onContextMenu={onContextMenu}
isCollapsed={isCollapsed}
/> />
) )
})} })}
@@ -329,7 +310,6 @@ export const TagsListItem: FunctionComponent<Props> = observer(
)} )}
</> </>
) )
}, })
)
TagsListItem.displayName = 'TagsListItem' TagsListItem.displayName = 'TagsListItem'

View File

@@ -5,14 +5,12 @@ import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useState } from 'react' import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import TagsSectionAddButton from './TagsSectionAddButton' import TagsSectionAddButton from './TagsSectionAddButton'
import TagsSectionTitle from './TagsSectionTitle' import TagsSectionTitle from './TagsSectionTitle'
import { classNames } from '@/Utils/ConcatenateClassNames'
type Props = { type Props = {
viewControllerManager: ViewControllerManager viewControllerManager: ViewControllerManager
isCollapsed: boolean
} }
const TagsSection: FunctionComponent<Props> = ({ viewControllerManager, isCollapsed }) => { const TagsSection: FunctionComponent<Props> = ({ viewControllerManager }) => {
const [hasMigration, setHasMigration] = useState<boolean>(false) const [hasMigration, setHasMigration] = useState<boolean>(false)
const checkIfMigrationNeeded = useCallback(() => { const checkIfMigrationNeeded = useCallback(() => {
@@ -55,7 +53,7 @@ const TagsSection: FunctionComponent<Props> = ({ viewControllerManager, isCollap
return ( return (
<section> <section>
<div className={classNames('section-title-bar', isCollapsed ? 'md-only:hidden lg-only:hidden' : '')}> <div className={'section-title-bar'}>
<div className="section-title-bar-header"> <div className="section-title-bar-header">
<TagsSectionTitle <TagsSectionTitle
features={viewControllerManager.featuresController} features={viewControllerManager.featuresController}
@@ -68,13 +66,7 @@ const TagsSection: FunctionComponent<Props> = ({ viewControllerManager, isCollap
/> />
</div> </div>
</div> </div>
<div <TagsList viewControllerManager={viewControllerManager} />
className={classNames(
'hidden',
isCollapsed ? 'mt-6 mb-7 border border-border md-only:block lg-only:block' : '',
)}
/>
<TagsList viewControllerManager={viewControllerManager} isCollapsed={isCollapsed} />
</section> </section>
) )
} }

View File

@@ -7,16 +7,15 @@ import { FunctionComponent } from 'react'
type Props = { type Props = {
tags: NavigationController tags: NavigationController
features: FeaturesController features: FeaturesController
className?: string
} }
const TagsSectionAddButton: FunctionComponent<Props> = ({ tags, className = '' }) => { const TagsSectionAddButton: FunctionComponent<Props> = ({ tags }) => {
return ( return (
<IconButton <IconButton
focusable={true} focusable={true}
icon="add" icon="add"
title="Create a new tag" title="Create a new tag"
className={`p-0 text-neutral ${className}`} className="p-0 text-neutral"
onClick={() => tags.createNewTemplate()} onClick={() => tags.createNewTemplate()}
/> />
) )

View File

@@ -9,10 +9,9 @@ type Props = {
features: FeaturesController features: FeaturesController
hasMigration: boolean hasMigration: boolean
onClickMigration: () => void onClickMigration: () => void
className?: string
} }
const TagsSectionTitle: FunctionComponent<Props> = ({ features, hasMigration, onClickMigration, className = '' }) => { const TagsSectionTitle: FunctionComponent<Props> = ({ features, hasMigration, onClickMigration }) => {
const entitledToFolders = features.hasFolders const entitledToFolders = features.hasFolders
const modal = usePremiumModal() const modal = usePremiumModal()
@@ -23,7 +22,7 @@ const TagsSectionTitle: FunctionComponent<Props> = ({ features, hasMigration, on
if (entitledToFolders) { if (entitledToFolders) {
return ( return (
<> <>
<div className={`title text-sm ${className}`}> <div className="title text-sm">
<span className="font-bold">Folders</span> <span className="font-bold">Folders</span>
{hasMigration && ( {hasMigration && (
<label className="ml-1 cursor-pointer font-bold text-info" onClick={onClickMigration}> <label className="ml-1 cursor-pointer font-bold text-info" onClick={onClickMigration}>
@@ -37,7 +36,7 @@ const TagsSectionTitle: FunctionComponent<Props> = ({ features, hasMigration, on
return ( return (
<> <>
<div className={`title text-sm ${className}`}> <div className="title text-sm">
<span className="font-bold">Tags</span> <span className="font-bold">Tags</span>
<Tooltip label={TAG_FOLDERS_FEATURE_TOOLTIP}> <Tooltip label={TAG_FOLDERS_FEATURE_TOOLTIP}>
<label className="ml-1 cursor-pointer font-bold text-passive-2" onClick={showPremiumAlert}> <label className="ml-1 cursor-pointer font-bold text-passive-2" onClick={showPremiumAlert}>

View File

@@ -67,11 +67,6 @@ $heading-height: 75px;
position: relative; position: relative;
min-width: 16ch; min-width: 16ch;
overflow: visible; overflow: visible;
margin-right: 20px;
@media screen and (min-width: 768px) {
max-width: 16ch;
}
} }
#save-status { #save-status {

View File

@@ -132,21 +132,6 @@
@include DimmedBackground(var(--sn-stylekit-info-color), 0.08); @include DimmedBackground(var(--sn-stylekit-info-color), 0.08);
} }
.transparent-info-color-background {
&::after {
@include DimmedBackground(var(--sn-stylekit-info-color), 0.12);
border-radius: 100px;
}
}
.transparent-info-color-background-hover {
&:hover {
&::after {
@extend .transparent-info-color-background;
}
}
}
svg.sk-circular-progress { svg.sk-circular-progress {
$pi: 3.14159265358979; $pi: 3.14159265358979;