From f0715df343137ae3d7e7046d29d848581cc930b6 Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Wed, 16 Apr 2025 15:22:31 +0300 Subject: [PATCH] F: Improve color and animation styling --- .vscode/extensions.json | 2 +- README.md | 2 +- .../src/app/navigation/navigation.tsx | 2 +- .../src/components/data-table/data-table.tsx | 11 +- .../src/components/data-table/index.tsx | 9 +- .../data-table/pagination-tools.tsx | 31 ++--- .../data-table/select-pagination.tsx | 46 ++++++++ .../src/components/data-table/table-body.tsx | 101 +++++----------- .../components/data-table/table-header.tsx | 1 + .../src/components/data-table/table-row.tsx | 108 ++++++++++++++++++ .../components/data-table/use-data-table.ts | 5 +- rsconcept/frontend/src/components/icons.tsx | 4 +- rsconcept/frontend/src/components/loader.tsx | 10 +- .../src/components/tabs/tab-label.tsx | 2 +- .../features/help/components/badge-help.tsx | 2 +- .../features/help/items/ui/help-rseditor.tsx | 4 +- .../library/components/pick-schema.tsx | 3 +- .../library/components/select-location.tsx | 2 +- .../dlg-edit-versions/table-versions.tsx | 5 +- .../library-page/table-library-items.tsx | 5 +- .../rsform/components/badge-constituenta.tsx | 10 +- .../rsform/components/pick-constituenta.tsx | 3 +- .../rsform/components/pick-substitutions.tsx | 3 +- .../rsform/components/refs-input/tooltip.ts | 12 +- .../rsform/components/rs-input/tooltip.ts | 11 +- .../rsform/components/wordform-button.tsx | 2 +- .../dlg-cst-template/tab-arguments.tsx | 3 +- .../dialogs/dlg-show-ast/dlg-show-ast.tsx | 2 +- .../editor-rsexpression/status-bar.tsx | 2 +- .../table-side-constituents.tsx | 13 +-- rsconcept/frontend/src/index.css | 24 +++- rsconcept/frontend/src/styling/colors.ts | 1 - rsconcept/frontend/src/styling/components.css | 10 +- rsconcept/frontend/src/styling/constants.css | 46 +++++--- rsconcept/frontend/src/styling/overrides.css | 4 + rsconcept/frontend/src/styling/utilities.css | 26 ++++- 36 files changed, 333 insertions(+), 194 deletions(-) create mode 100644 rsconcept/frontend/src/components/data-table/select-pagination.tsx create mode 100644 rsconcept/frontend/src/components/data-table/table-row.tsx diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 22ecb699..fd3c82ac 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -6,11 +6,11 @@ "fractalbrew.backticks", "streetsidesoftware.code-spell-checker", "streetsidesoftware.code-spell-checker-russian", - "kamikillerto.vscode-colorize", "batisteo.vscode-django", "ms-azuretools.vscode-docker", "dbaeumer.vscode-eslint", "seyyedkhandon.firacode", + "nize.oklch-preview", "ms-python.isort", "ms-vscode.powershell", "esbenp.prettier-vscode", diff --git a/README.md b/README.md index 9ec7e816..58887332 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ This readme file is used mostly to document project dependencies and conventions VS Code plugins
   - ESLint
-  - Colorize
+  - Oklch Color Preview
   - Tailwind CSS IntelliSense
   - Code Spell Checker (eng + rus)
   - Backticks
