diff --git a/webapp/packages/core-app/src/AppScreen/Main.m.css b/webapp/packages/core-app/src/AppScreen/Main.m.css new file mode 100644 index 0000000000..112e12bdde --- /dev/null +++ b/webapp/packages/core-app/src/AppScreen/Main.m.css @@ -0,0 +1,15 @@ +.space { + composes: theme-typography--body2 theme-background-primary from global; + display: flex; + flex-direction: row; + flex: 1; + overflow: hidden; +} +.pane { + composes: theme-background-surface theme-text-on-surface from global; + display: flex; + position: relative; +} +.loader { + height: 100%; +} diff --git a/webapp/packages/core-app/src/AppScreen/Main.tsx b/webapp/packages/core-app/src/AppScreen/Main.tsx index 5f7f3dff4b..d22b1173c9 100644 --- a/webapp/packages/core-app/src/AppScreen/Main.tsx +++ b/webapp/packages/core-app/src/AppScreen/Main.tsx @@ -6,45 +6,35 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; -import { getComputed, Loader, Pane, ResizerControls, Split, splitStyles, useSplitUserState, useStyles } from '@cloudbeaver/core-blocks'; +import { getComputed, Loader, Pane, ResizerControls, s, Split, useS, useSplitUserState } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { LeftBarPanelService, SideBarPanel, SideBarPanelService } from '@cloudbeaver/core-ui'; +import style from './Main.m.css'; import { RightArea } from './RightArea'; -const mainStyles = css` - space { - composes: theme-typography--body2 theme-background-primary from global; - } - Pane { - composes: theme-background-surface theme-text-on-surface from global; - display: flex; - position: relative; - overflow: hidden; - } - Loader { - height: 100%; - } -`; - export const Main = observer(function Main() { + const styles = useS(style); const sideBarPanelService = useService(SideBarPanelService); const leftBarPanelService = useService(LeftBarPanelService); - const styles = useStyles(mainStyles, splitStyles); const splitMainState = useSplitUserState('main'); const splitRightState = useSplitUserState('main-right'); const sideBarDisabled = getComputed(() => sideBarPanelService.tabsContainer.getDisplayed().length === 0); const leftBarDisabled = getComputed(() => leftBarPanelService.tabsContainer.getDisplayed().length === 0); - return styled(styles)( - - - - + return ( + +
+ + @@ -52,19 +42,19 @@ export const Main = observer(function Main() { - + - - + + - - , +
+
); }); diff --git a/webapp/packages/core-app/src/AppScreen/RightArea.m.css b/webapp/packages/core-app/src/AppScreen/RightArea.m.css new file mode 100644 index 0000000000..0ea8e73fb2 --- /dev/null +++ b/webapp/packages/core-app/src/AppScreen/RightArea.m.css @@ -0,0 +1,6 @@ +.loader { + height: 100%; +} +.slideBox { + flex: 1; +} diff --git a/webapp/packages/core-app/src/AppScreen/RightArea.tsx b/webapp/packages/core-app/src/AppScreen/RightArea.tsx index 6937e68bc6..105104905b 100644 --- a/webapp/packages/core-app/src/AppScreen/RightArea.tsx +++ b/webapp/packages/core-app/src/AppScreen/RightArea.tsx @@ -6,46 +6,21 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; -import { - Loader, - Pane, - ResizerControls, - SlideBox, - slideBoxStyles, - SlideElement, - SlideOverlay, - Split, - splitHorizontalStyles, - splitStyles, - useSplitUserState, - useStyles, -} from '@cloudbeaver/core-blocks'; +import { Loader, Pane, ResizerControls, s, SlideBox, SlideElement, SlideOverlay, Split, useS, useSplitUserState } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { OptionsPanelService } from '@cloudbeaver/core-ui'; import { NavigationTabsBar } from '@cloudbeaver/plugin-navigation-tabs'; import { ToolsPanel, ToolsPanelService } from '@cloudbeaver/plugin-tools-panel'; -const styles = css` - Pane { - composes: theme-background-surface theme-text-on-surface from global; - display: flex; - overflow: auto; - } - Loader { - height: 100%; - } - SlideBox { - flex: 1; - } -`; +import style from './RightArea.m.css'; interface Props { className?: string; } export const RightArea = observer(function RightArea({ className }) { + const styles = useS(style); const toolsPanelService = useService(ToolsPanelService); const optionsPanelService = useService(OptionsPanelService); const splitState = useSplitUserState('right-area'); @@ -55,29 +30,29 @@ export const RightArea = observer(function RightArea({ className }) { const toolsDisabled = activeTools.length === 0 || toolsPanelService.disabled; - return styled(useStyles(styles, splitStyles, splitHorizontalStyles, slideBoxStyles))( - + return ( + - + - + - + optionsPanelService.close()} /> - , + ); }); diff --git a/webapp/packages/core-app/src/Body.m.css b/webapp/packages/core-app/src/Body.m.css new file mode 100644 index 0000000000..60f9ce527a --- /dev/null +++ b/webapp/packages/core-app/src/Body.m.css @@ -0,0 +1,8 @@ +.bodyContent { + composes: theme-background-surface theme-text-on-surface theme-typography from global; + height: 100vh; + display: flex; + padding: 0 !important; + flex-direction: column; + overflow: hidden; +} diff --git a/webapp/packages/core-app/src/Body.tsx b/webapp/packages/core-app/src/Body.tsx index a4b52dde4d..6b8edd8dba 100644 --- a/webapp/packages/core-app/src/Body.tsx +++ b/webapp/packages/core-app/src/Body.tsx @@ -7,9 +7,8 @@ */ import { observer } from 'mobx-react-lite'; import { useLayoutEffect, useRef } from 'react'; -import styled, { css } from 'reshadow'; -import { Loader, useResource, useStyles } from '@cloudbeaver/core-blocks'; +import { Loader, s, useResource, useS, useStyles } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { DialogsPortal } from '@cloudbeaver/core-dialogs'; import { Notifications } from '@cloudbeaver/core-notifications'; @@ -21,24 +20,12 @@ import { ThemeService } from '@cloudbeaver/core-theming'; import { DNDProvider } from '@cloudbeaver/core-ui'; import { useAppVersion } from '@cloudbeaver/plugin-version'; -const bodyStyles = css` - theme { - composes: theme-background-surface theme-text-on-surface theme-typography from global; - height: 100vh; - display: flex; - padding: 0 !important; /* fix additional padding with modal reakit menu */ - flex-direction: column; - overflow: hidden; - } - Loader { - height: 100vh; - } -`; +import style from './Body.m.css'; export const Body = observer(function Body() { // const serverConfigLoader = useResource(Body, ServerConfigResource, undefined); + const styles = useS(style); const themeService = useService(ThemeService); - const style = useStyles(bodyStyles); const ref = useRef(null); useResource(Body, SessionPermissionsResource, undefined); const screenService = useService(ScreenService); @@ -56,15 +43,15 @@ export const Body = observer(function Body() { document.documentElement.dataset.backendVersion = backendVersion; }); - return styled(style)( + return ( - +
{Screen && } - +
-
, + ); }); diff --git a/webapp/packages/core-blocks/src/AppRefreshButton.m.css b/webapp/packages/core-blocks/src/AppRefreshButton.m.css new file mode 100644 index 0000000000..5e08d0eeb3 --- /dev/null +++ b/webapp/packages/core-blocks/src/AppRefreshButton.m.css @@ -0,0 +1,20 @@ +.button { + color: white; + font-weight: 500; + background-color: #2a7cb4; + padding: 5px 16px; + border-radius: 4px; + letter-spacing: 0.08929em; + font-size: 0.875rem; + text-transform: uppercase; + cursor: pointer; + outline: none; + border: none; + &:hover, + &:focus { + opacity: 0.8; + } + &:active { + opacity: 0.5; + } +} diff --git a/webapp/packages/core-blocks/src/AppRefreshButton.tsx b/webapp/packages/core-blocks/src/AppRefreshButton.tsx index a9d7849d86..59bd28501d 100644 --- a/webapp/packages/core-blocks/src/AppRefreshButton.tsx +++ b/webapp/packages/core-blocks/src/AppRefreshButton.tsx @@ -6,32 +6,11 @@ * you may not use this file except in compliance with the License. */ import type React from 'react'; -import styled, { css } from 'reshadow'; import { App, useService } from '@cloudbeaver/core-di'; +import { clsx } from '@cloudbeaver/core-utils'; -const style = css` - button { - color: white; - font-weight: 500; - background-color: #2a7cb4; - padding: 5px 16px; - border-radius: 4px; - letter-spacing: 0.08929em; - font-size: 0.875rem; - text-transform: uppercase; - cursor: pointer; - outline: none; - border: none; - &:hover, - &:focus { - opacity: 0.8; - } - &:active { - opacity: 0.5; - } - } -`; +import style from './AppRefreshButton.m.css'; interface IProps { className?: string; @@ -44,9 +23,9 @@ export const AppRefreshButton: React.FC = function AppRefreshButton({ cl app.start(); } - return styled(style)( - , + ); }; diff --git a/webapp/packages/core-blocks/src/Button.m.css b/webapp/packages/core-blocks/src/Button.m.css new file mode 100644 index 0000000000..73d5a3c61d --- /dev/null +++ b/webapp/packages/core-blocks/src/Button.m.css @@ -0,0 +1,62 @@ +.buttonLabel { + composes: theme-button__label from global; +} +.buttonIcon { + composes: theme-button__icon from global; +} +.ripple { + composes: theme-button_ripple from global; +} + +.button { + composes: theme-button from global; + display: flex; + + & .buttonLabel { + line-height: 1; + opacity: 1; + } + + & .buttonIcon { + & > * { + width: 100%; + } + + &.disabled { + opacity: 0.5; + } + } + + & .loader, + & .buttonLabel { + transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 0.3s; + } + + & .loader { + position: absolute; + opacity: 0 !important; + } + + &.loading { + & .loader { + opacity: 1 !important; + } + + & .buttonLabel { + opacity: 0; + } + } +} + +.raised { + composes: theme-button_raised from global; +} +.unelevated { + composes: theme-button_unelevated from global; +} +.outlined { + composes: theme-button_outlined from global; +} +.secondary { + composes: theme-button_secondary from global; +} diff --git a/webapp/packages/core-blocks/src/Button.tsx b/webapp/packages/core-blocks/src/Button.tsx index 6bcfab94dd..ff9944ef14 100644 --- a/webapp/packages/core-blocks/src/Button.tsx +++ b/webapp/packages/core-blocks/src/Button.tsx @@ -7,91 +7,16 @@ */ import { observable } from 'mobx'; import { observer } from 'mobx-react-lite'; -import styled, { css, use } from 'reshadow'; - -import type { ComponentStyle } from '@cloudbeaver/core-theming'; +import style from './Button.m.css'; import { IconOrImage } from './IconOrImage'; import { Loader } from './Loader/Loader'; +import { s } from './s'; import { useObjectRef } from './useObjectRef'; import { useObservableRef } from './useObservableRef'; -import { useStyles } from './useStyles'; - -const buttonStyles = css` - button-label { - composes: theme-button__label from global; - } - button-icon { - composes: theme-button__icon from global; - } - ripple { - composes: theme-button_ripple from global; - } - Button { - composes: theme-button from global; - display: flex; - - & IconOrImage { - width: 100%; - } - - &[disabled] IconOrImage { - opacity: 0.5; - } - - & Loader, - & button-label { - transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 0.3s; - } +import { useS } from './useS'; - & Loader { - position: absolute; - opacity: 0 !important; - } - - & button-label { - line-height: 1; - opacity: 1; - } - - &[|loading] { - & Loader { - opacity: 1 !important; - } - - & button-label { - opacity: 0; - } - } - - &[href] { - text-decoration: none !important; - } - } -`; - -const buttonMod = { - raised: css` - Button { - composes: theme-button_raised from global; - } - `, - unelevated: css` - Button { - composes: theme-button_unelevated from global; - } - `, - outlined: css` - Button { - composes: theme-button_outlined from global; - } - `, - secondary: css` - Button { - composes: theme-button_secondary from global; - } - `, -}; +type ButtonMod = Array<'raised' | 'unelevated' | 'outlined' | 'secondary'>; type ButtonProps = (React.ButtonHTMLAttributes & React.LinkHTMLAttributes & @@ -99,8 +24,7 @@ type ButtonProps = (React.ButtonHTMLAttributes; + mod?: ButtonMod; tag?: 'button' | 'a' | 'div'; href?: string; target?: '_blank' | '_self' | '_parent' | '_top'; @@ -114,7 +38,6 @@ export const Button = observer(function Button({ icon, viewBox, mod, - styles, tag = 'button', type = 'button', disabled = false, @@ -124,6 +47,7 @@ export const Button = observer(function Button({ className, ...rest }) { + const styles = useS(style); const handlersRef = useObjectRef({ onClick }); const state = useObservableRef( () => ({ @@ -155,16 +79,33 @@ export const Button = observer(function Button({ } const Button = tag; - return styled(useStyles(styles, buttonStyles, ...(mod || []).map(mod => buttonMod[mod])))( - , + {children} + + ); }); diff --git a/webapp/packages/core-blocks/src/Cell.m.css b/webapp/packages/core-blocks/src/Cell.m.css new file mode 100644 index 0000000000..34a58ddfbd --- /dev/null +++ b/webapp/packages/core-blocks/src/Cell.m.css @@ -0,0 +1,32 @@ +.main { + position: relative; + display: flex; + align-items: center; + padding: 8px; +} +.before { + margin-right: 16px; + width: 24px; + height: 24px; + flex-shrink: 0; +} +.after { + margin-left: 16px; + flex-shrink: 0; +} +.info { + composes: theme-typography--body2 from global; + flex: 1; + line-height: 1.4; + display: flex; + flex-direction: column; + font-weight: 500; +} +.description { + composes: theme-typography--caption from global; + line-height: 1.2; +} + +.ripple { + composes: theme-ripple from global; +} diff --git a/webapp/packages/core-blocks/src/Cell.tsx b/webapp/packages/core-blocks/src/Cell.tsx index 9c1e5b1dd4..c3cd42ee51 100644 --- a/webapp/packages/core-blocks/src/Cell.tsx +++ b/webapp/packages/core-blocks/src/Cell.tsx @@ -5,77 +5,34 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled, { css } from 'reshadow'; +import { observer } from 'mobx-react-lite'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; - -import { useStyles } from './useStyles'; +import style from './Cell.m.css'; +import { s } from './s'; +import { useS } from './useS'; interface Props { description?: React.ReactElement | string; before?: React.ReactElement; after?: React.ReactElement; - style?: ComponentStyle; ripple?: boolean; className?: string; + children?: React.ReactNode; } -const styles = css` - main { - position: relative; - display: flex; - align-items: center; - padding: 8px; - } - before { - margin-right: 16px; - width: 24px; - height: 24px; - flex-shrink: 0; - } - after { - margin-left: 16px; - flex-shrink: 0; - } - info { - composes: theme-typography--body2 from global; - flex: 1; - line-height: 1.4; - display: flex; - flex-direction: column; - font-weight: 500; - } - description { - composes: theme-typography--caption from global; - line-height: 1.2; - } -`; - -const RIPPLE_STYLES = css` - cell { - composes: theme-ripple from global; - } -`; +export const Cell = observer(function Cell({ before, after, description, className, ripple = true, children }) { + const styles = useS(style); -export const Cell: React.FC> = function Cell({ - before, - after, - description, - style, - className, - ripple = true, - children, -}) { - return styled(useStyles(styles, style, ripple && RIPPLE_STYLES))( - -
- {before} - + return ( +
+
+
{before}
+
{children} - {description && {description}} - - {after} + {description &&
{description}
} +
+
{after}
- , +
); -}; +}); diff --git a/webapp/packages/core-blocks/src/Code.m.css b/webapp/packages/core-blocks/src/Code.m.css new file mode 100644 index 0000000000..72d27418eb --- /dev/null +++ b/webapp/packages/core-blocks/src/Code.m.css @@ -0,0 +1,5 @@ +.codeContainer { + composes: theme-background-secondary theme-text-on-secondary from global; + padding: 16px; + border-radius: var(--theme-group-element-radius); +} diff --git a/webapp/packages/core-blocks/src/Code.tsx b/webapp/packages/core-blocks/src/Code.tsx index 78067153c6..5ddd3097e5 100644 --- a/webapp/packages/core-blocks/src/Code.tsx +++ b/webapp/packages/core-blocks/src/Code.tsx @@ -5,24 +5,22 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled, { css } from 'reshadow'; +import style from './Code.m.css'; +import { s } from './s'; +import { useS } from './useS'; +import {observer} from "mobx-react-lite"; interface Props { className?: string; + children?: React.ReactNode; } -const styles = css` - code-container { - composes: theme-background-secondary theme-text-on-secondary from global; - padding: 16px; - border-radius: var(--theme-group-element-radius); - } -`; +export const Code = observer(function Code({ children, className }) { + const styles = useS(style); -export const Code: React.FC> = function Code({ children, className }) { - return styled(styles)( - + return ( +
{children} - , +
); -}; +}); diff --git a/webapp/packages/core-blocks/src/ConnectionImageWithMask/ConnectionMark.tsx b/webapp/packages/core-blocks/src/ConnectionImageWithMask/ConnectionMark.tsx index 22d0a349ee..7c4620acc6 100644 --- a/webapp/packages/core-blocks/src/ConnectionImageWithMask/ConnectionMark.tsx +++ b/webapp/packages/core-blocks/src/ConnectionImageWithMask/ConnectionMark.tsx @@ -16,7 +16,8 @@ interface Props { className?: string; } -export const ConnectionMark: React.FC = observer(function ConnectionMark({ connected, className }) { +export const ConnectionMark = observer(function ConnectionMark({ connected, className }) { const styles = useS(style); + return
; }); diff --git a/webapp/packages/core-blocks/src/DisplayError.m.css b/webapp/packages/core-blocks/src/DisplayError.m.css new file mode 100644 index 0000000000..a9dca10b17 --- /dev/null +++ b/webapp/packages/core-blocks/src/DisplayError.m.css @@ -0,0 +1,25 @@ +.error { + width: 100%; + height: 100%; + display: flex; + overflow: auto; + + &.root { + height: 100vh; + } +} +.errorInnerBlock { + display: flex; + margin: auto; + padding: 16px 24px; + flex-direction: column; + align-items: center; +} +.notificationMark { + width: 40px; + height: 40px; +} +.details { + padding: 8px 16px; + white-space: pre-wrap; +} diff --git a/webapp/packages/core-blocks/src/DisplayError.tsx b/webapp/packages/core-blocks/src/DisplayError.tsx index f3d130246c..401bbac9ef 100644 --- a/webapp/packages/core-blocks/src/DisplayError.tsx +++ b/webapp/packages/core-blocks/src/DisplayError.tsx @@ -5,69 +5,44 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ +import { observer } from 'mobx-react-lite'; import type React from 'react'; -import styled, { css, use } from 'reshadow'; import { ENotificationType } from '@cloudbeaver/core-events'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { AppRefreshButton } from './AppRefreshButton'; +import style from './DisplayError.m.css'; +import { s } from './s'; import { NotificationMark } from './Snackbars/NotificationMark'; -import { useStyles } from './useStyles'; - -const style = css` - error { - width: 100%; - height: 100%; - display: flex; - overflow: auto; - - &[|root] { - height: 100vh; - } - } - error-inner-block { - display: flex; - margin: auto; - padding: 16px 24px; - flex-direction: column; - align-items: center; - } - NotificationMark { - width: 40px; - height: 40px; - } - details { - padding: 8px 16px; - } -`; +import { useS } from './useS'; interface Props { root?: boolean; error?: Error; errorInfo?: React.ErrorInfo; className?: string; - styles?: ComponentStyle; + children?: React.ReactNode; } -export const DisplayError: React.FC> = function DisplayError({ root, children, error, errorInfo, className, styles }) { +export const DisplayError = observer(function DisplayError({ root, children, error, errorInfo, className }) { + const styles = useS(style); const stack = errorInfo?.componentStack || error?.stack; - return styled(useStyles(style, styles))( - - - + return ( +
+
+

Something went wrong.

{root && } {children} {error && ( -
+
{error.toString()} {stack &&
} {stack} -
+
)} - - , +
+
); -}; +}); diff --git a/webapp/packages/core-blocks/src/ErrorBoundary.m.css b/webapp/packages/core-blocks/src/ErrorBoundary.m.css new file mode 100644 index 0000000000..0db5ac2ab6 --- /dev/null +++ b/webapp/packages/core-blocks/src/ErrorBoundary.m.css @@ -0,0 +1,3 @@ +.action { + padding: 8px 16px; +} diff --git a/webapp/packages/core-blocks/src/ErrorBoundary.tsx b/webapp/packages/core-blocks/src/ErrorBoundary.tsx index 907e9b1eb6..95e042db91 100644 --- a/webapp/packages/core-blocks/src/ErrorBoundary.tsx +++ b/webapp/packages/core-blocks/src/ErrorBoundary.tsx @@ -6,29 +6,21 @@ * you may not use this file except in compliance with the License. */ import React, { ErrorInfo } from 'react'; -import styled, { css } from 'reshadow'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { errorOf, LoadingError } from '@cloudbeaver/core-utils'; import { Button } from './Button'; import { DisplayError } from './DisplayError'; +import style from './ErrorBoundary.m.css'; import { ErrorContext, IExceptionContext } from './ErrorContext'; import { ExceptionMessage } from './ExceptionMessage'; -const style = css` - action { - padding: 8px 16px; - } -`; - interface Props { icon?: boolean; root?: boolean; inline?: boolean; remount?: boolean; className?: string; - styles?: ComponentStyle; onClose?: () => any; onRefresh?: () => any; } @@ -48,6 +40,7 @@ export class ErrorBoundary extends React.Component + return ( + {onClose && ( - +
- +
)} {this.canRefresh && ( - +
- +
)} -
, + ); } else { return ( @@ -100,7 +93,6 @@ export class ErrorBoundary extends React.Component diff --git a/webapp/packages/core-blocks/src/ExceptionMessage.m.css b/webapp/packages/core-blocks/src/ExceptionMessage.m.css new file mode 100644 index 0000000000..6001353799 --- /dev/null +++ b/webapp/packages/core-blocks/src/ExceptionMessage.m.css @@ -0,0 +1,107 @@ +.errorName { + composes: theme-typography--headline6 from global; +} + +.error { + flex: 1; + display: flex; + padding: 24px; + + &.icon { + padding: 0; + height: 100%; + width: 100%; + max-height: 24px; + max-width: 24px; + + & .errorIcon { + display: flex; + align-items: center; + align-content: center; + + & .iconOrImage { + height: 100%; + width: 100%; + } + } + } + + & .errorData { + padding: 0 16px; + + & .errorName { + height: 40px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + margin: 0; + + & span { + display: inline-block; + vertical-align: middle; + line-height: normal; + } + } + + .errorMessage { + flex: 1; + overflow: auto; + white-space: pre-wrap; + } + + .errorActions { + display: flex; + flex-shrink: 0; + align-items: center; + margin-top: 16px; + gap: 16px; + } + } + + &.inline { + align-items: center; + height: 38px; + padding: 0; + + & .errorData { + display: flex; + align-items: center; + padding: 0; + } + + & .errorIcon { + display: flex; + align-items: center; + align-content: center; + + & .iconOrImage { + height: 24px; + width: 24px; + } + } + + & .errorMessage { + line-height: 1.2; + -webkit-line-clamp: 2; + display: -webkit-box; + -webkit-box-orient: vertical; + overflow: hidden; + padding: 0 16px; + } + & .errorName { + display: none; + } + & .errorActions { + margin-top: 0; + } + } + + .errorActionClose { + cursor: pointer; + width: 18px; + height: 18px; + flex-shrink: 0; + } +} + + diff --git a/webapp/packages/core-blocks/src/ExceptionMessage.tsx b/webapp/packages/core-blocks/src/ExceptionMessage.tsx index 1b1a847d11..c0361409da 100644 --- a/webapp/packages/core-blocks/src/ExceptionMessage.tsx +++ b/webapp/packages/core-blocks/src/ExceptionMessage.tsx @@ -6,129 +6,27 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css, use } from 'reshadow'; - -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { Button } from './Button'; +import style from './ExceptionMessage.m.css'; import { Icon } from './Icon'; import { IconOrImage } from './IconOrImage'; import { useTranslate } from './localization/useTranslate'; +import { s } from './s'; import { useErrorDetails } from './useErrorDetails'; -import { useStyles } from './useStyles'; - -const style = css` - error { - flex: 1; - display: flex; - padding: 24px; - } - - error-name { - composes: theme-typography--headline6 from global; - height: 40px; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - margin: 0; - - & span { - display: inline-block; - vertical-align: middle; - line-height: normal; - } - } - - error-data { - padding: 0 16px; - } - - error-message { - flex: 1; - overflow: auto; - white-space: pre-wrap; - } - - error-actions { - display: flex; - flex-shrink: 0; - align-items: center; - margin-top: 16px; - gap: 16px; - } - - error[|inline] { - align-items: center; - height: 38px; - padding: 0; - - & error-data { - display: flex; - align-items: center; - padding: 0; - } - & error-icon { - display: flex; - align-items: center; - align-content: center; - - & IconOrImage { - height: 24px; - width: 24px; - } - } - & error-message { - line-height: 1.2; - -webkit-line-clamp: 2; - display: -webkit-box; - -webkit-box-orient: vertical; - overflow: hidden; - padding: 0 16px; - } - & error-name { - display: none; - } - & error-actions { - margin-top: 0; - } - } - error[|icon] { - padding: 0; - height: 100%; - width: 100%; - max-height: 24px; - max-width: 24px; - - & error-icon { - display: flex; - align-items: center; - align-content: center; - - & IconOrImage { - height: 100%; - width: 100%; - } - } - } - error-action-close { - cursor: pointer; - width: 18px; - height: 18px; - flex-shrink: 0; - } -`; +import { useS } from './useS'; interface Props { exception?: Error; icon?: boolean; inline?: boolean; className?: string; - styles?: ComponentStyle; onRetry?: () => void; onClose?: () => void; } -export const ExceptionMessage = observer(function ExceptionMessage({ exception = null, icon, inline, className, styles, onRetry, onClose }) { +export const ExceptionMessage = observer(function ExceptionMessage({ exception = null, icon, inline, className, onRetry, onClose }) { + const styles = useS(style); const translate = useTranslate(); const error = useErrorDetails(exception); @@ -141,21 +39,21 @@ export const ExceptionMessage = observer(function ExceptionMessage({ exce }; } - return styled(useStyles(style, styles))( - - - - + return ( +
+
+ +
{!icon && ( <> - - +
+

{translate('core_blocks_exception_message_error_title')} - - +

+
{translate('core_blocks_exception_message_error_message')} {onRetry && translate('ui_please_retry')} - - +
+
@@ -164,15 +62,15 @@ export const ExceptionMessage = observer(function ExceptionMessage({ exce {translate('ui_processing_retry')} )} - - +
+
{onClose && ( - +
- +
)} )} - , +
); }); diff --git a/webapp/packages/core-blocks/src/Expand/EXPANDABLE_FORM_STYLES.ts b/webapp/packages/core-blocks/src/Expand/EXPANDABLE_FORM_STYLES.ts deleted file mode 100644 index 8876bd2e9b..0000000000 --- a/webapp/packages/core-blocks/src/Expand/EXPANDABLE_FORM_STYLES.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2023 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 { css } from 'reshadow'; - -export const EXPANDABLE_FORM_STYLES = css` - expand-label { - composes: theme-typography--body2 from global; - font-weight: 400; - margin: 0; - text-transform: uppercase; - opacity: 0.9; - } -`; diff --git a/webapp/packages/core-blocks/src/Expand/Expandable.m.css b/webapp/packages/core-blocks/src/Expand/Expandable.m.css new file mode 100644 index 0000000000..7388b9f07b --- /dev/null +++ b/webapp/packages/core-blocks/src/Expand/Expandable.m.css @@ -0,0 +1,38 @@ +.disclosure { + border: none; + padding: 0; + margin: 0; + background: transparent; + color: inherit; + font: inherit; + outline: none; + cursor: pointer; + display: flex; + align-items: center; + max-width: max-content; +} +.expandIcon { + display: flex; + box-sizing: border-box; + flex-shrink: 0; + opacity: 0.5; + width: 16px; + height: 16px; + transform: rotate(-90deg); + margin-right: 8px; + + &.expanded { + transform: rotate(0deg); + } +} +.iconOrImage { + width: 100%; + height: 100%; +} +.expandLabel { + composes: theme-typography--body2 from global; + font-weight: 400; + margin: 0; + text-transform: uppercase; + opacity: 0.9; +} diff --git a/webapp/packages/core-blocks/src/Expand/Expandable.tsx b/webapp/packages/core-blocks/src/Expand/Expandable.tsx index 8d393d024b..f28fe867f3 100644 --- a/webapp/packages/core-blocks/src/Expand/Expandable.tsx +++ b/webapp/packages/core-blocks/src/Expand/Expandable.tsx @@ -8,12 +8,11 @@ import { observer } from 'mobx-react-lite'; import { forwardRef, ReactNode, useImperativeHandle } from 'react'; import { Disclosure, DisclosureContent, DisclosureStateReturn, useDisclosureState } from 'reakit'; -import styled, { css, use } from 'reshadow'; - -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { IconOrImage } from '../IconOrImage'; -import { useStyles } from '../useStyles'; +import { s } from '../s'; +import { useS } from '../useS'; +import style from './Expandable.m.css'; export type ExpandableState = Pick; @@ -22,61 +21,27 @@ interface Props { children: ReactNode; defaultExpanded?: boolean; disabled?: boolean; - style?: ComponentStyle; } -const styles = css` - Disclosure { - border: none; - padding: 0; - margin: 0; - background: transparent; - color: inherit; - font: inherit; - outline: none; - cursor: pointer; - display: flex; - align-items: center; - max-width: max-content; - } - expand-icon { - display: flex; - box-sizing: border-box; - flex-shrink: 0; - opacity: 0.5; - width: 16px; - height: 16px; - transform: rotate(-90deg); - margin-right: 8px; - - &[|expanded] { - transform: rotate(0deg); - } - } - IconOrImage { - width: 100%; - height: 100%; - } -`; - export const Expandable = observer( - forwardRef(function Expandable({ label, defaultExpanded, disabled, children, style }, ref) { + forwardRef(function Expandable({ label, defaultExpanded, disabled, children }, ref) { + const styles = useS(style); const disclosure = useDisclosureState({ visible: defaultExpanded ?? false }); useImperativeHandle(ref, () => disclosure); - return styled(useStyles(styles, style))( + return ( <> - - - - - {label} + +
+ +
+

{label}

<>{children} - , + ); }), ); diff --git a/webapp/packages/core-blocks/src/Iframe.m.css b/webapp/packages/core-blocks/src/Iframe.m.css new file mode 100644 index 0000000000..856823a939 --- /dev/null +++ b/webapp/packages/core-blocks/src/Iframe.m.css @@ -0,0 +1,4 @@ +.iframe { + composes: theme-border-color-background from global; + border: 1px solid; +} diff --git a/webapp/packages/core-blocks/src/Iframe.tsx b/webapp/packages/core-blocks/src/Iframe.tsx index e29cff1f53..84f31cc5d7 100644 --- a/webapp/packages/core-blocks/src/Iframe.tsx +++ b/webapp/packages/core-blocks/src/Iframe.tsx @@ -5,18 +5,15 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ +import { observer } from 'mobx-react-lite'; import type { DetailedHTMLProps, IframeHTMLAttributes } from 'react'; -import styled, { css } from 'reshadow'; -import { useStyles } from './useStyles'; +import style from './Iframe.m.css'; +import { s } from './s'; +import { useS } from './useS'; -const styles = css` - iframe { - composes: theme-border-color-background from global; - border: 1px solid; - } -`; +export const Iframe = observer, HTMLIFrameElement>>(function Iframe(props) { + const styles = useS(style); -export const Iframe: React.FC, HTMLIFrameElement>> = function Iframe(props) { - return styled(useStyles(styles))(