diff --git a/server/bundles/io.cloudbeaver.resources.drivers.base/plugin.xml b/server/bundles/io.cloudbeaver.resources.drivers.base/plugin.xml
index aa00541b0d..37808a0eeb 100644
--- a/server/bundles/io.cloudbeaver.resources.drivers.base/plugin.xml
+++ b/server/bundles/io.cloudbeaver.resources.drivers.base/plugin.xml
@@ -36,7 +36,7 @@
-
+
diff --git a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/session/WebSessionTest.java b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/session/WebSessionTest.java
index 4de3577d39..5c8aff73e7 100644
--- a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/session/WebSessionTest.java
+++ b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/session/WebSessionTest.java
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
- * Copyright (C) 2010-2025 DBeaver Corp and others
+ * Copyright (C) 2010-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,12 +62,15 @@ public class WebSessionTest extends CloudbeaverMockTest {
String created = session.getAttribute("createdKey", creator, disposer);
Assert.assertEquals("created", created);
- // After close() non-persistent attribute should be disposed; persistent remain
- session.close();
-
- Assert.assertTrue("disposer must be invoked during close()", disposed.get());
// persistent attribute should still be available
Assert.assertEquals("persistValue", session.getAttribute("persistentKey"));
+
+ session.close();
+
+ // persistent attribute should иу тгдд
+ Assert.assertNull("persistValue", session.getAttribute("persistentKey"));
+
+ Assert.assertTrue("disposer must be invoked during close()", disposed.get());
}
@Test
diff --git a/webapp/packages/core-blocks/src/Button.css b/webapp/packages/core-blocks/src/Button.css
index 803c66f177..013e968c72 100644
--- a/webapp/packages/core-blocks/src/Button.css
+++ b/webapp/packages/core-blocks/src/Button.css
@@ -42,10 +42,6 @@
min-width: 64px;
- font-family: Roboto, sans-serif;
- -moz-osx-font-smoothing: grayscale;
- -webkit-font-smoothing: antialiased;
-
font-weight: 500;
letter-spacing: 0.0892857143em;
text-decoration: none;
diff --git a/webapp/packages/core-blocks/src/Button.tsx b/webapp/packages/core-blocks/src/Button.tsx
index 546a889000..ebf17c2921 100644
--- a/webapp/packages/core-blocks/src/Button.tsx
+++ b/webapp/packages/core-blocks/src/Button.tsx
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2025 DBeaver Corp and others
+ * Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -8,7 +8,7 @@
import { createElement } from 'react';
import { observable } from 'mobx';
import { observer } from 'mobx-react-lite';
-import { Button as UIKitButton, ButtonIcon } from '@dbeaver/ui-kit';
+import { Button as UIKitButton, ButtonIcon, clsx } from '@dbeaver/ui-kit';
import { IconOrImage } from './IconOrImage.js';
import { useObjectRef } from './useObjectRef.js';
@@ -19,20 +19,20 @@ import './Button.css';
export type ButtonProps = (React.ButtonHTMLAttributes &
React.LinkHTMLAttributes &
React.HTMLAttributes) & {
- loading?: boolean;
- icon?: string;
- viewBox?: string;
- iconPlacement?: 'start' | 'end';
- iconSize?: number;
- variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
- size?: 'small' | 'medium' | 'large';
- tag?: 'button' | 'a' | 'div';
- href?: string;
- target?: '_blank' | '_self' | '_parent' | '_top';
- loader?: boolean;
- onClick?: React.MouseEventHandler | (() => Promise);
- download?: boolean;
- };
+ loading?: boolean;
+ icon?: string;
+ viewBox?: string;
+ iconPlacement?: 'start' | 'end';
+ iconSize?: number;
+ variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
+ size?: 'small' | 'medium' | 'large';
+ tag?: 'button' | 'a' | 'div';
+ href?: string;
+ target?: '_blank' | '_self' | '_parent' | '_top';
+ loader?: boolean;
+ onClick?: React.MouseEventHandler | (() => Promise);
+ download?: boolean;
+};
export const Button = observer(function Button({
children,
@@ -81,7 +81,15 @@ export const Button = observer(function Button({
const Tag = createElement(tag);
return (
-
+
{icon && (
diff --git a/webapp/packages/core-blocks/src/CommonDialog/CommonDialog/CommonDialogWrapper.module.css b/webapp/packages/core-blocks/src/CommonDialog/CommonDialog/CommonDialogWrapper.module.css
index 71c7abd8f4..f7e1c8762c 100644
--- a/webapp/packages/core-blocks/src/CommonDialog/CommonDialog/CommonDialogWrapper.module.css
+++ b/webapp/packages/core-blocks/src/CommonDialog/CommonDialog/CommonDialogWrapper.module.css
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
.dialog {
- composes: theme-background-surface theme-text-on-surface theme-elevation-z10 from global;
+ composes: theme-background-surface theme-text-on-surface from global;
&.fixedSize[data-size='small'] {
width: 404px;
diff --git a/webapp/packages/core-blocks/src/CommonDialog/CommonDialog/CommonDialogWrapper.tsx b/webapp/packages/core-blocks/src/CommonDialog/CommonDialog/CommonDialogWrapper.tsx
index 5d94bdeb7f..6a0f6e2e02 100644
--- a/webapp/packages/core-blocks/src/CommonDialog/CommonDialog/CommonDialogWrapper.tsx
+++ b/webapp/packages/core-blocks/src/CommonDialog/CommonDialog/CommonDialogWrapper.tsx
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2025 DBeaver Corp and others
+ * Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@ export const CommonDialogWrapper = observer | null | undefined}
diff --git a/webapp/packages/core-blocks/src/CommonDialog/DialogsPortal.module.css b/webapp/packages/core-blocks/src/CommonDialog/DialogsPortal.module.css
index 9f99726b35..65ed3c6269 100644
--- a/webapp/packages/core-blocks/src/CommonDialog/DialogsPortal.module.css
+++ b/webapp/packages/core-blocks/src/CommonDialog/DialogsPortal.module.css
@@ -10,7 +10,7 @@
}
.error {
- composes: theme-background-surface theme-text-on-surface theme-elevation-z10 from global;
+ composes: theme-background-surface theme-text-on-surface from global;
border-radius: 0.25rem;
}
diff --git a/webapp/packages/core-blocks/src/CommonDialog/DialogsPortal.tsx b/webapp/packages/core-blocks/src/CommonDialog/DialogsPortal.tsx
index 6b6c8aa1df..be30b18dbb 100644
--- a/webapp/packages/core-blocks/src/CommonDialog/DialogsPortal.tsx
+++ b/webapp/packages/core-blocks/src/CommonDialog/DialogsPortal.tsx
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2025 DBeaver Corp and others
+ * Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -87,7 +87,7 @@ const NestedDialog: React.FC = function NestedDialog({ dialog,
return (
-
+
* {
overflow: hidden;
@@ -36,7 +36,7 @@
opacity: 0.5;
width: var(--dbv-kit-disclosure-icon-size);
height: var(--dbv-kit-disclosure-icon-size);
- transition: transform 150ms ease-in-out;
+ transition: transform var(--duration-medium) var(--ease-smooth);
transform-origin: center;
transform: rotate(-90deg);
}
diff --git a/webapp/packages/core-blocks/src/FormControls/BaseDropdown.module.css b/webapp/packages/core-blocks/src/FormControls/BaseDropdown.module.css
index b1d974bf89..600b6fa06a 100644
--- a/webapp/packages/core-blocks/src/FormControls/BaseDropdown.module.css
+++ b/webapp/packages/core-blocks/src/FormControls/BaseDropdown.module.css
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
.menu {
- composes: theme-text-on-surface theme-background-surface theme-typography--caption theme-elevation-z3 from global;
+ composes: theme-text-on-surface theme-background-surface theme-typography--caption from global;
display: flex;
flex-direction: column;
max-height: 300px;
diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.module.css b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.module.css
index b5c58838b4..b782d4bdcd 100644
--- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.module.css
+++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.module.css
@@ -5,6 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
+
@layer components {
.field {
--dbv-kit-control-outline-offset: -8px;
@@ -41,34 +42,118 @@
border-width: var(--dbv-kit-control-outline-width);
}
}
-}
-.switchControl {
- composes: theme-switch from global;
-}
+ .switchControl {
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ width: 36px;
+ height: 20px;
+ vertical-align: middle;
+ outline: none;
+ flex-shrink: 0;
-.disabled {
- composes: theme-switch--disabled mdc-switch--disabled from global;
-}
+ &:not(.disabled):hover .switchControlThumb {
+ box-shadow:
+ 0px 3px 1px -2px rgba(0, 0, 0, 0.2),
+ 0px 2px 2px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 5px 0px rgba(0, 0, 0, 0.12),
+ 0px 0px 0px 8px color-mix(in srgb, var(--theme-on-surface) 4%, transparent);
+ }
-.checked {
- composes: theme-switch--checked mdc-switch--checked from global;
-}
+ &:not(.disabled):has(.switchInput:focus-visible) .switchControlThumb {
+ box-shadow:
+ 0px 3px 1px -2px rgba(0, 0, 0, 0.2),
+ 0px 2px 2px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 5px 0px rgba(0, 0, 0, 0.12),
+ 0px 0px 0px 12px color-mix(in srgb, var(--theme-on-surface) 8%, transparent);
+ }
+ }
-.switchControlTrack {
- composes: theme-switch__track from global;
-}
+ .switchInput {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ cursor: pointer;
+ margin: 0;
+ padding: 0;
+ z-index: 2;
-.switchInput {
- composes: theme-switch_native-control from global;
-}
+ &:disabled {
+ cursor: default;
+ pointer-events: none;
+ }
+ }
-.switchControlUnderlay {
- composes: theme-switch__thumb-underlay from global;
-}
+ .switchControlTrack {
+ box-sizing: border-box;
+ position: absolute;
+ top: 50%;
+ left: 0;
+ transform: translateY(-50%);
+ width: 100%;
+ height: 14px;
+ border: 1px solid var(--theme-on-surface, #000);
+ border-radius: 7px;
+ background-color: var(--theme-on-surface, #000);
+ opacity: 0.38;
+ border: none;
+ transition:
+ background-color var(--duration-fast) var(--ease-smooth-start),
+ border-color var(--duration-fast) var(--ease-smooth-start),
+ opacity var(--duration-fast) var(--ease-smooth-start);
+ }
-.switchControlThumb {
- composes: theme-switch__thumb from global;
+ .switchControlUnderlay {
+ margin-left: -2px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: margin-left var(--duration-fast) var(--ease-smooth-start);
+ }
+
+ .switchControlThumb {
+ box-sizing: border-box;
+ width: 20px;
+ height: 20px;
+ border: 10px solid var(--theme-switch-thumb, #fff);
+ border-radius: 50%;
+ background-color: var(--theme-surface, #fff);
+ box-shadow:
+ 0px 3px 1px -2px rgba(0, 0, 0, 0.2),
+ 0px 2px 2px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
+ pointer-events: none;
+ z-index: 1;
+ transition:
+ background-color var(--duration-fast) var(--ease-smooth-start),
+ border-color var(--duration-fast) var(--ease-smooth-start);
+ }
+
+ .checked {
+ & .switchControlTrack {
+ background-color: color-mix(in srgb, var(--theme-primary, #2a7cb4) 50%, transparent);
+ border-color: color-mix(in srgb, var(--theme-primary, #2a7cb4) 50%, transparent);
+ opacity: 1;
+ }
+
+ & .switchControlUnderlay {
+ margin-left: 18px;
+ }
+
+ & .switchControlThumb {
+ background-color: var(--theme-primary, #2a7cb4);
+ border-color: var(--theme-primary, #2a7cb4);
+ }
+ }
+
+ .disabled {
+ opacity: 0.38;
+ pointer-events: none;
+ }
}
.switchBody {
diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/SwitchDense.module.css b/webapp/packages/core-blocks/src/FormControls/Checkboxes/SwitchDense.module.css
index b7ed125044..b8d5b539bc 100644
--- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/SwitchDense.module.css
+++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/SwitchDense.module.css
@@ -5,14 +5,39 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
-.switchBody {
- composes: theme-switch_dense from global;
+@layer components {
+ .switchBody {
+ & .switchControl {
+ width: 24px;
+ height: 16px;
+ }
+
+ & .switchControlTrack {
+ height: 10px;
+ border-radius: 5px;
+ }
+
+ & .switchControlUnderlay {
+ margin-left: -3px;
+ }
+
+ & .switchControlThumb {
+ width: 14px;
+ height: 14px;
+ border-width: 7px;
+ }
+
+ & .checked .switchControlUnderlay {
+ margin-left: 13px;
+ }
+ }
+
+ /* overrides bold label style from SwitchDense.module.css because of specificity */
+ .switchBody .fieldLabel {
+ font-weight: initial;
+ }
}
+
.fieldLabel {
composes: theme-typography--body2 from global;
}
-
-/* overrides bold label style from SwitchDense.module.css because of specificity */
-.switchBody .fieldLabel {
- font-weight: initial;
-}
diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/SwitchPrimary.module.css b/webapp/packages/core-blocks/src/FormControls/Checkboxes/SwitchPrimary.module.css
index 6b876c5931..538663e78f 100644
--- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/SwitchPrimary.module.css
+++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/SwitchPrimary.module.css
@@ -5,10 +5,15 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
-.switchControl {
- composes: theme-switch_primary from global;
-}
+@layer components {
+ .switchBody {
+ .switchControl {
+ width: 36px;
+ height: 20px;
+ }
-.fieldLabel {
- font-weight: 500;
+ .fieldLabel {
+ font-weight: 500;
+ }
+ }
}
diff --git a/webapp/packages/core-blocks/src/FormControls/InputAutocompletionMenu.tsx b/webapp/packages/core-blocks/src/FormControls/InputAutocompletionMenu.tsx
index 4352e46c65..650804cd11 100644
--- a/webapp/packages/core-blocks/src/FormControls/InputAutocompletionMenu.tsx
+++ b/webapp/packages/core-blocks/src/FormControls/InputAutocompletionMenu.tsx
@@ -20,26 +20,25 @@ interface AutocompletionProps {
onSelect?: (proposal: InputAutocompleteProposal) => void;
}
-export const InputAutocompletionMenu = observer(forwardRef(function InputAutocompletionMenu({
- proposals,
- onSelect,
-}, ref) {
- const styles = useS(BaseDropdownStyles);
+export const InputAutocompletionMenu = observer(
+ forwardRef(function InputAutocompletionMenu({ proposals, onSelect }, ref) {
+ const styles = useS(BaseDropdownStyles);
- return (
-
-
- {proposals.map(proposal => (
- onSelect?.(proposal)}>
- {proposal.icon && (
-
-
-
- )}
- {proposal.displayString}
-
- ))}
-
-
- );
-}));
+ return (
+
+
+ {proposals.map(proposal => (
+ onSelect?.(proposal)}>
+ {proposal.icon && (
+
+
+
+ )}
+ {proposal.displayString}
+
+ ))}
+
+
+ );
+ }),
+);
diff --git a/webapp/packages/core-blocks/src/Loader/Loader.module.css b/webapp/packages/core-blocks/src/Loader/Loader.module.css
index f27219b826..687f9e3c75 100644
--- a/webapp/packages/core-blocks/src/Loader/Loader.module.css
+++ b/webapp/packages/core-blocks/src/Loader/Loader.module.css
@@ -28,7 +28,7 @@
justify-content: center;
align-items: center;
opacity: 0;
- transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 0.3s;
+ transition: opacity var(--duration-slow) var(--ease-smooth-start);
&:global(.animate) {
opacity: 1;
}
diff --git a/webapp/packages/core-blocks/src/Overlay/Overlay.module.css b/webapp/packages/core-blocks/src/Overlay/Overlay.module.css
index 6fdc5ee573..51e868d000 100644
--- a/webapp/packages/core-blocks/src/Overlay/Overlay.module.css
+++ b/webapp/packages/core-blocks/src/Overlay/Overlay.module.css
@@ -6,41 +6,41 @@
* you may not use this file except in compliance with the License.
*/
.overlay {
- composes: theme-text-on-primary from global;
- display: none;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- overflow: auto;
- position: absolute;
- margin: auto;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.4);
- box-shadow: none;
+ composes: theme-text-on-primary from global;
+ display: none;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ overflow: auto;
+ position: absolute;
+ margin: auto;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.4);
+ box-shadow: none;
- &.active {
- display: flex;
- }
+ &.active {
+ display: flex;
+ }
- &.fill {
- background-color: var(--theme-background-surface);
- & .box {
- box-shadow: none;
- }
+ &.fill {
+ background-color: var(--theme-background-surface);
+ & .box {
+ box-shadow: none;
}
+ }
}
.box {
- composes: theme-background-surface theme-text-on-surface theme-elevation-z6 from global;
- display: flex;
- flex-direction: column;
- justify-content: center;
- overflow: auto;
- border-radius: 0.25rem;
- align-items: normal;
- max-width: calc(100% - 48px);
- max-height: calc(100% - 48px);
+ composes: theme-background-surface theme-text-on-surface from global;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ overflow: auto;
+ border-radius: 0.25rem;
+ align-items: normal;
+ max-width: calc(100% - 48px);
+ max-height: calc(100% - 48px);
}
diff --git a/webapp/packages/core-blocks/src/Overlay/Overlay.tsx b/webapp/packages/core-blocks/src/Overlay/Overlay.tsx
index 1eb8841c61..c65e6fdb95 100644
--- a/webapp/packages/core-blocks/src/Overlay/Overlay.tsx
+++ b/webapp/packages/core-blocks/src/Overlay/Overlay.tsx
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
+ * Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ export const Overlay = observer>(function Overlay
return (
-
{children}
+
{children}
);
});
diff --git a/webapp/packages/core-blocks/src/SlideDialog/SlideDialog.css b/webapp/packages/core-blocks/src/SlideDialog/SlideDialog.css
index fff12d61ed..10bf4e4130 100644
--- a/webapp/packages/core-blocks/src/SlideDialog/SlideDialog.css
+++ b/webapp/packages/core-blocks/src/SlideDialog/SlideDialog.css
@@ -4,7 +4,7 @@
inset: 0;
z-index: 999;
background: rgb(0 0 0 / 0%);
- transition: background ease-in-out 0.3s;
+ transition: background var(--duration-slow) var(--ease-smooth);
pointer-events: none;
&[data-active] {
diff --git a/webapp/packages/core-blocks/src/Snackbars/SnackbarMarkups/SnackbarWrapper.module.css b/webapp/packages/core-blocks/src/Snackbars/SnackbarMarkups/SnackbarWrapper.module.css
index 1a3ee1d3eb..aa6704dc62 100644
--- a/webapp/packages/core-blocks/src/Snackbars/SnackbarMarkups/SnackbarWrapper.module.css
+++ b/webapp/packages/core-blocks/src/Snackbars/SnackbarMarkups/SnackbarWrapper.module.css
@@ -5,8 +5,9 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
+
.notification {
- composes: theme-background-surface theme-text-on-surface theme-elevation-z5 from global;
+ composes: theme-background-surface theme-text-on-surface from global;
position: relative;
display: flex;
box-sizing: border-box;
@@ -18,8 +19,8 @@
opacity: 0;
border-radius: var(--theme-group-element-radius);
transition:
- opacity 0.3s ease-in-out,
- transform 0.5s ease-in-out;
+ opacity var(--duration-slow) var(--ease-smooth),
+ transform var(--duration-slowest) var(--ease-smooth);
transform: translateX(-100%);
&.mounted {
@@ -31,8 +32,8 @@
opacity: 0;
transform: translateX(-100%);
transition:
- opacity 0.5s ease-in-out,
- transform 0.5s ease-in-out;
+ opacity var(--duration-slowest) var(--ease-smooth),
+ transform var(--duration-slowest) var(--ease-smooth);
}
}
diff --git a/webapp/packages/core-blocks/src/Snackbars/SnackbarMarkups/SnackbarWrapper.tsx b/webapp/packages/core-blocks/src/Snackbars/SnackbarMarkups/SnackbarWrapper.tsx
index 401889bff8..167c86883e 100644
--- a/webapp/packages/core-blocks/src/Snackbars/SnackbarMarkups/SnackbarWrapper.tsx
+++ b/webapp/packages/core-blocks/src/Snackbars/SnackbarMarkups/SnackbarWrapper.tsx
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2025 DBeaver Corp and others
+ * Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ export const SnackbarWrapper: React.FC> = functio
role="alert"
aria-live="assertive"
aria-atomic="true"
- className={s(styles, { notification: true, mounted, closing }, className)}
+ className={s(styles, { notification: true, mounted, closing }, 'tw:shadow-medium', className)}
>
{children}
{!persistent && onClose && (
diff --git a/webapp/packages/core-blocks/src/Split/ResizerControls.module.css b/webapp/packages/core-blocks/src/Split/ResizerControls.module.css
index 07cfdb2a69..42ca9b7384 100644
--- a/webapp/packages/core-blocks/src/Split/ResizerControls.module.css
+++ b/webapp/packages/core-blocks/src/Split/ResizerControls.module.css
@@ -5,6 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
+
.resizerControls {
composes: theme-background-background theme-text-on-secondary from global;
position: relative;
@@ -12,7 +13,7 @@
cursor: ew-resize;
user-select: none;
z-index: 1;
- transition: background-color 0.3s ease-in-out;
+ transition: background-color var(--duration-slow) var(--ease-smooth);
&:before {
content: ' ';
diff --git a/webapp/packages/core-blocks/src/Table/TableColumnValue.module.css b/webapp/packages/core-blocks/src/Table/TableColumnValue.module.css
index 3918a9c03f..ffa0276bdc 100644
--- a/webapp/packages/core-blocks/src/Table/TableColumnValue.module.css
+++ b/webapp/packages/core-blocks/src/Table/TableColumnValue.module.css
@@ -5,12 +5,13 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
+
.cell {
position: relative;
box-sizing: border-box;
height: 28px;
padding: 0 16px;
- transition: padding ease-in-out 0.24s;
+ transition: padding var(--duration-medium) var(--ease-smooth);
&.nowrap,
&.ellipsis {
diff --git a/webapp/packages/core-blocks/src/Table/TableItemExpand.module.css b/webapp/packages/core-blocks/src/Table/TableItemExpand.module.css
index eddaedb28e..f643dc9781 100644
--- a/webapp/packages/core-blocks/src/Table/TableItemExpand.module.css
+++ b/webapp/packages/core-blocks/src/Table/TableItemExpand.module.css
@@ -10,7 +10,7 @@
width: 16px;
height: 16px;
padding: 0;
- transition: transform ease-in-out 0.2s;
+ transition: transform var(--duration-medium) var(--ease-smooth);
&.expanded {
transform: rotate(180deg);
diff --git a/webapp/packages/core-blocks/src/Table/TableItemGroupExpand.module.css b/webapp/packages/core-blocks/src/Table/TableItemGroupExpand.module.css
index e9e9a4b0bc..f6ef3d5b01 100644
--- a/webapp/packages/core-blocks/src/Table/TableItemGroupExpand.module.css
+++ b/webapp/packages/core-blocks/src/Table/TableItemGroupExpand.module.css
@@ -20,7 +20,7 @@
cursor: pointer;
opacity: 0.5;
transform: rotate(-90deg);
- transition: transform 0.15s ease-in-out;
+ transition: transform var(--duration-medium) var(--ease-smooth);
&.expanded {
transform: rotate(0deg);
diff --git a/webapp/packages/core-theming/package.json b/webapp/packages/core-theming/package.json
index 7e37172ebb..67536515d3 100644
--- a/webapp/packages/core-theming/package.json
+++ b/webapp/packages/core-theming/package.json
@@ -40,15 +40,6 @@
"@dbeaver/cli": "workspace:*",
"@dbeaver/react-tests": "workspace:*",
"@fontsource/roboto": "^5",
- "@material/button": "^4",
- "@material/checkbox": "^4",
- "@material/elevation": "^4",
- "@material/layout-grid": "^4",
- "@material/radio": "^4",
- "@material/ripple": "^4",
- "@material/switch": "^4",
- "@material/theme": "^4",
- "@material/typography": "^4",
"rimraf": "^6",
"typescript": "^5",
"typescript-plugin-css-modules": "^5",
diff --git a/webapp/packages/core-theming/src/ThemeService.ts b/webapp/packages/core-theming/src/ThemeService.ts
index d611359b56..1d09c76286 100644
--- a/webapp/packages/core-theming/src/ThemeService.ts
+++ b/webapp/packages/core-theming/src/ThemeService.ts
@@ -14,11 +14,9 @@ import { type ISyncExecutor, SyncExecutor } from '@cloudbeaver/core-executor';
import type { Style } from './ComponentStyle.js';
import './styles/main/base.pure.css';
import './styles/main/color.pure.scss';
-import './styles/main/elevation.pure.scss';
import './styles/main/fonts.pure.css';
// TODO: important to keep normalize first
import './styles/main/normalize.pure.css';
-import './styles/main/typography.pure.scss';
import './styles/UiIconButton.css';
import './styles/UiSpinner.css';
import './styles/UiInput.css';
diff --git a/webapp/packages/core-theming/src/styles/_branding.scss b/webapp/packages/core-theming/src/styles/_branding.scss
index 51c503f89a..9673c7ba11 100644
--- a/webapp/packages/core-theming/src/styles/_branding.scss
+++ b/webapp/packages/core-theming/src/styles/_branding.scss
@@ -6,21 +6,6 @@
* you may not use this file except in compliance with the License.
*/
-@mixin stripes-background($color, $important: false) {
- // background-image: linear-gradient(
- // 45deg,
- // transparent 37.5%,
- // $color 37.5%,
- // $color 50%,
- // transparent 50%,
- // transparent 87.5%,
- // $color 87.5%,
- // $color 100%
- // );
- // background-size: 8px 8px;
- background-color: $color #{if($important, '!important', '')};
-}
-
@mixin delimiter($color) {
hr {
border-color: $color;
diff --git a/webapp/packages/core-theming/src/styles/_color.scss b/webapp/packages/core-theming/src/styles/_color.scss
index 27c5326897..95a87c4b84 100644
--- a/webapp/packages/core-theming/src/styles/_color.scss
+++ b/webapp/packages/core-theming/src/styles/_color.scss
@@ -6,90 +6,89 @@
* you may not use this file except in compliance with the License.
*/
-@mixin colors($query: mdc-feature-all()) {
- $feat-color: mdc-feature-create-target($query, color);
+@mixin colors() {
+ // Export all theme colors as CSS variables
+ --theme-primary: #{$mdc-theme-primary};
+ --theme-on-primary: #{$mdc-theme-on-primary};
+ --theme-secondary: #{$mdc-theme-secondary};
+ --theme-on-secondary: #{$mdc-theme-on-secondary};
+ --theme-error: #{$mdc-theme-error};
+ --theme-surface: #{$mdc-theme-surface};
+ --theme-on-surface: #{$mdc-theme-on-surface};
+ --theme-background: #{$mdc-theme-background};
+ --theme-sub-secondary: #{$mdc-theme-sub-secondary};
+ --theme-on-sub-secondary: #{$mdc-theme-on-sub-secondary};
+ --theme-positive: #{$color-positive};
+ --theme-on-positive: #{$color-on-positive};
+ --theme-negative: #{$color-negative};
+ --theme-status: #{$color-status};
+ --theme-link-color: #{$link-color};
+ --theme-input-color: #{$input-color};
+ --theme-input-color-disabled: #{$input-color-disabled};
+ --theme-input-color-readonly: #{$input-color-readonly};
+ --theme-input-color-placeholder: #{$input-color-placeholder};
+ --theme-input-border: #{$input-border};
+ --theme-input-border-readonly: #{$input-border-readonly};
+ --theme-input-border-disabled: #{$input-border-disabled};
+ --theme-input-background: #{$input-background};
+ --theme-input-background-disabled: #{$input-background-disabled};
+ --theme-input-background-readonly: #{$input-background-readonly};
+ --theme-switch-thumb: #{lighten($mdc-theme-surface, 5%)};
- /*:root {*/
- @include mdc-feature-targets($feat-color) {
- @each $style in map-keys($mdc-theme-property-values) {
- --theme-#{$style}: #{map-get($mdc-theme-property-values, $style)};
+ // Text color variants derived from $mdc-theme-text-colors
+ // Map keys "light"/"dark" describe the ink color, not the background.
+ // "on-light" (on light background) needs dark ink, "on-dark" needs light ink.
+ $light-ink-colors: map-get($mdc-theme-text-colors, light);
+ $dark-ink-colors: map-get($mdc-theme-text-colors, dark);
+
+ @each $variant in (primary, secondary, sub-secondary, hint, disabled, icon, negative) {
+ --theme-text-#{$variant}-on-light: #{map-get($dark-ink-colors, $variant)};
+ --theme-text-#{$variant}-on-dark: #{map-get($light-ink-colors, $variant)};
+ }
+
+ // Theme color utility classes
+ @each $color-name in (primary, on-primary, secondary, on-secondary, error, on-error, surface, on-surface, background, positive, negative, status) {
+ &.theme-text-#{$color-name},
+ .theme-text-#{$color-name} {
+ color: var(--theme-#{$color-name});
+
+ svg,
+ & > svg {
+ fill: var(--theme-#{$color-name});
+ }
+ }
+
+ &.theme-border-color-#{$color-name},
+ .theme-border-color-#{$color-name} {
+ border-color: var(--theme-#{$color-name}) !important;
+ }
+
+ &.theme-fill-#{$color-name},
+ .theme-fill-#{$color-name} {
+ fill: var(--theme-#{$color-name});
}
}
- /*}*/
- @each $style in map-keys($mdc-theme-property-values) {
- @if $style != 'background' and $style != 'surface' and $style != 'on-surface' {
- &.theme-text-#{$style},
- .theme-text-#{$style} {
- @include theme-ripple-color($query, $style);
-
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(color, $style, true);
- }
+ // Text variant utility classes (text-primary-on-light, text-hint-on-light, etc.)
+ @each $variant in (primary, secondary, sub-secondary, hint, disabled, icon, negative) {
+ @each $tone in (light, dark) {
+ &.theme-text-text-#{$variant}-on-#{$tone},
+ .theme-text-text-#{$variant}-on-#{$tone} {
+ color: var(--theme-text-#{$variant}-on-#{$tone});
svg,
& > svg {
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(fill, $style, true);
- }
- }
- }
- &.theme-border-color-#{$style},
- .theme-border-color-#{$style} {
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(border-color, $style, true);
- }
- }
- &.theme-fill-#{$style},
- .theme-fill-#{$style} {
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(fill, $style, true);
- }
- }
- } @else {
- &.theme-text-#{$style},
- .theme-text-#{$style} {
- @include theme-ripple-color($query, $style);
-
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(color, $style);
- }
-
- svg,
- & > svg {
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(fill, $style);
- }
- }
- }
- &.theme-background-#{$style},
- .theme-background-#{$style} {
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(background-color, $style);
- }
- }
- &.theme-border-color-#{$style},
- .theme-border-color-#{$style} {
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(border-color, $style, true);
- }
- }
- &.theme-fill-#{$style},
- .theme-fill-#{$style} {
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(fill, $style);
+ fill: var(--theme-text-#{$variant}-on-#{$tone});
}
}
}
}
- // CSS rules for using primary and secondary (plus light/dark variants) as background colors.
- @each $style in ('primary', 'secondary', 'positive') {
- &.theme-background-#{$style},
- .theme-background-#{$style} {
- @include mdc-feature-targets($feat-color) {
- @include mdc-theme-prop(background-color, $style, true);
- }
+ // Background color classes
+ @each $color-name in (primary, secondary, surface, background, positive) {
+ &.theme-background-#{$color-name},
+ .theme-background-#{$color-name} {
+ background-color: var(--theme-#{$color-name});
}
}
}
diff --git a/webapp/packages/core-theming/src/styles/_form-controls.scss b/webapp/packages/core-theming/src/styles/_form-controls.scss
index d3ce1285b0..9bdb2f1ac4 100644
--- a/webapp/packages/core-theming/src/styles/_form-controls.scss
+++ b/webapp/packages/core-theming/src/styles/_form-controls.scss
@@ -36,7 +36,7 @@
width: 0;
height: 0;
}
- /* clears the ‘X’ from Chrome */
+ /* clears the 'X' from Chrome */
&[type='search']::-webkit-search-decoration,
&[type='search']::-webkit-search-cancel-button,
&[type='search']::-webkit-search-results-button,
@@ -53,20 +53,21 @@
width: 100%;
border: 1px solid;
outline: none !important;
- border-radius: $theme-form-element-radius;
+ border-radius: var(--theme-form-element-radius);
+
+ color: var(--theme-input-color);
+ border-color: var(--theme-input-border);
+ background-color: var(--theme-input-background);
- @include mdc-theme-prop(color, input-color, false);
- @include mdc-theme-prop(border-color, input-border, false);
- @include mdc-theme-prop(background-color, input-background, false);
// we use box-shadow to overlap internal background-color style, we can't override it due to chrome bug
&:-internal-autofill-selected,
&:-internal-autofill-previewed {
- -webkit-text-fill-color: $mdc-theme-on-secondary;
- box-shadow: 0 0 0 50px $input-background inset;
+ -webkit-text-fill-color: var(--theme-on-secondary);
+ box-shadow: 0 0 0 50px var(--theme-input-background) inset;
}
&:user-invalid {
- @include mdc-theme-prop(border-color, negative, false);
+ border-color: var(--theme-negative);
}
&[type='color'] {
@@ -81,36 +82,36 @@
&:focus,
&[data-focus='true'] {
- @include mdc-theme-prop(border-color, primary, false);
+ border-color: var(--theme-primary);
}
&:not([data-select='true'])[readonly] {
- @include mdc-theme-prop(color, input-color-readonly, false);
- @include mdc-theme-prop(border-color, input-border-readonly, false);
- @include mdc-theme-prop(background-color, input-background-readonly, false);
+ color: var(--theme-input-color-readonly);
+ border-color: var(--theme-input-border-readonly);
+ background-color: var(--theme-input-background-readonly);
opacity: 1;
&:-internal-autofill-selected,
&:-internal-autofill-previewed {
- box-shadow: 0 0 0 50px $input-background-readonly inset;
+ box-shadow: 0 0 0 50px var(--theme-input-background-readonly) inset;
}
}
&[disabled] {
- @include mdc-theme-prop(color, input-color-readonly, false);
- @include mdc-theme-prop(border-color, input-border-readonly, false);
- @include mdc-theme-prop(background-color, input-background-readonly, false);
+ color: var(--theme-input-color-readonly);
+ border-color: var(--theme-input-border-readonly);
+ background-color: var(--theme-input-background-readonly);
pointer-events: all;
opacity: 1;
&:-internal-autofill-selected,
&:-internal-autofill-previewed {
- box-shadow: 0 0 0 50px $input-background-readonly inset;
+ box-shadow: 0 0 0 50px var(--theme-input-background-readonly) inset;
}
}
&[data-embedded='true'] {
&[disabled],
&:not([data-select='true'])[readonly] {
- @include mdc-theme-prop(border-color, background, false);
- @include mdc-theme-prop(background-color, input-background, false);
+ border-color: var(--theme-background);
+ background-color: var(--theme-input-background);
}
}
}
diff --git a/webapp/packages/core-theming/src/styles/_mixins.scss b/webapp/packages/core-theming/src/styles/_mixins.scss
index a4fde18382..414654ad3b 100644
--- a/webapp/packages/core-theming/src/styles/_mixins.scss
+++ b/webapp/packages/core-theming/src/styles/_mixins.scss
@@ -6,20 +6,10 @@
* you may not use this file except in compliance with the License.
*/
-@import '@material/theme/mixins';
-@import '@material/ripple/mixins';
-@import '@material/button/mixins';
-@import '@material/elevation/mixins';
-@import '@material/typography/mixins';
@import './variables';
@import './theme';
@import './color-scheme';
-@import './layout-grid';
@import './branding';
-@import './theme-ripple';
-@import './ripple';
@import './color';
-@import './switch';
-@import './placeholder';
@import './form-controls';
@import './link';
diff --git a/webapp/packages/core-theming/src/styles/_placeholder.scss b/webapp/packages/core-theming/src/styles/_placeholder.scss
deleted file mode 100644
index e80dbe9090..0000000000
--- a/webapp/packages/core-theming/src/styles/_placeholder.scss
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@mixin placeholder {
- .placeholder {
- box-sizing: border-box;
- overflow: hidden;
- position: relative;
- background: #f0f0f0;
- border-radius: $theme-form-element-radius;
- margin: 2px;
- animation: wave 1.5s linear infinite;
- }
-
- @keyframes wave {
- 0% {
- opacity: 0;
- }
-
- 50% {
- opacity: 1;
- }
-
- 100% {
- opacity: 0;
- }
- }
-}
diff --git a/webapp/packages/core-theming/src/styles/_ripple.scss b/webapp/packages/core-theming/src/styles/_ripple.scss
deleted file mode 100644
index 97c20dc522..0000000000
--- a/webapp/packages/core-theming/src/styles/_ripple.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@mixin ripple-core-styles($query: mdc-feature-all()) {
- $feat-structure: mdc-feature-create-target($query, structure);
-
- .theme-ripple-surface {
- @include mdc-ripple-surface($query: $query);
- @include mdc-states($query: $query);
- @include mdc-ripple-radius-bounded($query: $query);
-
- @include mdc-feature-targets($feat-structure) {
- position: relative;
- outline: none;
- overflow: hidden;
- }
-
- &--primary {
- @include mdc-states(primary, $query: $query);
- }
-
- &--accent {
- @include mdc-states(secondary, $query: $query);
- }
- }
-}
\ No newline at end of file
diff --git a/webapp/packages/core-theming/src/styles/_switch.scss b/webapp/packages/core-theming/src/styles/_switch.scss
deleted file mode 100644
index c0b5d518d4..0000000000
--- a/webapp/packages/core-theming/src/styles/_switch.scss
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@import '@material/switch/mixins';
-
-@mixin switch-core-styles($query: mdc-feature-all()) {
- @include mdc-switch-core-styles($query);
-
- .theme-switch {
- @extend .mdc-switch;
- }
- .theme-switch_native-control {
- @extend .mdc-switch__native-control;
-
- &:disabled {
- opacity: 0;
- }
- }
- .theme-switch__track {
- @extend .mdc-switch__track;
- }
- .theme-switch__thumb-underlay {
- @extend .mdc-switch__thumb-underlay;
- }
- .theme-switch__thumb {
- @extend .mdc-switch__thumb;
- }
- .theme-switch--checked {
- @extend .mdc-switch--checked;
- }
- .theme-switch--disabled {
- @extend .mdc-switch--disabled;
- }
-
- .theme-switch_dense {
- @include switch-core-styles-dense($query);
- }
-
- .theme-switch_dense .theme-switch_primary,
- .theme-switch_primary {
- $mdc-switch-baseline-theme-color: primary;
-
- @include mdc-switch-toggled-on-track-color($mdc-switch-baseline-theme-color, $query);
- @include mdc-switch-toggled-on-thumb-color($mdc-switch-baseline-theme-color, $query);
- @include mdc-switch-toggled-off-track-color($mdc-switch-toggled-off-track-color, $query);
- @include mdc-switch-toggled-off-thumb-color($mdc-switch-toggled-off-thumb-color, $query);
- }
-}
-
-@mixin switch-core-styles-dense($query: mdc-feature-all()) {
- $mdc-switch-baseline-theme-color: primary !global;
- $mdc-switch-track-width: 24px !global;
- $mdc-switch-track-height: 10px !global;
- $mdc-switch-thumb-diameter: 14px !global;
- $mdc-switch-ripple-size: 36px !global;
- $mdc-switch-toggled-off-thumb-color: lighten($mdc-switch-toggled-off-thumb-color, 5%) !global;
-
- $mdc-switch-minimum-size: 24px !global;
- $mdc-switch-maximum-size: $mdc-switch-ripple-size !global;
- $mdc-switch-density-scale: $mdc-density-default-scale !global;
- $mdc-switch-density-config: (
- size: (
- minimum: $mdc-switch-minimum-size,
- default: $mdc-switch-maximum-size,
- maximum: $mdc-switch-maximum-size,
- ),
- ) !global;
-
- $mdc-switch-thumb-offset: 2px !global;
-
- $mdc-switch-thumb-active-margin: $mdc-switch-track-width - $mdc-switch-thumb-diameter + $mdc-switch-thumb-offset * 2 !global;
-
- @include mdc-switch-core-styles($query);
-}
diff --git a/webapp/packages/core-theming/src/styles/_theme-dark.scss b/webapp/packages/core-theming/src/styles/_theme-dark.scss
index b6cc437dcc..898397d281 100644
--- a/webapp/packages/core-theming/src/styles/_theme-dark.scss
+++ b/webapp/packages/core-theming/src/styles/_theme-dark.scss
@@ -60,22 +60,6 @@ $mdc-theme-text-colors: (
),
);
-$mdc-ripple-dark-ink-opacities: (
- hover: 0.04,
- focus: 0.1,
- press: 0.1,
- selected: 0.06,
- activated: 0.1,
-) !default;
-
-$mdc-ripple-light-ink-opacities: (
- hover: 0.04,
- focus: 0.1,
- press: 0.1,
- selected: 0.06,
- activated: 0.1,
-) !default;
-
$theme-name: 'dark';
@import './mixins';
diff --git a/webapp/packages/core-theming/src/styles/_theme-light.scss b/webapp/packages/core-theming/src/styles/_theme-light.scss
index f804ce6c94..634a81a697 100644
--- a/webapp/packages/core-theming/src/styles/_theme-light.scss
+++ b/webapp/packages/core-theming/src/styles/_theme-light.scss
@@ -17,6 +17,7 @@ $mdc-theme-on-sub-secondary: #6d6d6d;
$mdc-theme-surface: #ffffff;
$mdc-theme-on-surface: #353535;
$mdc-theme-background: #dedede;
+$mdc-theme-error: #e94948;
$color-scheme: light;
$color-positive: #52c41a;
diff --git a/webapp/packages/core-theming/src/styles/_theme-ripple.scss b/webapp/packages/core-theming/src/styles/_theme-ripple.scss
deleted file mode 100644
index 667a77e3b3..0000000000
--- a/webapp/packages/core-theming/src/styles/_theme-ripple.scss
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@mixin theme-ripple-color($query, $color) {
- &.theme-ripple,
- .theme-ripple {
- @include mdc-states($color, $query: $query);
-
- &[aria-expanded='true'] {
- &::before {
- opacity: mdc-states-opacity($color, focus) + mdc-states-opacity($color, hover);
- }
- }
-
- &.theme-ripple-selectable {
- &[aria-selected='true'] {
- &::before {
- opacity: mdc-states-opacity($color, focus) + mdc-states-opacity($color, hover);
- }
- }
- }
- }
-}
-
-@mixin theme-ripple($query: mdc-feature-all()) {
- $feat-structure: mdc-feature-create-target($query, structure);
- @include mdc-ripple-common($query);
-
- &.theme-ripple,
- .theme-ripple {
- position: relative;
-
- &::before {
- @include mdc-ripple-surface($query);
- @include mdc-ripple-radius-bounded($query: $query);
-
- @include mdc-feature-targets($feat-structure) {
- position: absolute;
- content: '';
- opacity: 0;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- overflow: hidden;
- }
- }
-
- &.theme-ripple-background {
- @include mdc-theme-prop(background-color, background, false);
- @include mdc-theme-prop(color, text-hint-on-light, false);
-
- &.theme-ripple-selectable {
- &:hover {
- @include mdc-theme-prop(color, text-primary-on-light, false);
- }
-
- &[aria-selected='true'] {
- @include mdc-theme-prop(background-color, surface, false);
- @include mdc-theme-prop(color, text-primary-on-light, false);
-
- &::before {
- opacity: 0 !important;
- }
- }
- }
- }
-
- &.theme-ripple-secondary {
- @include mdc-theme-prop(background-color, secondary, false);
- @include mdc-theme-prop(color, text-hint-on-light, false);
-
- &.theme-ripple-selectable {
- &:hover {
- @include mdc-theme-prop(color, text-primary-on-light, false);
- }
-
- &[aria-selected='true'] {
- @include mdc-theme-prop(background-color, surface, false);
- @include mdc-theme-prop(color, text-primary-on-light, false);
-
- &::before {
- opacity: 0 !important;
- }
- }
- }
- }
-
- &.theme-ripple-surface {
- @include mdc-theme-prop(background-color, surface, false);
- @include mdc-theme-prop(color, text-hint-on-light, false);
-
- &.theme-ripple-selectable {
- &:hover {
- @include mdc-theme-prop(color, text-primary-on-light, false);
- }
-
- &[aria-selected='true'] {
- @include mdc-theme-prop(background-color, surface, false);
- @include mdc-theme-prop(color, text-primary-on-light, false);
-
- &::before {
- opacity: 0 !important;
- }
- }
- }
- }
- }
-}
diff --git a/webapp/packages/core-theming/src/styles/_variables.scss b/webapp/packages/core-theming/src/styles/_variables.scss
index 2abaebd2bb..4b9caec8a3 100644
--- a/webapp/packages/core-theming/src/styles/_variables.scss
+++ b/webapp/packages/core-theming/src/styles/_variables.scss
@@ -6,28 +6,6 @@
* you may not use this file except in compliance with the License.
*/
-$mdc-theme-extra-property-values: (
- sub-secondary: $mdc-theme-sub-secondary,
- on-sub-secondary: $mdc-theme-on-sub-secondary,
- positive: $color-positive,
- on-positive: $color-on-positive,
- negative: $color-negative,
- status: $color-status,
- link-color: $link-color,
- input-color: $input-color,
- input-color-disabled: $input-color-disabled,
- input-color-readonly: $input-color-readonly,
- input-color-placeholder: $input-color-placeholder,
- input-border: $input-border,
- input-border-readonly: $input-border-readonly,
- input-border-disabled: $input-border-disabled,
- input-background: $input-background,
- input-background-disabled: $input-background-disabled,
- input-background-readonly: $input-background-readonly,
-);
-
-$mdc-theme-property-values: map-merge($mdc-theme-property-values, $mdc-theme-extra-property-values);
-
$theme-class: 'theme-#{$theme-name}';
$theme-form-element-radius: 3px !default;
$theme-group-element-radius: 4px !default;
@@ -51,6 +29,8 @@ $app-height: 100vh !default;
--theme-form-element-radius: #{$theme-form-element-radius};
--theme-group-element-radius: #{$theme-group-element-radius};
--theme-menu-bar-small-action-radius: #{$theme-menu-bar-small-action-radius};
+ --theme-font-family: Roboto, sans-serif;
+ --theme-font-family-mono: RobotoMono, sans-serif;
}
@layer components {
diff --git a/webapp/packages/core-theming/src/styles/layout-grid.scss b/webapp/packages/core-theming/src/styles/layout-grid.scss
deleted file mode 100644
index 767f4b15a8..0000000000
--- a/webapp/packages/core-theming/src/styles/layout-grid.scss
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@import "@material/layout-grid/variables";
-@import "@material/layout-grid/mixins";
-
-@mixin layout-grid($query: mdc-feature-all()) {
- :root {
- @each $size in map-keys($mdc-layout-grid-columns) {
- --mdc-layout-grid-margin-#{$size}: #{map-get($mdc-layout-grid-default-margin, $size)};
- --mdc-layout-grid-gutter-#{$size}: #{map-get($mdc-layout-grid-default-gutter, $size)};
- --mdc-layout-grid-column-width-#{$size}: #{map-get($mdc-layout-grid-column-width, $size)};
- }
- }
-
- .layout-grid {
- @each $size in map-keys($mdc-layout-grid-columns) {
- @include mdc-layout-grid-media-query_($size) {
- $margin: map-get($mdc-layout-grid-default-margin, $size);
-
- @include mdc-layout-grid($size, $margin, $mdc-layout-grid-max-width);
- }
- }
- }
-
- .layout-grid__inner {
- @each $size in map-keys($mdc-layout-grid-columns) {
- @include mdc-layout-grid-media-query_($size) {
- $margin: map-get($mdc-layout-grid-default-margin, $size);
- $gutter: map-get($mdc-layout-grid-default-gutter, $size);
-
- @include mdc-layout-grid-inner($size, $margin, $gutter);
- }
- }
- }
-
- .layout-grid__cell {
- // select the upper breakpoint
- $upper-breakpoint: nth(map-keys($mdc-layout-grid-columns), 1);
-
- @each $size in map-keys($mdc-layout-grid-columns) {
- @include mdc-layout-grid-media-query_($size) {
- $gutter: map-get($mdc-layout-grid-default-gutter, $size);
-
- @include mdc-layout-grid-cell($size, $mdc-layout-grid-default-column-span, $gutter);
-
- @for $span from 1 through map-get($mdc-layout-grid-columns, $upper-breakpoint) {
- // Span classes.
- @at-root .layout-grid__cell--span-#{$span},
- .layout-grid__cell--span-#{$span}-#{$size},
- .layout-grid__cell[data-span="#{$span}"],
- .layout-grid__cell[data-span-#{$size}="#{$span}"] {
- @include mdc-layout-grid-cell-span_($size, $span, $gutter);
- }
- }
- }
- }
-
- // Order override classes.
- @for $i from 1 through map-get($mdc-layout-grid-columns, $upper-breakpoint) {
- &--order-#{$i} {
- @include mdc-layout-grid-cell-order($i);
- }
- }
-
- // Alignment classes.
- &--align-top {
- @include mdc-layout-grid-cell-align(top);
- }
-
- &--align-middle {
- @include mdc-layout-grid-cell-align(middle);
- }
-
- &--align-bottom {
- @include mdc-layout-grid-cell-align(bottom);
- }
- }
-
- .layout-grid--fixed-column-width,
- .layout-grid[data-grid-fixed-width=true] {
- @each $size in map-keys($mdc-layout-grid-columns) {
- @include mdc-layout-grid-media-query_($size) {
- $margin: map-get($mdc-layout-grid-default-margin, $size);
- $gutter: map-get($mdc-layout-grid-default-gutter, $size);
- $column-width: map-get($mdc-layout-grid-column-width, $size);
-
- @include mdc-layout-grid-fixed-column-width($size, $margin, $gutter, $column-width);
- }
- }
- }
-
- .layout-grid--align-left,
- [data--grid-align="left"] {
- margin-right: auto;
- margin-left: 0;
- }
-
- .layout-grid--align-right,
- [data-grid-align="right"] {
- margin-right: 0;
- margin-left: auto;
- }
-}
diff --git a/webapp/packages/core-theming/src/styles/main/app-loading-screen.pure.css b/webapp/packages/core-theming/src/styles/main/app-loading-screen.pure.css
index 590c4a9fac..774e41e819 100644
--- a/webapp/packages/core-theming/src/styles/main/app-loading-screen.pure.css
+++ b/webapp/packages/core-theming/src/styles/main/app-loading-screen.pure.css
@@ -8,14 +8,14 @@
display: flex;
align-items: center;
justify-content: center;
- transition: opacity 0.3s;
+ transition: opacity var(--duration-slow);
background: white;
}
#app-loading-screen .app-loading-screen__logo-spinner {
transform-origin: center;
- -webkit-animation:spin 2s linear infinite;
- -moz-animation:spin 2s linear infinite;
- animation:spin 2s linear infinite;
+ -webkit-animation: spin var(--duration-spin) var(--ease-evenly) infinite;
+ -moz-animation: spin var(--duration-spin) var(--ease-evenly) infinite;
+ animation: spin var(--duration-spin) var(--ease-evenly) infinite;
}
:not(:empty) + #app-loading-screen.app-loading-screen--fade-out {
opacity: 0;
@@ -24,6 +24,19 @@
display: none;
}
-@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
-@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
-@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
\ No newline at end of file
+@-moz-keyframes spin {
+ 100% {
+ -moz-transform: rotate(360deg);
+ }
+}
+@-webkit-keyframes spin {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ }
+}
+@keyframes spin {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
diff --git a/webapp/packages/core-theming/src/styles/main/dark.theme.scss b/webapp/packages/core-theming/src/styles/main/dark.theme.scss
index bcc66c712e..f89cf9370f 100644
--- a/webapp/packages/core-theming/src/styles/main/dark.theme.scss
+++ b/webapp/packages/core-theming/src/styles/main/dark.theme.scss
@@ -13,13 +13,8 @@
@include colors;
@include color-scheme;
@include css-variables;
- @include ripple-core-styles;
- @include theme-ripple;
- @include layout-grid;
@include form-controls;
- @include switch-core-styles;
@include link;
- @include placeholder;
@include delimiter($mdc-theme-secondary);
@include branding-overflow;
}
diff --git a/webapp/packages/core-theming/src/styles/main/elevation.pure.scss b/webapp/packages/core-theming/src/styles/main/elevation.pure.scss
deleted file mode 100644
index 750fe71c68..0000000000
--- a/webapp/packages/core-theming/src/styles/main/elevation.pure.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@import '@material/elevation/mixins';
-
-@mixin elevation-core-styles($query: mdc-feature-all()) {
- $feat-animation: mdc-feature-create-target($query, animation);
- $feat-structure: mdc-feature-create-target($query, structure);
-
- @for $z-value from 0 through 24 {
- .theme-elevation-z#{$z-value} {
- @include mdc-elevation($z-value, $query: $query);
- }
- }
-
- .theme-elevation-transition {
- @include mdc-feature-targets($feat-animation) {
- transition: mdc-elevation-transition-value();
- }
-
- @include mdc-feature-targets($feat-structure) {
- will-change: $mdc-elevation-property;
- }
- }
-}
-
-@include elevation-core-styles;
diff --git a/webapp/packages/core-theming/src/styles/main/light.theme.scss b/webapp/packages/core-theming/src/styles/main/light.theme.scss
index 51e516175f..7fedd53c91 100644
--- a/webapp/packages/core-theming/src/styles/main/light.theme.scss
+++ b/webapp/packages/core-theming/src/styles/main/light.theme.scss
@@ -13,13 +13,8 @@
@include colors;
@include color-scheme;
@include css-variables;
- @include ripple-core-styles;
- @include theme-ripple;
- @include layout-grid;
@include form-controls;
- @include switch-core-styles;
@include link;
- @include placeholder;
@include delimiter($mdc-theme-secondary);
@include branding-overflow;
}
diff --git a/webapp/packages/core-theming/src/styles/main/typography.pure.scss b/webapp/packages/core-theming/src/styles/main/typography.pure.scss
deleted file mode 100644
index 751f013bd4..0000000000
--- a/webapp/packages/core-theming/src/styles/main/typography.pure.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@import '@material/typography/mixins';
-
-@mixin typography-core-styles($query: mdc-feature-all()) {
- .theme-typography {
- @include mdc-typography-base($query: $query);
- }
-
- @each $style in map-keys($mdc-typography-styles) {
- .theme-typography--#{$style} {
- @include mdc-typography($style, $query: $query);
- }
- }
-}
-
-@include typography-core-styles;
\ No newline at end of file
diff --git a/webapp/packages/core-theming/src/styles/theme-dark.module.scss b/webapp/packages/core-theming/src/styles/theme-dark.module.scss
index 55d48c0873..7dc927147f 100644
--- a/webapp/packages/core-theming/src/styles/theme-dark.module.scss
+++ b/webapp/packages/core-theming/src/styles/theme-dark.module.scss
@@ -9,13 +9,8 @@
@import './theme-dark';
@include theme-matcher;
-@include layout-grid;
@include colors;
-@include ripple-core-styles;
-@include theme-ripple;
-@include switch-core-styles;
@include form-controls;
@include link;
-@include placeholder;
@include delimiter($mdc-theme-background);
@include branding-overflow;
diff --git a/webapp/packages/core-theming/src/styles/theme-light.module.scss b/webapp/packages/core-theming/src/styles/theme-light.module.scss
index 1ff9994780..076759280f 100644
--- a/webapp/packages/core-theming/src/styles/theme-light.module.scss
+++ b/webapp/packages/core-theming/src/styles/theme-light.module.scss
@@ -9,13 +9,8 @@
@import './theme-light';
@include theme-matcher;
-@include layout-grid;
@include colors;
-@include ripple-core-styles;
-@include theme-ripple;
-@include switch-core-styles;
@include form-controls;
@include link;
-@include placeholder;
@include delimiter($mdc-theme-background);
@include branding-overflow;
diff --git a/webapp/packages/core-ui/src/ContextMenu/MenuBar/MenuBarItem.module.css b/webapp/packages/core-ui/src/ContextMenu/MenuBar/MenuBarItem.module.css
index 9419c54dbb..eb47601250 100644
--- a/webapp/packages/core-ui/src/ContextMenu/MenuBar/MenuBarItem.module.css
+++ b/webapp/packages/core-ui/src/ContextMenu/MenuBar/MenuBarItem.module.css
@@ -60,6 +60,7 @@
display: none;
& .icon {
+ fill: var(--theme-on-primary);
width: 12px;
}
}
diff --git a/webapp/packages/core-ui/src/Tabs/Tab/Tab.module.css b/webapp/packages/core-ui/src/Tabs/Tab/Tab.module.css
index b91ceb1ef8..6566dd6914 100644
--- a/webapp/packages/core-ui/src/Tabs/Tab/Tab.module.css
+++ b/webapp/packages/core-ui/src/Tabs/Tab/Tab.module.css
@@ -6,10 +6,6 @@
* you may not use this file except in compliance with the License.
*/
-.placeholder {
- composes: placeholder from global;
-}
-
.tab {
position: relative;
font-weight: normal;
diff --git a/webapp/packages/plugin-administration/src/ConfigurationWizard/Finish/FinishPage.module.css b/webapp/packages/plugin-administration/src/ConfigurationWizard/Finish/FinishPage.module.css
index 8dacd1a186..26a6841563 100644
--- a/webapp/packages/plugin-administration/src/ConfigurationWizard/Finish/FinishPage.module.css
+++ b/webapp/packages/plugin-administration/src/ConfigurationWizard/Finish/FinishPage.module.css
@@ -1,17 +1,21 @@
.layoutGrid {
- composes: layout-grid from global;
+ display: grid;
+ box-sizing: border-box;
width: 100%;
flex: 1;
+ padding: 24px;
}
.layoutGridInner {
- composes: layout-grid__inner from global;
+ display: grid;
+ grid-template-columns: repeat(12, 1fr);
+ gap: 24px;
min-height: 100%;
}
.layoutGridCell {
- composes: layout-grid__cell from global;
composes: theme-background-surface theme-text-on-surface theme-border-color-background from global;
+ grid-column: 1 / -1;
position: relative;
border: solid 1px;
padding: 16px 24px;
diff --git a/webapp/packages/plugin-codemirror6/package.json b/webapp/packages/plugin-codemirror6/package.json
index 3c429143eb..8996eb8570 100644
--- a/webapp/packages/plugin-codemirror6/package.json
+++ b/webapp/packages/plugin-codemirror6/package.json
@@ -27,6 +27,7 @@
"@cloudbeaver/core-localization": "workspace:*",
"@cloudbeaver/core-theming": "workspace:*",
"@cloudbeaver/core-utils": "workspace:*",
+ "@cloudbeaver/plugin-tailwindcss-theme": "workspace:*",
"@codemirror/autocomplete": "^6",
"@codemirror/commands": "^6",
"@codemirror/lang-html": "^6",
diff --git a/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor-autocompletion.scss b/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor-autocompletion.scss
deleted file mode 100644
index b05bff013e..0000000000
--- a/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor-autocompletion.scss
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@mixin base-code-editor-autocompletion() {
- .cm-tooltip.cm-tooltip-autocomplete {
- &>:global(ul) {
- border-radius: var(--theme-form-element-radius);
- }
-
- & :global(li) {
- display: flex;
- align-items: center;
- }
-
- & .cm-completionIcon {
- opacity: 1;
- width: 16px;
- height: 16px;
- padding: 0;
- margin-right: .6em;
-
- &:not(:global([src])) {
- opacity: 0;
- }
- }
-
- & :global(li):hover {
- @include mdc-theme-prop(background, sub-secondary, false);
- @include mdc-theme-prop(color, on-secondary, false);
- }
-
- & :global(li):global([aria-selected=true]) {
- @include mdc-theme-prop(background, secondary, false);
- @include mdc-theme-prop(color, text-primary-on-light, false);
- }
- }
-
- .cm-tooltip.cm-completionInfo {
- margin-left: 8px;
- }
-}
\ No newline at end of file
diff --git a/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor-tooltip.scss b/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor-tooltip.scss
deleted file mode 100644
index 45e900d061..0000000000
--- a/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor-tooltip.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@mixin base-code-editor-tooltip() {
- .cm-tooltip {
- @include mdc-theme-prop(background-color, surface, false);
- @include mdc-theme-prop(color, on-surface, false);
- @include mdc-elevation(3);
- @include mdc-typography(body2);
- border: none;
- border-radius: var(--theme-form-element-radius);
- }
-}
\ No newline at end of file
diff --git a/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor.scss b/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor.scss
deleted file mode 100644
index 6a8a5cc71b..0000000000
--- a/webapp/packages/plugin-codemirror6/src/theme/_base-code-editor.scss
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2025 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@mixin base-code-editor() {
- .editor,
- .cm-editor,
- .cm-mergeView,
- .cm-mergeViewEditors,
- .cm-scroller,
- .ReactCodemirror {
- width: 100%;
- height: 100% !important;
- }
-
- .editor,
- .ReactCodemirror,
- .cm-mergeView,
- .cm-mergeViewEditors,
- .cm-editor,
- .cm-gotoLine {
- @include mdc-typography('body2');
- }
-
- .cm-mergeViewEditor:first-child {
- border-right: 1px solid;
- @include mdc-theme-prop(border-color, background, false);
- }
-
- .editor .cm-highlightTab {
- opacity: 0.6;
- color: var(--theme-text-hint-on-light);
- pointer-events: none;
- }
-
- .editor .cm-newline {
- color: var(--theme-text-hint-on-light);
- opacity: 0.6;
- margin-left: 4px;
- cursor: default;
- pointer-events: none;
- }
-
- .editor .cm-highlightSpace {
- background-image: radial-gradient(circle at 50% 55%, var(--theme-text-hint-on-light) 15%, transparent 5%);
- opacity: 0.6;
- background-position: center;
- }
-
- .editor {
- @include mdc-theme-prop(background-color, surface, false);
- @include mdc-theme-prop(color, on-surface, false);
- }
-
- .editor .cm-scroller {
- outline: none;
- line-height: unset;
- }
-
- .editor .cm-content {
- caret-color: $cursor;
- }
-
- .editor .cm-cursor {
- border-left-color: $cursor;
- }
-
- .editor .cm-link {
- &.cm-link-loaded {
- @include mdc-theme-prop(color, primary, false);
- text-decoration: underline;
- cursor: pointer;
- }
- }
-
- .editor .cm-dropCursor {
- border-left: 1.2px solid $cursor;
- }
-
- .editor .cm-gutters,
- .cm-panel {
- @include mdc-theme-prop(background-color, surface, false);
- @include mdc-theme-prop(color, text-hint-on-light, false);
- @include mdc-theme-prop(border-color, background, false);
- }
-
- .cm-panels-top,
- .cm-panels-bottom {
- @include mdc-theme-prop(border-color, background, false);
- }
-
- .editor .cm-activeLine {
- box-shadow: 0 0 0 2px $mdc-theme-sub-secondary;
- }
-
- .editor .cm-activeLineGutter {
- @include mdc-theme-prop(color, on-surface, false);
- }
-
- .ͼ2 .cm-activeLine:not(.cm-changedLine, .cm-deletedLine),
- .ͼ2 .cm-activeLineGutter:not(.cm-changedLineGutter, .cm-deletedLineGutter) {
- background-color: unset;
- }
-
- .editor .active-query {
- /* disable because look too ugly */
- /*
- display: inline-block;
- @include mdc-theme-prop(background, secondary, false);
- */
- }
-
- .editor .cm-gotoLine.cm-panel {
- display: flex;
- align-items: flex-end;
- flex-wrap: wrap;
- padding: 4px 8px;
- gap: 8px;
- min-width: 160px;
- container-type: inline-size;
-
- & label {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- text-transform: uppercase;
- letter-spacing: -0.1px;
- gap: 4px;
- }
-
- & input {
- @include mdc-typography('body2');
- max-width: 60px;
- height: 24px;
- padding-inline: 8px;
-
- &:focus {
- @include mdc-theme-prop(border-color, primary, false);
- }
- }
- & .cm-button {
- @include mdc-typography('body2');
- background: transparent;
- height: 24px;
- padding-block: 0;
- margin-right: 24px;
-
- font-weight: 500;
- text-transform: uppercase;
-
- color: var(--theme-primary);
- border-radius: 4px;
- border-color: var(--theme-primary);
-
- &:hover {
- background: color-mix(in srgb, transparent, var(--theme-primary) 5%);
- }
-
- @container (width < 240px) {
- display: none;
- }
- }
-
- & button[name='close'] {
- margin-left: auto;
- padding: 0 8px;
- top: 4px;
- height: 24px;
- width: 24px;
- border-radius: 4px;
- background: transparent;
- color: var(--theme-on-surface);
- border-color: var(--theme-on-surface);
- font-size: 16px;
-
- &:hover {
- background: color-mix(in srgb, transparent, var(--theme-on-surface) 5%);
- }
- }
- }
-
- .editor .cm-content ::selection {
- @include mdc-theme-prop(background, primary, false);
- color: white;
- }
-
- .editor .cm-lineNumbers .cm-gutterElement {
- min-width: 3ch;
- box-sizing: content-box;
- }
-
- .editor .cm-gutters .cm-foldGutter .cm-gutterElement {
- display: flex;
- align-items: center;
- cursor: pointer;
- user-select: none;
- }
-
- .editor .cm-gutters .cm-foldGutter .cm-gutterElement-icon {
- padding: 0 3px 0 5px;
- width: 20px;
- height: 12px;
- display: flex;
-
- &.cm-foldGutter-folded :global(svg) {
- transform: rotate(-90deg);
- }
- }
-
- .editor .cm-gutters .query-status .cm-gutterElement {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 14px;
-
- .running-query-line {
- display: flex;
- height: 8px;
- width: 8px;
- border-radius: 100%;
- @include mdc-theme-prop(background, primary, false);
- }
-
- .running-query-error-line {
- display: flex;
- height: 8px;
- width: 8px;
- border-radius: 100%;
- @include mdc-theme-prop(background, negative, false);
- }
- }
-
- .editor .tok-keyword {
- color: $keyword;
- font-weight: bold;
- }
-
- .editor .tok-operator {
- color: $operator;
- }
-
- .editor .tok-variable-2 {
- color: $variable-2;
- }
-
- .editor .tok-variable-3,
- .editor .tok-type {
- color: $variable-3;
- }
-
- .editor .tok-builtin {
- color: $builtin;
- }
-
- .editor .tok-atom {
- color: $atom;
- }
-
- .editor .tok-number {
- color: $number;
- }
-
- .editor .tok-def {
- color: $def;
- }
-
- .editor .tok-string {
- color: $string;
- }
-
- .editor .tok-string2 {
- color: $string-2;
- }
-
- .editor .tok-comment {
- color: $comment;
- }
-
- .editor .tok-variable {
- color: $variable;
- }
-
- .editor .tok-tag {
- color: $tag;
- }
-
- .editor .tok-meta {
- color: $meta;
- }
-
- .editor .tok-attribute {
- color: $attribute;
- }
-
- .editor .tok-property {
- color: $property;
- }
-
- .editor .tok-qualifier {
- color: $qualifier;
- }
-
- .editor .tok-variable-3,
- .editor .tok-type {
- color: $variable-3;
- }
-
- .editor .tok-typeName {
- color: $type-name;
- }
-
- .editor .tok-punctuation {
- color: $punctuation;
- }
-
- .editor .tok-propertyName {
- color: $property-name;
- }
-
- .editor .tok-className {
- color: $class-name;
- }
-
- .editor .tok-bool {
- color: $bool;
- }
-
- .editor .tok-variableName {
- color: $variable-name;
- }
-
- .editor .tok-labelName {
- color: $label-name;
- }
-}
diff --git a/webapp/packages/plugin-codemirror6/src/theme/base-code-editor-autocompletion.css b/webapp/packages/plugin-codemirror6/src/theme/base-code-editor-autocompletion.css
new file mode 100644
index 0000000000..f80a707396
--- /dev/null
+++ b/webapp/packages/plugin-codemirror6/src/theme/base-code-editor-autocompletion.css
@@ -0,0 +1,39 @@
+/* Increase specificity by selector repetition */
+.cm-tooltip.cm-tooltip {
+ &.cm-tooltip-autocomplete {
+ & > ul {
+ border-radius: var(--theme-form-element-radius);
+ }
+
+ & li {
+ display: flex;
+ align-items: center;
+
+ &:hover {
+ background: var(--theme-sub-secondary);
+ color: var(--theme-on-secondary);
+ }
+
+ &[aria-selected='true'] {
+ background: var(--theme-secondary);
+ color: var(--theme-text-primary-on-light);
+ }
+ }
+
+ & .cm-completionIcon {
+ opacity: 1;
+ width: 16px;
+ height: 16px;
+ padding: 0;
+ margin-right: 0.6em;
+
+ &:not([src]) {
+ opacity: 0;
+ }
+ }
+ }
+
+ &.cm-completionInfo {
+ margin-left: 8px;
+ }
+}
diff --git a/webapp/packages/plugin-codemirror6/src/theme/base-code-editor-tooltip.css b/webapp/packages/plugin-codemirror6/src/theme/base-code-editor-tooltip.css
new file mode 100644
index 0000000000..acd4fee8c9
--- /dev/null
+++ b/webapp/packages/plugin-codemirror6/src/theme/base-code-editor-tooltip.css
@@ -0,0 +1,14 @@
+@import '@cloudbeaver/plugin-tailwindcss-theme/tailwind.css';
+
+/* Increase specificity by selector repetition */
+.cm-tooltip.cm-tooltip {
+ @apply tw:typography-body2;
+ box-shadow:
+ 0px 3px 3px -2px rgba(0, 0, 0, 0.2),
+ 0px 3px 4px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 8px 0px rgba(0, 0, 0, 0.12);
+ background-color: var(--theme-surface);
+ color: var(--theme-on-surface);
+ border: none;
+ border-radius: var(--theme-form-element-radius);
+}
diff --git a/webapp/packages/plugin-codemirror6/src/theme/base-code-editor.css b/webapp/packages/plugin-codemirror6/src/theme/base-code-editor.css
new file mode 100644
index 0000000000..1cbf02a625
--- /dev/null
+++ b/webapp/packages/plugin-codemirror6/src/theme/base-code-editor.css
@@ -0,0 +1,327 @@
+@import '@cloudbeaver/plugin-tailwindcss-theme/tailwind.css';
+/* Increase specificity by selector repetition */
+.editor.editor,
+.cm-editor.cm-editor,
+.cm-mergeView.cm-mergeView,
+.cm-mergeViewEditors.cm-mergeViewEditors,
+.cm-scroller.cm-scroller,
+.ReactCodemirror.ReactCodemirror {
+ width: 100%;
+ height: 100% !important;
+}
+
+.editor.editor,
+.ReactCodemirror.ReactCodemirror,
+.cm-mergeView.cm-mergeView,
+.cm-mergeViewEditors.cm-mergeViewEditors,
+.cm-editor.cm-editor,
+.cm-gotoLine.cm-gotoLine {
+ @apply tw:typography-body2;
+}
+
+.cm-mergeViewEditor.cm-mergeViewEditor {
+ &:first-child {
+ border-right: 1px solid;
+ border-color: var(--theme-background);
+ }
+}
+
+.editor.editor {
+ background-color: var(--theme-surface);
+ color: var(--theme-on-surface);
+
+ & .cm-highlightTab {
+ opacity: 0.6;
+ color: var(--theme-text-hint-on-light);
+ pointer-events: none;
+ }
+
+ & .cm-newline {
+ color: var(--theme-text-hint-on-light);
+ opacity: 0.6;
+ margin-left: 4px;
+ cursor: default;
+ pointer-events: none;
+ }
+
+ & .cm-highlightSpace {
+ background-image: radial-gradient(circle at 50% 55%, var(--theme-text-hint-on-light) 15%, transparent 5%);
+ opacity: 0.6;
+ background-position: center;
+ }
+
+ & .cm-scroller {
+ outline: none;
+ line-height: unset;
+ }
+
+ & .cm-content {
+ caret-color: var(--editor-cursor);
+ }
+
+ & .cm-cursor {
+ border-left-color: var(--editor-cursor);
+ }
+
+ & .cm-link {
+ &.cm-link-loaded {
+ color: var(--theme-primary);
+ text-decoration: underline;
+ cursor: pointer;
+ }
+ }
+
+ & .cm-dropCursor {
+ border-left: 1.2px solid var(--editor-cursor);
+ }
+
+ & .cm-gutters {
+ background-color: var(--theme-surface);
+ color: var(--theme-text-hint-on-light);
+ border-color: var(--theme-background);
+ }
+
+ & .cm-activeLine {
+ box-shadow: 0 0 0 2px var(--theme-sub-secondary);
+ }
+
+ & .cm-activeLineGutter {
+ color: var(--theme-on-surface);
+ }
+
+ & .cm-gotoLine.cm-panel {
+ display: flex;
+ align-items: flex-end;
+ flex-wrap: wrap;
+ padding: 4px 8px;
+ gap: 8px;
+ min-width: 160px;
+ container-type: inline-size;
+
+ & label {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ text-transform: uppercase;
+ letter-spacing: -0.1px;
+ gap: 4px;
+ }
+
+ & input {
+ @apply tw:typography-body2;
+ max-width: 60px;
+ height: 24px;
+ padding-inline: 8px;
+
+ &:focus {
+ border-color: var(--theme-primary);
+ }
+ }
+ & .cm-button {
+ @apply tw:typography-body2;
+ background: transparent;
+ height: 24px;
+ padding-block: 0;
+ margin-right: 24px;
+
+ font-weight: 500;
+ text-transform: uppercase;
+
+ color: var(--theme-primary);
+ border-radius: 4px;
+ border-color: var(--theme-primary);
+
+ &:hover {
+ background: color-mix(in srgb, transparent, var(--theme-primary) 5%);
+ }
+
+ @container (width < 240px) {
+ display: none;
+ }
+ }
+
+ & button[name='close'] {
+ margin-left: auto;
+ padding: 0 8px;
+ top: 4px;
+ height: 24px;
+ width: 24px;
+ border-radius: 4px;
+ background: transparent;
+ color: var(--theme-on-surface);
+ border-color: var(--theme-on-surface);
+ font-size: 16px;
+
+ &:hover {
+ background: color-mix(in srgb, transparent, var(--theme-on-surface) 5%);
+ }
+ }
+ }
+
+ & .cm-content ::selection {
+ background: var(--theme-primary);
+ color: white;
+ }
+
+ & .cm-lineNumbers .cm-gutterElement {
+ min-width: 3ch;
+ box-sizing: content-box;
+ }
+
+ & .cm-gutters .cm-foldGutter .cm-gutterElement {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ user-select: none;
+ }
+
+ & .cm-gutters .cm-foldGutter .cm-gutterElement-icon {
+ padding: 0 3px 0 5px;
+ width: 20px;
+ height: 12px;
+ display: flex;
+
+ &.cm-foldGutter-folded svg {
+ transform: rotate(-90deg);
+ }
+ }
+
+ & .cm-gutters .query-status .cm-gutterElement {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 14px;
+
+ .running-query-line {
+ display: flex;
+ height: 8px;
+ width: 8px;
+ border-radius: 100%;
+ background: var(--theme-primary);
+ }
+
+ .running-query-error-line {
+ display: flex;
+ height: 8px;
+ width: 8px;
+ border-radius: 100%;
+ background: var(--theme-negative);
+ }
+ }
+
+ & .tok-keyword {
+ color: var(--editor-keyword);
+ font-weight: bold;
+ }
+
+ & .tok-operator {
+ color: var(--editor-operator);
+ }
+
+ & .tok-variable-2 {
+ color: var(--editor-variable-2);
+ }
+
+ & .tok-variable-3,
+ & .tok-type {
+ color: var(--editor-variable-3);
+ }
+
+ & .tok-builtin {
+ color: var(--editor-builtin);
+ }
+
+ & .tok-atom {
+ color: var(--editor-atom);
+ }
+
+ & .tok-number {
+ color: var(--editor-number);
+ }
+
+ & .tok-def {
+ color: var(--editor-def);
+ }
+
+ & .tok-string {
+ color: var(--editor-string);
+ }
+
+ & .tok-string2 {
+ color: var(--editor-string-2);
+ }
+
+ & .tok-comment {
+ color: var(--editor-comment);
+ }
+
+ & .tok-variable {
+ color: var(--editor-variable);
+ }
+
+ & .tok-tag {
+ color: var(--editor-tag);
+ }
+
+ & .tok-meta {
+ color: var(--editor-meta);
+ }
+
+ & .tok-attribute {
+ color: var(--editor-attribute);
+ }
+
+ & .tok-property {
+ color: var(--editor-property);
+ }
+
+ & .tok-qualifier {
+ color: var(--editor-qualifier);
+ }
+
+ & .tok-typeName {
+ color: var(--editor-type-name);
+ }
+
+ & .tok-punctuation {
+ color: var(--editor-punctuation);
+ }
+
+ & .tok-propertyName {
+ color: var(--editor-property-name);
+ }
+
+ & .tok-className {
+ color: var(--editor-class-name);
+ }
+
+ & .tok-bool {
+ color: var(--editor-bool);
+ }
+
+ & .tok-variableName {
+ color: var(--editor-variable-name);
+ }
+
+ & .tok-labelName {
+ color: var(--editor-label-name);
+ }
+}
+
+.cm-panel.cm-panel {
+ background-color: var(--theme-surface);
+ color: var(--theme-text-hint-on-light);
+ border-color: var(--theme-background);
+}
+
+.cm-panels-top.cm-panels-top,
+.cm-panels-bottom.cm-panels-bottom {
+ border-color: var(--theme-background) !important;
+}
+
+.ͼ2.ͼ2 {
+ & .cm-activeLine:not(.cm-changedLine, .cm-deletedLine),
+ & .cm-activeLineGutter:not(.cm-changedLineGutter, .cm-deletedLineGutter) {
+ background-color: unset;
+ }
+}
diff --git a/webapp/packages/plugin-codemirror6/src/theme/dark.css b/webapp/packages/plugin-codemirror6/src/theme/dark.css
new file mode 100644
index 0000000000..1a2d0b92cf
--- /dev/null
+++ b/webapp/packages/plugin-codemirror6/src/theme/dark.css
@@ -0,0 +1,31 @@
+.theme-dark {
+ --editor-meta: #ff1717;
+ --editor-keyword: rgb(115, 158, 202);
+ --editor-atom: #56c8d8;
+ --editor-number: rgb(192, 192, 192);
+ --editor-def: #00f;
+ --editor-variable: rgb(126, 186, 211);
+ --editor-variable-2: rgb(193, 170, 108);
+ --editor-variable-3: rgb(193, 170, 108);
+ --editor-property: rgb(126, 186, 211);
+ --editor-operator: rgb(126, 186, 211);
+ --editor-comment: rgb(102, 151, 104);
+ --editor-string: rgb(202, 197, 128);
+ --editor-string-2: #f50;
+ --editor-qualifier: #555;
+ --editor-builtin: #ab87ff;
+ --editor-bracket: #cc7;
+ --editor-tag: #170;
+ --editor-attribute: #00c;
+ --editor-link: #219;
+ --editor-error: #f00;
+ --editor-delimiter: rgb(238, 204, 100);
+ --editor-cursor: #fff;
+ --editor-type-name: #c586c0;
+ --editor-class-name: #c586c0;
+ --editor-punctuation: #ffffff8c;
+ --editor-property-name: #569cd6;
+ --editor-bool: #56c8d8;
+ --editor-variable-name: #56c8d8;
+ --editor-label-name: #cf6edf;
+}
diff --git a/webapp/packages/plugin-codemirror6/src/theme/dark.module.scss b/webapp/packages/plugin-codemirror6/src/theme/dark.module.scss
deleted file mode 100644
index d8ce497fb0..0000000000
--- a/webapp/packages/plugin-codemirror6/src/theme/dark.module.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@import '@cloudbeaver/core-theming/src/styles/theme-dark';
-@import './base-code-editor';
-@import './base-code-editor-autocompletion';
-@import './base-code-editor-tooltip';
-
-$meta: #ff1717;
-$keyword: rgb(115, 158, 202);
-$atom: #56c8d8;
-$number: rgb(192, 192, 192);
-$def: #00f;
-$variable: rgb(126, 186, 211);
-$variable-2: rgb(193, 170, 108);
-$variable-3: rgb(193, 170, 108);
-$property: rgb(126, 186, 211);
-$operator: rgb(126, 186, 211);
-$comment: rgb(102, 151, 104);
-$string: rgb(202, 197, 128);
-$string-2: #f50;
-$qualifier: #555;
-$builtin: #ab87ff;
-$bracket: #cc7;
-$tag: #170;
-$attribute: #00c;
-$link: #219;
-$error: #f00;
-$delimiter: rgb(238, 204, 100);
-$cursor: #fff;
-$active-query: $color-positive;
-$type-name: #c586c0;
-$class-name: #c586c0;
-$punctuation: #ffffff8c;
-$property-name: #569cd6;
-$bool: #56c8d8;
-$variable-name: #56c8d8;
-$label-name: #cf6edf;
-
-:global .#{$theme-class} {
- @include base-code-editor;
- @include base-code-editor-autocompletion;
- @include base-code-editor-tooltip;
-}
diff --git a/webapp/packages/plugin-codemirror6/src/theme/light.css b/webapp/packages/plugin-codemirror6/src/theme/light.css
new file mode 100644
index 0000000000..d1d8028dc8
--- /dev/null
+++ b/webapp/packages/plugin-codemirror6/src/theme/light.css
@@ -0,0 +1,31 @@
+.theme-light {
+ --editor-meta: #ff1717;
+ --editor-keyword: #07a;
+ --editor-atom: #905;
+ --editor-number: #905;
+ --editor-def: #00f;
+ --editor-variable: black;
+ --editor-variable-2: #a8bd00;
+ --editor-variable-3: #a8bd00;
+ --editor-property: black;
+ --editor-operator: #a67f59;
+ --editor-comment: #3f7f5f;
+ --editor-string: #1f8900;
+ --editor-string-2: #f50;
+ --editor-qualifier: #555;
+ --editor-builtin: #07a;
+ --editor-bracket: #cc7;
+ --editor-tag: #170;
+ --editor-attribute: #00c;
+ --editor-link: #905;
+ --editor-error: #f00;
+ --editor-delimiter: rgb(238, 204, 100);
+ --editor-cursor: #000;
+ --editor-type-name: #007acc;
+ --editor-class-name: #007acc;
+ --editor-punctuation: #6d6d6d;
+ --editor-property-name: #c42626;
+ --editor-bool: #905;
+ --editor-variable-name: #905;
+ --editor-label-name: #81a1c1;
+}
diff --git a/webapp/packages/plugin-codemirror6/src/theme/light.module.scss b/webapp/packages/plugin-codemirror6/src/theme/light.module.scss
deleted file mode 100644
index aad7e81507..0000000000
--- a/webapp/packages/plugin-codemirror6/src/theme/light.module.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
- *
- * Licensed under the Apache License, Version 2.0.
- * you may not use this file except in compliance with the License.
- */
-
-@import '@cloudbeaver/core-theming/src/styles/theme-light';
-@import './base-code-editor';
-@import './base-code-editor-autocompletion';
-@import './base-code-editor-tooltip';
-
-$meta: #ff1717;
-$keyword: #07a;
-$atom: #905;
-$number: #905;
-$def: #00f;
-$variable: black;
-$variable-2: #a8bd00;
-$variable-3: #a8bd00;
-$property: black;
-$operator: #a67f59;
-$comment: #3f7f5f;
-$string: #1f8900;
-$string-2: #f50;
-$qualifier: #555;
-$builtin: #07a;
-$bracket: #cc7;
-$tag: #170;
-$attribute: #00c;
-$link: #905;
-$error: #f00;
-$delimiter: rgb(238, 204, 100);
-$cursor: #000;
-$active-query: $color-positive;
-$type-name: #007acc;
-$class-name: #007acc;
-$punctuation: #6d6d6d;
-$property-name: #c42626;
-$bool: #905;
-$variable-name: #905;
-$label-name: #81a1c1;
-
-:global .#{$theme-class} {
- @include base-code-editor;
- @include base-code-editor-autocompletion;
- @include base-code-editor-tooltip;
-}
diff --git a/webapp/packages/plugin-codemirror6/src/theme/styles.ts b/webapp/packages/plugin-codemirror6/src/theme/styles.ts
index 35199acad6..0370735f6a 100644
--- a/webapp/packages/plugin-codemirror6/src/theme/styles.ts
+++ b/webapp/packages/plugin-codemirror6/src/theme/styles.ts
@@ -1,24 +1,24 @@
/*
* CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2024 DBeaver Corp and others
+ * Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { ThemeSelector } from '@cloudbeaver/core-theming';
-
-import type Dark from './dark.module.scss';
-import type Light from './light.module.scss';
+import './base-code-editor.css';
+import './base-code-editor-autocompletion.css';
+import './base-code-editor-tooltip.css';
export const EDITOR_BASE_STYLES: ThemeSelector = async theme => {
- let styles: typeof Light & typeof Dark;
+ let styles: any;
switch (theme) {
case 'dark':
- styles = (await import('./dark.module.scss')).default;
+ styles = (await import('./dark.css')).default;
break;
default:
- styles = (await import('./light.module.scss')).default;
+ styles = (await import('./light.css')).default;
break;
}
diff --git a/webapp/packages/plugin-codemirror6/tsconfig.json b/webapp/packages/plugin-codemirror6/tsconfig.json
index 7ef04e01e0..b551442b8b 100644
--- a/webapp/packages/plugin-codemirror6/tsconfig.json
+++ b/webapp/packages/plugin-codemirror6/tsconfig.json
@@ -27,6 +27,9 @@
},
{
"path": "../core-utils"
+ },
+ {
+ "path": "../plugin-tailwindcss-theme"
}
],
"include": [
diff --git a/webapp/packages/plugin-connection-preferences/src/ConnectionPreferencesForm/ConnectionPreferencesForm.tsx b/webapp/packages/plugin-connection-preferences/src/ConnectionPreferencesForm/ConnectionPreferencesForm.tsx
index 19348bcbf8..49545a3bcc 100644
--- a/webapp/packages/plugin-connection-preferences/src/ConnectionPreferencesForm/ConnectionPreferencesForm.tsx
+++ b/webapp/packages/plugin-connection-preferences/src/ConnectionPreferencesForm/ConnectionPreferencesForm.tsx
@@ -61,7 +61,7 @@ export const ConnectionPreferencesForm = observer