F: Improve styling and do a pass on UI
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run

This commit is contained in:
Ivan 2025-03-09 21:59:21 +03:00
parent 2ad5fd4c39
commit 4f9a94c933
93 changed files with 375 additions and 422 deletions

View File

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

View File

@ -13,15 +13,14 @@ export function Footer() {
'text-xs sm:text-sm select-none whitespace-nowrap text-prim-600 bg-prim-100'
)}
>
<div className='flex gap-3'>
<nav className='flex gap-3' aria-label='Вторичная навигация'>
<TextURL text='Библиотека' href='/library' color='' />
<TextURL text='Справка' href='/manuals' color='' />
<TextURL text='Центр Концепт' href={external_urls.concept} color='' />
<TextURL text='Экстеор' href='/manuals?topic=exteor' color='' />
</div>
<div>
</nav>
<p>© 2024 ЦИВТ КОНЦЕПТ</p>
</div>
</footer>
);
}

View File

@ -11,7 +11,7 @@ export const GlobalTooltips = () => {
id={globalIDs.tooltip}
layer='z-topmost'
place='right-start'
className='mt-8 max-w-[20rem] break-words'
className='mt-8 max-w-80 break-words'
/>
<Tooltip
float

View File

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

View File

@ -39,7 +39,7 @@ export function Navigation() {
<ToggleNavigation />
<div
className={clsx(
'pl-2 pr-[1.5rem] sm:pr-[0.9rem] h-[3rem]', //
'pl-2 pr-6 sm:pr-4 h-12', //
'flex',
'cc-shadow-border'
)}

View File

@ -22,18 +22,16 @@ export function NavigationButton({ icon, title, hideTitle, className, style, onC
data-tooltip-content={title}
onClick={onClick}
className={clsx(
'p-2 h-min',
'flex items-center gap-1',
'p-2 flex items-center gap-1',
'cursor-pointer',
'clr-btn-nav cc-animate-color duration-500',
'rounded-xl',
'font-controls whitespace-nowrap',
className
)}
style={style}
>
{icon ? <span>{icon}</span> : null}
{icon ? icon : null}
{text ? <span className='hidden sm:inline'>{text}</span> : null}
</button>
);

View File

@ -1,34 +1,28 @@
import clsx from 'clsx';
'use client';
import { IconDarkTheme, IconLightTheme, IconPin, IconUnpin } from '@/components/Icons';
import { useAppLayoutStore } from '@/stores/appLayout';
import { usePreferencesStore } from '@/stores/preferences';
import { globalIDs, PARAMETER } from '@/utils/constants';
import { globalIDs } from '@/utils/constants';
export function ToggleNavigation() {
const darkMode = usePreferencesStore(state => state.darkMode);
const toggleDarkMode = usePreferencesStore(state => state.toggleDarkMode);
const noNavigation = useAppLayoutStore(state => state.noNavigation);
const noNavigationAnimation = useAppLayoutStore(state => state.noNavigationAnimation);
const toggleNoNavigation = useAppLayoutStore(state => state.toggleNoNavigation);
const iconSize = !noNavigationAnimation ? '0.75rem' : '1rem';
return (
<div
className={clsx(
'absolute top-0 right-0 z-navigation',
'min-h-[2rem] min-w-[2rem]',
'flex items-end justify-center gap-1',
'select-none',
!noNavigation && 'flex-col-reverse'
)}
style={{
willChange: 'height, width',
transitionProperty: 'height, width',
transitionDuration: `${PARAMETER.moveDuration}ms`,
height: noNavigationAnimation ? '2rem' : '3rem',
width: noNavigationAnimation ? '3rem' : '2rem'
}}
<div className='absolute top-0 right-0 z-navigation h-12 grid'>
<button
tabIndex={-1}
type='button'
className='p-1 cursor-pointer self-start'
onClick={toggleNoNavigation}
data-tooltip-id={globalIDs.tooltip}
data-tooltip-content={noNavigationAnimation ? 'Показать навигацию' : 'Скрыть навигацию'}
>
{!noNavigationAnimation ? <IconPin size='0.75rem' /> : null}
{noNavigationAnimation ? <IconUnpin size='0.75rem' /> : null}
</button>
{!noNavigationAnimation ? (
<button
tabIndex={-1}
@ -42,17 +36,6 @@ export function ToggleNavigation() {
{!darkMode ? <IconLightTheme size='0.75rem' /> : null}
</button>
) : null}
<button
tabIndex={-1}
type='button'
className='p-1 cursor-pointer'
onClick={toggleNoNavigation}
data-tooltip-id={globalIDs.tooltip}
data-tooltip-content={noNavigationAnimation ? 'Показать навигацию' : 'Скрыть навигацию'}
>
{!noNavigationAnimation ? <IconPin size={iconSize} /> : null}
{noNavigationAnimation ? <IconUnpin size={iconSize} /> : null}
</button>
</div>
);
}

View File

@ -76,7 +76,7 @@ export function UserDropdown({ isOpen, hideDropdown }: UserDropdownProps) {
}
return (
<Dropdown id={globalIDs.user_dropdown} className='min-w-[18ch] max-w-[12rem]' stretchLeft isOpen={isOpen}>
<Dropdown id={globalIDs.user_dropdown} className='min-w-[18ch] max-w-48' stretchLeft isOpen={isOpen}>
<DropdownButton
text={user.username}
title='Профиль пользователя'
@ -105,7 +105,7 @@ export function UserDropdown({ isOpen, hideDropdown }: UserDropdownProps) {
) : null}
{user.is_staff ? (
<DropdownButton
text='REST API' // prettier: split-line
text='REST API' //
icon={<IconRESTapi size='1rem' />}
className='border-t'
onClick={gotoRestApi}
@ -113,21 +113,21 @@ export function UserDropdown({ isOpen, hideDropdown }: UserDropdownProps) {
) : null}
{user.is_staff ? (
<DropdownButton
text='База данных' // prettier: split-line
text='База данных' //
icon={<IconDatabase size='1rem' />}
onClick={gotoAdmin}
/>
) : null}
{user?.is_staff ? (
<DropdownButton
text='Иконки' // prettier: split-line
text='Иконки' //
icon={<IconImage size='1rem' />}
onClick={gotoIcons}
/>
) : null}
{user.is_staff ? (
<DropdownButton
text='Структура БД' // prettier: split-line
text='Структура БД' //
icon={<IconDBStructure size='1rem' />}
onClick={gotoDatabaseSchema}
className='border-b'

View File

@ -41,7 +41,7 @@ export function Button({
disabled={disabled ?? loading}
className={clsx(
'inline-flex gap-2 items-center justify-center',
'select-none disabled:cursor-auto',
'font-medium select-none disabled:cursor-auto',
'clr-btn-default cc-animate-color',
{
'border rounded-sm': !noBorder,
@ -61,7 +61,7 @@ export function Button({
{...restProps}
>
{icon ? icon : null}
{text ? <span className='font-medium'>{text}</span> : null}
{text ? <span>{text}</span> : null}
</button>
);
}

View File

@ -32,7 +32,7 @@ export function SubmitButton({ text = 'ОК', icon, disabled, loading, className
disabled={disabled || loading}
{...restProps}
>
{icon ? <span>{icon}</span> : null}
{icon ? icon : null}
{text ? <span>{text}</span> : null}
</button>
);

View File

@ -14,7 +14,7 @@ export function SortingIcon<TData>({ column }: SortingIconProps<TData>) {
{{
desc: <IconSortDesc size='1rem' />,
asc: <IconSortAsc size='1rem' />
}[column.getIsSorted() as string] ?? <IconSortDesc size='1rem' className='opacity-0 hover:opacity-50' />}
}[column.getIsSorted() as string] ?? <IconSortDesc size='1rem' className='opacity-0 group-hover:opacity-25' />}
</>
);
}

View File

@ -72,12 +72,12 @@ export function TableBody<TData>({
'cc-scroll-row',
'clr-hover cc-animate-color',
!noHeader && 'scroll-mt-[calc(2px+2rem)]',
row.getIsSelected() ? 'clr-selected' : index % 2 === 0 ? 'bg-prim-200' : 'bg-prim-100'
row.getIsSelected() ? 'clr-selected' : 'odd:bg-prim-200 even:bg-prim-100'
)}
style={{ ...(conditionalRowStyles ? getRowStyles(row) : []) }}
>
{enableRowSelection ? (
<td key={`select-${row.id}`} className='pl-3 pr-1 align-middle border-y'>
<td key={`select-${row.id}`} className='pl-3 pr-1 border-y'>
<SelectRow row={row} onChangeLastSelected={onChangeLastSelected} />
</td>
) : null}

View File

@ -31,7 +31,7 @@ export function TableHeader<TData>({
{table.getHeaderGroups().map((headerGroup: HeaderGroup<TData>) => (
<tr key={headerGroup.id}>
{enableRowSelection ? (
<th className='pl-3 pr-1 align-middle'>
<th className='pl-3 pr-1' scope='col'>
<SelectAll table={table} resetLastSelected={resetLastSelected} />
</th>
) : null}
@ -39,17 +39,16 @@ export function TableHeader<TData>({
<th
key={header.id}
colSpan={header.colSpan}
className='pl-2 py-2 text-xs font-medium select-none whitespace-nowrap'
scope='col'
className='cc-table-header group'
style={{
paddingRight: enableSorting && header.column.getCanSort() ? '0px' : '2px',
textAlign: 'start',
width: `calc(var(--header-${header?.id}-size) * 1px)`,
cursor: enableSorting && header.column.getCanSort() ? 'pointer' : 'auto'
}}
onClick={enableSorting ? header.column.getToggleSortingHandler() : undefined}
>
{!header.isPlaceholder ? (
<span className='inline-flex align-middle gap-1'>
<span className='inline-flex gap-1'>
{flexRender(header.column.columnDef.header, header.getContext())}
{enableSorting && header.column.getCanSort() ? <SortingIcon column={header.column} /> : null}
</span>

View File

@ -1,3 +1,4 @@
import React from 'react';
import clsx from 'clsx';
import { PARAMETER } from '@/utils/constants';
@ -5,6 +6,9 @@ import { PARAMETER } from '@/utils/constants';
import { type Styling } from '../props';
interface DropdownProps extends Styling {
/** Reference to the dropdown element. */
ref?: React.Ref<HTMLDivElement>;
/** Unique ID for the dropdown. */
id?: string;

View File

@ -52,9 +52,9 @@ export function DropdownButton({
data-tooltip-hidden={hideTitle}
{...restProps}
>
{icon ? icon : null}
{text ? <span>{text}</span> : null}
{children ? children : null}
{!children && icon ? icon : null}
{!children && text ? <span>{text}</span> : null}
</button>
);
}

View File

@ -171,16 +171,9 @@ export interface IconProps {
className?: string;
}
function MetaIconSVG({ viewBox, size = '1.5rem', className, props, children }: React.PropsWithChildren<IconSVGProps>) {
function MetaIconSVG({ viewBox, size = '1.5rem', props, children }: React.PropsWithChildren<IconSVGProps>) {
return (
<svg
width={size}
height={size}
className={`w-[${size}] h-[${size}] ${className}`}
fill='currentColor'
viewBox={viewBox}
{...props}
>
<svg width={size} height={size} fill='currentColor' viewBox={viewBox} {...props}>
{children}
</svg>
);
@ -205,7 +198,7 @@ export function IconLogin(props: IconProps) {
export function CheckboxChecked() {
return (
<svg className='w-3 h-3' viewBox='0 0 512 512' fill='#ffffff'>
<svg className='w-4 h-4 p-0.75' viewBox='0 0 512 512' fill='#ffffff'>
<path d='M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7l233.4-233.3c12.5-12.5 32.8-12.5 45.3 0z' />
</svg>
);
@ -213,7 +206,7 @@ export function CheckboxChecked() {
export function CheckboxNull() {
return (
<svg className='w-3 h-3' viewBox='0 0 16 16' fill='#ffffff'>
<svg className='w-4 h-4 p-0.25' viewBox='0 0 16 16' fill='#ffffff'>
<path d='M2 7.75A.75.75 0 012.75 7h10a.75.75 0 010 1.5h-10A.75.75 0 012 7.75z' />
</svg>
);

View File

@ -90,7 +90,7 @@ export function InfoError({ error }: InfoErrorProps) {
<div
className={clsx(
'cc-fade-in',
'min-w-[25rem]',
'min-w-100',
'px-3 py-2 flex flex-col',
'text-warn-600 text-sm font-semibold',
'select-text'

View File

@ -64,10 +64,8 @@ export function Checkbox({
>
<div
className={clsx(
'max-w-[1rem] min-w-[1rem] h-4', //
'pt-[0.05rem] pl-[0.05rem]',
'w-4 h-4', //
'border rounded-xs',
'cc-animate-color',
{
'bg-sec-600 text-sec-0': value !== false,
'bg-prim-100': value === false

View File

@ -66,9 +66,7 @@ export function CheckboxTristate({
<div
className={clsx(
'w-4 h-4', //
'pt-[0.05rem] pl-[0.05rem]',
'border rounded-xs',
'cc-animate-color',
{
'bg-sec-600 text-sec-0': value !== false,
'bg-prim-100': value === false

View File

@ -42,7 +42,7 @@ export function SearchBar({
<div className={clsx('relative', className)} {...restProps}>
{!noIcon ? (
<IconSearch
className='absolute top-[-0.125rem] left-3 translate-y-1/2 pointer-events-none clr-text-controls'
className='absolute -top-0.5 left-3 translate-y-1/2 pointer-events-none clr-text-controls'
size='1.25rem'
/>
) : null}

View File

@ -93,28 +93,36 @@ export function ModalForm({
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'
onSubmit={handleSubmit}
aria-labelledby='modal-title'
>
{helpTopic && !hideHelpWhen?.() ? (
<BadgeHelp
topic={helpTopic} //
className='float-left mt-2 ml-2'
topic={helpTopic}
className='absolute z-pop left-0 mt-2 ml-2'
padding='p-0'
contentClass='sm:max-w-[40rem]'
contentClass='sm:max-w-160'
/>
) : null}
<MiniButton
noPadding
aria-label='Закрыть'
titleHtml={prepareTooltip('Закрыть диалоговое окно', 'ESC')}
icon={<IconClose size='1.25rem' />}
className='float-right mt-2 mr-2'
onClick={handleCancel}
className='absolute z-pop right-0 mt-2 mr-2'
onClick={hideDialog}
/>
{header ? <h1 className='px-12 py-2 select-none'>{header}</h1> : null}
{header ? (
<h1 id='modal-title' className='px-12 py-2 select-none'>
{header}
</h1>
) : null}
<div
className={clsx(
@ -137,10 +145,10 @@ export function ModalForm({
autoFocus
text={submitText}
title={!canSubmit ? submitInvalidTooltip : ''}
className='min-w-[7rem]'
className='min-w-28'
disabled={!canSubmit}
/>
<Button text='Отмена' className='min-w-[7rem]' onClick={handleCancel} />
<Button text='Отмена' aria-label='Закрыть' className='min-w-28' onClick={handleCancel} />
</div>
</form>
</div>

View File

@ -37,19 +37,27 @@ export function ModalView({
<div
className={clsx(
'cc-animate-modal',
'z-modal absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
'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?.() ? (
<BadgeHelp topic={helpTopic} className='float-left mt-2 ml-2' padding='p-0' contentClass='sm:max-w-[40rem]' />
<BadgeHelp
topic={helpTopic}
className='absolute z-pop left-0 mt-2 ml-2'
padding='p-0'
contentClass='sm:max-w-160'
/>
) : null}
<MiniButton
noPadding
aria-label='Закрыть'
titleHtml={prepareTooltip('Закрыть диалоговое окно', 'ESC')}
icon={<IconClose size='1.25rem' />}
className='float-right mt-2 mr-2'
className='absolute z-pop right-0 mt-2 mr-2'
onClick={hideDialog}
/>
@ -71,9 +79,12 @@ export function ModalView({
{children}
</div>
<div className='z-pop my-2 flex gap-12 justify-center text-sm'>
<Button text='Закрыть' className='min-w-[7rem]' onClick={hideDialog} />
</div>
<Button
text='Закрыть'
aria-label='Закрыть'
className='z-pop my-2 mx-auto text-sm min-w-28'
onClick={hideDialog}
/>
</div>
</div>
);

View File

@ -18,7 +18,7 @@ export function TabLabel({ label, title, titleHtml, hideTitle, className, ...oth
return (
<TabImpl
className={clsx(
'min-w-[5.5rem] h-full',
'min-w-20 h-full',
'px-2 py-1 flex justify-center',
'clr-hover cc-animate-color duration-150',
'text-sm whitespace-nowrap font-controls',

View File

@ -1,7 +1,6 @@
'use client';
import { useEffect, useState } from 'react';
import clsx from 'clsx';
import { urls, useConceptNavigation } from '@/app';
@ -51,7 +50,7 @@ export function Component() {
}
return (
<form className={clsx('cc-fade-in cc-column', 'w-[24rem] mx-auto', 'px-6 mt-3')} onSubmit={handleSubmit}>
<form className='cc-fade-in cc-column w-96 mx-auto px-6 mt-3' onSubmit={handleSubmit}>
<TextInput
id='new_password'
type='password'
@ -77,7 +76,7 @@ export function Component() {
<SubmitButton
text='Установить пароль'
className='self-center w-[12rem] mt-3'
className='self-center w-48 mt-3'
loading={isPending}
disabled={!canSubmit}
/>

View File

@ -18,7 +18,7 @@ export function InfoCstClass({ header }: InfoCstClassProps) {
return (
<p key={`${prefixes.cst_status_list}${index}`}>
<span
className={clsx('inline-block', 'min-w-[7rem]', 'px-1', 'border', 'text-center text-sm font-controls')}
className={clsx('inline-block', 'min-w-28', 'px-1', 'border', 'text-center text-sm font-controls')}
style={{ backgroundColor: colorBgCstClass(cstClass) }}
>
{labelCstClass(cstClass)}

View File

@ -25,9 +25,9 @@ import { HelpTopic } from '../../models/helpTopic';
export function HelpOssGraph() {
return (
<div className='flex flex-col'>
<h1 className='sm:pr-[6rem]'>Граф синтеза</h1>
<h1 className='sm:pr-24'>Граф синтеза</h1>
<div className='flex flex-col sm:flex-row'>
<div className='sm:w-[14rem]'>
<div className='sm:w-56'>
<h1>Настройка графа</h1>
<li>
<IconFitImage className='inline-icon' /> Вписать в экран
@ -51,7 +51,7 @@ export function HelpOssGraph() {
<Divider vertical margins='mx-3 mt-3' className='hidden sm:block' />
<div className='sm:w-[21rem]'>
<div className='sm:w-84'>
<h1>Изменение узлов</h1>
<li>Клик на операцию выделение</li>
<li>Esc сбросить выделение</li>
@ -73,7 +73,7 @@ export function HelpOssGraph() {
<Divider margins='my-3' className='hidden sm:block' />
<div className='flex flex-col-reverse mb-3 sm:flex-row'>
<div className='sm:w-[14rem]'>
<div className='sm:w-56'>
<h1>Общие</h1>
<li>
<IconReset className='inline-icon' /> Сбросить изменения
@ -85,7 +85,7 @@ export function HelpOssGraph() {
<Divider vertical margins='mx-3' className='hidden sm:block' />
<div className='dense w-[21rem]'>
<div className='dense w-84'>
<h1>Контекстное меню</h1>
<li>
<IconRSForm className='inline-icon icon-green' /> Статус связанной{' '}

View File

@ -29,7 +29,7 @@ export function HelpRSGraphTerm() {
<div className='flex flex-col'>
<h1>Граф термов</h1>
<div className='flex flex-col sm:flex-row'>
<div className='sm:w-[14rem]'>
<div className='sm:w-56'>
<h1>Настройка графа</h1>
<li>Цвет покраска узлов</li>
<li>
@ -45,7 +45,7 @@ export function HelpRSGraphTerm() {
<Divider vertical margins='mx-3 mt-3' className='hidden sm:block' />
<div className='sm:w-[21rem]'>
<div className='sm:w-84'>
<h1>Изменение узлов</h1>
<li>Клик на узел выделение</li>
<li>

View File

@ -31,14 +31,14 @@ export function TopicsDropdown({ activeTopic, onChangeTopic }: TopicsDropdownPro
<div
ref={menu.ref}
className={clsx(
'absolute left-0 w-[13.5rem]', // prettier: split-lines
'absolute left-0 w-54', // prettier: split-lines
'flex flex-col',
'z-topmost',
'text-xs sm:text-sm',
'select-none',
{
'top-0': noNavigation,
'top-[3rem]': !noNavigation
'top-12': !noNavigation
}
)}
>
@ -48,7 +48,7 @@ export function TopicsDropdown({ activeTopic, onChangeTopic }: TopicsDropdownPro
title='Список тем'
hideTitle={menu.isOpen}
icon={!menu.isOpen ? <IconMenuUnfold size='1.25rem' /> : <IconMenuFold size='1.25rem' />}
className={clsx('w-[3rem] h-7 rounded-none border-l-0', menu.isOpen && 'border-b-0')}
className={clsx('w-12 h-7 rounded-none border-l-0', menu.isOpen && 'border-b-0')}
onClick={menu.toggle}
/>
<SelectTree

View File

@ -19,7 +19,7 @@ import {
type IRenameLocationDTO,
type IUpdateLibraryItemDTO,
type IVersionCreateDTO,
type IVersionInfo,
type IVersionExInfo,
type IVersionUpdateDTO,
schemaLibraryItem,
schemaLibraryItemArray,
@ -154,7 +154,7 @@ export const libraryApi = {
}
}),
versionUpdate: (data: { itemID: number; version: IVersionUpdateDTO }) =>
axiosPatch<IVersionUpdateDTO, IVersionInfo>({
axiosPatch<IVersionUpdateDTO, IVersionExInfo>({
schema: schemaVersionInfo,
endpoint: `/api/versions/${data.version.id}`,
request: {

View File

@ -34,6 +34,9 @@ export interface IRenameLocationDTO {
/** Represents library item version information. */
export type IVersionInfo = z.infer<typeof schemaVersionInfo>;
/** Represents library item version extended information. */
export type IVersionExInfo = z.infer<typeof schemaVersionExInfo>;
/** Represents data, used for cloning {@link IRSForm}. */
export type ICloneLibraryItemDTO = z.infer<typeof schemaCloneLibraryItem>;
@ -129,6 +132,10 @@ export const schemaVersionInfo = z.strictObject({
time_create: z.string().datetime({ offset: true })
});
export const schemaVersionExInfo = schemaVersionInfo.extend({
item: z.number()
});
export const schemaVersionUpdate = z.strictObject({
id: z.number(),
version: z.string().nonempty(errorMsg.requiredField),

View File

@ -83,7 +83,7 @@ export function EditorLibraryItem({ schema, isAttachedToOSS }: EditorLibraryItem
return (
<div className='flex flex-col'>
<div className='relative flex justify-stretch sm:mb-1 max-w-[30rem] gap-3'>
<div className='relative flex justify-stretch sm:mb-1 max-w-120 gap-3'>
<MiniButton
noHover
noPadding
@ -103,8 +103,8 @@ export function EditorLibraryItem({ schema, isAttachedToOSS }: EditorLibraryItem
<div className='relative'>
{ownerSelector.isOpen ? (
<div className='absolute top-[-0.5rem] left-[4rem]'>
<SelectUser className='w-[25rem] sm:w-[26rem] text-sm' value={schema.owner} onChange={onSelectUser} />
<div className='absolute -top-2 right-0'>
<SelectUser className='w-100 text-sm' value={schema.owner} onChange={onSelectUser} />
</div>
) : null}
<ValueIcon

View File

@ -40,7 +40,7 @@ export function MiniSelectorOSS({ items, onSelect, className, ...restProps }: Mi
<Label text='Список ОСС' className='border-b px-3 py-1' />
{items.map((reference, index) => (
<DropdownButton
className='min-w-[5rem]'
className='min-w-20'
key={`${prefixes.oss_list}${index}`}
text={reference.alias}
onClick={event => onSelect(event, reference)}

View File

@ -33,7 +33,7 @@ export function SelectLocationHead({
}
return (
<div ref={menu.ref} className={clsx('h-full text-right relative', className)} {...restProps}>
<div ref={menu.ref} className={clsx('text-right relative', className)} {...restProps}>
<SelectorButton
transparent
tabIndex={-1}
@ -51,16 +51,12 @@ export function SelectLocationHead({
.map((head, index) => {
return (
<DropdownButton
className='w-[10rem]'
key={`${prefixes.location_head_list}${index}`}
onClick={() => handleChange(head)}
title={describeLocationHead(head)}
>
<div className='inline-flex items-center gap-3'>
<IconLocationHead value={head} size='1rem' />
{labelLocationHead(head)}
</div>
</DropdownButton>
icon={<IconLocationHead value={head} size='1rem' />}
text={labelLocationHead(head)}
/>
);
})}
</Dropdown>

View File

@ -59,7 +59,7 @@ export function DlgChangeLocation() {
onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-[35rem]', 'pb-3 px-6 flex gap-3 h-[9rem]')}
>
<div className='flex flex-col gap-2 min-w-[7rem] h-min'>
<div className='flex flex-col gap-2 min-w-[7rem]'>
<Label className='select-none' text='Корень' />
<Controller
control={control}

View File

@ -114,8 +114,8 @@ export function DlgCloneLibraryItem() {
</div>
</div>
<div className='flex justify-between gap-3'>
<div className='flex flex-col gap-2 w-[7rem] h-min'>
<div className='flex gap-3'>
<div className='flex flex-col gap-2 w-[7rem]'>
<Label text='Корень' />
<Controller
control={control} //

View File

@ -1,7 +1,6 @@
'use client';
import { useState } from 'react';
import clsx from 'clsx';
import { useUsers } from '@/features/users';
import { SelectUser, TableUsers } from '@/features/users/components';
@ -42,15 +41,15 @@ export function DlgEditEditors() {
<ModalForm
header='Список редакторов'
submitText='Сохранить список'
className='flex flex-col w-[35rem] px-6 gap-3 pb-6'
className='flex flex-col w-140 px-6 gap-3 pb-6'
onSubmit={handleSubmit}
>
<div className={clsx('flex self-center items-center', 'text-sm font-semibold')}>
<div className='self-center text-sm font-semibold'>
<span>Всего редакторов [{selected.length}]</span>
<MiniButton
noHover
title='Очистить список'
className='py-0'
className='py-0 align-middle'
icon={<IconRemove size='1.5rem' className='icon-red' />}
disabled={selected.length === 0}
onClick={() => setSelected([])}
@ -65,7 +64,7 @@ export function DlgEditEditors() {
filter={id => !selected.includes(id)} //
value={null}
onChange={onAddEditor}
className='w-[25rem]'
className='w-100'
/>
</div>
</ModalForm>

View File

@ -85,7 +85,7 @@ export function DlgEditVersions() {
}
return (
<ModalView header='Редактирование версий' className='flex flex-col w-[40rem] px-6 gap-3 pb-6'>
<ModalView header='Редактирование версий' className='flex flex-col w-160 px-6 gap-3 pb-3'>
<TableVersions
processing={isProcessing}
items={schema.versions.reverse()}
@ -100,7 +100,7 @@ export function DlgEditVersions() {
{...register('version')}
dense
label='Версия'
className='w-[16rem] mr-3'
className='w-64 mr-3'
error={formErrors.version}
/>
<div className='cc-icons h-fit'>

View File

@ -1,7 +1,6 @@
'use client';
import { useIntl } from 'react-intl';
import clsx from 'clsx';
import { MiniButton } from '@/components/Control';
import { createColumnHelper, DataTable, type IConditionalStyle } from '@/components/DataTable';
@ -33,7 +32,7 @@ export function TableVersions({ processing, items, onDelete, selected, onSelect
columnHelper.accessor('version', {
id: 'version',
header: 'Версия',
cell: props => <div className='min-w-[6rem] max-w-[6rem] text-ellipsis'>{props.getValue()}</div>
cell: props => <div className='w-24 text-ellipsis'>{props.getValue()}</div>
}),
columnHelper.accessor('description', {
id: 'description',
@ -62,16 +61,15 @@ export function TableVersions({ processing, items, onDelete, selected, onSelect
id: 'actions',
size: 0,
cell: props => (
<div className='h-[1.25rem] w-[1.25rem]'>
<MiniButton
title='Удалить версию'
className='align-middle'
noHover
noPadding
disabled={processing}
icon={<IconRemove size='1.25rem' className='icon-red' />}
onClick={event => handleDeleteVersion(event, props.row.original.id)}
/>
</div>
)
})
];
@ -90,7 +88,7 @@ export function TableVersions({ processing, items, onDelete, selected, onSelect
dense
noFooter
headPosition='0'
className={clsx('mb-2', 'max-h-[17.4rem] min-h-[17.4rem]', 'border', 'cc-scroll-y')}
className='mb-2 h-70 border cc-scroll-y'
data={items}
columns={columns}
onRowClicked={rowData => onSelect(rowData.id)}

View File

@ -103,7 +103,7 @@ export function FormCreateItem() {
return (
<form
className={clsx('cc-fade-in cc-column', 'min-w-[30rem] max-w-[30rem] mx-auto', 'px-6 py-3')}
className={clsx('cc-fade-in cc-column', 'min-w-120 max-w-120 mx-auto', 'px-6 py-3')}
onSubmit={event => void handleSubmit(onSubmit)(event)}
onChange={resetErrors}
>
@ -151,7 +151,7 @@ export function FormCreateItem() {
{...register('alias')}
label='Сокращение'
placeholder={file && 'Загрузить из файла'}
className='w-[16rem]'
className='w-64'
error={errors.alias}
/>
<div className='flex flex-col items-center gap-2'>
@ -206,7 +206,7 @@ export function FormCreateItem() {
/>
<div className='flex justify-between gap-3 grow'>
<div className='flex flex-col gap-2 min-w-[7rem] h-min'>
<div className='flex flex-col gap-2 min-w-28'>
<Label text='Корень' />
<Controller
control={control} //
@ -247,8 +247,8 @@ export function FormCreateItem() {
</div>
<div className='flex justify-around gap-6 py-3'>
<SubmitButton text='Создать схему' loading={isPending} className='min-w-[10rem]' />
<Button text='Отмена' className='min-w-[10rem]' onClick={() => handleCancel()} />
<SubmitButton text='Создать схему' loading={isPending} className='min-w-40' />
<Button text='Отмена' className='min-w-40' onClick={() => handleCancel()} />
</div>
{serverError ? <InfoError error={serverError} /> : null}
</form>

View File

@ -56,7 +56,7 @@ export function LibraryPage() {
<ToolbarSearch total={libraryItems.length} filtered={filtered.length} />
<div className='relative cc-fade-in flex'>
<MiniButton
className='absolute z-tooltip top-[0.25rem] right-0 cc-animate-position'
className='absolute z-tooltip top-1 right-0 cc-animate-position'
title='Выгрузить в формате CSV'
icon={<IconCSV size='1.25rem' className='icon-green' />}
onClick={handleDownloadCSV}

View File

@ -40,7 +40,7 @@ export function TableLibraryItems({ items }: TableLibraryItemsProps) {
}
}
];
const tableHeight = useFitHeight('2.2rem');
const tableHeight = useFitHeight('2.25rem');
function handleOpenItem(item: ILibraryItem, event: React.MouseEvent<Element>) {
const selection = window.getSelection();

View File

@ -78,21 +78,14 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
<div
className={clsx(
'sticky top-0', //
'h-[2.2rem]',
'h-9',
'flex items-center gap-3',
'border-b',
'text-sm',
'clr-input'
)}
>
<div
className={clsx(
'ml-3 pt-1 self-center',
'min-w-[4.5rem] sm:min-w-[7.4rem]',
'select-none',
'whitespace-nowrap'
)}
>
<div className={clsx('ml-3 pt-1 self-center', 'min-w-18 sm:min-w-30', 'select-none', 'whitespace-nowrap')}>
{filtered} из {total}
</div>
@ -124,7 +117,7 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
<SelectUser
noBorder
placeholder='Выберите владельца'
className='min-w-[15rem] text-sm mx-1 mb-1'
className='min-w-60 text-sm mx-1 mb-1'
value={filterUser}
onChange={setFilterUser}
/>
@ -144,7 +137,7 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
id='library_search'
placeholder='Поиск'
noBorder
className={clsx('min-w-[7rem] sm:min-w-[10rem] max-w-[20rem]', folderMode && 'grow')}
className={clsx('min-w-28 sm:min-w-40 max-w-80', folderMode && 'grow')}
query={query}
onChangeQuery={setQuery}
/>
@ -167,31 +160,26 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
/>
<Dropdown isOpen={headMenu.isOpen} stretchLeft>
<DropdownButton title='Переключение в режим Проводник' onClick={handleToggleFolder}>
<div className='inline-flex items-center gap-3'>
<IconFolderTree size='1rem' className='clr-text-controls' />
<span>проводник...</span>
</div>
</DropdownButton>
<DropdownButton className='w-[10rem]' onClick={() => handleChange(null)}>
<div className='inline-flex items-center gap-3'>
<IconFolder size='1rem' className='clr-text-controls' />
<span>отображать все</span>
</div>
</DropdownButton>
<DropdownButton
title='Переключение в режим Проводник'
text='проводник...'
icon={<IconFolderTree size='1rem' className='clr-text-controls' />}
onClick={handleToggleFolder}
/>
<DropdownButton
text='отображать все'
icon={<IconFolder size='1rem' className='clr-text-controls' />}
onClick={() => handleChange(null)}
/>
{Object.values(LocationHead).map((head, index) => {
return (
<DropdownButton
className='w-[10rem]'
key={`${prefixes.location_head_list}${index}`}
onClick={() => handleChange(head)}
title={describeLocationHead(head)}
>
<div className='inline-flex items-center gap-3'>
<IconLocationHead value={head} size='1rem' />
{labelLocationHead(head)}
</div>
</DropdownButton>
text={labelLocationHead(head)}
icon={<IconLocationHead value={head} size='1rem' />}
/>
);
})}
</Dropdown>
@ -203,7 +191,7 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
placeholder='Путь'
noIcon
noBorder
className='w-[4.5rem] sm:w-[5rem] grow'
className='w-18 sm:w-20 grow'
query={path}
onChangeQuery={setPath}
/>

View File

@ -63,7 +63,7 @@ export function ViewSideLocation({ isVisible, onRenameLocation }: ViewSideLocati
return (
<div
className={clsx('max-w-[10rem] sm:max-w-[15rem]', 'flex flex-col', 'text:xs sm:text-sm', 'select-none')}
className={clsx('max-w-40 sm:max-w-60', 'flex flex-col', 'text:xs sm:text-sm', 'select-none')}
style={{
transitionProperty: 'width, min-width, opacity',
transitionDuration: `${PARAMETER.moveDuration}ms`,
@ -73,7 +73,7 @@ export function ViewSideLocation({ isVisible, onRenameLocation }: ViewSideLocati
opacity: isVisible ? 1 : 0
}}
>
<div className='h-[2.08rem] flex justify-between items-center pr-1 pl-[0.125rem]'>
<div className='h-8 flex justify-between items-center pr-1 pl-0.5'>
<BadgeHelp topic={HelpTopic.UI_LIBRARY} contentClass='text-sm' offset={5} place='right-start' />
<div className='cc-icons'>
{canRename ? (

View File

@ -37,7 +37,7 @@ export function useLibraryColumns() {
<MiniButton
noPadding
noHover
className='pl-2 max-h-[1rem] translate-y-[-0.125rem]'
className='pl-2 max-h-4 -translate-y-0.5'
onClick={handleToggleFolder}
titleHtml='Переключение в режим Проводник'
icon={<IconFolderTree size='1.25rem' className='clr-text-controls' />}
@ -58,7 +58,7 @@ export function useLibraryColumns() {
minSize: 80,
maxSize: 150,
enableSorting: true,
cell: props => <div className='min-w-[5rem]'>{props.getValue()}</div>,
cell: props => <span className='min-w-20'>{props.getValue()}</span>,
sortingFn: 'text'
}),
columnHelper.accessor('title', {
@ -84,7 +84,7 @@ export function useLibraryColumns() {
id: 'time_update',
header: isSmall ? 'Дата' : 'Обновлена',
cell: props => (
<div className='whitespace-nowrap'>
<span className='whitespace-nowrap'>
{new Date(props.getValue()).toLocaleString(intl.locale, {
year: '2-digit',
month: '2-digit',
@ -94,7 +94,7 @@ export function useLibraryColumns() {
minute: '2-digit'
})
})}
</div>
</span>
),
enableSorting: true,
sortingFn: 'datetime',

View File

@ -113,7 +113,7 @@ export function PickMultiOperation({ rows, items, value, onChange, className, ..
>
<SelectOperation
noBorder
items={nonSelectedItems} // prettier: split-line
items={nonSelectedItems} //
value={lastSelected}
onChange={handleSelect}
/>

View File

@ -99,7 +99,7 @@ export function DlgCreateOperation() {
submitText='Создать'
canSubmit={isValid}
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
className='w-[40rem] px-6 h-[32rem]'
className='w-160 px-6 h-128'
helpTopic={HelpTopic.CC_OSS}
>
<Tabs
@ -108,9 +108,7 @@ export function DlgCreateOperation() {
selectedIndex={activeTab}
onSelect={handleSelectTab}
>
<TabList
className={clsx('self-center absolute top-[2.4rem]', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}
>
<TabList className={clsx('self-center absolute top-10', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}>
<TabLabel
title={describeOperationType(OperationType.INPUT)}
label={labelOperationType(OperationType.INPUT)}

View File

@ -71,7 +71,7 @@ export function DlgEditOperation() {
submitText='Сохранить'
canSubmit={methods.formState.isValid}
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
className='w-[40rem] px-6 h-[32rem]'
className='w-160 px-6 h-128'
helpTopic={HelpTopic.UI_SUBSTITUTIONS}
hideHelpWhen={() => activeTab !== TabID.SUBSTITUTION}
>
@ -82,12 +82,12 @@ export function DlgEditOperation() {
onSelect={setActiveTab}
>
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}>
<TabLabel title='Текстовые поля' label='Карточка' className='w-[8rem]' />
<TabLabel title='Текстовые поля' label='Карточка' className='w-32' />
{target.operation_type === OperationType.SYNTHESIS ? (
<TabLabel title='Выбор аргументов операции' label='Аргументы' className='w-[8rem]' />
<TabLabel title='Выбор аргументов операции' label='Аргументы' className='w-32' />
) : null}
{target.operation_type === OperationType.SYNTHESIS ? (
<TabLabel titleHtml='Таблица отождествлений' label='Отождествления' className='w-[8rem]' />
<TabLabel titleHtml='Таблица отождествлений' label='Отождествления' className='w-32' />
) : null}
</TabList>

View File

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

View File

@ -120,7 +120,7 @@ export function DlgRelocateConstituents() {
submitText='Переместить'
canSubmit={isValid && destinationItem !== undefined}
onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-[40rem] h-[33rem]', 'py-3 px-6')}
className={clsx('w-160 h-[33rem]', 'py-3 px-6')}
helpTopic={HelpTopic.UI_RELOCATE_CST}
>
<div className='flex flex-col border'>

View File

@ -39,9 +39,8 @@ export function EditorOssCard() {
onKeyDown={handleInput}
className={clsx(
'cc-fade-in',
'md:max-w-fit max-w-[32rem] min-w-fit',
'pt-[1.9rem]',
'flex flex-row flex-wrap px-6 justify-center'
'md:max-w-fit max-w-128 min-w-fit',
'flex flex-row flex-wrap pt-8 px-6 justify-center'
)}
>
<div className='cc-column px-3'>

View File

@ -4,7 +4,6 @@
import { useEffect } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { type IUpdateLibraryItemDTO, LibraryItemType, schemaUpdateLibraryItem } from '@/features/library';
import { useUpdateItem } from '@/features/library/backend/useUpdateItem';
@ -58,7 +57,7 @@ export function FormOSS() {
return (
<form
id={globalIDs.library_item_editor}
className={clsx('mt-1 min-w-[22rem] sm:w-[30rem]', 'flex flex-col pt-1')}
className='mt-1 min-w-88 sm:w-120 flex flex-col pt-1'
onSubmit={event => void handleSubmit(onSubmit)(event)}
>
<TextInput
@ -74,7 +73,7 @@ export function FormOSS() {
id='schema_alias'
{...register('alias')}
label='Сокращение'
className='w-[16rem]'
className='w-64'
disabled={!isMutable}
error={errors.alias}
/>

View File

@ -167,7 +167,7 @@ export function NodeContextMenu({ isOpen, operation, cursorX, cursorY, onHide }:
}
return (
<div ref={ref} className='absolute select-none' style={{ top: cursorY, left: cursorX }}>
<div ref={ref} className='relative' style={{ top: `calc(${cursorY}px - 2.5rem)`, left: cursorX }}>
<Dropdown
isOpen={isOpen}
stretchLeft={cursorX >= window.innerWidth - MENU_WIDTH}

View File

@ -10,7 +10,6 @@ import {
useOnSelectionChange,
useReactFlow
} from 'reactflow';
import clsx from 'clsx';
import { useMainHeight } from '@/stores/appLayout';
import { useDialogsStore } from '@/stores/dialogs';
@ -191,20 +190,12 @@ export function OssFlow() {
return (
<div tabIndex={-1} className='relative' onKeyDown={handleKeyDown}>
<div
className={clsx(
'absolute z-pop top-[1.9rem] right-1/2 translate-x-1/2',
'pt-1 rounded-b-2xl',
'cc-blur',
'hover:bg-prim-100 hover:bg-opacity-50'
)}
>
<ToolbarOssGraph
className='absolute z-pop top-8 right-1/2 translate-x-1/2'
onCreate={handleCreateOperation}
onDelete={handleDeleteSelected}
onResetPositions={() => setToggleReset(prev => !prev)}
/>
</div>
<NodeContextMenu isOpen={isContextMenuOpen} onHide={() => setIsContextMenuOpen(false)} {...menuProps} />

View File

@ -1,6 +1,7 @@
'use client';
import { useReactFlow } from 'reactflow';
import clsx from 'clsx';
import { HelpTopic } from '@/features/help';
import { BadgeHelp } from '@/features/help/components';
@ -22,6 +23,7 @@ import {
IconReset,
IconSave
} from '@/components/Icons';
import { type Styling } from '@/components/props';
import { useDialogsStore } from '@/stores/dialogs';
import { PARAMETER } from '@/utils/constants';
import { prepareTooltip } from '@/utils/utils';
@ -34,13 +36,19 @@ import { useOssEdit } from '../OssEditContext';
import { VIEW_PADDING } from './OssFlow';
import { useGetPositions } from './useGetPositions';
interface ToolbarOssGraphProps {
interface ToolbarOssGraphProps extends Styling {
onCreate: () => void;
onDelete: () => void;
onResetPositions: () => void;
}
export function ToolbarOssGraph({ onCreate, onDelete, onResetPositions }: ToolbarOssGraphProps) {
export function ToolbarOssGraph({
onCreate,
onDelete,
onResetPositions,
className,
...restProps
}: ToolbarOssGraphProps) {
const { schema, selected, isMutable, canDeleteOperation: canDelete } = useOssEdit();
const isProcessing = useMutatingOss();
const { fitView } = useReactFlow();
@ -119,7 +127,16 @@ export function ToolbarOssGraph({ onCreate, onDelete, onResetPositions }: Toolba
}
return (
<div className='flex flex-col items-center'>
<div
className={clsx(
'flex flex-col items-center pt-1',
'rounded-b-2xl',
'cc-blur',
'hover:bg-prim-100 hover:bg-opacity-50',
className
)}
{...restProps}
>
<div className='cc-icons'>
<MiniButton
title='Сбросить изменения'
@ -164,7 +181,7 @@ export function ToolbarOssGraph({ onCreate, onDelete, onResetPositions }: Toolba
}
onClick={toggleEdgeAnimate}
/>
<BadgeHelp topic={HelpTopic.UI_OSS_GRAPH} contentClass='sm:max-w-[40rem]' offset={4} />
<BadgeHelp topic={HelpTopic.UI_OSS_GRAPH} contentClass='sm:max-w-160' offset={4} />
</div>
{isMutable ? (
<div className='cc-icons'>

View File

@ -282,7 +282,7 @@ export function colorBgGraphNode(cst: IConstituenta, coloringScheme: GraphColori
if (coloringScheme === 'schemas') {
return colorBgSchemas(cst.parent_schema_index);
}
return '';
return APP_COLORS.bgGreen50;
}
/**

View File

@ -1,6 +1,5 @@
import clsx from 'clsx';
import { type Styling } from '@/components/props';
import { APP_COLORS } from '@/styling/colors';
import { globalIDs } from '@/utils/constants';
@ -8,7 +7,7 @@ import { colorFgCstStatus } from '../colors';
import { CstClass, type IConstituenta } from '../models/rsform';
import { useCstTooltipStore } from '../stores/cstTooltip';
interface BadgeConstituentaProps extends Styling {
interface BadgeConstituentaProps {
/** Prefix for tooltip ID. */
prefixID?: string;
@ -19,25 +18,17 @@ interface BadgeConstituentaProps extends Styling {
/**
* Displays a badge with a constituenta alias and information tooltip.
*/
export function BadgeConstituenta({ value, prefixID, className, style }: BadgeConstituentaProps) {
export function BadgeConstituenta({ value, prefixID }: BadgeConstituentaProps) {
const setActiveCst = useCstTooltipStore(state => state.setActiveCst);
return (
<div
id={prefixID ? `${prefixID}${value.id}` : undefined}
className={clsx(
'min-w-[3.1rem] max-w-[3.1rem]',
'px-1',
'border rounded-md',
value.is_inherited && 'border-dashed',
'text-center font-medium whitespace-nowrap',
className
)}
className={clsx('cc-badge-constituenta', value.is_inherited && 'border-dashed')}
style={{
borderColor: colorFgCstStatus(value.status),
color: colorFgCstStatus(value.status),
backgroundColor: value.cst_class === CstClass.BASIC ? APP_COLORS.bgGreen25 : APP_COLORS.bgInput,
...style
backgroundColor: value.cst_class === CstClass.BASIC ? APP_COLORS.bgGreen25 : APP_COLORS.bgInput
}}
data-tooltip-id={globalIDs.constituenta_tooltip}
onMouseEnter={() => setActiveCst(value)}

View File

@ -18,7 +18,7 @@ export function BadgeGrammeme({ grammeme }: BadgeGrammemeProps) {
return (
<div
className={clsx(
'min-w-[3rem]', //
'min-w-12', //
'px-1',
'border rounded-md',
'text-sm font-medium text-center whitespace-nowrap'

View File

@ -8,13 +8,7 @@ import { InfoConstituenta } from './InfoConstituenta';
export function ConstituentaTooltip() {
const hoverCst = useCstTooltipStore(state => state.activeCst);
return (
<Tooltip
clickable
id={globalIDs.constituenta_tooltip}
layer='z-topmost'
className='max-w-[30rem]'
hidden={!hoverCst}
>
<Tooltip clickable id={globalIDs.constituenta_tooltip} layer='z-topmost' className='max-w-120' hidden={!hoverCst}>
{hoverCst ? <InfoConstituenta data={hoverCst} onClick={event => event.stopPropagation()} /> : null}
</Tooltip>
);

View File

@ -187,7 +187,7 @@ export function PickSubstitutions({
columnHelper.accessor(item => item.original_source.alias, {
id: 'right_schema',
size: 100,
cell: props => <div className='min-w-[8rem] text-ellipsis text-right'>{props.getValue()}</div>
cell: props => <div className='min-w-32 text-ellipsis text-right'>{props.getValue()}</div>
}),
columnHelper.display({
id: 'actions',

View File

@ -52,7 +52,7 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
{...register('alias')}
error={errors.alias}
/>
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} contentClass='sm:max-w-[40rem]' />
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} contentClass='sm:max-w-160' />
</div>
<TextArea

View File

@ -77,9 +77,9 @@ export function DlgCstTemplate() {
onSelect={setActiveTab}
>
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}>
<TabLabel label='Шаблон' title='Выбор шаблона выражения' className='w-[8rem]' />
<TabLabel label='Аргументы' title='Подстановка аргументов шаблона' className='w-[8rem]' />
<TabLabel label='Конституента' title='Редактирование конституенты' className='w-[8rem]' />
<TabLabel label='Шаблон' title='Выбор шаблона выражения' className='w-32' />
<TabLabel label='Аргументы' title='Подстановка аргументов шаблона' className='w-32' />
<TabLabel label='Конституента' title='Редактирование конституенты' className='w-32' />
</TabList>
<FormProvider {...methods}>

View File

@ -93,19 +93,17 @@ export function TabArguments() {
argumentsHelper.display({
id: 'actions',
size: 0,
cell: props => (
<div className='h-[1.25rem] w-[1.25rem]'>
{props.row.original.value ? (
cell: props =>
props.row.original.value ? (
<MiniButton
title='Очистить значение'
noPadding
noHover
className='align-middle'
icon={<IconRemove size='1.25rem' className='icon-red' />}
onClick={() => handleClearArgument(props.row.original)}
/>
) : null}
</div>
)
) : null
})
];
@ -150,12 +148,7 @@ export function TabArguments() {
{selectedArgument?.alias || 'ARG'}
</span>
<span>=</span>
<RSInput
noTooltip
className='w-[12rem]'
value={argumentValue}
onChange={newValue => setArgumentValue(newValue)}
/>
<RSInput noTooltip className='w-48' value={argumentValue} onChange={newValue => setArgumentValue(newValue)} />
<div className='flex'>
<MiniButton
title='Подставить значение аргумента'

View File

@ -102,7 +102,7 @@ export function DlgEditReference() {
canSubmit={methods.formState.isValid}
onCancel={onCancel}
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
className='w-[40rem] px-6 h-[32rem]'
className='w-160 px-6 h-[32rem]'
helpTopic={HelpTopic.TERM_CONTROL}
>
<Tabs

View File

@ -1,7 +1,6 @@
'use client';
import { useState } from 'react';
import clsx from 'clsx';
import { HelpTopic } from '@/features/help';
@ -123,7 +122,7 @@ export function DlgEditWordForms() {
header='Редактирование словоформ'
submitText='Сохранить'
onSubmit={handleSubmit}
className='flex flex-col w-[40rem] px-6'
className='flex flex-col w-160 px-6'
helpTopic={HelpTopic.TERM_CONTROL}
>
<TextArea
@ -135,15 +134,12 @@ export function DlgEditWordForms() {
value={target.term_resolved}
/>
<div className='mt-3 mb-2'>
<Label text='Параметры словоформы' />
</div>
<Label className='mt-3 mb-2' text='Параметры словоформы' />
<div className='flex'>
<TextArea
placeholder='Введите текст'
className='min-w-[20rem] min-h-[5rem]'
rows={2}
className='min-w-80'
rows={3}
value={inputText}
onChange={event => setInputText(event.target.value)}
/>
@ -165,7 +161,7 @@ export function DlgEditWordForms() {
</div>
<SelectMultiGrammeme
placeholder='Выберите граммемы'
className='min-w-[15rem] h-fit'
className='min-w-60 h-fit'
value={inputGrams}
onChange={setInputGrams}
/>
@ -188,12 +184,12 @@ export function DlgEditWordForms() {
onClick={handleGenerateLexeme}
/>
</div>
<div className={clsx('mt-3 mb-2 mx-auto', 'flex items-center', 'text-sm text-center font-semibold')}>
<div>Заданные вручную словоформы [{forms.length}]</div>
<div className='mt-3 mb-2 mx-auto text-sm font-semibold'>
<span>Заданные вручную словоформы [{forms.length}]</span>
<MiniButton
noHover
title='Сбросить все словоформы'
className='py-0'
className='py-0 align-middle'
icon={<IconRemove size='1.5rem' className='icon-red' />}
disabled={isProcessing || forms.length === 0}
onClick={handleResetAll}

View File

@ -48,15 +48,14 @@ export function TableWordForms({ forms, setForms, onFormSelect }: TableWordForms
id: 'actions',
size: 0,
cell: props => (
<div className='h-[1.25rem] w-[1.25rem]'>
<MiniButton
noHover
noPadding
className='align-middle'
title='Удалить словоформу'
icon={<IconRemove size='1.25rem' className='icon-red' />}
onClick={() => handleDeleteRow(props.row.index)}
/>
</div>
)
})
];

View File

@ -3,7 +3,6 @@
import { Suspense, useState } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { Loader } from '@/components/Loader';
import { ModalForm } from '@/components/Modal';
@ -54,7 +53,7 @@ export function DlgInlineSynthesis() {
<ModalForm
header='Импорт концептуальной схем'
submitText='Добавить конституенты'
className='w-[40rem] h-[33rem] px-6'
className='w-160 h-132 px-6'
canSubmit={methods.formState.isValid && sourceID !== null}
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
>
@ -64,18 +63,22 @@ export function DlgInlineSynthesis() {
selectedIndex={activeTab}
onSelect={setActiveTab}
>
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}>
<TabLabel label='Схема' title='Источник конституент' className='w-[8rem]' />
<TabList className='mb-3 self-center flex border divide-x rounded-none bg-prim-200'>
<TabLabel
label='Схема' //
title='Источник конституент'
className='w-32'
/>
<TabLabel
label='Содержание'
title={!sourceID ? 'Выберите схему' : 'Перечень конституент'}
className='w-[8rem]'
className='w-32'
disabled={!sourceID}
/>
<TabLabel
label='Отождествления'
title={!sourceID ? 'Выберите схему' : 'Таблица отождествлений'}
className='w-[8rem]'
className='w-32'
disabled={!sourceID}
/>
</TabList>

View File

@ -29,7 +29,7 @@ export function DlgShowAST() {
<ModalView className='relative w-[calc(100dvw-3rem)] h-[calc(100dvh-6rem)]' helpTopic={HelpTopic.UI_FORMULA_TREE}>
<div
className={clsx(
'absolute z-pop top-0 -mt-1 right-1/2 translate-x-1/2 max-w-[60ch]',
'absolute z-pop top-2 right-1/2 translate-x-1/2 max-w-[60ch]',
'px-2 rounded-2xl',
'cc-blur bg-prim-100',
'text-lg text-center'

View File

@ -47,7 +47,7 @@ export function DlgSubstituteCst() {
submitInvalidTooltip='Выберите две различные конституенты'
canSubmit={isValid}
onSubmit={event => void handleSubmit(onSubmit)(event)}
className={clsx('w-[40rem]', 'px-6 pb-3')}
className={clsx('w-160', 'px-6 pb-3')}
helpTopic={HelpTopic.UI_SUBSTITUTIONS}
>
<Controller

View File

@ -224,7 +224,7 @@ export function FormConstituenta({ disabled, id, toggleReset, schema, activeCst,
id='cst_convention'
{...register('item_data.convention')}
fitContent
className='max-h-[8rem]'
className='max-h-32'
spellCheck
label={isBasic ? 'Конвенция' : 'Комментарий'}
placeholder={isBasic ? 'Договоренность об интерпретации' : 'Пояснение разработчика'}
@ -250,7 +250,7 @@ export function FormConstituenta({ disabled, id, toggleReset, schema, activeCst,
disabled={disabled || !isModified}
icon={<IconSave size='1.25rem' />}
/>
<div className='absolute z-pop top-[0.1rem] left-full cc-icons'>
<div className='absolute z-pop top-1/2 -translate-y-1/2 left-full cc-icons'>
{activeCst.has_inherited_children && !activeCst.is_inherited ? (
<Indicator
icon={<IconPredecessor size='1.25rem' className='text-sec-600' />}

View File

@ -156,7 +156,7 @@ export function ToolbarConstituenta({
/>
</>
) : null}
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} contentClass='sm:max-w-[40rem]' />
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} contentClass='sm:max-w-160' />
</div>
);
}

View File

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

View File

@ -38,16 +38,11 @@ export function StatusBar({ isModified, processing, activeCst, parseData, onAnal
})();
return (
<div
className={clsx(
'absolute z-pop top-[-0.5rem] right-1/2 translate-x-1/2 w-fit',
'pl-[8.5rem] xs:pl-[2rem] 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
tabIndex={0}
className={clsx(
'w-[10rem] h-[1.75rem]',
'w-40 h-7',
'px-2 flex items-center justify-center',
'border',
'select-none',
@ -68,7 +63,7 @@ export function StatusBar({ isModified, processing, activeCst, parseData, onAnal
{!processing ? (
<div className='cc-fade-in flex items-center gap-2'>
<IconExpressionStatus size='1rem' value={status} />
<span className='pb-[0.125rem] font-controls pr-2'>{labelExpressionStatus(status)}</span>
<span className='pb-0.5 font-controls pr-2'>{labelExpressionStatus(status)}</span>
</div>
) : null}
</div>

View File

@ -4,7 +4,6 @@
import { useEffect } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { urls, useConceptNavigation } from '@/app';
import {
@ -71,7 +70,7 @@ export function FormRSForm() {
return (
<form
id={globalIDs.library_item_editor}
className={clsx('mt-1 min-w-[22rem] sm:w-[30rem]', 'flex flex-col pt-1')}
className='mt-1 min-w-88 sm:w-120 flex flex-col pt-1'
onSubmit={event => void handleSubmit(onSubmit)(event)}
>
<TextInput
@ -87,7 +86,7 @@ export function FormRSForm() {
id='schema_alias'
{...register('alias')}
label='Сокращение'
className='w-[16rem]'
className='w-64'
disabled={!isContentEditable}
error={errors.alias}
/>

View File

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

View File

@ -123,10 +123,10 @@ export function EditorRSList() {
return false;
}
const tableHeight = useFitHeight('4.05rem + 5px');
const tableHeight = useFitHeight('4rem + 5px');
return (
<div tabIndex={-1} onKeyDown={handleKeyDown} className='relative cc-fade-in pt-[1.9rem]'>
<div tabIndex={-1} onKeyDown={handleKeyDown} className='relative cc-fade-in pt-8'>
{isContentEditable ? <ToolbarRSList /> : null}
{isContentEditable ? (
<div className='flex items-center border-b'>
@ -136,7 +136,7 @@ export function EditorRSList() {
<SearchBar
id='constituents_search'
noBorder
className='w-[8rem]'
className='w-32'
query={filterText}
onChangeQuery={setFilterText}
/>
@ -144,7 +144,7 @@ export function EditorRSList() {
) : null}
<MiniButton
className='absolute z-pop top-[4.45rem] md:top-[2.15rem] right-[1rem] cc-animate-position'
className='absolute z-pop top-18 right-4'
title='Выгрузить в формате CSV'
icon={<IconCSV size='1.25rem' className='icon-green' />}
onClick={handleDownloadCSV}

View File

@ -77,9 +77,7 @@ export function TableRSList({
minSize: 150,
maxSize: 200,
cell: props => (
<div className={clsx('min-w-[9.3rem] max-w-[9.3rem]', 'text-xs break-words')}>
{truncateToSymbol(props.getValue(), TYPIFICATION_TRUNCATE)}
</div>
<div className='w-40 text-xs break-words'>{truncateToSymbol(props.getValue(), TYPIFICATION_TRUNCATE)}</div>
)
}),
columnHelper.accessor(cst => cst.term_resolved || cst.term_raw || '', {
@ -126,7 +124,7 @@ export function TableRSList({
<DataTable
dense
noFooter
className={clsx('min-h-[16rem]', 'cc-scroll-y', 'text-sm', 'select-none')}
className={clsx('min-h-64', 'cc-scroll-y', 'text-sm', 'select-none')}
style={{ maxHeight: maxHeight }}
data={items ?? []}
columns={columns}

View File

@ -20,9 +20,9 @@ export function GraphSelectors() {
return (
<div className='relative border rounded-b-none select-none clr-input rounded-t-md pointer-events-auto'>
<div className='absolute z-pop right-[2.5rem] top-[0.25rem]'>
{coloring === 'status' ? <BadgeHelp topic={HelpTopic.UI_CST_STATUS} contentClass='min-w-[25rem]' /> : null}
{coloring === 'type' ? <BadgeHelp topic={HelpTopic.UI_CST_CLASS} contentClass='min-w-[25rem]' /> : null}
<div className='absolute z-pop right-10 h-10 flex items-center'>
{coloring === 'status' ? <BadgeHelp topic={HelpTopic.UI_CST_STATUS} contentClass='min-w-100' /> : null}
{coloring === 'type' ? <BadgeHelp topic={HelpTopic.UI_CST_CLASS} contentClass='min-w-100]' /> : null}
{coloring === 'schemas' ? <SchemasGuide /> : null}
</div>
<SelectSingle

View File

@ -36,27 +36,17 @@ export function SchemasGuide() {
})();
return (
<div tabIndex={-1} id={globalIDs.graph_schemas} className='p-1'>
<div tabIndex={-1} id={globalIDs.graph_schemas}>
<IconHelp size='1.25rem' className='icon-primary' />
<Tooltip
anchorSelect={`#${globalIDs.graph_schemas}`}
place='right'
className='max-w-[25rem] break-words text-base'
>
<div>
<span
className='min-w-[0.6rem] min-h-[0.6rem] border inline-block mr-1 rounded-full'
style={{ backgroundColor: colorBgSchemas(0) }}
/>
Текущая схема
<Tooltip anchorSelect={`#${globalIDs.graph_schemas}`} place='right' className='max-w-100 break-words text-base'>
<div className='inline-flex items-center gap-2'>
<span className='w-2.5 h-2.5 border rounded-full' style={{ backgroundColor: colorBgSchemas(0) }} />
<span>Текущая схема</span>
</div>
{schemas.map((alias, index) => (
<div key={`${prefixes.schemas_list}${index}`}>
<span
className='min-w-[0.6rem] min-h-[0.6rem] border inline-block mr-1 rounded-full'
style={{ backgroundColor: colorBgSchemas(index + 1) }}
/>
{alias}
<div key={`${prefixes.schemas_list}${index}`} className='inline-flex items-center gap-2'>
<span className='w-2.5 h-2.5 border rounded-full' style={{ backgroundColor: colorBgSchemas(index + 1) }} />
<span>{alias}</span>
</div>
))}
</Tooltip>

View File

@ -183,13 +183,14 @@ export function TGFlow() {
<div
className={clsx(
'absolute z-pop top-[4.4rem] sm:top-[4.1rem] left-[0.5rem] sm:left-[0.65rem] w-[13.5rem]',
'flex flex-col pointer-events-none'
'absolute z-pop top-18 sm:top-16 left-2 sm:left-3 w-54',
'flex flex-col',
'pointer-events-none'
)}
>
<div className='px-2 pb-1 select-none whitespace-nowrap cc-blur rounded-xl'>
<span className='px-2 pb-1 select-none whitespace-nowrap cc-blur rounded-xl'>
Выбор {selected.length} из {schema.stats?.count_all ?? 0}
</div>
</span>
<GraphSelectors />
<ViewHidden items={hidden} />
</div>

View File

@ -36,11 +36,14 @@ export function ToolbarFocusedCst() {
}
return (
<div className='items-center cc-icons'>
<div className='w-[7.8rem] text-right select-none' style={{ color: APP_COLORS.fgPurple }}>
<div className='flex items-center cc-icons'>
<div className='w-31 mt-0.5 text-right select-none' style={{ color: APP_COLORS.fgPurple }}>
<span>
Фокус
<b className='px-1'> {focusCst.alias} </b>
<b className='pr-1'> {focusCst.alias} </b>
</span>
</div>
<MiniButton
titleHtml='Сбросить фокус'
icon={<IconReset size='1.25rem' className='icon-primary' />}

View File

@ -146,7 +146,7 @@ export function ToolbarTermGraph() {
title='Граф ступеней'
onClick={handleShowTypeGraph}
/>
<BadgeHelp topic={HelpTopic.UI_GRAPH_TERM} contentClass='sm:max-w-[40rem]' offset={4} />
<BadgeHelp topic={HelpTopic.UI_GRAPH_TERM} contentClass='sm:max-w-160' offset={4} />
</div>
);
}

View File

@ -46,9 +46,9 @@ export function ViewHidden({ items }: ViewHiddenProps) {
return null;
}
return (
<div className='flex flex-col relative'>
<div className='grid relative'>
<MiniButton
className='absolute right-[calc(0.7rem-2px)] top-2 pointer-events-auto'
className='absolute right-[calc(0.75rem-2px)] top-2 pointer-events-auto'
noPadding
noHover
title={!isFolded ? 'Свернуть' : 'Развернуть'}
@ -56,7 +56,7 @@ export function ViewHidden({ items }: ViewHiddenProps) {
onClick={toggleFolded}
/>
<div className={clsx('pt-2 clr-input border-x pb-2', { 'border-b rounded-b-md': isFolded })}>
<div className={clsx('py-2 clr-input border-x', { 'border-b rounded-b-md': isFolded })}>
<div
className='w-fit select-none'
style={{
@ -73,7 +73,7 @@ export function ViewHidden({ items }: ViewHiddenProps) {
<div
tabIndex={-1}
className={clsx(
'flex flex-wrap justify-center gap-2 py-2 mt-[-0.5rem]',
'flex flex-wrap justify-center gap-2 py-2 -mt-2',
'text-sm',
'clr-input border-x border-b rounded-b-md',
'cc-scroll-y'
@ -94,7 +94,7 @@ export function ViewHidden({ items }: ViewHiddenProps) {
<button
key={`${prefixes.cst_hidden_list}${cst.alias}`}
type='button'
className='min-w-[3rem] rounded-md text-center select-none'
className='w-12 rounded-md text-center select-none'
style={{
backgroundColor: colorBgGraphNode(cst, coloring),
...(localSelected.includes(cstID)

View File

@ -31,7 +31,7 @@ export function ConstituentsSearch({ dense }: ConstituentsSearchProps) {
<SearchBar
id='constituents_search'
noBorder
className='min-w-[6rem] w-[6rem] mr-2 grow'
className='min-w-24 mr-2 grow'
query={query}
onChangeQuery={setQuery}
/>

View File

@ -46,18 +46,16 @@ export function SelectGraphFilter({ value, dense, className, onChange, ...restPr
const source = value as DependencyMode;
return (
<DropdownButton
className={!dense ? 'w-[18rem]' : undefined}
className={!dense ? 'w-72' : undefined}
key={`${prefixes.cst_source_list}${index}`}
onClick={() => handleChange(source)}
icon={<IconDependencyMode value={source} size='1rem' />}
>
<div className='inline-flex items-center gap-1'>
{<IconDependencyMode value={source} size='1rem' />}
{!dense ? (
<span>
<b>{labelCstSource(source)}:</b> {describeCstSource(source)}
</span>
) : null}
</div>
</DropdownButton>
);
})}

View File

@ -45,18 +45,16 @@ export function SelectMatchMode({ value, dense, className, onChange, ...restProp
const matchMode = value as CstMatchMode;
return (
<DropdownButton
className={!dense ? 'w-[20rem]' : undefined}
className={!dense ? 'w-80' : undefined}
key={`${prefixes.cst_source_list}${index}`}
onClick={() => handleChange(matchMode)}
icon={<IconCstMatchMode value={matchMode} size='1rem' />}
>
<div className='inline-flex items-center gap-1'>
{<IconCstMatchMode value={matchMode} size='1rem' />}
{!dense ? (
<span>
<b>{labelCstMatchMode(matchMode)}:</b> {describeCstMatchMode(matchMode)}
</span>
) : null}
</div>
</DropdownButton>
);
})}

View File

@ -51,9 +51,7 @@ export function TableSideConstituents({ autoScroll = true, maxHeight }: TableSid
header: () => <span className='pl-3'>Имя</span>,
size: 65,
minSize: 65,
cell: props => (
<BadgeConstituenta className='mr-[-0.5rem]' value={props.row.original} prefixID={prefixes.cst_side_table} />
)
cell: props => <BadgeConstituenta value={props.row.original} prefixID={prefixes.cst_side_table} />
}),
columnHelper.accessor(cst => describeConstituenta(cst), {
id: 'description',
@ -61,17 +59,7 @@ export function TableSideConstituents({ autoScroll = true, maxHeight }: TableSid
size: 1000,
minSize: 250,
maxSize: 1000,
cell: props => (
<TextContent
noTooltip
text={props.getValue()}
maxLength={DESCRIPTION_MAX_SYMBOLS}
style={{
textWrap: 'pretty',
fontSize: 12
}}
/>
)
cell: props => <TextContent noTooltip text={props.getValue()} maxLength={DESCRIPTION_MAX_SYMBOLS} />
})
];
@ -108,7 +96,7 @@ export function TableSideConstituents({ autoScroll = true, maxHeight }: TableSid
headPosition='0'
enableHiding
noDataComponent={
<NoData className='min-h-[5rem]'>
<NoData className='min-h-20'>
<p>Список конституент пуст</p>
<p>Измените параметры фильтра</p>
</NoData>

View File

@ -29,8 +29,8 @@ export function ViewConstituents({ isBottom, isMounted }: ViewConstituentsProps)
className={clsx(
'border', // prettier: split-lines
{
'mt-[2.2rem] rounded-l-md rounded-r-none h-fit overflow-visible': !isBottom,
'mt-3 mx-6 rounded-md md:max-w-[45.8rem] overflow-hidden': isBottom
'mt-9 rounded-l-md rounded-r-none h-fit overflow-visible': !isBottom,
'mt-3 mx-6 rounded-md overflow-hidden': isBottom
}
)}
style={{

View File

@ -29,15 +29,14 @@ export function TableUsers({ items, onDelete }: TableUsersProps) {
id: 'actions',
size: 0,
cell: props => (
<div className='h-[1.25rem] w-[1.25rem]'>
<MiniButton
title='Удалить из списка'
className='align-middle'
noHover
noPadding
icon={<IconRemove size='1.25rem' className='icon-red' />}
onClick={() => onDelete(props.row.original.id)}
/>
</div>
)
})
];

View File

@ -55,13 +55,16 @@ export function FormSignup() {
return (
<form
className='cc-column cc-fade-in mx-auto w-[36rem] px-6 py-3'
className='cc-column cc-fade-in mx-auto w-144 px-6 py-3'
onSubmit={event => void handleSubmit(onSubmit)(event)}
onChange={resetErrors}
>
<h1>Новый пользователь</h1>
<div className='flex gap-12'>
<div className='cc-column'>
<fieldset className='cc-column w-60'>
<legend className='sr-only'>Данные для входа</legend>
<TextInput
id='username'
{...register('username')}
@ -70,7 +73,6 @@ export function FormSignup() {
spellCheck={false}
pattern={patterns.login}
title='Минимум 3 знака. Латинские буквы и цифры. Не может начинаться с цифры'
className='w-[15rem]'
error={errors.username}
/>
<TextInput
@ -79,7 +81,6 @@ export function FormSignup() {
{...register('password')}
autoComplete='new-password'
label='Пароль'
className='w-[15rem]'
error={errors.password}
/>
<TextInput
@ -88,12 +89,13 @@ export function FormSignup() {
{...register('password2')}
label='Повторите пароль'
autoComplete='new-password'
className='w-[15rem]'
error={errors.password2}
/>
</div>
</fieldset>
<fieldset className='cc-column w-60 relative'>
<legend className='sr-only'>Информация о пользователе</legend>
<div className='cc-column w-[15rem] relative'>
<IconHelp id={globalIDs.email_tooltip} className='absolute top-0 right-0 icon-primary' size='1.25rem' />
<Tooltip anchorSelect={`#${globalIDs.email_tooltip}`} offset={6}>
электронная почта используется для восстановления пароля
@ -122,7 +124,7 @@ export function FormSignup() {
autoComplete='family-name'
error={errors.last_name}
/>
</div>
</fieldset>
</div>
<div className='flex gap-1 text-sm'>
@ -134,14 +136,14 @@ export function FormSignup() {
<TextURL text='правила поведения на Портале...' href={urls.help_topic(HelpTopic.INFO_RULES)} />
</div>
<div className='flex justify-around my-3'>
<div className='flex justify-around mt-3'>
<SubmitButton
text='Регистрировать'
className='min-w-[10rem]'
className='min-w-40'
loading={isPending}
disabled={!acceptPrivacy || !acceptRules}
/>
<Button text='Назад' className='min-w-[10rem]' onClick={() => handleCancel()} />
<Button text='Назад' className='min-w-40' onClick={() => handleCancel()} />
</div>
{serverError ? <ServerError error={serverError} /> : null}
</form>

View File

@ -2,7 +2,6 @@
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import clsx from 'clsx';
import { urls, useConceptNavigation } from '@/app';
import { type IChangePasswordDTO, schemaChangePassword } from '@/features/auth';
@ -36,7 +35,7 @@ export function EditorPassword() {
return (
<form
className={clsx('max-w-[16rem]', 'px-6 py-2 flex flex-col justify-between', 'border-l-2')}
className='max-w-64 px-6 py-2 flex flex-col justify-between border-l-2'
onSubmit={event => void handleSubmit(onSubmit)(event)}
onChange={resetErrors}
>

View File

@ -46,7 +46,7 @@ export function EditorProfile() {
return (
<form
className='cc-column w-[18rem] px-6 py-2'
className='cc-column w-72 px-6 py-2'
onSubmit={event => void handleSubmit(onSubmit)(event)}
onChange={resetErrors}
>

View File

@ -228,3 +228,28 @@
transition-timing-function: var(--transition-bezier);
transition-duration: var(--duration-select);
}
@utility cc-badge-constituenta {
width: 3rem;
padding-inline: 0.25rem;
border-width: 1px;
border-radius: 0.5rem;
text-align: center;
font-weight: 500;
white-space: nowrap;
}
@utility cc-table-header {
text-align: start;
padding: 0.5rem;
font-size: var(--text-xs);
line-height: var(--tw-leading, var(--text-xs--line-height));
font-weight: 500;
white-space: nowrap;
-webkit-user-select: none;
user-select: none;
}

View File

@ -33,7 +33,7 @@ export const PARAMETER = {
errorNodeLabel: '[ERROR]',
exteorVersion: '4.9.7',
TOOLTIP_WIDTH: 'max-w-[29rem]'
TOOLTIP_WIDTH: 'max-w-120'
};
/**