F: Improve styling pt2

This commit is contained in:
Ivan 2025-03-10 16:01:40 +03:00
parent a85112e265
commit 99507a9b8d
87 changed files with 202 additions and 345 deletions

View File

@ -25,7 +25,7 @@ export function ApplicationLayout() {
return ( return (
<NavigationState> <NavigationState>
<div className='min-w-80 antialiased h-full max-w-[120rem] mx-auto'> <div className='min-w-80 antialiased h-full max-w-480 mx-auto'>
<ToasterThemed <ToasterThemed
className='text-[14px]' className='text-[14px]'
style={{ marginTop: noNavigationAnimation ? '1.5rem' : '3.5rem' }} style={{ marginTop: noNavigationAnimation ? '1.5rem' : '3.5rem' }}

View File

@ -1,11 +1,10 @@
import { useNavigation } from 'react-router'; import { useNavigation } from 'react-router';
import clsx from 'clsx';
import { useDebounce } from 'use-debounce'; import { useDebounce } from 'use-debounce';
import { Loader } from '@/components/Loader'; import { Loader } from '@/components/Loader';
import { ModalBackdrop } from '@/components/Modal/ModalBackdrop';
import { PARAMETER } from '@/utils/constants'; import { PARAMETER } from '@/utils/constants';
// TODO: add animation
export function GlobalLoader() { export function GlobalLoader() {
const navigation = useNavigation(); const navigation = useNavigation();
@ -17,16 +16,9 @@ export function GlobalLoader() {
} }
return ( return (
<div className='fixed top-0 left-0 w-full h-full z-modal cursor-default'> <div className='cc-modal-wrapper'>
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} /> <ModalBackdrop />
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')} /> <div className='cc-fade-in px-10 border rounded-xl bg-prim-100'>
<div
className={clsx(
'px-10 mb-10',
'z-modal absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
'border rounded-xl bg-prim-100'
)}
>
<Loader scale={6} /> <Loader scale={6} />
</div> </div>
</div> </div>

View File

@ -1,8 +1,7 @@
import clsx from 'clsx';
import { useMutationErrors } from '@/backend/useMutationErrors'; import { useMutationErrors } from '@/backend/useMutationErrors';
import { Button } from '@/components/Control'; import { Button } from '@/components/Control';
import { DescribeError } from '@/components/InfoError'; import { DescribeError } from '@/components/InfoError';
import { ModalBackdrop } from '@/components/Modal/ModalBackdrop';
import { useEscapeKey } from '@/hooks/useEscapeKey'; import { useEscapeKey } from '@/hooks/useEscapeKey';
import { useDialogsStore } from '@/stores/dialogs'; import { useDialogsStore } from '@/stores/dialogs';
@ -19,18 +18,11 @@ export function MutationErrors() {
hideDialog(); hideDialog();
return ( return (
<div className='fixed top-0 left-0 w-full h-full z-modal cursor-default'> <div className='cc-modal-wrapper'>
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} /> <ModalBackdrop onHide={resetErrors} />
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')} /> <div className='px-10 py-3 flex flex-col items-center border rounded-xl bg-prim-100' role='alertdialog'>
<div
className={clsx(
'px-10 mb-10 py-3 flex flex-col items-center',
'z-modal absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
'border rounded-xl bg-prim-100'
)}
>
<h1 className='py-2 select-none'>Ошибка при обработке</h1> <h1 className='py-2 select-none'>Ошибка при обработке</h1>
<div className={clsx('px-3 flex flex-col', 'text-warn-600 text-sm font-semibold', 'select-text')}> <div className='px-3 flex flex-col text-warn-600 text-sm font-semibold select-text'>
<DescribeError error={mutationErrors[0]} /> <DescribeError error={mutationErrors[0]} />
</div> </div>
<Button onClick={resetErrors} className='w-fit' text='Закрыть' /> <Button onClick={resetErrors} className='w-fit' text='Закрыть' />

View File

@ -8,6 +8,7 @@ export function Logo() {
return ( return (
<img <img
alt='' alt=''
aria-hidden
className='max-h-7 w-fit max-w-46' className='max-h-7 w-fit max-w-46'
src={size.isSmall ? '/logo_sign.svg' : !darkMode ? '/logo_full.svg' : '/logo_full_dark.svg'} src={size.isSmall ? '/logo_sign.svg' : !darkMode ? '/logo_full.svg' : '/logo_full_dark.svg'}
/> />

View File

@ -1,9 +1,6 @@
import clsx from 'clsx';
import { IconLibrary2, IconManuals, IconNewItem2 } from '@/components/Icons'; import { IconLibrary2, IconManuals, IconNewItem2 } from '@/components/Icons';
import { useWindowSize } from '@/hooks/useWindowSize'; import { useWindowSize } from '@/hooks/useWindowSize';
import { useAppLayoutStore } from '@/stores/appLayout'; import { useAppLayoutStore } from '@/stores/appLayout';
import { PARAMETER } from '@/utils/constants';
import { urls } from '../urls'; import { urls } from '../urls';
@ -28,34 +25,16 @@ export function Navigation() {
router.push({ path: urls.create_schema, newTab: event.ctrlKey || event.metaKey }); router.push({ path: urls.create_schema, newTab: event.ctrlKey || event.metaKey });
return ( return (
<nav <nav className='z-navigation sticky top-0 left-0 right-0 select-none bg-prim-100'>
className={clsx(
'z-navigation', //
'sticky top-0 left-0 right-0',
'select-none',
'bg-prim-100'
)}
>
<ToggleNavigation /> <ToggleNavigation />
<div <div
className={clsx( className='pl-2 pr-6 sm:pr-4 h-12 flex cc-shadow-border'
'pl-2 pr-6 sm:pr-4 h-12', //
'flex',
'cc-shadow-border'
)}
style={{ style={{
willChange: 'max-height, translate',
transitionProperty: 'max-height, translate',
transitionDuration: `${PARAMETER.moveDuration}ms`,
maxHeight: noNavigationAnimation ? '0rem' : '3rem', maxHeight: noNavigationAnimation ? '0rem' : '3rem',
translate: noNavigationAnimation ? '0 -1.5rem' : '0' translate: noNavigationAnimation ? '0 -1.5rem' : '0'
}} }}
> >
<div <div className='flex items-center mr-auto cursor-pointer' onClick={!size.isSmall ? navigateHome : undefined}>
tabIndex={-1}
className={clsx('flex items-center mr-auto', !size.isSmall && 'cursor-pointer')}
onClick={!size.isSmall ? navigateHome : undefined}
>
<Logo /> <Logo />
</div> </div>
<div className='flex gap-2 items-center'> <div className='flex gap-2 items-center'>

View File

@ -17,7 +17,7 @@ export function Divider({ vertical, margins = 'mx-2', className, ...restProps }:
return ( return (
<div <div
className={clsx( className={clsx(
margins, //prettier: split-lines margins, //
className, className,
{ {
'border-x': vertical, 'border-x': vertical,

View File

@ -3,7 +3,6 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { type Table } from '@tanstack/react-table'; import { type Table } from '@tanstack/react-table';
import clsx from 'clsx';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
@ -34,7 +33,7 @@ export function PaginationTools<TData>({
); );
return ( return (
<div className={clsx('flex justify-end items-center', 'my-2', 'text-sm', 'clr-text-controls', 'select-none')}> <div className='flex justify-end items-center my-2 text-sm clr-text-controls select-none'>
<span className='mr-3'> <span className='mr-3'>
{`${table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1} {`${table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1}
- -

View File

@ -41,7 +41,7 @@ export function FileInput({ id, label, acceptType, title, className, style, onCh
}; };
return ( return (
<div className={clsx('py-2', 'flex flex-col gap-2 items-center', className)} style={style}> <div className={clsx('py-2 flex flex-col gap-2 items-center', className)} style={style}>
<input <input
id={id} id={id}
type='file' type='file'

View File

@ -109,7 +109,7 @@ export function SelectMulti<Option, Group extends GroupBase<Option> = GroupBase<
...theme, ...theme,
borderRadius: 0, borderRadius: 0,
spacing: { spacing: {
...theme.spacing, // prettier: split-lines ...theme.spacing,
baseUnit: size.isSmall ? 2 : 4, baseUnit: size.isSmall ? 2 : 4,
menuGutter: size.isSmall ? 4 : 8, menuGutter: size.isSmall ? 4 : 8,
controlHeight: size.isSmall ? 28 : 38 controlHeight: size.isSmall ? 28 : 38

View File

@ -107,7 +107,7 @@ export function SelectSingle<Option, Group extends GroupBase<Option> = GroupBase
...theme, ...theme,
borderRadius: 0, borderRadius: 0,
spacing: { spacing: {
...theme.spacing, // prettier: split-lines ...theme.spacing,
baseUnit: size.isSmall ? 2 : 4, baseUnit: size.isSmall ? 2 : 4,
menuGutter: 2, menuGutter: 2,
controlHeight: size.isSmall ? 28 : 38 controlHeight: size.isSmall ? 28 : 38

View File

@ -50,13 +50,13 @@ export function SelectTree<ItemType>({
setFolded(items.filter(item => getParent(value) !== item && getParent(getParent(value)) !== item)); setFolded(items.filter(item => getParent(value) !== item && getParent(getParent(value)) !== item));
}, [value, getParent, items]); }, [value, getParent, items]);
function onFoldItem(target: ItemType, showChildren: boolean) { function onFoldItem(target: ItemType) {
setFolded(prev => setFolded(prev =>
items.filter(item => { items.filter(item => {
if (item === target) { if (item === target) {
return !showChildren; return !prev.includes(target);
} }
if (!showChildren && (getParent(item) === target || getParent(getParent(item)) === target)) { if (!prev.includes(target) && (getParent(item) === target || getParent(getParent(item)) === target)) {
return true; return true;
} else { } else {
return prev.includes(item); return prev.includes(item);
@ -65,17 +65,21 @@ export function SelectTree<ItemType>({
); );
} }
function handleClickFold(event: React.MouseEvent<Element>, target: ItemType, showChildren: boolean) { function handleClickFold(event: React.MouseEvent<Element>, target: ItemType) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
onFoldItem(target, showChildren); onFoldItem(target);
} }
function handleSetValue(event: React.MouseEvent<Element>, target: ItemType) { function handleClickItem(event: React.MouseEvent<Element>, target: ItemType) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
if (event.ctrlKey || event.metaKey) {
onFoldItem(target);
} else {
onChange(target); onChange(target);
} }
}
return ( return (
<div tabIndex={-1} {...restProps}> <div tabIndex={-1} {...restProps}>
@ -95,7 +99,7 @@ export function SelectTree<ItemType>({
)} )}
data-tooltip-id={globalIDs.tooltip} data-tooltip-id={globalIDs.tooltip}
data-tooltip-html={getDescription(item)} data-tooltip-html={getDescription(item)}
onClick={event => handleSetValue(event, item)} onClick={event => handleClickItem(event, item)}
style={{ style={{
borderBottomWidth: isActive ? '1px' : '0px', borderBottomWidth: isActive ? '1px' : '0px',
willChange: 'max-height, opacity, padding', willChange: 'max-height, opacity, padding',
@ -109,11 +113,11 @@ export function SelectTree<ItemType>({
> >
{foldable.has(item) ? ( {foldable.has(item) ? (
<MiniButton <MiniButton
className={clsx('absolute left-[0.3rem]', !folded.includes(item) ? 'top-[0.4rem]' : 'top-1')} className={clsx('absolute left-1', !folded.includes(item) ? 'top-1.5' : 'top-1')}
noPadding noPadding
noHover noHover
icon={!folded.includes(item) ? <IconDropArrow size='1rem' /> : <IconPageRight size='1.25rem' />} icon={!folded.includes(item) ? <IconDropArrow size='1rem' /> : <IconPageRight size='1.25rem' />}
onClick={event => handleClickFold(event, item, folded.includes(item))} onClick={event => handleClickFold(event, item)}
/> />
) : null} ) : null}
{getParent(item) === item ? getLabel(item) : `- ${getLabel(item).toLowerCase()}`} {getParent(item) === item ? getLabel(item) : `- ${getLabel(item).toLowerCase()}`}

View File

@ -1,19 +1,14 @@
'use client'; 'use client';
import clsx from 'clsx';
interface ModalBackdropProps { interface ModalBackdropProps {
onHide: () => void; onHide?: () => void;
} }
export function ModalBackdrop({ onHide }: ModalBackdropProps) { export function ModalBackdrop({ onHide }: ModalBackdropProps) {
return ( return (
<> <>
<div className={clsx('z-bottom', 'fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} /> <div className='z-bottom fixed inset-0 backdrop-blur-[3px] opacity-50' />
<div <div className='z-bottom fixed inset-0 bg-prim-0 opacity-25' onClick={onHide} />
className={clsx('z-bottom', 'fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')}
onClick={onHide}
/>
</> </>
); );
} }

View File

@ -87,15 +87,10 @@ export function ModalForm({
} }
return ( return (
<div className='fixed top-0 left-0 w-full h-full z-modal isolate cursor-default'> <div className='cc-modal-wrapper'>
<ModalBackdrop onHide={handleCancel} /> <ModalBackdrop onHide={handleCancel} />
<form <form
className={clsx( className='cc-animate-modal grid border rounded-xl bg-prim-100'
'cc-animate-modal',
'absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
'grid',
'border rounded-xl bg-prim-100'
)}
role='dialog' role='dialog'
onSubmit={handleSubmit} onSubmit={handleSubmit}
aria-labelledby='modal-title' aria-labelledby='modal-title'

View File

@ -1,19 +1,12 @@
import clsx from 'clsx';
import { Loader } from '@/components/Loader'; import { Loader } from '@/components/Loader';
import { ModalBackdrop } from './ModalBackdrop';
export function ModalLoader() { export function ModalLoader() {
return ( return (
<div className='fixed top-0 left-0 w-full h-full z-modal isolate cursor-default'> <div className='cc-modal-wrapper'>
<div className={clsx('z-bottom fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} /> <ModalBackdrop />
<div className={clsx('z-bottom fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')} /> <div className='cc-animate-modal p-20 border rounded-xl bg-prim-100'>
<div
className={clsx(
'cc-animate-modal p-20',
'z-modal absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
'border rounded-xl bg-prim-100'
)}
>
<Loader circular scale={6} /> <Loader circular scale={6} />
</div> </div>
</div> </div>

View File

@ -32,17 +32,9 @@ export function ModalView({
useEscapeKey(hideDialog); useEscapeKey(hideDialog);
return ( return (
<div className='fixed top-0 left-0 w-full h-full z-modal isolate cursor-default'> <div className='cc-modal-wrapper'>
<ModalBackdrop onHide={hideDialog} /> <ModalBackdrop onHide={hideDialog} />
<div <div className='cc-animate-modal grid border rounded-xl bg-prim-100' role='dialog'>
className={clsx(
'cc-animate-modal',
'absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
'grid',
'border rounded-xl bg-prim-100'
)}
role='dialog'
>
{helpTopic && !hideHelpWhen?.() ? ( {helpTopic && !hideHelpWhen?.() ? (
<BadgeHelp <BadgeHelp
topic={helpTopic} topic={helpTopic}

View File

@ -20,5 +20,5 @@ interface ValueStatsProps extends Styling, Titled {
* Displays statistics value with an icon. * Displays statistics value with an icon.
*/ */
export function ValueStats(props: ValueStatsProps) { export function ValueStats(props: ValueStatsProps) {
return <ValueIcon dense smallThreshold={SMALL_THRESHOLD} textClassName='min-w-[1.4rem]' {...props} />; return <ValueIcon dense smallThreshold={SMALL_THRESHOLD} textClassName='min-w-5' {...props} />;
} }

View File

@ -2,7 +2,6 @@
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { urls, useConceptNavigation } from '@/app'; import { urls, useConceptNavigation } from '@/app';
@ -56,11 +55,11 @@ export function LoginPage() {
} }
return ( return (
<form <form
className={clsx('cc-column cc-fade-in', 'w-[24rem] mx-auto', 'pt-12 pb-6 px-6')} className='cc-column cc-fade-in w-96 mx-auto pt-12 pb-6 px-6'
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
onChange={resetErrors} onChange={resetErrors}
> >
<img alt='Концепт Портал' src={resources.logo} className='max-h-[2.5rem] min-w-[2.5rem] mb-3' /> <img alt='Концепт Портал' src={resources.logo} className='max-h-10 min-w-10 mb-3' />
<TextInput <TextInput
id='username' id='username'
autoComplete='username' autoComplete='username'
@ -82,7 +81,7 @@ export function LoginPage() {
error={errors.password} error={errors.password}
/> />
<SubmitButton text='Войти' className='self-center w-[12rem] mt-3' loading={isPending} /> <SubmitButton text='Войти' className='self-center w-48 mt-3' loading={isPending} />
<div className='flex flex-col text-sm'> <div className='flex flex-col text-sm'>
<TextURL text='Восстановить пароль...' href='/restore-password' /> <TextURL text='Восстановить пароль...' href='/restore-password' />
<TextURL text='Нет аккаунта? Зарегистрируйтесь...' href='/signup' /> <TextURL text='Нет аккаунта? Зарегистрируйтесь...' href='/signup' />

View File

@ -1,7 +1,6 @@
'use client'; 'use client';
import { useState } from 'react'; import { useState } from 'react';
import clsx from 'clsx';
import { isAxiosError } from '@/backend/apiTransport'; import { isAxiosError } from '@/backend/apiTransport';
import { SubmitButton, TextURL } from '@/components/Control'; import { SubmitButton, TextURL } from '@/components/Control';
@ -33,11 +32,7 @@ export function Component() {
); );
} else { } else {
return ( return (
<form <form className='cc-fade-in cc-column w-96 mx-auto px-6 mt-3' onSubmit={handleSubmit} onChange={clearServerError}>
className={clsx('cc-fade-in cc-column', 'w-[24rem] mx-auto', 'px-6 mt-3')}
onSubmit={handleSubmit}
onChange={clearServerError}
>
<TextInput <TextInput
id='email' id='email'
autoComplete='email' autoComplete='email'
@ -48,12 +43,7 @@ export function Component() {
onChange={event => setEmail(event.target.value)} onChange={event => setEmail(event.target.value)}
/> />
<SubmitButton <SubmitButton text='Запросить пароль' className='self-center w-48 mt-3' loading={isPending} disabled={!email} />
text='Запросить пароль'
className='self-center w-[12rem] mt-3'
loading={isPending}
disabled={!email}
/>
{serverError ? <ServerError error={serverError} /> : null} {serverError ? <ServerError error={serverError} /> : null}
</form> </form>
); );

View File

@ -52,7 +52,7 @@ export function BadgeHelp({ topic, padding = 'p-1', className, contentClass, sty
{...restProps} {...restProps}
> >
<Suspense fallback={<Loader />}> <Suspense fallback={<Loader />}>
<div className='absolute right-1 text-sm top-[0.4rem] clr-input' onClick={event => event.stopPropagation()}> <div className='absolute right-1 text-sm top-2 clr-input' onClick={event => event.stopPropagation()}>
<TextURL text='Справка...' href={`/manuals?topic=${topic}`} /> <TextURL text='Справка...' href={`/manuals?topic=${topic}`} />
</div> </div>
<TopicPage topic={topic} /> <TopicPage topic={topic} />

View File

@ -1,5 +1,3 @@
import clsx from 'clsx';
import { CstClass } from '@/features/rsform'; import { CstClass } from '@/features/rsform';
import { colorBgCstClass } from '@/features/rsform/colors'; import { colorBgCstClass } from '@/features/rsform/colors';
import { describeCstClass, labelCstClass } from '@/features/rsform/labels'; import { describeCstClass, labelCstClass } from '@/features/rsform/labels';
@ -18,7 +16,7 @@ export function InfoCstClass({ header }: InfoCstClassProps) {
return ( return (
<p key={`${prefixes.cst_status_list}${index}`}> <p key={`${prefixes.cst_status_list}${index}`}>
<span <span
className={clsx('inline-block', 'min-w-28', 'px-1', 'border', 'text-center text-sm font-controls')} className='inline-block min-w-28 px-1 border text-center text-sm font-controls'
style={{ backgroundColor: colorBgCstClass(cstClass) }} style={{ backgroundColor: colorBgCstClass(cstClass) }}
> >
{labelCstClass(cstClass)} {labelCstClass(cstClass)}

View File

@ -21,7 +21,7 @@ export function InfoCstStatus({ title }: InfoCstStatusProps) {
<span <span
className={clsx( className={clsx(
'inline-block', // 'inline-block', //
'min-w-[7rem]', 'min-w-28',
'px-1', 'px-1',
'border', 'border',
'text-center text-sm font-controls' 'text-center text-sm font-controls'

View File

@ -69,7 +69,7 @@ export function HelpRSGraphTerm() {
<Divider margins='my-3' className='hidden sm:block' /> <Divider margins='my-3' className='hidden sm:block' />
<div className='flex flex-col-reverse mb-3 sm:flex-row'> <div className='flex flex-col-reverse mb-3 sm:flex-row'>
<div className='sm:w-[14rem]'> <div className='sm:w-56'>
<h1>Общие</h1> <h1>Общие</h1>
<li> <li>
<IconOSS className='inline-icon' /> переход к связанной <LinkTopic text='ОСС' topic={HelpTopic.CC_OSS} /> <IconOSS className='inline-icon' /> переход к связанной <LinkTopic text='ОСС' topic={HelpTopic.CC_OSS} />
@ -88,7 +88,7 @@ export function HelpRSGraphTerm() {
<Divider vertical margins='mx-3' className='hidden sm:block' /> <Divider vertical margins='mx-3' className='hidden sm:block' />
<div className='dense w-[21rem]'> <div className='dense w-84'>
<h1>Выделение</h1> <h1>Выделение</h1>
<li> <li>
<IconGraphCollapse className='inline-icon' /> все влияющие <IconGraphCollapse className='inline-icon' /> все влияющие

View File

@ -67,7 +67,7 @@ export function HelpRSMenu() {
<Divider vertical margins='mx-3' /> <Divider vertical margins='mx-3' />
<div className='w-[18rem]'> <div className='w-72'>
<h2>Режимы работы</h2> <h2>Режимы работы</h2>
<li> <li>
<IconAlert size='1.25rem' className='inline-icon icon-red' /> работа в анонимном режиме. Переход на страницу <IconAlert size='1.25rem' className='inline-icon icon-red' /> работа в анонимном режиме. Переход на страницу

View File

@ -27,7 +27,7 @@ export function ManualsPage() {
} }
return ( return (
<div className='flex mx-auto max-w-[80rem]' role='manuals' style={{ minHeight: mainHeight }}> <div className='flex mx-auto max-w-320' role='manuals' style={{ minHeight: mainHeight }}>
<TopicsList activeTopic={activeTopic} onChangeTopic={topic => onSelectTopic(topic)} /> <TopicsList activeTopic={activeTopic} onChangeTopic={topic => onSelectTopic(topic)} />
<ViewTopic topic={activeTopic} /> <ViewTopic topic={activeTopic} />
</div> </div>

View File

@ -31,7 +31,7 @@ export function TopicsDropdown({ activeTopic, onChangeTopic }: TopicsDropdownPro
<div <div
ref={menu.ref} ref={menu.ref}
className={clsx( className={clsx(
'absolute left-0 w-54', // prettier: split-lines 'absolute left-0 w-54', //
'flex flex-col', 'flex flex-col',
'z-topmost', 'z-topmost',
'text-xs sm:text-sm', 'text-xs sm:text-sm',
@ -59,11 +59,7 @@ export function TopicsDropdown({ activeTopic, onChangeTopic }: TopicsDropdownPro
getParent={item => topicParent.get(item) ?? item} getParent={item => topicParent.get(item) ?? item}
getLabel={labelHelpTopic} getLabel={labelHelpTopic}
getDescription={describeHelpTopic} getDescription={describeHelpTopic}
className={clsx( className='border-r border-t rounded-none cc-scroll-y bg-prim-200'
'border-r border-t rounded-none', // prettier: split-lines
'cc-scroll-y',
'bg-prim-200'
)}
style={{ style={{
maxHeight: treeHeight, maxHeight: treeHeight,
willChange: 'clip-path', willChange: 'clip-path',

View File

@ -25,7 +25,7 @@ export function TopicsStatic({ activeTopic, onChangeTopic }: TopicsStaticProps)
getDescription={describeHelpTopic} getDescription={describeHelpTopic}
className={clsx( className={clsx(
'sticky top-0 left-0', 'sticky top-0 left-0',
'min-w-[14.5rem] max-w-[14.5rem] sm:min-w-[12.5rem] sm:max-w-[12.5rem] md:min-w-[14.5rem] md:max-w-[14.5rem]', 'min-w-58 max-w-58 sm:min-w-50 sm:max-w-50 md:min-w-58 md:max-w-58',
'cc-scroll-y', 'cc-scroll-y',
'self-start', 'self-start',
'border-x border-t rounded-none', 'border-x border-t rounded-none',

View File

@ -119,7 +119,7 @@ export function PickSchema({
className='mt-1' className='mt-1'
onClick={() => locationMenu.toggle()} onClick={() => locationMenu.toggle()}
/> />
<Dropdown isOpen={locationMenu.isOpen} stretchLeft className='w-[20rem] h-[12.5rem]'> <Dropdown isOpen={locationMenu.isOpen} stretchLeft className='w-80 h-50'>
<SelectLocation <SelectLocation
value={filterLocation} value={filterLocation}
prefix={prefixes.folders_list} prefix={prefixes.folders_list}
@ -147,7 +147,7 @@ export function PickSchema({
columns={columns} columns={columns}
conditionalRowStyles={conditionalRowStyles} conditionalRowStyles={conditionalRowStyles}
noDataComponent={ noDataComponent={
<div className='cc-column dense p-3 items-center min-h-[6rem]'> <div className='cc-column dense p-3 items-center min-h-24'>
<p>Список схем пуст</p> <p>Список схем пуст</p>
<p>Измените параметры фильтра</p> <p>Измените параметры фильтра</p>
</div> </div>

View File

@ -51,14 +51,14 @@ export function SelectLocation({ value, dense, prefix, onClick, className, style
} }
return ( return (
<div className={clsx('flex flex-col', 'cc-scroll-y', className)} style={style}> <div className={clsx('flex flex-col cc-scroll-y', className)} style={style}>
{items.map((item, index) => {items.map((item, index) =>
!item.parent || !folded.includes(item.parent) ? ( !item.parent || !folded.includes(item.parent) ? (
<div <div
tabIndex={-1} tabIndex={-1}
key={`${prefix}${index}`} key={`${prefix}${index}`}
className={clsx( className={clsx(
!dense && 'min-h-[2.0825rem] sm:min-h-[2.3125rem]', !dense && 'h-7 sm:h-8',
'pr-3 py-1 flex items-center gap-2', 'pr-3 py-1 flex items-center gap-2',
'cc-scroll-row', 'cc-scroll-row',
'clr-hover cc-animate-color', 'clr-hover cc-animate-color',

View File

@ -35,22 +35,14 @@ export function SelectLocationContext({
} }
return ( return (
<div <div ref={menu.ref} className={clsx('relative h-full -mt-1 -ml-6 text-right self-start', className)} {...restProps}>
ref={menu.ref}
className={clsx('relative h-full mt-[-0.25rem] ml-[-1.5rem]', 'text-right self-start', className)}
{...restProps}
>
<MiniButton <MiniButton
title={title} title={title}
hideTitle={menu.isOpen} hideTitle={menu.isOpen}
icon={<IconFolderTree size='1.25rem' className='icon-green' />} icon={<IconFolderTree size='1.25rem' className='icon-green' />}
onClick={() => menu.toggle()} onClick={() => menu.toggle()}
/> />
<Dropdown <Dropdown isOpen={menu.isOpen} className={clsx('w-80 h-50 z-tooltip', dropdownHeight)}>
isOpen={menu.isOpen}
className={clsx('w-[20rem] h-[12.5rem] z-tooltip', dropdownHeight)}
margin='mt-[-0.25rem]'
>
<SelectLocation <SelectLocation
value={value} value={value}
prefix={prefixes.folders_list} prefix={prefixes.folders_list}

View File

@ -34,7 +34,7 @@ export function SelectVersion({ id, className, items, value, onChange, ...restPr
return ( return (
<SelectSingle <SelectSingle
id={id} id={id}
className={clsx('min-w-[12rem] text-ellipsis', className)} className={clsx('min-w-48 text-ellipsis', className)}
options={options} options={options}
value={{ value: value, label: labelVersion(value, items) }} value={{ value: value, label: labelVersion(value, items) }}
onChange={data => onChange(data?.value ?? 'latest')} onChange={data => onChange(data?.value ?? 'latest')}

View File

@ -40,7 +40,7 @@ export function ToolbarItemAccess({
} }
return ( return (
<div className='absolute z-bottom top-[4.5rem] right-0 w-[12rem] flex pr-2'> <div className='absolute z-bottom top-18 right-0 w-48 flex pr-2'>
<Label text='Доступ' className='self-center select-none' /> <Label text='Доступ' className='self-center select-none' />
<div className='ml-auto cc-icons'> <div className='ml-auto cc-icons'>
<SelectAccessPolicy <SelectAccessPolicy
@ -68,7 +68,7 @@ export function ToolbarItemAccess({
onClick={toggleReadOnly} onClick={toggleReadOnly}
disabled={role === UserRole.READER || isProcessing} disabled={role === UserRole.READER || isProcessing}
/> />
<BadgeHelp topic={HelpTopic.ACCESS} className='mt-[0.125rem]' offset={4} /> <BadgeHelp topic={HelpTopic.ACCESS} className='mt-0.5' offset={4} />
</div> </div>
</div> </div>
); );

View File

@ -2,7 +2,6 @@
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { z } from 'zod'; import { z } from 'zod';
import { useAuthSuspense } from '@/features/auth'; import { useAuthSuspense } from '@/features/auth';
@ -57,9 +56,9 @@ export function DlgChangeLocation() {
submitInvalidTooltip={`Допустимы буквы, цифры, подчерк, пробел и "!". Сегмент пути не может начинаться и заканчиваться пробелом. Общая длина (с корнем) не должна превышать ${limits.location_len}`} submitInvalidTooltip={`Допустимы буквы, цифры, подчерк, пробел и "!". Сегмент пути не может начинаться и заканчиваться пробелом. Общая длина (с корнем) не должна превышать ${limits.location_len}`}
canSubmit={isValid && isDirty} canSubmit={isValid && isDirty}
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-[35rem]', 'pb-3 px-6 flex gap-3 h-[9rem]')} className='w-140 pb-3 px-6 flex gap-3 h-36'
> >
<div className='flex flex-col gap-2 min-w-[7rem]'> <div className='flex flex-col gap-2 min-w-28'>
<Label className='select-none' text='Корень' /> <Label className='select-none' text='Корень' />
<Controller <Controller
control={control} control={control}
@ -77,11 +76,11 @@ export function DlgChangeLocation() {
control={control} control={control}
name='location' name='location'
render={({ field }) => ( render={({ field }) => (
<SelectLocationContext dropdownHeight='max-h-[9.2rem]' value={field.value} onChange={field.onChange} /> <SelectLocationContext dropdownHeight='max-h-36' value={field.value} onChange={field.onChange} />
)} )}
/> />
<Controller <Controller
control={control} // control={control}
name='location' name='location'
render={({ field }) => ( render={({ field }) => (
<TextArea <TextArea

View File

@ -2,7 +2,6 @@
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { urls, useConceptNavigation } from '@/app'; import { urls, useConceptNavigation } from '@/app';
import { useAuthSuspense } from '@/features/auth'; import { useAuthSuspense } from '@/features/auth';
@ -69,7 +68,7 @@ export function DlgCloneLibraryItem() {
submitText='Создать' submitText='Создать'
canSubmit={isValid} canSubmit={isValid}
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('px-6 py-2', 'cc-column', 'max-h-full w-[30rem]')} className='px-6 py-2 cc-column h-fit w-120'
> >
<TextInput <TextInput
id='dlg_full_name' // id='dlg_full_name' //
@ -77,14 +76,9 @@ export function DlgCloneLibraryItem() {
{...register('title')} {...register('title')}
error={errors.title} error={errors.title}
/> />
<div className='flex justify-between gap-3'> <div className='flex justify-between gap-3'>
<TextInput <TextInput id='dlg_alias' label='Сокращение' className='w-64' {...register('alias')} error={errors.alias} />
id='dlg_alias'
label='Сокращение'
className='w-[16rem]'
{...register('alias')}
error={errors.alias}
/>
<div className='flex flex-col gap-2'> <div className='flex flex-col gap-2'>
<Label text='Доступ' className='self-center select-none' /> <Label text='Доступ' className='self-center select-none' />
<div className='ml-auto cc-icons'> <div className='ml-auto cc-icons'>
@ -115,7 +109,7 @@ export function DlgCloneLibraryItem() {
</div> </div>
<div className='flex gap-3'> <div className='flex gap-3'>
<div className='flex flex-col gap-2 w-[7rem]'> <div className='flex flex-col gap-2 w-28'>
<Label text='Корень' /> <Label text='Корень' />
<Controller <Controller
control={control} // control={control} //

View File

@ -2,7 +2,6 @@
import { Controller, useForm, useWatch } from 'react-hook-form'; import { Controller, useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { Checkbox, TextArea, TextInput } from '@/components/Input'; import { Checkbox, TextArea, TextInput } from '@/components/Input';
import { ModalForm } from '@/components/Modal'; import { ModalForm } from '@/components/Modal';
@ -45,13 +44,13 @@ export function DlgCreateVersion() {
return ( return (
<ModalForm <ModalForm
header='Создание версии' header='Создание версии'
className={clsx('cc-column', 'w-[30rem]', 'py-2 px-6')} className='cc-column w-120 py-2 px-6'
canSubmit={canSubmit} canSubmit={canSubmit}
submitInvalidTooltip={errorMsg.versionTaken} submitInvalidTooltip={errorMsg.versionTaken}
submitText='Создать' submitText='Создать'
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
> >
<TextInput id='dlg_version' {...register('version')} dense label='Версия' className='w-[16rem]' /> <TextInput id='dlg_version' {...register('version')} dense label='Версия' className='w-64' />
<TextArea id='dlg_description' {...register('description')} spellCheck label='Описание' rows={3} /> <TextArea id='dlg_description' {...register('description')} spellCheck label='Описание' rows={3} />
{selected.length > 0 ? ( {selected.length > 0 ? (
<Controller <Controller

View File

@ -3,7 +3,6 @@
import { useRef } from 'react'; import { useRef } from 'react';
import { Controller, useForm, useWatch } from 'react-hook-form'; import { Controller, useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { urls, useConceptNavigation } from '@/app'; import { urls, useConceptNavigation } from '@/app';
import { useAuthSuspense } from '@/features/auth'; import { useAuthSuspense } from '@/features/auth';
@ -103,7 +102,7 @@ export function FormCreateItem() {
return ( return (
<form <form
className={clsx('cc-fade-in cc-column', 'min-w-120 max-w-120 mx-auto', 'px-6 py-3')} className='cc-fade-in cc-column min-w-120 max-w-120 mx-auto px-6 py-3'
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
onChange={resetErrors} onChange={resetErrors}
> >

View File

@ -63,7 +63,7 @@ export function TableLibraryItems({ items }: TableLibraryItemsProps) {
className={clsx('text-xs sm:text-sm cc-scroll-y h-fit border-b', { 'border-l': folderMode })} className={clsx('text-xs sm:text-sm cc-scroll-y h-fit border-b', { 'border-l': folderMode })}
style={{ maxHeight: tableHeight }} style={{ maxHeight: tableHeight }}
noDataComponent={ noDataComponent={
<div className='cc-column dense p-3 items-center min-h-[6rem]'> <div className='cc-column dense p-3 items-center min-h-24'>
<p>Список схем пуст</p> <p>Список схем пуст</p>
<p className='flex gap-6'> <p className='flex gap-6'>
<TextURL text='Создать схему' href='/library/create' /> <TextURL text='Создать схему' href='/library/create' />

View File

@ -75,21 +75,12 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
} }
return ( return (
<div <div className='sticky top-0 h-9 flex gap-3 border-b text-sm clr-input items-center'>
className={clsx( <div className='ml-3 min-w-18 sm:min-w-30 select-none whitespace-nowrap'>
'sticky top-0', //
'h-9',
'flex items-center gap-3',
'border-b',
'text-sm',
'clr-input'
)}
>
<div className={clsx('ml-3 pt-1 self-center', 'min-w-18 sm:min-w-30', 'select-none', 'whitespace-nowrap')}>
{filtered} из {total} {filtered} из {total}
</div> </div>
<div className='cc-icons'> <div className='cc-icons h-full items-center'>
<MiniButton <MiniButton
title='Видимость' title='Видимость'
icon={<IconItemVisibility value={true} className={tripleToggleColor(isVisible)} />} icon={<IconItemVisibility value={true} className={tripleToggleColor(isVisible)} />}
@ -103,7 +94,7 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
icon={<IconUserSearch size='1.25rem' className={userActive ? 'icon-green' : 'icon-primary'} />} icon={<IconUserSearch size='1.25rem' className={userActive ? 'icon-green' : 'icon-primary'} />}
onClick={userMenu.toggle} onClick={userMenu.toggle}
/> />
<Dropdown isOpen={userMenu.isOpen} margin='mt-[0.2rem]'> <Dropdown isOpen={userMenu.isOpen}>
<DropdownButton <DropdownButton
text='Я - Владелец' text='Я - Владелец'
icon={<IconOwner size='1.25rem' className={tripleToggleColor(isOwned)} />} icon={<IconOwner size='1.25rem' className={tripleToggleColor(isOwned)} />}
@ -142,10 +133,10 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
onChangeQuery={setQuery} onChangeQuery={setQuery}
/> />
{!folderMode ? ( {!folderMode ? (
<div ref={headMenu.ref} className='relative flex items-center h-full py-1 select-none'> <div ref={headMenu.ref} className='relative flex items-center h-full select-none'>
<SelectorButton <SelectorButton
transparent transparent
className='h-full rounded-lg' className='rounded-lg py-1'
titleHtml={(head ? describeLocationHead(head) : 'Выберите каталог') + '<br/>Ctrl + клик - Проводник'} titleHtml={(head ? describeLocationHead(head) : 'Выберите каталог') + '<br/>Ctrl + клик - Проводник'}
hideTitle={headMenu.isOpen} hideTitle={headMenu.isOpen}
icon={ icon={

View File

@ -85,7 +85,7 @@ export function ViewSideLocation({ isVisible, onRenameLocation }: ViewSideLocati
) : null} ) : null}
{!!location ? ( {!!location ? (
<MiniButton <MiniButton
title={subfolders ? 'Вложенные папки: Вкл' : 'Вложенные папки: Выкл'} // prettier: split-lines title={subfolders ? 'Вложенные папки: Вкл' : 'Вложенные папки: Выкл'}
icon={<IconShowSubfolders value={subfolders} />} icon={<IconShowSubfolders value={subfolders} />}
onClick={toggleSubfolders} onClick={toggleSubfolders}
/> />

View File

@ -12,7 +12,7 @@ export function OperationTooltip() {
clickable clickable
id={globalIDs.operation_tooltip} id={globalIDs.operation_tooltip}
layer='z-topmost' layer='z-topmost'
className='max-w-[35rem] dense' className='max-w-140 dense'
style={{ maxHeight: '30rem', overflowY: 'auto' }} style={{ maxHeight: '30rem', overflowY: 'auto' }}
hidden={!hoverOperation} hidden={!hoverOperation}
> >

View File

@ -2,7 +2,6 @@
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { type ILibraryItem, LibraryItemType } from '@/features/library'; import { type ILibraryItem, LibraryItemType } from '@/features/library';
import { useLibrary } from '@/features/library/backend/useLibrary'; import { useLibrary } from '@/features/library/backend/useLibrary';
@ -55,7 +54,7 @@ export function DlgChangeInputSchema() {
header='Выбор концептуальной схемы' header='Выбор концептуальной схемы'
submitText='Подтвердить выбор' submitText='Подтвердить выбор'
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-[35rem]', 'pb-3 px-6 cc-column')} className='w-140 pb-3 px-6 cc-column'
> >
<div className='flex justify-between gap-3 items-center'> <div className='flex justify-between gap-3 items-center'>
<div className='flex gap-3'> <div className='flex gap-3'>

View File

@ -64,7 +64,7 @@ export function TabInputOperation() {
<TextInput <TextInput
id='operation_alias' // id='operation_alias' //
label='Сокращение' label='Сокращение'
className='w-[16rem]' className='w-64'
{...register('item_data.alias')} {...register('item_data.alias')}
error={errors.item_data?.alias} error={errors.item_data?.alias}
/> />

View File

@ -29,7 +29,7 @@ export function TabSynthesisOperation() {
<TextInput <TextInput
id='operation_alias' id='operation_alias'
label='Сокращение' label='Сокращение'
className='w-[16rem]' className='w-64'
{...register('item_data.alias')} {...register('item_data.alias')}
error={errors.item_data?.alias} error={errors.item_data?.alias}
/> />

View File

@ -2,7 +2,6 @@
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
@ -44,7 +43,7 @@ export function DlgDeleteOperation() {
header='Удаление операции' header='Удаление операции'
submitText='Подтвердить удаление' submitText='Подтвердить удаление'
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-[35rem]', 'pb-3 px-6 cc-column', 'select-none')} className='w-140 pb-3 px-6 cc-column select-none'
helpTopic={HelpTopic.CC_PROPAGATION} helpTopic={HelpTopic.CC_PROPAGATION}
> >
<TextInput disabled dense noBorder id='operation_alias' label='Операция' value={target.alias} /> <TextInput disabled dense noBorder id='operation_alias' label='Операция' value={target.alias} />

View File

@ -3,7 +3,6 @@
import { useState } from 'react'; import { useState } from 'react';
import { Controller, useForm, useWatch } from 'react-hook-form'; import { Controller, useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
import { type ILibraryItem } from '@/features/library'; import { type ILibraryItem } from '@/features/library';
@ -120,7 +119,7 @@ export function DlgRelocateConstituents() {
submitText='Переместить' submitText='Переместить'
canSubmit={isValid && destinationItem !== undefined} canSubmit={isValid && destinationItem !== undefined}
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-160 h-[33rem]', 'py-3 px-6')} className='w-160 h-132 py-3 px-6'
helpTopic={HelpTopic.UI_RELOCATE_CST} helpTopic={HelpTopic.UI_RELOCATE_CST}
> >
<div className='flex flex-col border'> <div className='flex flex-col border'>

View File

@ -13,7 +13,7 @@ export function OssStats({ stats }: OssStatsProps) {
return ( return (
<div <div
className={clsx( className={clsx(
'mt-3 md:ml-5 md:mt-8 md:w-[12rem] w-[14rem] h-min mx-auto', // prettier: split-lines 'mt-3 md:ml-5 md:mt-8 md:w-48 w-56 h-min mx-auto', //
'grid grid-cols-3 gap-1 justify-items-end' 'grid grid-cols-3 gap-1 justify-items-end'
)} )}
> >

View File

@ -1,5 +1,3 @@
import clsx from 'clsx';
import { APP_COLORS } from '@/styling/colors'; import { APP_COLORS } from '@/styling/colors';
import { colorFgGrammeme } from '../colors'; import { colorFgGrammeme } from '../colors';
@ -17,12 +15,7 @@ interface BadgeGrammemeProps {
export function BadgeGrammeme({ grammeme }: BadgeGrammemeProps) { export function BadgeGrammeme({ grammeme }: BadgeGrammemeProps) {
return ( return (
<div <div
className={clsx( className='min-w-12 px-1 border rounded-md text-sm font-medium text-center whitespace-nowrap'
'min-w-12', //
'px-1',
'border rounded-md',
'text-sm font-medium text-center whitespace-nowrap'
)}
style={{ style={{
borderColor: colorFgGrammeme(grammeme), borderColor: colorFgGrammeme(grammeme),
color: colorFgGrammeme(grammeme), color: colorFgGrammeme(grammeme),

View File

@ -12,12 +12,10 @@ interface InfoConstituentaProps extends React.ComponentProps<'div'> {
export function InfoConstituenta({ data, className, ...restProps }: InfoConstituentaProps) { export function InfoConstituenta({ data, className, ...restProps }: InfoConstituentaProps) {
return ( return (
<div className={clsx('dense min-w-[15rem] break-words', className)} {...restProps}> <div className={clsx('dense min-w-60 break-words', className)} {...restProps}>
<h2 className='cursor-default' title={data.is_inherited ? ' наследник' : undefined}> <h2 className='cursor-default' title={data.is_inherited ? ' наследник' : undefined}>
{data.alias} {data.alias}
{data.is_inherited ? ( {data.is_inherited ? <IconChild size='1rem' className='inline-icon align-middle ml-1 mt-1' /> : null}
<IconChild size='1rem' className='inline-icon translate-y-[-0.1rem] translate-x-[0.125rem]' />
) : null}
</h2> </h2>
{data.term_resolved ? ( {data.term_resolved ? (
<p> <p>

View File

@ -93,7 +93,7 @@ export function PickConstituenta({
columns={columns} columns={columns}
conditionalRowStyles={conditionalRowStyles} conditionalRowStyles={conditionalRowStyles}
noDataComponent={ noDataComponent={
<NoData className='min-h-[6rem]'> <NoData className='min-h-24'>
<p>Список конституент пуст</p> <p>Список конституент пуст</p>
<p>Измените параметры фильтра</p> <p>Измените параметры фильтра</p>
</NoData> </NoData>

View File

@ -99,14 +99,14 @@ export function PickMultiConstituenta({
return ( return (
<div className={clsx(noBorder ? '' : 'border', className)} {...restProps}> <div className={clsx(noBorder ? '' : 'border', className)} {...restProps}>
<div className={clsx('px-3 flex justify-between items-center', 'clr-input', 'border-b', 'rounded-t-md')}> <div className='px-3 flex justify-between items-center clr-input border-b rounded-t-md'>
<div className='w-[24ch] select-none whitespace-nowrap'> <div className='w-[24ch] select-none whitespace-nowrap'>
{items.length > 0 ? `Выбраны ${value.length} из ${items.length}` : 'Конституенты'} {items.length > 0 ? `Выбраны ${value.length} из ${items.length}` : 'Конституенты'}
</div> </div>
<SearchBar <SearchBar
id='dlg_constituents_search' id='dlg_constituents_search'
noBorder noBorder
className='min-w-[6rem] pr-2 grow' className='min-w-24 pr-2 grow'
query={filterText} query={filterText}
onChangeQuery={setFilterText} onChangeQuery={setFilterText}
/> />
@ -122,6 +122,7 @@ export function PickMultiConstituenta({
className='w-fit' className='w-fit'
/> />
</div> </div>
<DataTable <DataTable
id={id} id={id}
dense dense

View File

@ -167,7 +167,7 @@ export function PickSubstitutions({
columnHelper.accessor(item => item.substitution_source.alias, { columnHelper.accessor(item => item.substitution_source.alias, {
id: 'left_schema', id: 'left_schema',
size: 100, size: 100,
cell: props => <div className='min-w-[10.5rem] text-ellipsis text-left'>{props.getValue()}</div> cell: props => <div className='min-w-43 text-ellipsis text-left'>{props.getValue()}</div>
}), }),
columnHelper.accessor(item => item.substitution.alias, { columnHelper.accessor(item => item.substitution.alias, {
id: 'left_alias', id: 'left_alias',
@ -230,8 +230,8 @@ export function PickSubstitutions({
return ( return (
<div className={clsx('flex flex-col', className)} {...restProps}> <div className={clsx('flex flex-col', className)} {...restProps}>
<div className='flex items-end gap-3 justify-stretch'> <div className='flex items-center gap-3'>
<div className='grow flex flex-col basis-1/2 gap-[0.125rem] border-x border-t clr-input rounded-t-md'> <div className='grow flex flex-col basis-1/2 gap-1 border-x border-t clr-input rounded-t-md'>
<SelectLibraryItem <SelectLibraryItem
noBorder noBorder
placeholder='Выберите аргумент' placeholder='Выберите аргумент'
@ -241,7 +241,7 @@ export function PickSubstitutions({
/> />
<SelectConstituenta noBorder items={leftItems} value={leftCst} onChange={setLeftCst} /> <SelectConstituenta noBorder items={leftItems} value={leftCst} onChange={setLeftCst} />
</div> </div>
<div className='flex flex-col gap-1'> <div className='flex flex-col justify-center gap-1'>
<MiniButton <MiniButton
title={deleteRight ? 'Заменить правую' : 'Заменить левую'} title={deleteRight ? 'Заменить правую' : 'Заменить левую'}
onClick={toggleDelete} onClick={toggleDelete}
@ -255,14 +255,14 @@ export function PickSubstitutions({
/> />
<MiniButton <MiniButton
title='Добавить в таблицу отождествлений' title='Добавить в таблицу отождествлений'
className='mb-[0.375rem] grow-0' className='grow-0'
icon={<IconReplace size='1.5rem' className='icon-primary' />} icon={<IconReplace size='1.5rem' className='icon-primary' />}
disabled={!leftCst || !rightCst || (leftCst === rightCst && !allowSelfSubstitution)} disabled={!leftCst || !rightCst || (leftCst === rightCst && !allowSelfSubstitution)}
onClick={addSubstitution} onClick={addSubstitution}
/> />
</div> </div>
<div className='grow basis-1/2 flex flex-col gap-[0.125rem] border-x border-t clr-input rounded-t-md'> <div className='grow basis-1/2 flex flex-col gap-1 border-x border-t clr-input rounded-t-md'>
<SelectLibraryItem <SelectLibraryItem
noBorder noBorder
placeholder='Выберите аргумент' placeholder='Выберите аргумент'
@ -285,7 +285,7 @@ export function PickSubstitutions({
columns={columns} columns={columns}
headPosition='0' headPosition='0'
noDataComponent={ noDataComponent={
<NoData className='min-h-[2rem]'> <NoData className='min-h-8'>
<p>Список пуст</p> <p>Список пуст</p>
<p>Добавьте отождествление</p> <p>Добавьте отождествление</p>
</NoData> </NoData>

View File

@ -29,7 +29,7 @@ import { rsHoverTooltip } from './tooltip';
interface RSInputProps interface RSInputProps
extends Pick< extends Pick<
ReactCodeMirrorProps, ReactCodeMirrorProps,
| 'id' // prettier: split-lines | 'id' //
| 'height' | 'height'
| 'minHeight' | 'minHeight'
| 'maxHeight' | 'maxHeight'

View File

@ -1,6 +1,5 @@
import { type Extension } from '@codemirror/state'; import { type Extension } from '@codemirror/state';
import { hoverTooltip, type TooltipView } from '@codemirror/view'; import { hoverTooltip, type TooltipView } from '@codemirror/view';
import clsx from 'clsx';
import { labelCstTypification } from '../../labels'; import { labelCstTypification } from '../../labels';
import { type IConstituenta, type IRSForm } from '../../models/rsform'; import { type IConstituenta, type IRSForm } from '../../models/rsform';
@ -33,14 +32,7 @@ export function rsHoverTooltip(schema: IRSForm, canClick?: boolean): Extension {
*/ */
function domTooltipConstituenta(cst?: IConstituenta, canClick?: boolean): TooltipView { function domTooltipConstituenta(cst?: IConstituenta, canClick?: boolean): TooltipView {
const dom = document.createElement('div'); const dom = document.createElement('div');
dom.className = clsx( dom.className = 'max-h-100 max-w-100 min-w-40 dense p-2 border shadow-md cc-scroll-y text-sm font-main';
'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
'dense',
'p-2',
'border shadow-md',
'cc-scroll-y',
'text-sm font-main'
);
if (!cst) { if (!cst) {
const text = document.createElement('p'); const text = document.createElement('p');

View File

@ -60,7 +60,7 @@ const editorSetup: BasicSetupOptions = {
interface RefsInputInputProps interface RefsInputInputProps
extends Pick< extends Pick<
ReactCodeMirrorProps, ReactCodeMirrorProps,
| 'id' // prettier: split-lines | 'id' //
| 'height' | 'height'
| 'minHeight' | 'minHeight'
| 'maxHeight' | 'maxHeight'
@ -85,7 +85,7 @@ interface RefsInputInputProps
export const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>( export const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
( (
{ {
id, // prettier: split-lines id, //
label, label,
disabled, disabled,
schema, schema,

View File

@ -65,7 +65,7 @@ export function refsHoverTooltip(schema: IRSForm, canClick?: boolean): Extension
function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | null, canClick?: boolean): TooltipView { function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | null, canClick?: boolean): TooltipView {
const dom = document.createElement('div'); const dom = document.createElement('div');
dom.className = clsx( dom.className = clsx(
'max-h-[25rem] max-w-[25rem] min-w-[10rem]', 'max-h-100 max-w-100 min-w-40',
'dense', 'dense',
'p-2 flex flex-col', 'p-2 flex flex-col',
'border shadow-md', 'border shadow-md',
@ -87,12 +87,7 @@ function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | n
parseGrammemes(ref.form).forEach(gramStr => { parseGrammemes(ref.form).forEach(gramStr => {
const gram = document.createElement('div'); const gram = document.createElement('div');
gram.id = `tooltip-${gramStr}`; gram.id = `tooltip-${gramStr}`;
gram.className = clsx( gram.className = 'min-w-12 px-1 border rounded-md text-sm text-center whitespace-nowrap';
'min-w-[3rem]', //
'px-1',
'border rounded-md',
'text-sm text-center whitespace-nowrap'
);
gram.style.borderWidth = '1px'; gram.style.borderWidth = '1px';
gram.style.borderColor = colorFgGrammeme(gramStr); gram.style.borderColor = colorFgGrammeme(gramStr);
gram.style.color = colorFgGrammeme(gramStr); gram.style.color = colorFgGrammeme(gramStr);
@ -123,7 +118,7 @@ function domTooltipSyntacticReference(
): TooltipView { ): TooltipView {
const dom = document.createElement('div'); const dom = document.createElement('div');
dom.className = clsx( dom.className = clsx(
'max-h-[25rem] max-w-[25rem] min-w-[10rem]', 'max-h-100 max-w-100 min-w-40',
'dense', 'dense',
'p-2 flex flex-col', 'p-2 flex flex-col',
'border shadow-md', 'border shadow-md',

View File

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

View File

@ -43,7 +43,7 @@ export function DlgCreateCst() {
onSubmit={event => void methods.handleSubmit(onSubmit)(event)} onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
submitInvalidTooltip={errorMsg.aliasInvalid} submitInvalidTooltip={errorMsg.aliasInvalid}
submitText='Создать' submitText='Создать'
className='cc-column w-[35rem] max-h-[30rem] py-2 px-6' className='cc-column w-140 max-h-120 py-2 px-6'
> >
<FormProvider {...methods}> <FormProvider {...methods}>
<FormCreateCst schema={schema} /> <FormCreateCst schema={schema} />

View File

@ -43,15 +43,8 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
return ( return (
<> <>
<div className='flex items-center self-center gap-3'> <div className='flex items-center self-center gap-3'>
<SelectCstType id='dlg_cst_type' className='w-[16rem]' value={cst_type} onChange={handleTypeChange} /> <SelectCstType id='dlg_cst_type' className='w-64' value={cst_type} onChange={handleTypeChange} />
<TextInput <TextInput id='dlg_cst_alias' dense label='Имя' className='w-28' {...register('alias')} error={errors.alias} />
id='dlg_cst_alias'
dense
label='Имя'
className='w-[7rem]'
{...register('alias')}
error={errors.alias}
/>
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} contentClass='sm:max-w-160' /> <BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} contentClass='sm:max-w-160' />
</div> </div>
@ -61,7 +54,7 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
spellCheck spellCheck
label='Термин' label='Термин'
placeholder='Обозначение для текстовых определений' placeholder='Обозначение для текстовых определений'
className='max-h-[3.6rem]' className='max-h-15'
{...register('term_raw')} {...register('term_raw')}
error={errors.term_raw} error={errors.term_raw}
/> />
@ -105,7 +98,7 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
fitContent fitContent
label='Текстовое определение' label='Текстовое определение'
placeholder='Текстовая интерпретация формального выражения' placeholder='Текстовая интерпретация формального выражения'
className='max-h-[3.6rem]' className='max-h-15'
value={field.value} value={field.value}
onChange={field.onChange} onChange={field.onChange}
/> />
@ -132,7 +125,7 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
fitContent fitContent
label={isBasic ? 'Конвенция' : 'Комментарий'} label={isBasic ? 'Конвенция' : 'Комментарий'}
placeholder={isBasic ? 'Договоренность об интерпретации' : 'Пояснение разработчика'} placeholder={isBasic ? 'Договоренность об интерпретации' : 'Пояснение разработчика'}
className='max-h-[5.4rem]' className='max-h-20'
{...register('convention')} {...register('convention')}
/> />
)} )}

View File

@ -3,7 +3,6 @@
import { Suspense, useState } from 'react'; import { Suspense, useState } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form'; import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
@ -65,7 +64,7 @@ export function DlgCstTemplate() {
<ModalForm <ModalForm
header='Создание конституенты из шаблона' header='Создание конституенты из шаблона'
submitText='Создать' submitText='Создать'
className='w-[43rem] h-[35rem] px-6' className='w-172 h-140 px-6'
canSubmit={isValid} canSubmit={isValid}
onSubmit={event => void methods.handleSubmit(onSubmit)(event)} onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
helpTopic={HelpTopic.RSL_TEMPLATES} helpTopic={HelpTopic.RSL_TEMPLATES}
@ -76,7 +75,7 @@ export function DlgCstTemplate() {
selectedIndex={activeTab} selectedIndex={activeTab}
onSelect={setActiveTab} onSelect={setActiveTab}
> >
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}> <TabList className='mb-4 self-center flex border divide-x rounded-none bg-prim-200'>
<TabLabel label='Шаблон' title='Выбор шаблона выражения' className='w-32' /> <TabLabel label='Шаблон' title='Выбор шаблона выражения' className='w-32' />
<TabLabel label='Аргументы' title='Подстановка аргументов шаблона' className='w-32' /> <TabLabel label='Аргументы' title='Подстановка аргументов шаблона' className='w-32' />
<TabLabel label='Конституента' title='Редактирование конституенты' className='w-32' /> <TabLabel label='Конституента' title='Редактирование конституенты' className='w-32' />

View File

@ -3,7 +3,6 @@
import { useState } from 'react'; import { useState } from 'react';
import { useFormContext, useWatch } from 'react-hook-form'; import { useFormContext, useWatch } from 'react-hook-form';
import { createColumnHelper } from '@tanstack/react-table'; import { createColumnHelper } from '@tanstack/react-table';
import clsx from 'clsx';
import { MiniButton } from '@/components/Control'; import { MiniButton } from '@/components/Control';
import { DataTable, type IConditionalStyle } from '@/components/DataTable'; import { DataTable, type IConditionalStyle } from '@/components/DataTable';
@ -79,16 +78,7 @@ export function TabArguments() {
argumentsHelper.accessor(arg => arg.typification, { argumentsHelper.accessor(arg => arg.typification, {
id: 'type', id: 'type',
enableHiding: true, enableHiding: true,
cell: props => ( cell: props => <div className='w-36 text-sm break-words'>{props.getValue()}</div>
<div
className={clsx(
'min-w-[9.3rem] max-w-[9.3rem]', //
'text-sm break-words'
)}
>
{props.getValue()}
</div>
)
}), }),
argumentsHelper.display({ argumentsHelper.display({
id: 'actions', id: 'actions',
@ -120,27 +110,15 @@ export function TabArguments() {
dense dense
noFooter noFooter
noHeader noHeader
className={clsx( className='h-23 cc-scroll-y text-sm border select-none'
'max-h-[5.8rem] min-h-[5.8rem]', //
'cc-scroll-y',
'text-sm',
'border',
'select-none'
)}
data={args} data={args}
columns={columns} columns={columns}
conditionalRowStyles={conditionalRowStyles} conditionalRowStyles={conditionalRowStyles}
noDataComponent={<NoData className='min-h-[3.6rem]'>Аргументы отсутствуют</NoData>} noDataComponent={<NoData className='min-h-14'>Аргументы отсутствуют</NoData>}
onRowClicked={handleSelectArgument} onRowClicked={handleSelectArgument}
/> />
<div <div className='my-3 flex gap-2 justify-center items-center select-none'>
className={clsx(
'my-4', //
'flex gap-2 justify-center items-center',
'select-none'
)}
>
<span <span
title='Выберите аргумент из списка сверху и значение из списка снизу' title='Выберите аргумент из списка сверху и значение из списка снизу'
className='font-semibold text-center' className='font-semibold text-center'
@ -181,7 +159,7 @@ export function TabArguments() {
noTooltip noTooltip
id='result' id='result'
placeholder='Итоговое определение' placeholder='Итоговое определение'
className='mt-[1.1rem]' className='mt-4'
height='5.1rem' height='5.1rem'
value={definition} value={definition}
/> />

View File

@ -60,7 +60,7 @@ export function TabTemplate() {
<SelectSingle <SelectSingle
noBorder noBorder
placeholder='Источник' placeholder='Источник'
className='w-[12rem]' className='w-48'
options={templateSelector} options={templateSelector}
value={templateID ? { value: templateID, label: templates.find(item => item.id == templateID)!.title } : null} value={templateID ? { value: templateID, label: templates.find(item => item.id == templateID)!.title } : null}
onChange={data => onChangeTemplateID(data ? data.value : null)} onChange={data => onChangeTemplateID(data ? data.value : null)}

View File

@ -1,7 +1,6 @@
'use client'; 'use client';
import { useState } from 'react'; import { useState } from 'react';
import clsx from 'clsx';
import { Checkbox } from '@/components/Input'; import { Checkbox } from '@/components/Input';
import { ModalForm } from '@/components/Modal'; import { ModalForm } from '@/components/Modal';
@ -40,7 +39,7 @@ export function DlgDeleteCst() {
header='Удаление конституент' header='Удаление конституент'
submitText={expandOut ? 'Удалить с зависимыми' : 'Удалить'} submitText={expandOut ? 'Удалить с зависимыми' : 'Удалить'}
onSubmit={handleSubmit} onSubmit={handleSubmit}
className={clsx('cc-column', 'max-w-[60vw] min-w-[30rem]', 'px-6')} className='cc-column max-w-[60vw] min-w-120 px-6'
> >
<ListConstituents title='Выбраны к удалению' list={selected} schema={schema} prefix={prefixes.cst_delete_list} /> <ListConstituents title='Выбраны к удалению' list={selected} schema={schema} prefix={prefixes.cst_delete_list} />
<ListConstituents <ListConstituents

View File

@ -1,5 +1,3 @@
import clsx from 'clsx';
import { labelConstituenta } from '../../labels'; import { labelConstituenta } from '../../labels';
import { type IRSForm } from '../../models/rsform'; import { type IRSForm } from '../../models/rsform';
@ -18,7 +16,7 @@ export function ListConstituents({ list, schema, title, prefix }: ListConstituen
{title}: <b>{list.length}</b> {title}: <b>{list.length}</b>
</p> </p>
) : null} ) : null}
<div className={clsx('h-[9rem]', 'px-3', 'cc-scroll-y', 'border', 'whitespace-nowrap')}> <div className='h-36 px-3 cc-scroll-y border whitespace-nowrap'>
{list.map(id => { {list.map(id => {
const cst = schema.cstByID.get(id); const cst = schema.cstByID.get(id);
return cst ? <p key={`${prefix}${cst.id}`}>{labelConstituenta(cst)}</p> : null; return cst ? <p key={`${prefix}${cst.id}`}>{labelConstituenta(cst)}</p> : null;

View File

@ -3,7 +3,6 @@
import { useState } from 'react'; import { useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { z } from 'zod'; import { z } from 'zod';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
@ -102,7 +101,7 @@ export function DlgEditReference() {
canSubmit={methods.formState.isValid} canSubmit={methods.formState.isValid}
onCancel={onCancel} onCancel={onCancel}
onSubmit={event => void methods.handleSubmit(onSubmit)(event)} onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
className='w-160 px-6 h-[32rem]' className='w-160 px-6 h-128'
helpTopic={HelpTopic.TERM_CONTROL} helpTopic={HelpTopic.TERM_CONTROL}
> >
<Tabs <Tabs
@ -111,7 +110,7 @@ export function DlgEditReference() {
selectedIndex={activeTab} selectedIndex={activeTab}
onSelect={handleChangeTab} onSelect={handleChangeTab}
> >
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}> <TabList className='mb-3 self-center flex border divide-x rounded-none bg-prim-200'>
<TabLabel title='Отсылка на термин в заданной словоформе' label={labelReferenceType(ReferenceType.ENTITY)} /> <TabLabel title='Отсылка на термин в заданной словоформе' label={labelReferenceType(ReferenceType.ENTITY)} />
<TabLabel <TabLabel
title='Установление синтаксической связи с отсылкой на термин' title='Установление синтаксической связи с отсылкой на термин'

View File

@ -46,7 +46,7 @@ export function TabEntityReference() {
dense dense
label='Конституента' label='Конституента'
placeholder='Имя' placeholder='Имя'
className='w-[11rem]' className='w-44'
{...register('entity.entity')} {...register('entity.entity')}
/> />
<TextInput <TextInput

View File

@ -28,7 +28,7 @@ export function TabSyntacticReference() {
type='number' type='number'
dense dense
label='Смещение' label='Смещение'
className='max-w-[10rem]' className='max-w-40'
{...register('syntactic.offset')} {...register('syntactic.offset')}
/> />
<TextInput <TextInput

View File

@ -1,7 +1,5 @@
'use client'; 'use client';
import clsx from 'clsx';
import { MiniButton } from '@/components/Control'; import { MiniButton } from '@/components/Control';
import { createColumnHelper, DataTable } from '@/components/DataTable'; import { createColumnHelper, DataTable } from '@/components/DataTable';
import { IconRemove } from '@/components/Icons'; import { IconRemove } from '@/components/Icons';
@ -37,7 +35,7 @@ export function TableWordForms({ forms, setForms, onFormSelect }: TableWordForms
size: 350, size: 350,
minSize: 500, minSize: 500,
maxSize: 500, maxSize: 500,
cell: props => <div className='min-w-[25rem]'>{props.getValue()}</div> cell: props => <div className='min-w-100'>{props.getValue()}</div>
}), }),
columnHelper.accessor('grams', { columnHelper.accessor('grams', {
id: 'grams', id: 'grams',
@ -65,12 +63,12 @@ export function TableWordForms({ forms, setForms, onFormSelect }: TableWordForms
dense dense
noFooter noFooter
noHeader noHeader
className={clsx('mb-2', 'max-h-[17.4rem] min-h-[17.4rem]', 'border', 'text-sm', 'cc-scroll-y')} className='mb-2 max-h-70 min-h-70 border text-sm cc-scroll-y'
data={forms} data={forms}
columns={columns} columns={columns}
headPosition='0' headPosition='0'
noDataComponent={ noDataComponent={
<NoData className='min-h-[2rem]'> <NoData className='min-h-8'>
<p>Список пуст</p> <p>Список пуст</p>
<p>Добавьте словоформу</p> <p>Добавьте словоформу</p>
</NoData> </NoData>

View File

@ -26,7 +26,7 @@ export function DlgGraphParams() {
header='Настройки графа термов' header='Настройки графа термов'
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
submitText='Применить' submitText='Применить'
className='flex gap-6 justify-between px-6 pb-3 w-[30rem]' className='flex gap-6 justify-between px-6 pb-3 w-120'
> >
<div className='flex flex-col gap-1'> <div className='flex flex-col gap-1'>
<h1 className='mb-2'>Преобразования</h1> <h1 className='mb-2'>Преобразования</h1>

View File

@ -2,7 +2,6 @@
import { useForm, useWatch } from 'react-hook-form'; import { useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
@ -53,12 +52,12 @@ export function DlgRenameCst() {
submitInvalidTooltip='Введите незанятое имя, соответствующее типу' submitInvalidTooltip='Введите незанятое имя, соответствующее типу'
canSubmit={isValid} canSubmit={isValid}
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-[30rem]', 'py-6 pr-3 pl-6 flex gap-3 justify-center items-center ')} className='w-120 py-6 pr-3 pl-6 flex gap-3 justify-center items-center'
helpTopic={HelpTopic.CC_CONSTITUENTA} helpTopic={HelpTopic.CC_CONSTITUENTA}
> >
<SelectCstType <SelectCstType
id='dlg_cst_type' id='dlg_cst_type'
className='w-[16rem]' className='w-64'
value={cst_type} value={cst_type}
onChange={handleChangeType} onChange={handleChangeType}
disabled={target.is_inherited} disabled={target.is_inherited}
@ -68,7 +67,7 @@ export function DlgRenameCst() {
{...register('alias')} {...register('alias')}
dense dense
label='Имя' label='Имя'
className='w-[7rem]' className='w-28'
/> />
</ModalForm> </ModalForm>
); );

View File

@ -1,6 +1,5 @@
'use client'; 'use client';
import clsx from 'clsx';
import { QRCodeSVG } from 'qrcode.react'; import { QRCodeSVG } from 'qrcode.react';
import { ModalView } from '@/components/Modal'; import { ModalView } from '@/components/Modal';
@ -13,7 +12,7 @@ export interface DlgShowQRProps {
export function DlgShowQR() { export function DlgShowQR() {
const { target } = useDialogsStore(state => state.props as DlgShowQRProps); const { target } = useDialogsStore(state => state.props as DlgShowQRProps);
return ( return (
<ModalView className={clsx('w-[25rem]', 'pb-6 pt-12 flex justify-center items-center')}> <ModalView className='w-100 pb-6 pt-12 flex justify-center items-center'>
<div className='bg-[#ffffff] p-4 border'> <div className='bg-[#ffffff] p-4 border'>
<QRCodeSVG value={target} size={256} /> <QRCodeSVG value={target} size={256} />
</div> </div>

View File

@ -2,7 +2,6 @@
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
@ -47,7 +46,7 @@ export function DlgSubstituteCst() {
submitInvalidTooltip='Выберите две различные конституенты' submitInvalidTooltip='Выберите две различные конституенты'
canSubmit={isValid} canSubmit={isValid}
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-160', 'px-6 pb-3')} className='w-160 px-6 pb-3'
helpTopic={HelpTopic.UI_SUBSTITUTIONS} helpTopic={HelpTopic.UI_SUBSTITUTIONS}
> >
<Controller <Controller

View File

@ -44,7 +44,7 @@ export function DlgUploadRSForm() {
canSubmit={!!file} canSubmit={!!file}
onSubmit={handleSubmit} onSubmit={handleSubmit}
submitText='Загрузить' submitText='Загрузить'
className='w-[25rem] px-6' className='w-100 px-6'
> >
<FileInput label='Выбрать файл' acceptType={EXTEOR_TRS_FILE} onChange={handleFile} /> <FileInput label='Выбрать файл' acceptType={EXTEOR_TRS_FILE} onChange={handleFile} />
<Checkbox <Checkbox

View File

@ -76,8 +76,8 @@ export function EditorConstituenta() {
className={clsx( className={clsx(
'relative', 'relative',
'cc-fade-in', 'cc-fade-in',
'min-h-[20rem] max-w-[calc(min(100vw,95rem))] mx-auto', 'min-h-80 max-w-[calc(min(100vw,95rem))] mx-auto',
'flex pt-[1.9rem]', 'flex pt-8',
'overflow-y-auto overflow-x-clip', 'overflow-y-auto overflow-x-clip',
{ 'flex-col md:items-center': isNarrow } { 'flex-col md:items-center': isNarrow }
)} )}
@ -90,7 +90,7 @@ export function EditorConstituenta() {
onSubmit={initiateSubmit} onSubmit={initiateSubmit}
onReset={() => setToggleReset(prev => !prev)} onReset={() => setToggleReset(prev => !prev)}
/> />
<div className='mx-0 md:mx-auto pt-[2rem] md:w-[48.8rem] shrink-0 xs:pt-0'> <div className='mx-0 md:mx-auto pt-8 md:w-195 shrink-0 xs:pt-0'>
{activeCst ? ( {activeCst ? (
<FormConstituenta <FormConstituenta
id={globalIDs.constituenta_editor} id={globalIDs.constituenta_editor}

View File

@ -28,7 +28,7 @@ export function EditorControls({ constituenta, disabled, onEditTerm }: EditorCon
} }
return ( return (
<div className='absolute z-pop top-0 left-[4.7rem] flex select-none'> <div className='absolute z-pop top-0 left-19 flex select-none'>
{!disabled || isProcessing ? ( {!disabled || isProcessing ? (
<MiniButton <MiniButton
title={isModified ? tooltipText.unsaved : `Редактировать словоформы термина`} title={isModified ? tooltipText.unsaved : `Редактировать словоформы термина`}
@ -40,10 +40,10 @@ export function EditorControls({ constituenta, disabled, onEditTerm }: EditorCon
) : null} ) : null}
<div <div
className={clsx( className={clsx(
'pt-1 sm:pl-[1.375rem] pl-1', // 'pt-1 sm:pl-5 pl-1',
'text-sm font-medium whitespace-nowrap', 'text-sm font-medium whitespace-nowrap',
'select-text cursor-default', 'select-text cursor-default',
disabled && !isProcessing && 'pl-[1.6rem] sm:pl-[2.8rem]' disabled && !isProcessing && 'pl-6 sm:pl-11'
)} )}
> >
<span>Имя </span> <span>Имя </span>

View File

@ -91,7 +91,7 @@ export function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsP
return ( return (
<div <div
className={clsx( className={clsx(
'max-w-[28rem] min-w-[28rem] xs:max-w-[38.5rem] xs:min-w-[38.5rem] sm:max-w-160 sm:min-w-160 md:max-w-fit mx-1 sm:mx-0', 'max-w-112 min-w-112 xs:max-w-154 xs:min-w-154 sm:max-w-160 sm:min-w-160 md:max-w-fit mx-1 sm:mx-0',
'flex-wrap', 'flex-wrap',
'divide-solid', 'divide-solid',
'text-xs md:text-sm', 'text-xs md:text-sm',

View File

@ -31,7 +31,7 @@ export function RSLocalButton({
data-tooltip-content={title} data-tooltip-content={title}
data-tooltip-hidden={hideTitle} data-tooltip-hidden={hideTitle}
className={clsx( className={clsx(
'w-[1.7rem] sm:w-[2rem] h-5 sm:h-6', 'w-7 sm:w-8 h-5 sm:h-6',
'cursor-pointer disabled:cursor-default', 'cursor-pointer disabled:cursor-default',
'rounded-none', 'rounded-none',
'clr-hover clr-text-controls cc-animate-color', 'clr-hover clr-text-controls cc-animate-color',

View File

@ -27,8 +27,8 @@ export function RSTokenButton({ token, disabled, onInsert }: RSTokenButtonProps)
'font-math', 'font-math',
'cursor-pointer disabled:cursor-default', 'cursor-pointer disabled:cursor-default',
{ {
'w-[3.7rem] md:w-[4.5rem]': label.length > 3, 'w-14.5 md:w-18': label.length > 3,
'w-[1.85rem] md:w-[2.25rem]': label.length <= 3 'w-7.25 md:w-9': label.length <= 3
} }
)} )}
data-tooltip-id={globalIDs.tooltip} data-tooltip-id={globalIDs.tooltip}

View File

@ -38,7 +38,12 @@ export function StatusBar({ isModified, processing, activeCst, parseData, onAnal
})(); })();
return ( return (
<div className={clsx('absolute z-pop -top-2 right-1/2 translate-x-1/2 w-fit', 'pl-34 xs:pl-8 flex gap-1')}> <div
className={clsx(
'absolute z-pop -top-2 right-1/2 translate-x-1/2 w-fit', //
'pl-34 xs:pl-8 flex gap-1'
)}
>
<div <div
tabIndex={0} tabIndex={0}
className={clsx( className={clsx(

View File

@ -16,7 +16,7 @@ export function ToolbarRSExpression({ disabled, showTypeGraph, showAST }: Toolba
const toggleControls = usePreferencesStore(state => state.toggleShowExpressionControls); const toggleControls = usePreferencesStore(state => state.toggleShowExpressionControls);
return ( return (
<div className='absolute z-pop top-[-0.5rem] right-0 cc-icons'> <div className='absolute z-pop -top-2 right-0 cc-icons'>
{!disabled || isProcessing ? ( {!disabled || isProcessing ? (
<MiniButton <MiniButton
title='Отображение специальной клавиатуры' title='Отображение специальной клавиатуры'

View File

@ -36,10 +36,10 @@ export function EditorRSFormCard() {
<div <div
onKeyDown={handleInput} onKeyDown={handleInput}
className={clsx( className={clsx(
'relative', 'relative', //
'cc-fade-in', 'cc-fade-in',
'md:w-fit md:max-w-fit max-w-[32rem]', 'md:w-fit md:max-w-fit max-w-128',
'flex flex-row flex-wrap px-6 pt-[1.9rem]' 'flex flex-row flex-wrap px-6 pt-8'
)} )}
> >
<ToolbarItemCard onSubmit={initiateSubmit} schema={schema} isMutable={isMutable} deleteSchema={deleteSchema} /> <ToolbarItemCard onSubmit={initiateSubmit} schema={schema} isMutable={isMutable} deleteSchema={deleteSchema} />

View File

@ -32,7 +32,7 @@ export function RSFormStats({ stats, isArchive }: RSFormStatsProps) {
return ( return (
<div <div
className={clsx( className={clsx(
'mt-3 md:ml-5 md:mt-8 md:w-56 w-80 h-min mx-auto', // prettier: split-lines 'mt-3 md:ml-5 md:mt-8 md:w-56 w-80 h-min mx-auto', //
'grid grid-cols-4 gap-1 justify-items-end' 'grid grid-cols-4 gap-1 justify-items-end'
)} )}
> >

View File

@ -55,7 +55,7 @@ export function ToolbarVersioning({ blockReload }: ToolbarVersioningProps) {
} }
return ( return (
<div className='absolute z-bottom top-[-0.4rem] right-[0rem] pr-2 cc-icons'> <div className='absolute z-bottom -top-2 right-0 pr-2 cc-icons'>
{isMutable ? ( {isMutable ? (
<> <>
<MiniButton <MiniButton

View File

@ -1,7 +1,5 @@
'use client'; 'use client';
import clsx from 'clsx';
import { TextURL } from '@/components/Control'; import { TextURL } from '@/components/Control';
import { createColumnHelper, DataTable, type RowSelectionState, type VisibilityState } from '@/components/DataTable'; import { createColumnHelper, DataTable, type RowSelectionState, type VisibilityState } from '@/components/DataTable';
import { NoData, TextContent } from '@/components/View'; import { NoData, TextContent } from '@/components/View';
@ -124,7 +122,7 @@ export function TableRSList({
<DataTable <DataTable
dense dense
noFooter noFooter
className={clsx('min-h-64', 'cc-scroll-y', 'text-sm', 'select-none')} className='min-h-64 cc-scroll-y text-sm select-none'
style={{ maxHeight: maxHeight }} style={{ maxHeight: maxHeight }}
data={items ?? []} data={items ?? []}
columns={columns} columns={columns}

View File

@ -74,8 +74,8 @@ export function ViewHidden({ items }: ViewHiddenProps) {
tabIndex={-1} tabIndex={-1}
className={clsx( className={clsx(
'flex flex-wrap justify-center gap-2 py-2 -mt-2', 'flex flex-wrap justify-center gap-2 py-2 -mt-2',
'text-sm',
'clr-input border-x border-b rounded-b-md', 'clr-input border-x border-b rounded-b-md',
'text-sm',
'cc-scroll-y' 'cc-scroll-y'
)} )}
style={{ style={{

View File

@ -76,7 +76,7 @@ export function RSTabs({ activeID, activeTab }: RSTabsProps) {
onSelect={onSelectTab} onSelect={onSelectTab}
defaultFocus defaultFocus
selectedTabClassName='clr-selected' selectedTabClassName='clr-selected'
className='relative flex flex-col mx-auto min-w-fit items-center' className='relative flex flex-col min-w-fit items-center'
> >
<TabList <TabList
className={clsx( className={clsx(

View File

@ -26,13 +26,10 @@ export function ViewConstituents({ isBottom, isMounted }: ViewConstituentsProps)
return ( return (
<aside <aside
className={clsx( className={clsx('border', {
'border', // prettier: split-lines
{
'mt-9 rounded-l-md rounded-r-none h-fit overflow-visible': !isBottom, 'mt-9 rounded-l-md rounded-r-none h-fit overflow-visible': !isBottom,
'mt-3 mx-6 rounded-md overflow-hidden': isBottom 'mt-3 mx-6 rounded-md overflow-hidden': isBottom
} })}
)}
style={{ style={{
willChange: 'opacity, max-width', willChange: 'opacity, max-width',
transitionProperty: 'opacity, max-width', transitionProperty: 'opacity, max-width',

View File

@ -4,15 +4,25 @@
@import './constants.css' layer(base); @import './constants.css' layer(base);
/* Uncomment to debug layering and overflow */
/* *,
*::after,
*::before {
background: hsla(135, 50%, 50%, 0.05) !important;
outline: 2px solid hotpink !important;
:focus,
:focus-visible,
:focus-within {
outline: 2px solid hotpink !important;
}
} */
@layer utilities { @layer utilities {
*, *,
*::after, *::after,
*::before { *::before {
box-sizing: border-box; box-sizing: border-box;
/* Uncomment to debug layering and overflow */
/* background: hsla(135, 50%, 50%, 0.05); */
/* outline: 2px solid hotpink; */
} }
} }

View File

@ -253,3 +253,14 @@
-webkit-user-select: none; -webkit-user-select: none;
user-select: none; user-select: none;
} }
@utility cc-modal-wrapper {
isolation: isolate;
z-index: var(--z-index-modal);
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
}