diff --git a/rsconcept/frontend/src/app/navigation/navigation.tsx b/rsconcept/frontend/src/app/navigation/navigation.tsx
index 77d2bb11..7acb6a1d 100644
--- a/rsconcept/frontend/src/app/navigation/navigation.tsx
+++ b/rsconcept/frontend/src/app/navigation/navigation.tsx
@@ -34,7 +34,7 @@ export function Navigation() {
       
diff --git a/rsconcept/frontend/src/components/data-table/data-table.tsx b/rsconcept/frontend/src/components/data-table/data-table.tsx index a26c84a2..5653905f 100644 --- a/rsconcept/frontend/src/components/data-table/data-table.tsx +++ b/rsconcept/frontend/src/components/data-table/data-table.tsx @@ -19,19 +19,10 @@ import { PaginationTools } from './pagination-tools'; import { TableBody } from './table-body'; import { TableFooter } from './table-footer'; import { TableHeader } from './table-header'; -import { useDataTable } from './use-data-table'; +import { type IConditionalStyle, useDataTable } from './use-data-table'; export { createColumnHelper, type RowSelectionState, type VisibilityState }; -/** Style to conditionally apply to rows. */ -export interface IConditionalStyle { - /** Callback to determine if the style should be applied. */ - when: (rowData: TData) => boolean; - - /** Style to apply. */ - style: React.CSSProperties; -} - export interface DataTableProps extends Styling, Pick, 'data' | 'columns' | 'onRowSelectionChange' | 'onColumnVisibilityChange'> { diff --git a/rsconcept/frontend/src/components/data-table/index.tsx b/rsconcept/frontend/src/components/data-table/index.tsx index fc8bfb12..2e2d6fb0 100644 --- a/rsconcept/frontend/src/components/data-table/index.tsx +++ b/rsconcept/frontend/src/components/data-table/index.tsx @@ -1,7 +1,2 @@ -export { - createColumnHelper, - DataTable, - type IConditionalStyle, - type RowSelectionState, - type VisibilityState -} from './data-table'; +export { createColumnHelper, DataTable, type RowSelectionState, type VisibilityState } from './data-table'; +export { type IConditionalStyle } from './use-data-table'; diff --git a/rsconcept/frontend/src/components/data-table/pagination-tools.tsx b/rsconcept/frontend/src/components/data-table/pagination-tools.tsx index 58593661..3f0ee03b 100644 --- a/rsconcept/frontend/src/components/data-table/pagination-tools.tsx +++ b/rsconcept/frontend/src/components/data-table/pagination-tools.tsx @@ -1,13 +1,12 @@ 'use no memo'; 'use client'; -import { useCallback } from 'react'; import { type Table } from '@tanstack/react-table'; -import { prefixes } from '@/utils/constants'; - import { IconPageFirst, IconPageLast, IconPageLeft, IconPageRight } from '../icons'; +import { SelectPagination } from './select-pagination'; + interface PaginationToolsProps { id?: string; table: Table; @@ -21,15 +20,6 @@ export function PaginationTools({ onChangePaginationOption, paginationOptions }: PaginationToolsProps) { - const handlePaginationOptionsChange = useCallback( - (event: React.ChangeEvent) => { - const perPage = Number(event.target.value); - table.setPageSize(perPage); - onChangePaginationOption?.(perPage); - }, - [table, onChangePaginationOption] - ); - return (
@@ -93,19 +83,12 @@ export function PaginationTools({
- + table={table} + paginationOptions={paginationOptions} + onChange={onChangePaginationOption} + />
); } diff --git a/rsconcept/frontend/src/components/data-table/select-pagination.tsx b/rsconcept/frontend/src/components/data-table/select-pagination.tsx new file mode 100644 index 00000000..a304f1a9 --- /dev/null +++ b/rsconcept/frontend/src/components/data-table/select-pagination.tsx @@ -0,0 +1,46 @@ +'use no memo'; +'use client'; + +import { useCallback } from 'react'; +import { type Table } from '@tanstack/react-table'; + +import { prefixes } from '@/utils/constants'; + +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../input/select'; + +interface SelectPaginationProps { + id?: string; + table: Table; + paginationOptions: number[]; + onChange?: (newValue: number) => void; +} + +export function SelectPagination({ id, table, paginationOptions, onChange }: SelectPaginationProps) { + const handlePaginationOptionsChange = useCallback( + (newValue: string) => { + const perPage = Number(newValue); + table.setPageSize(perPage); + onChange?.(perPage); + }, + [table, onChange] + ); + + return ( + + ); +} diff --git a/rsconcept/frontend/src/components/data-table/table-body.tsx b/rsconcept/frontend/src/components/data-table/table-body.tsx index 72f1e43a..14b7a2c9 100644 --- a/rsconcept/frontend/src/components/data-table/table-body.tsx +++ b/rsconcept/frontend/src/components/data-table/table-body.tsx @@ -1,11 +1,11 @@ 'use no memo'; +'use client'; import { useCallback } from 'react'; -import { type Cell, flexRender, type Row, type Table } from '@tanstack/react-table'; -import clsx from 'clsx'; +import { type Row, type Table } from '@tanstack/react-table'; -import { SelectRow } from './select-row'; -import { type IConditionalStyle } from '.'; +import { TableRow } from './table-row'; +import { type IConditionalStyle } from './use-data-table'; interface TableBodyProps { table: Table; @@ -30,82 +30,43 @@ export function TableBody({ onRowClicked, onRowDoubleClicked }: TableBodyProps) { - const handleRowClicked = useCallback( - (target: Row, event: React.MouseEvent) => { - onRowClicked?.(target.original, event); - if (table.options.enableRowSelection && target.getCanSelect()) { - if (event.shiftKey && !!lastSelected && lastSelected !== target.id) { - const { rows, rowsById } = table.getRowModel(); - const lastIndex = rowsById[lastSelected].index; - const currentIndex = target.index; - const toggleRows = rows.slice( - lastIndex > currentIndex ? currentIndex : lastIndex + 1, - lastIndex > currentIndex ? lastIndex : currentIndex + 1 - ); - const newSelection: Record = {}; - toggleRows.forEach(row => { - newSelection[row.id] = !target.getIsSelected(); - }); - table.setRowSelection(prev => ({ ...prev, ...newSelection })); - onChangeLastSelected(null); - } else { - onChangeLastSelected(target.id); - target.toggleSelected(!target.getIsSelected()); - } - } - }, - [table, lastSelected, onChangeLastSelected, onRowClicked] + const getRowStyles = useCallback( + (row: Row) => + conditionalRowStyles + ?.filter(item => !!item.style && item.when(row.original)) + ?.reduce((prev, item) => ({ ...prev, ...item.style }), {}), + + [conditionalRowStyles] ); - const getRowStyles = useCallback( + const getRowClasses = useCallback( (row: Row) => { - return { - ...conditionalRowStyles! - .filter(item => item.when(row.original)) - .reduce((prev, item) => ({ ...prev, ...item.style }), {}) - }; + return conditionalRowStyles + ?.filter(item => !!item.className && item.when(row.original)) + ?.reduce((prev, item) => { + prev.push(item.className!); + return prev; + }, [] as string[]); }, [conditionalRowStyles] ); return ( - {table.getRowModel().rows.map((row: Row, index) => ( - ) => ( + handleRowClicked(row, event)} - onDoubleClick={event => onRowDoubleClicked?.(row.original, event)} - > - {table.options.enableRowSelection ? ( - - - - ) : null} - {row.getVisibleCells().map((cell: Cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - + table={table} + row={row} + className={getRowClasses(row)?.join(' ')} + style={conditionalRowStyles ? { ...getRowStyles(row) } : undefined} + noHeader={noHeader} + dense={dense} + lastSelected={lastSelected} + onChangeLastSelected={onChangeLastSelected} + onRowClicked={onRowClicked} + onRowDoubleClicked={onRowDoubleClicked} + /> ))} ); diff --git a/rsconcept/frontend/src/components/data-table/table-header.tsx b/rsconcept/frontend/src/components/data-table/table-header.tsx index 1f7396e7..bfa4e7ce 100644 --- a/rsconcept/frontend/src/components/data-table/table-header.tsx +++ b/rsconcept/frontend/src/components/data-table/table-header.tsx @@ -1,4 +1,5 @@ 'use no memo'; +'use client'; import { flexRender, type Header, type HeaderGroup, type Table } from '@tanstack/react-table'; import clsx from 'clsx'; diff --git a/rsconcept/frontend/src/components/data-table/table-row.tsx b/rsconcept/frontend/src/components/data-table/table-row.tsx new file mode 100644 index 00000000..347b9dad --- /dev/null +++ b/rsconcept/frontend/src/components/data-table/table-row.tsx @@ -0,0 +1,108 @@ +'use no memo'; + +import { useCallback } from 'react'; +import { type Cell, flexRender, type Row, type Table } from '@tanstack/react-table'; +import clsx from 'clsx'; + +import { cn } from '../utils'; + +import { SelectRow } from './select-row'; + +interface TableRowProps { + table: Table; + row: Row; + + className?: string; + style?: React.CSSProperties; + + noHeader?: boolean; + dense?: boolean; + + lastSelected: string | null; + onChangeLastSelected: (newValue: string | null) => void; + + onRowClicked?: (rowData: TData, event: React.MouseEvent) => void; + onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent) => void; +} + +export function TableRow({ + table, + row, + className, + style, + noHeader, + dense, + lastSelected, + onChangeLastSelected, + onRowClicked, + onRowDoubleClicked +}: TableRowProps) { + const hasBG = className?.includes('bg-') ?? false; + + const handleRowClicked = useCallback( + (target: Row, event: React.MouseEvent) => { + onRowClicked?.(target.original, event); + if (table.options.enableRowSelection && target.getCanSelect()) { + if (event.shiftKey && !!lastSelected && lastSelected !== target.id) { + const { rows, rowsById } = table.getRowModel(); + const lastIndex = rowsById[lastSelected].index; + const currentIndex = target.index; + const toggleRows = rows.slice( + lastIndex > currentIndex ? currentIndex : lastIndex + 1, + lastIndex > currentIndex ? lastIndex : currentIndex + 1 + ); + const newSelection: Record = {}; + toggleRows.forEach(row => { + newSelection[row.id] = !target.getIsSelected(); + }); + table.setRowSelection(prev => ({ ...prev, ...newSelection })); + onChangeLastSelected(null); + } else { + onChangeLastSelected(target.id); + target.toggleSelected(!target.getIsSelected()); + } + } + }, + [table, lastSelected, onChangeLastSelected, onRowClicked] + ); + + return ( + handleRowClicked(row, event)} + onDoubleClick={event => onRowDoubleClicked?.(row.original, event)} + > + {table.options.enableRowSelection ? ( + + + + ) : null} + {row.getVisibleCells().map((cell: Cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + ); +} diff --git a/rsconcept/frontend/src/components/data-table/use-data-table.ts b/rsconcept/frontend/src/components/data-table/use-data-table.ts index de43a338..8d1cc0d5 100644 --- a/rsconcept/frontend/src/components/data-table/use-data-table.ts +++ b/rsconcept/frontend/src/components/data-table/use-data-table.ts @@ -21,7 +21,10 @@ export interface IConditionalStyle { when: (rowData: TData) => boolean; /** Style to apply. */ - style: React.CSSProperties; + style?: React.CSSProperties; + + /** Classname to apply. */ + className?: string; } interface UseDataTableProps diff --git a/rsconcept/frontend/src/components/icons.tsx b/rsconcept/frontend/src/components/icons.tsx index 16def543..f3375f6f 100644 --- a/rsconcept/frontend/src/components/icons.tsx +++ b/rsconcept/frontend/src/components/icons.tsx @@ -200,7 +200,7 @@ export function IconLogin(props: IconProps) { export function CheckboxChecked() { return ( - + ); @@ -208,7 +208,7 @@ export function CheckboxChecked() { export function CheckboxNull() { return ( - + ); diff --git a/rsconcept/frontend/src/components/loader.tsx b/rsconcept/frontend/src/components/loader.tsx index 4b30c880..ed1e7853 100644 --- a/rsconcept/frontend/src/components/loader.tsx +++ b/rsconcept/frontend/src/components/loader.tsx @@ -1,7 +1,5 @@ 'use client'; -import { APP_COLORS } from '@/styling/colors'; - interface LoaderProps { /** Scale of the loader from 1 to 10. */ scale?: number; @@ -57,8 +55,8 @@ const animatePulse = (startBig: boolean, duration: string) => { export function Loader({ scale = 5, circular }: LoaderProps) { if (circular) { return ( -
- +
+ {animateRotation('2.25s')} @@ -73,8 +71,8 @@ export function Loader({ scale = 5, circular }: LoaderProps) { ); } else { return ( -
- +
+ {animatePulse(true, '0.8s')} diff --git a/rsconcept/frontend/src/components/tabs/tab-label.tsx b/rsconcept/frontend/src/components/tabs/tab-label.tsx index 0b303b68..e10a46b3 100644 --- a/rsconcept/frontend/src/components/tabs/tab-label.tsx +++ b/rsconcept/frontend/src/components/tabs/tab-label.tsx @@ -28,7 +28,7 @@ export function TabLabel({ className={clsx( 'min-w-20 h-full', 'px-2 py-1 flex justify-center', - 'cc-hover cc-animate-color duration-150', + 'cc-hover cc-animate-color duration-select', 'text-sm whitespace-nowrap font-controls', 'select-none hover:cursor-pointer', 'outline-hidden', diff --git a/rsconcept/frontend/src/features/help/components/badge-help.tsx b/rsconcept/frontend/src/features/help/components/badge-help.tsx index aa60f77b..9c4305b2 100644 --- a/rsconcept/frontend/src/features/help/components/badge-help.tsx +++ b/rsconcept/frontend/src/features/help/components/badge-help.tsx @@ -51,7 +51,7 @@ export function BadgeHelp({ topic, padding = 'p-1', className, contentClass, sty {...restProps} > }> -
event.stopPropagation()}> +
event.stopPropagation()}>
diff --git a/rsconcept/frontend/src/features/help/items/ui/help-rseditor.tsx b/rsconcept/frontend/src/features/help/items/ui/help-rseditor.tsx index ebd7af3c..8d92a3a2 100644 --- a/rsconcept/frontend/src/features/help/items/ui/help-rseditor.tsx +++ b/rsconcept/frontend/src/features/help/items/ui/help-rseditor.tsx @@ -71,12 +71,12 @@ export function HelpRSEditor() { текущая конституента
  • - + текущей
  • - + текущей
  • diff --git a/rsconcept/frontend/src/features/library/components/pick-schema.tsx b/rsconcept/frontend/src/features/library/components/pick-schema.tsx index f9fd9d58..2213c6b1 100644 --- a/rsconcept/frontend/src/features/library/components/pick-schema.tsx +++ b/rsconcept/frontend/src/features/library/components/pick-schema.tsx @@ -8,7 +8,6 @@ import { IconClose, IconFolderTree } from '@/components/icons'; import { SearchBar } from '@/components/input'; import { type Styling } from '@/components/props'; import { cn } from '@/components/utils'; -import { APP_COLORS } from '@/styling/colors'; import { prefixes } from '@/utils/constants'; import { type ILibraryItem, type LibraryItemType } from '../backend/types'; @@ -91,7 +90,7 @@ export function PickSchema({ const conditionalRowStyles: IConditionalStyle[] = [ { when: (item: ILibraryItem) => item.id === value, - style: { backgroundColor: APP_COLORS.bgSelected } + className: 'bg-selected' } ]; diff --git a/rsconcept/frontend/src/features/library/components/select-location.tsx b/rsconcept/frontend/src/features/library/components/select-location.tsx index 95ef148a..26c54f02 100644 --- a/rsconcept/frontend/src/features/library/components/select-location.tsx +++ b/rsconcept/frontend/src/features/library/components/select-location.tsx @@ -62,7 +62,7 @@ export function SelectLocation({ value, dense, prefix, onClick, className, style !dense && 'h-7 sm:h-8', 'pr-3 py-1 flex items-center gap-2', 'cc-scroll-row', - 'cc-hover cc-animate-color', + 'cc-hover cc-animate-color duration-fade', 'cursor-pointer', 'leading-3 sm:leading-4', activeNode === item && 'cc-selected' diff --git a/rsconcept/frontend/src/features/library/dialogs/dlg-edit-versions/table-versions.tsx b/rsconcept/frontend/src/features/library/dialogs/dlg-edit-versions/table-versions.tsx index bb0d7f22..88862c92 100644 --- a/rsconcept/frontend/src/features/library/dialogs/dlg-edit-versions/table-versions.tsx +++ b/rsconcept/frontend/src/features/library/dialogs/dlg-edit-versions/table-versions.tsx @@ -5,7 +5,6 @@ import { useIntl } from 'react-intl'; import { MiniButton } from '@/components/control'; import { createColumnHelper, DataTable, type IConditionalStyle } from '@/components/data-table'; import { IconRemove } from '@/components/icons'; -import { APP_COLORS } from '@/styling/colors'; import { type IVersionInfo } from '../../backend/types'; @@ -77,9 +76,7 @@ export function TableVersions({ processing, items, onDelete, selected, onSelect const conditionalRowStyles: IConditionalStyle[] = [ { when: (version: IVersionInfo) => version.id === selected, - style: { - backgroundColor: APP_COLORS.bgSelected - } + className: 'bg-selected' } ]; diff --git a/rsconcept/frontend/src/features/library/pages/library-page/table-library-items.tsx b/rsconcept/frontend/src/features/library/pages/library-page/table-library-items.tsx index 9d052d1d..b78fd48c 100644 --- a/rsconcept/frontend/src/features/library/pages/library-page/table-library-items.tsx +++ b/rsconcept/frontend/src/features/library/pages/library-page/table-library-items.tsx @@ -9,7 +9,6 @@ import { DataTable, type IConditionalStyle, type VisibilityState } from '@/compo import { useWindowSize } from '@/hooks/use-window-size'; import { useFitHeight } from '@/stores/app-layout'; import { usePreferencesStore } from '@/stores/preferences'; -import { APP_COLORS } from '@/styling/colors'; import { type ILibraryItem, LibraryItemType } from '../../backend/types'; import { useLibrarySearchStore } from '../../stores/library-search'; @@ -35,9 +34,7 @@ export function TableLibraryItems({ items }: TableLibraryItemsProps) { const conditionalRowStyles: IConditionalStyle[] = [ { when: (item: ILibraryItem) => item.item_type === LibraryItemType.OSS, - style: { - color: APP_COLORS.fgGreen - } + className: 'text-accent-green-foreground' } ]; const tableHeight = useFitHeight('2.25rem'); diff --git a/rsconcept/frontend/src/features/rsform/components/badge-constituenta.tsx b/rsconcept/frontend/src/features/rsform/components/badge-constituenta.tsx index b6f1fa07..be593edf 100644 --- a/rsconcept/frontend/src/features/rsform/components/badge-constituenta.tsx +++ b/rsconcept/frontend/src/features/rsform/components/badge-constituenta.tsx @@ -1,6 +1,5 @@ import clsx from 'clsx'; -import { APP_COLORS } from '@/styling/colors'; import { globalIDs } from '@/utils/constants'; import { colorFgCstStatus } from '../colors'; @@ -24,11 +23,14 @@ export function BadgeConstituenta({ value, prefixID }: BadgeConstituentaProps) { return (
    setActiveCst(value)} diff --git a/rsconcept/frontend/src/features/rsform/components/pick-constituenta.tsx b/rsconcept/frontend/src/features/rsform/components/pick-constituenta.tsx index 37af849c..45ebb4d9 100644 --- a/rsconcept/frontend/src/features/rsform/components/pick-constituenta.tsx +++ b/rsconcept/frontend/src/features/rsform/components/pick-constituenta.tsx @@ -7,7 +7,6 @@ import { SearchBar } from '@/components/input'; import { type Styling } from '@/components/props'; import { cn } from '@/components/utils'; import { NoData } from '@/components/view'; -import { APP_COLORS } from '@/styling/colors'; import { describeConstituenta } from '../labels'; import { type IConstituenta } from '../models/rsform'; @@ -68,7 +67,7 @@ export function PickConstituenta({ const conditionalRowStyles: IConditionalStyle[] = [ { when: (cst: IConstituenta) => cst.id === value?.id, - style: { backgroundColor: APP_COLORS.bgSelected } + className: 'bg-selected' } ]; diff --git a/rsconcept/frontend/src/features/rsform/components/pick-substitutions.tsx b/rsconcept/frontend/src/features/rsform/components/pick-substitutions.tsx index 1fe2e070..c465abf6 100644 --- a/rsconcept/frontend/src/features/rsform/components/pick-substitutions.tsx +++ b/rsconcept/frontend/src/features/rsform/components/pick-substitutions.tsx @@ -12,7 +12,6 @@ import { IconAccept, IconPageLeft, IconPageRight, IconRemove, IconReplace } from import { type Styling } from '@/components/props'; import { cn } from '@/components/utils'; import { NoData } from '@/components/view'; -import { APP_COLORS } from '@/styling/colors'; import { errorMsg } from '@/utils/labels'; import { type ICstSubstitute } from '../backend/types'; @@ -224,7 +223,7 @@ export function PickSubstitutions({ const conditionalRowStyles: IConditionalStyle[] = [ { when: (item: IMultiSubstitution) => item.is_suggestion, - style: { backgroundColor: APP_COLORS.bgOrange50 } + className: 'bg-accent-orange50' } ]; diff --git a/rsconcept/frontend/src/features/rsform/components/refs-input/tooltip.ts b/rsconcept/frontend/src/features/rsform/components/refs-input/tooltip.ts index 81b957eb..60be00dd 100644 --- a/rsconcept/frontend/src/features/rsform/components/refs-input/tooltip.ts +++ b/rsconcept/frontend/src/features/rsform/components/refs-input/tooltip.ts @@ -3,7 +3,6 @@ import { type Extension } from '@codemirror/state'; import { hoverTooltip, type TooltipView } from '@codemirror/view'; import clsx from 'clsx'; -import { APP_COLORS } from '@/styling/colors'; import { findContainedNodes } from '@/utils/codemirror'; import { describeConstituentaTerm, labelGrammeme } from '../../labels'; @@ -67,9 +66,9 @@ function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | n 'max-h-100 max-w-100 min-w-40', 'dense', 'p-2 flex flex-col', - 'border shadow-md', + 'rounded-md shadow-md', 'cc-scroll-y', - 'text-sm', + 'text-sm bg-card', 'select-none cursor-auto' ); @@ -86,9 +85,8 @@ function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | n parseGrammemes(ref.form).forEach(gramStr => { const gram = document.createElement('div'); gram.id = `tooltip-${gramStr}`; - gram.className = 'min-w-12 px-1 border rounded-lg text-sm text-center whitespace-nowrap'; + gram.className = 'min-w-12 px-1 border rounded-lg text-sm text-center whitespace-nowrap bg-accent'; gram.style.borderWidth = '1px'; - gram.style.backgroundColor = APP_COLORS.bgInput; gram.innerText = labelGrammeme(gramStr); grams.appendChild(gram); }); @@ -117,9 +115,9 @@ function domTooltipSyntacticReference( 'max-h-100 max-w-100 min-w-40', 'dense', 'p-2 flex flex-col', - 'border shadow-md', + 'rounded-md shadow-md', 'cc-scroll-y', - 'text-sm', + 'text-sm bg-card', 'select-none cursor-auto' ); diff --git a/rsconcept/frontend/src/features/rsform/components/rs-input/tooltip.ts b/rsconcept/frontend/src/features/rsform/components/rs-input/tooltip.ts index c43e9ead..21b03f2a 100644 --- a/rsconcept/frontend/src/features/rsform/components/rs-input/tooltip.ts +++ b/rsconcept/frontend/src/features/rsform/components/rs-input/tooltip.ts @@ -1,5 +1,6 @@ import { type Extension } from '@codemirror/state'; import { hoverTooltip, type TooltipView } from '@codemirror/view'; +import clsx from 'clsx'; import { labelCstTypification } from '../../labels'; import { type IConstituenta, type IRSForm } from '../../models/rsform'; @@ -32,7 +33,15 @@ export function rsHoverTooltip(schema: IRSForm, canClick?: boolean): Extension { */ function domTooltipConstituenta(cst?: IConstituenta, canClick?: boolean): TooltipView { const dom = document.createElement('div'); - dom.className = 'max-h-100 max-w-100 min-w-40 dense p-2 border shadow-md cc-scroll-y text-sm font-main'; + dom.className = clsx( + 'max-h-100 max-w-100 min-w-40', + 'dense', + 'p-2', + 'rounded-md shadow-md', + 'cc-scroll-y', + 'text-sm font-main bg-card', + 'select-none cursor-auto' + ); if (!cst) { const text = document.createElement('p'); diff --git a/rsconcept/frontend/src/features/rsform/components/wordform-button.tsx b/rsconcept/frontend/src/features/rsform/components/wordform-button.tsx index 51909f5e..03a2d7ae 100644 --- a/rsconcept/frontend/src/features/rsform/components/wordform-button.tsx +++ b/rsconcept/frontend/src/features/rsform/components/wordform-button.tsx @@ -21,7 +21,7 @@ export function WordformButton({ text, example, grams, onSelectGrams, isSelected 'p-1', 'border rounded-none', 'cursor-pointer', - 'cc-controls cc-hover cc-animate-color', + 'cc-controls hover:bg-accent hover:text-foreground cc-animate-color', isSelected && 'cc-selected' )} {...restProps} diff --git a/rsconcept/frontend/src/features/rsform/dialogs/dlg-cst-template/tab-arguments.tsx b/rsconcept/frontend/src/features/rsform/dialogs/dlg-cst-template/tab-arguments.tsx index 533fbe5f..e04b1404 100644 --- a/rsconcept/frontend/src/features/rsform/dialogs/dlg-cst-template/tab-arguments.tsx +++ b/rsconcept/frontend/src/features/rsform/dialogs/dlg-cst-template/tab-arguments.tsx @@ -9,7 +9,6 @@ import { DataTable, type IConditionalStyle } from '@/components/data-table'; import { IconAccept, IconRemove, IconReset } from '@/components/icons'; import { NoData } from '@/components/view'; import { useDialogsStore } from '@/stores/dialogs'; -import { APP_COLORS } from '@/styling/colors'; import { type ICstCreateDTO } from '../../backend/types'; import { PickConstituenta } from '../../components/pick-constituenta'; @@ -100,7 +99,7 @@ export function TabArguments() { const conditionalRowStyles: IConditionalStyle[] = [ { when: (arg: IArgumentValue) => arg.alias === selectedArgument?.alias, - style: { backgroundColor: APP_COLORS.bgSelected } + className: 'bg-selected' } ]; diff --git a/rsconcept/frontend/src/features/rsform/dialogs/dlg-show-ast/dlg-show-ast.tsx b/rsconcept/frontend/src/features/rsform/dialogs/dlg-show-ast/dlg-show-ast.tsx index 26036d0a..d38d6ea1 100644 --- a/rsconcept/frontend/src/features/rsform/dialogs/dlg-show-ast/dlg-show-ast.tsx +++ b/rsconcept/frontend/src/features/rsform/dialogs/dlg-show-ast/dlg-show-ast.tsx @@ -47,7 +47,7 @@ export function DlgShowAST() { {!isDragging && hoverNodeDebounced ? (
    {expression.slice(0, hoverNodeDebounced.start)} - + {expression.slice(hoverNodeDebounced.start, hoverNodeDebounced.finish)} {expression.slice(hoverNodeDebounced.finish)} diff --git a/rsconcept/frontend/src/features/rsform/pages/rsform-page/editor-rsexpression/status-bar.tsx b/rsconcept/frontend/src/features/rsform/pages/rsform-page/editor-rsexpression/status-bar.tsx index 0d2ee8c8..51bf981c 100644 --- a/rsconcept/frontend/src/features/rsform/pages/rsform-page/editor-rsexpression/status-bar.tsx +++ b/rsconcept/frontend/src/features/rsform/pages/rsform-page/editor-rsexpression/status-bar.tsx @@ -49,7 +49,7 @@ export function StatusBar({ className, isModified, processing, activeCst, parseD 'select-none', 'cursor-pointer', 'focus-frame outline-none', - 'transition-colors duration-500' + 'transition-colors duration-fade' )} style={{ backgroundColor: processing ? APP_COLORS.bgDefault : colorStatusBar(status) }} data-tooltip-id={globalIDs.tooltip} diff --git a/rsconcept/frontend/src/features/rsform/pages/rsform-page/view-constituents/table-side-constituents.tsx b/rsconcept/frontend/src/features/rsform/pages/rsform-page/view-constituents/table-side-constituents.tsx index 3dcf40d6..b0d31163 100644 --- a/rsconcept/frontend/src/features/rsform/pages/rsform-page/view-constituents/table-side-constituents.tsx +++ b/rsconcept/frontend/src/features/rsform/pages/rsform-page/view-constituents/table-side-constituents.tsx @@ -4,7 +4,6 @@ import { useEffect } from 'react'; import { createColumnHelper, DataTable, type IConditionalStyle } from '@/components/data-table'; import { NoData, TextContent } from '@/components/view'; -import { APP_COLORS } from '@/styling/colors'; import { PARAMETER, prefixes } from '@/utils/constants'; import { BadgeConstituenta } from '../../../components/badge-constituenta'; @@ -66,21 +65,15 @@ export function TableSideConstituents({ autoScroll = true, maxHeight }: TableSid const conditionalRowStyles: IConditionalStyle[] = [ { when: (cst: IConstituenta) => !!activeCst && cst.id === activeCst.id, - style: { - backgroundColor: APP_COLORS.bgSelected - } + className: 'bg-selected' }, { when: (cst: IConstituenta) => !!activeCst && cst.spawner === activeCst.id && cst.id !== activeCst.id, - style: { - backgroundColor: APP_COLORS.bgOrange50 - } + className: 'bg-accent-orange50' }, { when: (cst: IConstituenta) => !!activeCst && cst.spawn.includes(activeCst.id), - style: { - backgroundColor: APP_COLORS.bgGreen50 - } + className: 'bg-accent-green50' } ]; diff --git a/rsconcept/frontend/src/index.css b/rsconcept/frontend/src/index.css index 5bc6429c..36bd8f24 100644 --- a/rsconcept/frontend/src/index.css +++ b/rsconcept/frontend/src/index.css @@ -45,6 +45,23 @@ --color-sec-400: var(--clr-sec-400); --color-sec-600: var(--clr-sec-600); + --color-accent-red: var(--acc-bg-red); + --color-accent-green: var(--acc-bg-green); + --color-accent-green25: var(--acc-bg-green25); + --color-accent-green50: var(--acc-bg-green50); + --color-accent-blue: var(--acc-bg-blue); + --color-accent-purple: var(--acc-bg-purple); + --color-accent-teal: var(--acc-bg-teal); + --color-accent-orange: var(--acc-bg-orange); + --color-accent-orange50: var(--acc-bg-orange50); + + --color-accent-red-foreground: var(--acc-fg-red); + --color-accent-green-foreground: var(--acc-fg-green); + --color-accent-blue-foreground: var(--acc-fg-blue); + --color-accent-purple-foreground: var(--acc-fg-purple); + --color-accent-teal-foreground: var(--acc-fg-teal); + --color-accent-orange-foreground: var(--acc-fg-orange); + /* stylelint-disable-next-line custom-property-pattern */ --z-index-*: initial; --z-index-bottom: 0; @@ -66,11 +83,12 @@ --ease-bezier: cubic-bezier(0.4, 0, 0.2, 1); - --duration-move: 500ms; + /* Animation durations */ + --duration-select: 100ms; + --duration-dropdown: 200ms; --duration-modal: 300ms; --duration-fade: 300ms; - --duration-dropdown: 200ms; - --duration-select: 100ms; + --duration-move: 500ms; /* ========= shadcn theme ============ */ diff --git a/rsconcept/frontend/src/styling/colors.ts b/rsconcept/frontend/src/styling/colors.ts index b0d6b59e..8f7d5c00 100644 --- a/rsconcept/frontend/src/styling/colors.ts +++ b/rsconcept/frontend/src/styling/colors.ts @@ -29,7 +29,6 @@ export const APP_COLORS = { bgGreen25: 'var(--acc-bg-green25)', bgGreen50: 'var(--acc-bg-green50)', - bgOrange50: 'var(--acc-bg-orange50)', fgRed: 'var(--acc-fg-red)', fgGreen: 'var(--acc-fg-green)', diff --git a/rsconcept/frontend/src/styling/components.css b/rsconcept/frontend/src/styling/components.css index 7ab1ea9a..f9cc48bb 100644 --- a/rsconcept/frontend/src/styling/components.css +++ b/rsconcept/frontend/src/styling/components.css @@ -9,13 +9,21 @@ cursor: pointer; white-space: nowrap; - transition-property: background-color; + transition-property: background-color, color; transition-timing-function: var(--ease-bezier); transition-duration: 500ms; &:hover { background-color: var(--color-accent); } + + .dark & { + color: color-mix(in oklab, var(--color-foreground) 70%, transparent); + + &:hover { + color: var(--color-foreground); + } + } } @utility cc-btn-primary { diff --git a/rsconcept/frontend/src/styling/constants.css b/rsconcept/frontend/src/styling/constants.css index 62ad0632..fb5e97be 100644 --- a/rsconcept/frontend/src/styling/constants.css +++ b/rsconcept/frontend/src/styling/constants.css @@ -28,10 +28,10 @@ --clr-prim-999: oklch(000% 0 0deg); --clr-sec-0: oklch(100% 0 0deg); - --clr-sec-100: oklch(095% 0.050 262deg); - --clr-sec-200: oklch(088% 0.050 262deg); - --clr-sec-400: oklch(075% 0.150 262deg); - --clr-sec-600: oklch(060% 0.250 262deg); + --clr-sec-100: oklch(095% 0.025 262deg); + --clr-sec-200: oklch(090% 0.050 262deg); + --clr-sec-400: oklch(073% 0.140 262deg); + --clr-sec-600: oklch(060% 0.230 262deg); --clr-warn-600: oklch(060% 0.250 27deg); --clr-ok-600: oklch(060% 0.250 138deg); @@ -39,23 +39,27 @@ --clr-select-node: oklch(080% 0.250 180deg); /* Highlight accents */ - --acc-bg-red: oklch(085% 0.150 27deg); + --acc-bg-red: oklch(083% 0.120 27deg); --acc-bg-green: oklch(085% 0.150 138deg); --acc-bg-blue: oklch(085% 0.150 262deg); --acc-bg-purple: oklch(085% 0.200 295deg); - --acc-bg-teal: oklch(085% 0.200 210deg); - --acc-bg-orange: oklch(085% 0.150 62deg); + --acc-bg-teal: oklch(082% 0.180 210deg); + --acc-bg-orange: oklch(085% 0.130 62deg); - --acc-bg-green25: oklch(097% 0.150 138deg); - --acc-bg-green50: oklch(090% 0.150 138deg); + --acc-bg-green25: oklch(097% 0.080 138deg); + --acc-bg-green50: oklch(092% 0.150 138deg); --acc-bg-orange50: oklch(090% 0.044 62deg); --acc-fg-red: oklch(060% 0.220 27deg); - --acc-fg-green: oklch(060% 0.250 138deg); - --acc-fg-blue: oklch(060% 0.300 262deg); + --acc-fg-green: oklch(060% 0.220 138deg); + --acc-fg-blue: oklch(060% 0.230 262deg); --acc-fg-purple: oklch(060% 0.250 295deg); - --acc-fg-teal: oklch(060% 0.150 210deg); + --acc-fg-teal: oklch(060% 0.140 210deg); --acc-fg-orange: oklch(060% 0.150 62deg); + + /* React Tooltip */ + --rt-color-white: var(--clr-prim-0); + --rt-color-dark: var(--clr-prim-999); } /* Dark Theme */ @@ -69,15 +73,15 @@ --clr-prim-999: oklch(095% 0 0deg); --clr-sec-0: oklch(100% 0 0deg); - --clr-sec-100: oklch(025% 0.200 295deg); - --clr-sec-200: oklch(035% 0.150 295deg); + --clr-sec-100: oklch(030% 0.075 70deg); + --clr-sec-200: oklch(040% 0.150 295deg); --clr-sec-400: oklch(055% 0.200 295deg); - --clr-sec-600: oklch(070% 0.250 295deg); + --clr-sec-600: oklch(070% 0.170 295deg); --clr-warn-600: oklch(065% 0.200 27deg); --clr-ok-600: oklch(065% 0.200 138deg); - --clr-select-node: oklch(070% 0.250 180deg); + --clr-select-node: oklch(070% 0.160 180deg); /* Highlight accents */ --acc-bg-red: oklch(050% 0.150 27deg); @@ -91,10 +95,14 @@ --acc-bg-green50: oklch(038% 0.200 138deg); --acc-bg-orange50: oklch(038% 0.075 62deg); - --acc-fg-red: oklch(075% 0.200 27deg); + --acc-fg-red: oklch(073% 0.200 27deg); --acc-fg-green: oklch(075% 0.150 138deg); - --acc-fg-blue: oklch(075% 0.150 262deg); - --acc-fg-purple: oklch(075% 0.250 295deg); + --acc-fg-blue: oklch(075% 0.135 262deg); + --acc-fg-purple: oklch(075% 0.150 295deg); --acc-fg-teal: oklch(075% 0.150 210deg); --acc-fg-orange: oklch(075% 0.150 62deg); + + /* React Tooltip */ + --rt-color-white: var(--clr-prim-999); + --rt-color-dark: var(--clr-prim-0); } diff --git a/rsconcept/frontend/src/styling/overrides.css b/rsconcept/frontend/src/styling/overrides.css index f6e6b33b..8ee2072d 100644 --- a/rsconcept/frontend/src/styling/overrides.css +++ b/rsconcept/frontend/src/styling/overrides.css @@ -19,6 +19,10 @@ .cm-tooltip { z-index: 100; + + border-color: var(--clr-prim-400); + border-width: 1px; + border-radius: 0.25rem; } .cm-selectionBackground { diff --git a/rsconcept/frontend/src/styling/utilities.css b/rsconcept/frontend/src/styling/utilities.css index 3d64549b..d5e83cba 100644 --- a/rsconcept/frontend/src/styling/utilities.css +++ b/rsconcept/frontend/src/styling/utilities.css @@ -22,7 +22,6 @@ @utility cc-hover { &:hover:not(:disabled) { - color: var(--color-accent-foreground); background-color: var(--color-accent); } } @@ -181,3 +180,28 @@ mask-composite: intersect; } + +@utility duration-select { + --tw-duration: var(--duration-select); + transition-duration: var(--duration-select); +} + +@utility duration-dropdown { + --tw-duration: var(--duration-dropdown); + transition-duration: var(--duration-dropdown); +} + +@utility duration-modal { + --tw-duration: var(--duration-modal); + transition-duration: var(--duration-modal); +} + +@utility duration-fade { + --tw-duration: var(--duration-fade); + transition-duration: var(--duration-fade); +} + +@utility duration-move { + --tw-duration: var(--duration-move); + transition-duration: var(--duration-move); +}