Improve help UI for small screens

This commit is contained in:
IRBorisov 2024-06-09 20:40:41 +03:00
parent 3d2cf353f3
commit decd0da6cd
24 changed files with 141 additions and 72 deletions

View File

@ -155,6 +155,7 @@
"Булеан",
"Бурбаки",
"Версионирование",
"Владельцом",
"Десинглетон",
"доксинг",
"интерпретируемости",

View File

@ -33,7 +33,8 @@ function Tooltip({
delayHide={100}
opacity={0.97}
className={clsx(
'overflow-auto sm:overflow-hidden overscroll-contain',
'max-h-[calc(100svh-6rem)]',
'overflow-y-auto overflow-x-hidden sm:overflow-hidden overscroll-contain',
'border shadow-md',
'text-balance',
layer,

View File

@ -14,6 +14,7 @@ import { HelpTopic } from '@/models/miscellaneous';
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
import { generateAlias, validateNewAlias } from '@/models/rsformAPI';
import { inferTemplatedType, substituteTemplateArgs } from '@/models/rslangAPI';
import { PARAMETER } from '@/utils/constants';
import FormCreateCst from '../DlgCreateCst/FormCreateCst';
import ArgumentsTab, { IArgumentsState } from './ArgumentsTab';
@ -144,7 +145,11 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
onSubmit={handleSubmit}
>
<Overlay position='top-0 right-[6rem]'>
<BadgeHelp topic={HelpTopic.RSL_TEMPLATES} className='max-w-[40rem]' offset={12} />
<BadgeHelp
topic={HelpTopic.RSL_TEMPLATES}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
offset={12}
/>
</Overlay>
<Tabs
selectedTabClassName='clr-selected'

View File

@ -1,5 +1,6 @@
'use client';
import clsx from 'clsx';
import { AnimatePresence } from 'framer-motion';
import { useLayoutEffect, useMemo, useState } from 'react';
@ -12,6 +13,7 @@ import AnimateFade from '@/components/wrap/AnimateFade';
import { HelpTopic } from '@/models/miscellaneous';
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
import { generateAlias, isBaseSet, isBasicConcept, isFunctional, validateNewAlias } from '@/models/rsformAPI';
import { PARAMETER } from '@/utils/constants';
import { labelCstType } from '@/utils/labels';
import { SelectorCstType } from '@/utils/selectors';
@ -52,7 +54,11 @@ function FormCreateCst({ schema, state, partialUpdate, setValidated }: FormCreat
value={{ value: state.cst_type, label: labelCstType(state.cst_type) }}
onChange={data => partialUpdate({ cst_type: data?.value ?? CstType.BASE })}
/>
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} className='max-w-[40rem] max-h-[calc(100svh-2rem)]' />
<BadgeHelp
topic={HelpTopic.CC_CONSTITUENTA}
offset={16}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
/>
<TextInput
id='dlg_cst_alias'
dense

View File

@ -11,6 +11,7 @@ import TabLabel from '@/components/ui/TabLabel';
import { ReferenceType } from '@/models/language';
import { HelpTopic } from '@/models/miscellaneous';
import { IRSForm } from '@/models/rsform';
import { PARAMETER } from '@/utils/constants';
import { labelReferenceType } from '@/utils/labels';
import EntityTab from './EntityTab';
@ -69,10 +70,14 @@ function DlgEditReference({ hideWindow, schema, initial, onSave }: DlgEditRefere
hideWindow={hideWindow}
canSubmit={isValid}
onSubmit={handleSubmit}
className='w-[40rem] px-6 min-h-[34rem]'
className='w-[40rem] px-6 min-h-[35rem]'
>
<Overlay position='top-0 right-[4rem]'>
<BadgeHelp topic={HelpTopic.TERM_CONTROL} className='max-w-[35rem]' offset={14} />
<Overlay position='top-0 right-0'>
<BadgeHelp
topic={HelpTopic.TERM_CONTROL}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
offset={14}
/>
</Overlay>
<Tabs
@ -82,15 +87,10 @@ function DlgEditReference({ hideWindow, schema, initial, onSave }: DlgEditRefere
onSelect={setActiveTab}
>
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none')}>
<TabLabel
title='Отсылка на термин в заданной словоформе'
label={labelReferenceType(ReferenceType.ENTITY)}
className='w-[12rem]'
/>
<TabLabel title='Отсылка на термин в заданной словоформе' label={labelReferenceType(ReferenceType.ENTITY)} />
<TabLabel
title='Установление синтаксической связи с отсылкой на термин'
label={labelReferenceType(ReferenceType.SYNTACTIC)}
className='w-[12rem]'
/>
</TabList>

View File

@ -22,7 +22,7 @@ function SelectWordForm({ selected, setSelected }: SelectWordFormProps) {
);
return (
<div className='text-sm'>
<div className='text-xs sm:text-sm'>
{DefaultWordForms.slice(0, 12).map((data, index) => (
<WordformButton
key={`${prefixes.wordform_list}${index}`}

View File

@ -17,7 +17,7 @@ function WordformButton({ text, example, grams, onSelectGrams, isSelected, ...re
tabIndex={-1}
onClick={() => onSelectGrams(grams)}
className={clsx(
'min-w-[6.15rem]',
'min-w-[4.15rem] sm:min-w-[6.15rem]',
'p-1',
'border rounded-none',
'cursor-pointer',

View File

@ -16,6 +16,7 @@ import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '@/models/lang
import { parseGrammemes, wordFormEquals } from '@/models/languageAPI';
import { HelpTopic } from '@/models/miscellaneous';
import { IConstituenta, TermForm } from '@/models/rsform';
import { PARAMETER } from '@/utils/constants';
import { prompts } from '@/utils/labels';
import { IGrammemeOption, SelectorGrammemes, SelectorGrammemesList } from '@/utils/selectors';
@ -131,7 +132,11 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
className='flex flex-col w-[40rem] px-6'
>
<Overlay position='top-[-0.2rem] left-[8rem]'>
<BadgeHelp topic={HelpTopic.TERM_CONTROL} className='max-w-[38rem]' offset={3} />
<BadgeHelp
topic={HelpTopic.TERM_CONTROL}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
offset={3}
/>
</Overlay>
<TextArea
@ -179,33 +184,36 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
/>
</div>
<Overlay position='top-2 left-0'>
<MiniButton
noHover
title='Внести словоформу'
icon={<IconAccept size='1.5rem' className='icon-green' />}
disabled={textProcessor.loading || !inputText || inputGrams.length == 0}
onClick={handleAddForm}
/>
<MiniButton
noHover
title='Генерировать стандартные словоформы'
icon={<IconMoveDown size='1.5rem' className='icon-primary' />}
disabled={textProcessor.loading || !inputText}
onClick={handleGenerateLexeme}
/>
</Overlay>
<div className={clsx('mt-3 mb-2', 'flex self-center items-center', 'text-sm text-center font-semibold')}>
<span>Заданные вручную словоформы [{forms.length}]</span>
<MiniButton
noHover
title='Сбросить все словоформы'
className='py-0'
icon={<IconRemove size='1.5rem' className='icon-red' />}
disabled={textProcessor.loading || forms.length === 0}
onClick={handleResetAll}
/>
<div className='flex justify-between'>
<div className='cc-icons'>
<MiniButton
noHover
title='Внести словоформу'
icon={<IconAccept size='1.5rem' className='icon-green' />}
disabled={textProcessor.loading || !inputText || inputGrams.length == 0}
onClick={handleAddForm}
/>
<MiniButton
noHover
title='Генерировать стандартные словоформы'
icon={<IconMoveDown size='1.5rem' className='icon-primary' />}
disabled={textProcessor.loading || !inputText}
onClick={handleGenerateLexeme}
/>
</div>
<div
className={clsx('mt-3 mb-2', 'w-full flex justify-center items-center', 'text-sm text-center font-semibold')}
>
<div>Заданные вручную словоформы [{forms.length}]</div>
<MiniButton
noHover
title='Сбросить все словоформы'
className='py-0'
icon={<IconRemove size='1.5rem' className='icon-red' />}
disabled={textProcessor.loading || forms.length === 0}
onClick={handleResetAll}
/>
</div>
</div>
<WordFormsTable forms={forms} setForms={setForms} onFormSelect={handleSelectForm} />

View File

@ -12,6 +12,7 @@ import usePartialUpdate from '@/hooks/usePartialUpdate';
import { HelpTopic } from '@/models/miscellaneous';
import { CstType, ICstRenameData } from '@/models/rsform';
import { generateAlias, validateNewAlias } from '@/models/rsformAPI';
import { PARAMETER } from '@/utils/constants';
import { labelCstType } from '@/utils/labels';
import { SelectorCstType } from '@/utils/selectors';
@ -47,7 +48,7 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
hideWindow={hideWindow}
canSubmit={validated}
onSubmit={handleSubmit}
className={clsx('w-[30rem]', 'py-6 px-6 flex gap-3 justify-center items-center')}
className={clsx('w-[30rem]', 'py-6 pr-3 pl-6 flex justify-center items-center')}
>
<SelectSingle
id='dlg_cst_type'
@ -60,15 +61,20 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
}}
onChange={data => updateData({ cst_type: data?.value ?? CstType.BASE })}
/>
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} className='max-w-[40rem] max-h-[calc(100svh-2rem)]' />
<TextInput
id='dlg_cst_alias'
dense
label='Имя'
className='w-[7rem]'
className='w-[7rem] ml-3'
value={cstData.alias}
onChange={event => updateData({ alias: event.target.value })}
/>
<BadgeHelp
topic={HelpTopic.CC_CONSTITUENTA}
offset={16}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
/>
</Modal>
);
}

View File

@ -11,7 +11,7 @@ import { HelpTopic } from '@/models/miscellaneous';
import { SyntaxTree } from '@/models/rslang';
import { graphDarkT, graphLightT } from '@/styling/color';
import { colorBgSyntaxTree } from '@/styling/color';
import { resources } from '@/utils/constants';
import { PARAMETER, resources } from '@/utils/constants';
import { labelSyntaxTree } from '@/utils/labels';
interface DlgShowASTProps extends Pick<ModalProps, 'hideWindow'> {
@ -55,7 +55,7 @@ function DlgShowAST({ hideWindow, syntaxTree, expression }: DlgShowASTProps) {
return (
<Modal readonly hideWindow={hideWindow} className='px-6'>
<Overlay position='left-[-1rem] top-[0.25rem]'>
<BadgeHelp topic={HelpTopic.UI_FORMULA_TREE} className='max-w-[32rem]' />
<BadgeHelp topic={HelpTopic.UI_FORMULA_TREE} className={PARAMETER.TOOLTIP_WIDTH} />
</Overlay>
<div className='my-2 text-lg text-center'>
{!hoverNode ? expression : null}

View File

@ -14,7 +14,7 @@ import SelectorButton from '@/components/ui/SelectorButton';
import useDropdown from '@/hooks/useDropdown';
import { LocationHead } from '@/models/library';
import { HelpTopic } from '@/models/miscellaneous';
import { prefixes } from '@/utils/constants';
import { PARAMETER, prefixes } from '@/utils/constants';
import { describeLocationHead, labelLocationHead } from '@/utils/labels';
import { tripleToggleColor } from '@/utils/utils';
@ -170,7 +170,12 @@ function SearchPanel({
/>
</div>
<BadgeHelp topic={HelpTopic.UI_LIBRARY} className='max-w-[28rem] text-sm' offset={5} place='right-start' />
<BadgeHelp
topic={HelpTopic.UI_LIBRARY}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'text-sm')}
offset={5}
place='right-start'
/>
</div>
);
}

View File

@ -1,8 +1,31 @@
import { IconHide, IconImmutable, IconPrivate, IconProtected, IconPublic } from '@/components/Icons';
function HelpAccess() {
return (
<div>
<h1>Организация доступов</h1>
<p>TBD.</p>
<p>Редактирование контента осуществляется Редакторами и Владельцом.</p>
<p>Редактирование прав и доступов осуществляется Владельцом.</p>
<p>
Доступ к контенту на Портале может быть ограничен владельцем каждой схемы в рамках <b>политики доступа</b>.
</p>
<li>
<IconPublic className='inline-icon icon-green' /> публичная политика не ограничивает чтение схемы
</li>
<li>
<IconProtected className='inline-icon icon-blue' /> защитная политика запрещает доступ для всех кроме редакторов
и владельца схемы
</li>
<li>
<IconPrivate className='inline-icon icon-red' /> личная политика оставляет доступ к схеме только владельцу
</li>
<li>
<IconHide className='inline-icon' /> режим скрытия схемы из списка в Библиотеке не ограничивает доступ к схеме
по прямой ссылке
</li>
<li>
<IconImmutable className='inline-icon' /> режим защиты от редактирования предохраняет от случайных изменений
</li>
</div>
);
}

View File

@ -5,10 +5,8 @@ function HelpFormulaTree() {
return (
<div>
<h1>Дерево разбора выражения</h1>
<p>
Дерево разбора получено путем семантических преобразований дерева синтаксического разбора. Оно отражает
структуру грамматически корректного выражения языка родов структур.
</p>
<p>Дерево получено путем семантических преобразований дерева синтаксического разбора.</p>
<p>Оно отражает структуру грамматически корректного выражения языка родов структур.</p>
<li>Порядок узлов в рамках одного уровня может отличаться от их порядка в выражении</li>
<li>При наведении курсора на узел в тексте выделяется соответствующий ему фрагмент</li>
<li>Текст в узле дерева соответствует элементу языка</li>

View File

@ -26,8 +26,8 @@ function HelpTermGraph() {
const { colors } = useConceptOptions();
return (
<div className='flex flex-col'>
<div className='flex'>
<div className='dense w-[14rem]'>
<div className='flex flex-col sm:flex-row'>
<div className='w-full sm:w-[14rem]'>
<h1>Настройка графа</h1>
<li>Цвет покраска узлов</li>
<li>Граф расположение</li>
@ -43,9 +43,9 @@ function HelpTermGraph() {
</li>
</div>
<Divider vertical margins='mx-3 mt-3' />
<Divider vertical margins='mx-3 mt-3' className='hidden sm:block' />
<div className='dense w-[21rem]'>
<div className='w-full sm:w-[21rem]'>
<h1>Изменение узлов</h1>
<li>Клик на конституенту выделение</li>
<li>
@ -66,10 +66,10 @@ function HelpTermGraph() {
</div>
</div>
<Divider margins='my-3' />
<Divider margins='my-3' className='hidden sm:block' />
<div className='flex mb-3'>
<div className='dense w-[14rem]'>
<div className='flex mb-3 flex-col-reverse sm:flex-row'>
<div className='w-full sm:w-[14rem]'>
<h1>Общие</h1>
<li>
<IconFilter className='inline-icon' /> Открыть настройки
@ -82,7 +82,7 @@ function HelpTermGraph() {
</li>
</div>
<Divider vertical margins='mx-3' />
<Divider vertical margins='mx-3' className='hidden sm:block' />
<div className='dense w-[21rem]'>
<h1>Выделение</h1>

View File

@ -10,6 +10,7 @@ import Overlay from '@/components/ui/Overlay';
import { useAccessMode } from '@/context/AccessModeContext';
import { HelpTopic } from '@/models/miscellaneous';
import { UserLevel } from '@/models/user';
import { PARAMETER } from '@/utils/constants';
import { prepareTooltip } from '@/utils/labels';
import { useOssEdit } from '../OssEditContext';
@ -57,7 +58,7 @@ function RSFormToolbar({ modified, anonymous, subscribed, onSubmit, onDestroy }:
onClick={onDestroy}
/>
) : null}
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} className='max-w-[30rem]' />
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} className={PARAMETER.TOOLTIP_WIDTH} />
</Overlay>
);
}

View File

@ -13,6 +13,7 @@ import BadgeHelp from '@/components/info/BadgeHelp';
import MiniButton from '@/components/ui/MiniButton';
import Overlay from '@/components/ui/Overlay';
import { HelpTopic } from '@/models/miscellaneous';
import { PARAMETER } from '@/utils/constants';
import { prepareTooltip, tooltips } from '@/utils/labels';
interface ConstituentaToolbarProps {
@ -94,7 +95,7 @@ function ConstituentaToolbar({
disabled={disabled || modified}
onClick={onMoveDown}
/>
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} />
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} className={PARAMETER.TOOLTIP_WIDTH} />
</Overlay>
);
}

View File

@ -30,10 +30,10 @@ function ControlsOverlay({ constituenta, disabled, modified, processing, onRenam
) : null}
<div
className={clsx(
'pt-1 pl-[1.375rem]', // prettier: split lines
'pt-1 sm:pl-[1.375rem] pl-1', // prettier: split lines
'text-sm font-medium whitespace-nowrap',
'select-text cursor-default',
disabled && !processing && 'pl-[2.8rem]'
disabled && !processing && 'pl-[1.6rem] sm:pl-[2.8rem]'
)}
>
<span>Имя </span>

View File

@ -21,7 +21,7 @@ function ExpressionToolbar({ disabled, showControls, toggleControls, showAST }:
}
return (
<Overlay position='top-[-0.5rem] right-0 cc-icons'>
<Overlay position='top-[-0.5rem] right-0' className='cc-icons'>
<MiniButton
title='Изменить шрифт'
onClick={toggleFont}

View File

@ -41,10 +41,12 @@ function StatusBar({ isModified, processing, constituenta, parseData, onAnalyze
tabIndex={0}
className={clsx(
'w-[10rem] h-[1.75rem]',
'scale-75 sm:scale-100 mx-[-2.5rem] sm:m-0',
'px-2 flex items-center justify-center gap-2',
'border',
'select-none',
'cursor-pointer',
'translate-x-[-1.5rem]',
'focus-frame',
'duration-500 transition-colors'
)}

View File

@ -11,6 +11,7 @@ import { useAccessMode } from '@/context/AccessModeContext';
import { AccessPolicy, ILibraryItemEditor } from '@/models/library';
import { HelpTopic } from '@/models/miscellaneous';
import { UserLevel } from '@/models/user';
import { PARAMETER } from '@/utils/constants';
interface AccessToolbarProps {
visible: boolean;
@ -59,7 +60,7 @@ function AccessToolbar({ visible, toggleVisible, readOnly, toggleReadOnly, contr
disabled={accessLevel === UserLevel.READER || controller.isProcessing}
/>
<BadgeHelp topic={HelpTopic.ACCESS} className='max-w-[30rem]' offset={4} />
<BadgeHelp topic={HelpTopic.ACCESS} className={PARAMETER.TOOLTIP_WIDTH} offset={4} />
</div>
</Overlay>
);

View File

@ -10,6 +10,7 @@ import Overlay from '@/components/ui/Overlay';
import { useAccessMode } from '@/context/AccessModeContext';
import { HelpTopic } from '@/models/miscellaneous';
import { UserLevel } from '@/models/user';
import { PARAMETER } from '@/utils/constants';
import { prepareTooltip } from '@/utils/labels';
import { useRSEdit } from '../RSEditContext';
@ -57,7 +58,7 @@ function RSFormToolbar({ modified, anonymous, subscribed, onSubmit, onDestroy }:
onClick={onDestroy}
/>
) : null}
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} className='max-w-[30rem]' />
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} className={PARAMETER.TOOLTIP_WIDTH} />
</Overlay>
);
}

View File

@ -3,6 +3,7 @@ import BadgeHelp from '@/components/info/BadgeHelp';
import MiniButton from '@/components/ui/MiniButton';
import Overlay from '@/components/ui/Overlay';
import { HelpTopic } from '@/models/miscellaneous';
import { PARAMETER } from '@/utils/constants';
import { useRSEdit } from '../RSEditContext';
@ -34,7 +35,7 @@ function VersionsToolbar() {
/>
</>
) : null}
<BadgeHelp topic={HelpTopic.VERSIONS} className='max-w-[30rem]' offset={4} />
<BadgeHelp topic={HelpTopic.VERSIONS} className={PARAMETER.TOOLTIP_WIDTH} offset={4} />
</Overlay>
);
}

View File

@ -1,3 +1,5 @@
import clsx from 'clsx';
import {
IconClustering,
IconClusteringOff,
@ -13,6 +15,7 @@ import {
import BadgeHelp from '@/components/info/BadgeHelp';
import MiniButton from '@/components/ui/MiniButton';
import { HelpTopic } from '@/models/miscellaneous';
import { PARAMETER } from '@/utils/constants';
import { useRSEdit } from '../RSEditContext';
@ -111,7 +114,11 @@ function GraphToolbar({
title='Сохранить изображение'
onClick={onSaveImage}
/>
<BadgeHelp topic={HelpTopic.UI_GRAPH_TERM} className='max-w-[calc(100vw-4rem)]' offset={4} />
<BadgeHelp
topic={HelpTopic.UI_GRAPH_TERM}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
offset={4}
/>
</div>
);
}

View File

@ -16,7 +16,9 @@ export const PARAMETER = {
graphPopupDelay: 500, // milliseconds delay for graph popup selections
graphRefreshDelay: 10, // milliseconds delay for graph viewpoint reset
logicLabel: 'LOGIC'
logicLabel: 'LOGIC',
TOOLTIP_WIDTH: 'max-w-[29rem]'
};
/**