From dce7797bba5b9b893fcb7674fc9ce7682656c8b8 Mon Sep 17 00:00:00 2001 From: sergeyteleshev Date: Tue, 1 Jul 2025 15:36:37 +0200 Subject: [PATCH] [CB] move radio button to ui-kit #6031 (#3533) * dbeaver/pro#6031 replaces old radio button with ui-kit one * lint fix * Update webapp/packages/core-blocks/src/FormControls/RadioGroup.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * pr fixes * adds labelledby for options configType * adds gap:0 for vertical radio group * pr fixes * cleanup * radio button fixes for dark theme * nowrap for radio button words --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com> --- .../@dbeaver/ui-kit/src/Radio/RadioGroup.css | 6 +- .../@dbeaver/ui-kit/src/Radio/RadioGroup.tsx | 2 +- .../FormControls/Checkboxes/Switch.module.css | 4 - .../core-blocks/src/FormControls/Radio.css | 37 ++++++++++ .../src/FormControls/Radio.module.css | 73 ------------------- .../core-blocks/src/FormControls/Radio.tsx | 53 ++++---------- .../src/FormControls/RadioGroup.tsx | 18 +++-- .../core-theming/src/styles/_mixins.scss | 1 - .../core-theming/src/styles/_radio.scss | 67 ----------------- .../src/styles/main/dark.theme.scss | 1 - .../src/styles/main/light.theme.scss | 1 - .../src/styles/theme-dark.module.scss | 1 - .../src/styles/theme-light.module.scss | 1 - .../src/ContextMenu/MenuActionElement.tsx | 2 +- .../src/ContextMenu/MenuItemRenderer.tsx | 2 +- .../src/ConnectionForm/Options/Options.tsx | 8 +- .../BooleanValuePresentation.module.css | 7 +- .../BooleanValue/BooleanValuePresentation.tsx | 6 -- 18 files changed, 77 insertions(+), 213 deletions(-) create mode 100644 webapp/packages/core-blocks/src/FormControls/Radio.css delete mode 100644 webapp/packages/core-blocks/src/FormControls/Radio.module.css delete mode 100644 webapp/packages/core-theming/src/styles/_radio.scss diff --git a/common-react/@dbeaver/ui-kit/src/Radio/RadioGroup.css b/common-react/@dbeaver/ui-kit/src/Radio/RadioGroup.css index 22d52b2903..12afce2503 100644 --- a/common-react/@dbeaver/ui-kit/src/Radio/RadioGroup.css +++ b/common-react/@dbeaver/ui-kit/src/Radio/RadioGroup.css @@ -1,13 +1,11 @@ @layer base { .dbv-kit-radio-group { display: flex; + gap: calc(var(--dbv-kit-radio-gap) * 4); &.dbv-kit-radio-group--vertical { flex-direction: column; - } - - &:not(.dbv-kit-radio-group--vertical) .dbv-kit-radio { - margin-inline-end: calc(var(--dbv-kit-radio-gap) * 4); + gap: 0; } } diff --git a/common-react/@dbeaver/ui-kit/src/Radio/RadioGroup.tsx b/common-react/@dbeaver/ui-kit/src/Radio/RadioGroup.tsx index 8b9e0da40a..9297cd82d9 100644 --- a/common-react/@dbeaver/ui-kit/src/Radio/RadioGroup.tsx +++ b/common-react/@dbeaver/ui-kit/src/Radio/RadioGroup.tsx @@ -48,7 +48,7 @@ export function RadioGroup({ className, children, labelledBy, label, ['aria-labe )} <_RadioGroup - aria-labelledby={labelledById} + aria-labelledby={ariaLabel ? undefined : labelledById} aria-label={ariaLabel} className={clsx('dbv-kit-radio-group', className, props.vertical && 'dbv-kit-radio-group--vertical')} > 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 16fdcc9eeb..6592a0de39 100644 --- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.module.css +++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.module.css @@ -33,10 +33,6 @@ composes: theme-switch__thumb from global; } -.radioRipple { - composes: theme-radio_ripple from global; -} - .switchBody { display: flex; align-items: center; diff --git a/webapp/packages/core-blocks/src/FormControls/Radio.css b/webapp/packages/core-blocks/src/FormControls/Radio.css new file mode 100644 index 0000000000..7ea174b684 --- /dev/null +++ b/webapp/packages/core-blocks/src/FormControls/Radio.css @@ -0,0 +1,37 @@ +/* + * 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. + */ + +@layer components { + .theme-dark .radio-field { + --dbv-kit-radio-hover-shadow-color: color-mix(in srgb, var(--theme-on-secondary), black 60%); + } + + .radio-field { + display: flex; + align-items: center; + + --dbv-kit-radio-active-border: var(--theme-primary); + --dbv-kit-radio-active-foreground: var(--theme-primary); + + --dbv-kit-radio-inactive-border: color-mix(in srgb, var(--theme-on-secondary), white 30%); + + --dbv-kit-radio-hover-shadow-color: color-mix(in srgb, var(--theme-on-secondary), white 80%); + + --dbv-kit-radio-medium-dot-size: 0.3; + + --dbv-kit-radio-medium-height: 32px; + --dbv-kit-radio-small-height: 24px; + + --dbv-kit-radio-small-gap: calc(var(--dbv-kit-radio-gap) * 0.25); + --dbv-kit-radio-medium-gap: calc(var(--dbv-kit-radio-gap) * 3); + + & .dbv-kit-radio__title { + white-space: nowrap; + } + } +} diff --git a/webapp/packages/core-blocks/src/FormControls/Radio.module.css b/webapp/packages/core-blocks/src/FormControls/Radio.module.css deleted file mode 100644 index 21903df506..0000000000 --- a/webapp/packages/core-blocks/src/FormControls/Radio.module.css +++ /dev/null @@ -1,73 +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. - */ -.radio { - composes: theme-radio from global; -} - -.radioNoRipple { - composes: theme-radio_no-ripple from global; -} - -.radioBackground { - composes: theme-radio_background from global; -} -.input { - composes: theme-radio_native-control from global; -} -.radioOuterCircle { - composes: theme-radio_outer-circle from global; -} -.radioInnerCircle { - composes: theme-radio_inner-circle from global; -} -.radioRipple { - composes: theme-radio_ripple from global; -} -.field { - display: inline-flex; - align-items: center; - vertical-align: middle; -} -.label { - cursor: pointer; - .disabled { - cursor: auto; - } -} - -.primary { - composes: theme-radio_primary from global; -} - -.small { - composes: theme-radio_small from global; -} - -.field.menu { - padding: 0; - - & .radio { - width: 14px; - height: 14px; - } - & .radioBackground { - width: 14px; - height: 14px; - } - & .radioInnerCircle { - border-width: 7px; - } -} - -.disabledRadio { - composes: theme-radio_disabled from global; -} - -.disabledInput { - opacity: 0 !important; -} diff --git a/webapp/packages/core-blocks/src/FormControls/Radio.tsx b/webapp/packages/core-blocks/src/FormControls/Radio.tsx index cfc4d57a96..d01bc01824 100644 --- a/webapp/packages/core-blocks/src/FormControls/Radio.tsx +++ b/webapp/packages/core-blocks/src/FormControls/Radio.tsx @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * 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. @@ -10,17 +10,16 @@ import { useCallback, useContext } from 'react'; import { filterLayoutFakeProps, getLayoutProps } from '../Containers/filterLayoutFakeProps.js'; import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps.js'; -import { s } from '../s.js'; -import { useS } from '../useS.js'; import { Field } from './Field.js'; import { FormContext } from './FormContext.js'; -import style from './Radio.module.css'; import { RadioGroupContext } from './RadioGroupContext.js'; +import { clsx, Radio as UiKitRadio } from '@dbeaver/ui-kit'; +import type { ControlSize } from '@dbeaver/ui-kit/types/controls'; +import './Radio.css'; -type BaseProps = Omit, 'onChange' | 'value' | 'checked'> & +type BaseProps = Omit, 'onChange' | 'value' | 'checked' | 'size'> & ILayoutSizeProps & { - mod?: Array<'primary' | 'small' | 'menu'>; - ripple?: boolean; + size?: ControlSize; }; type ControlledProps = BaseProps & { @@ -50,14 +49,10 @@ export const Radio: RadioType = observer(function Radio({ id: controlledId, checked: controlledChecked, onChange, - mod, - ripple = true, className, children, ...rest }: ControlledProps | ObjectProps) { - const styles = useS(style); - const layoutProps = getLayoutProps(rest); rest = filterLayoutFakeProps(rest); const formContext = useContext(FormContext); @@ -100,35 +95,17 @@ export const Radio: RadioType = observer(function Radio({ } return ( - -
+ - -
-
-
-
- {ripple &&
} -
- + ); }); diff --git a/webapp/packages/core-blocks/src/FormControls/RadioGroup.tsx b/webapp/packages/core-blocks/src/FormControls/RadioGroup.tsx index 9a3f0012a3..be9660f727 100644 --- a/webapp/packages/core-blocks/src/FormControls/RadioGroup.tsx +++ b/webapp/packages/core-blocks/src/FormControls/RadioGroup.tsx @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * 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. @@ -9,11 +9,12 @@ import { observer } from 'mobx-react-lite'; import { useCallback, useContext, useMemo, useState } from 'react'; import { FormContext } from './FormContext.js'; +import { RadioGroup as UiKitRadioGroup } from '@dbeaver/ui-kit'; import { type IRadioGroupContext, RadioGroupContext } from './RadioGroupContext.js'; -type BaseProps = React.PropsWithChildren<{ +type BaseProps = React.PropsWithChildren> & { name: string; -}>; +}; type ControlledProps = BaseProps & { value?: T; @@ -41,6 +42,7 @@ export const RadioGroup: RadioGroupType = observer(function RadioGroup({ state, onChange, children, + ...rest }: ControlledProps | ObjectProps) { const formContext = useContext(FormContext); const [selfValue, setValue] = useState(); @@ -72,8 +74,14 @@ export const RadioGroup: RadioGroupType = observer(function RadioGroup({ value, onChange: handleChange, }), - [value, value, handleChange], + [value, handleChange], ); - return {children}; + return ( + + + {children} + + + ); }); diff --git a/webapp/packages/core-theming/src/styles/_mixins.scss b/webapp/packages/core-theming/src/styles/_mixins.scss index d9bee48bd4..a4fde18382 100644 --- a/webapp/packages/core-theming/src/styles/_mixins.scss +++ b/webapp/packages/core-theming/src/styles/_mixins.scss @@ -19,7 +19,6 @@ @import './theme-ripple'; @import './ripple'; @import './color'; -@import './radio'; @import './switch'; @import './placeholder'; @import './form-controls'; diff --git a/webapp/packages/core-theming/src/styles/_radio.scss b/webapp/packages/core-theming/src/styles/_radio.scss deleted file mode 100644 index 3b86adc689..0000000000 --- a/webapp/packages/core-theming/src/styles/_radio.scss +++ /dev/null @@ -1,67 +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/radio/mixins'; - -@mixin radio-core-styles($query: mdc-feature-all()) { - @include mdc-radio-core-styles; - - .theme-radio { - @extend .mdc-radio; - } - - .theme-radio_native-control { - @extend .mdc-radio__native-control; - - &:disabled { - opacity: 0; - } - } - - .theme-radio_background { - @extend .mdc-radio__background; - } - - .theme-radio_outer-circle { - @extend .mdc-radio__outer-circle; - } - - .theme-radio_inner-circle { - @extend .mdc-radio__inner-circle; - } - - .theme-radio_ripple { - @extend .mdc-radio__ripple; - } - - .theme-radio--disabled { - @extend .mdc-radio--disabled; - } - - .theme-radio_primary { - $mdc-radio-baseline-theme-color: primary; - $mdc-radio-unchecked-color: rgba(mdc-theme-prop-value(on-surface), 0.54); - $mdc-radio-disabled-circle-color: rgba(mdc-theme-prop-value(on-surface), 0.26); - - @include mdc-radio-unchecked-stroke-color($mdc-radio-unchecked-color, $query: $query); - @include mdc-radio-checked-stroke-color($mdc-radio-baseline-theme-color, $query: $query); - @include mdc-radio-ink-color($mdc-radio-baseline-theme-color, $query: $query); - @include mdc-radio-disabled-unchecked-stroke-color($mdc-radio-disabled-circle-color, $query: $query); - @include mdc-radio-disabled-checked-stroke-color($mdc-radio-disabled-circle-color, $query: $query); - @include mdc-radio-disabled-ink-color($mdc-radio-disabled-circle-color, $query: $query); - @include mdc-radio-focus-indicator-color($mdc-radio-baseline-theme-color, $query: $query); - } - - .theme-radio_small { - @include mdc-radio-density(-3); - } - - .theme-radio_no-ripple { - @include mdc-radio-ripple-size(0); - } -} 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 694d1cf8be..bcc66c712e 100644 --- a/webapp/packages/core-theming/src/styles/main/dark.theme.scss +++ b/webapp/packages/core-theming/src/styles/main/dark.theme.scss @@ -17,7 +17,6 @@ @include theme-ripple; @include layout-grid; @include form-controls; - @include radio-core-styles; @include switch-core-styles; @include link; @include placeholder; 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 aa0f20549f..51e516175f 100644 --- a/webapp/packages/core-theming/src/styles/main/light.theme.scss +++ b/webapp/packages/core-theming/src/styles/main/light.theme.scss @@ -17,7 +17,6 @@ @include theme-ripple; @include layout-grid; @include form-controls; - @include radio-core-styles; @include switch-core-styles; @include link; @include placeholder; 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 2376824606..55d48c0873 100644 --- a/webapp/packages/core-theming/src/styles/theme-dark.module.scss +++ b/webapp/packages/core-theming/src/styles/theme-dark.module.scss @@ -13,7 +13,6 @@ @include colors; @include ripple-core-styles; @include theme-ripple; -@include radio-core-styles; @include switch-core-styles; @include form-controls; @include link; 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 7f823e7b1b..1ff9994780 100644 --- a/webapp/packages/core-theming/src/styles/theme-light.module.scss +++ b/webapp/packages/core-theming/src/styles/theme-light.module.scss @@ -13,7 +13,6 @@ @include colors; @include ripple-core-styles; @include theme-ripple; -@include radio-core-styles; @include switch-core-styles; @include form-controls; @include link; diff --git a/webapp/packages/core-ui/src/ContextMenu/MenuActionElement.tsx b/webapp/packages/core-ui/src/ContextMenu/MenuActionElement.tsx index ba3cd0be98..21c1b260f7 100644 --- a/webapp/packages/core-ui/src/ContextMenu/MenuActionElement.tsx +++ b/webapp/packages/core-ui/src/ContextMenu/MenuActionElement.tsx @@ -49,7 +49,7 @@ export const MenuActionElement = observer(function Menu > } + icon={} tooltip={actionInfo.tooltip} loading={loading} /> diff --git a/webapp/packages/core-ui/src/ContextMenu/MenuItemRenderer.tsx b/webapp/packages/core-ui/src/ContextMenu/MenuItemRenderer.tsx index 2732591fa3..428aa75171 100644 --- a/webapp/packages/core-ui/src/ContextMenu/MenuItemRenderer.tsx +++ b/webapp/packages/core-ui/src/ContextMenu/MenuItemRenderer.tsx @@ -106,7 +106,7 @@ export const MenuItemRenderer = observer(function MenuIt checked={item.checked} onClick={() => onClick()} > - } tooltip={item.tooltip} /> + } tooltip={item.tooltip} /> ); } diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx index 9e762fa505..e79c16ac45 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx @@ -84,6 +84,7 @@ const driverConfiguration: IDriverConfiguration[] = [ isVisible: driver => driver.configurationTypes.includes(DriverConfigurationType.Url), }, ]; + export const Options: TabContainerPanelComponent = observer(function Options({ formState, tabId }) { const { selected } = useTab(tabId); const isAdmin = usePermission(EAdminPermission.admin); @@ -106,6 +107,7 @@ export const Options: TabContainerPanelComponent = observe const connectionInfoAuthPropertiesResource = useResource(Options, ConnectionInfoAuthPropertiesResource, optionsPart.connectionKey, { active: selected && !!optionsPart.connectionKey, }); + const configurationTypeLabel = translate('connections_connection_configuration'); //@TODO it's here until the profile implementation in the CloudBeaver const readonly = formState.isDisabled || formState.isReadOnly || connectionInfoAuthResource.data?.authModel === PROFILE_AUTH_MODEL_ID; @@ -220,17 +222,17 @@ export const Options: TabContainerPanelComponent = observe {translate('connections_connection_driver')} {configurationTypes.length > 1 && ( - + - + {configurationTypes.map(conf => ( {conf.name} diff --git a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.module.css b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.module.css index 8f63e0d889..1550c7ff0f 100644 --- a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.module.css +++ b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.module.css @@ -9,8 +9,5 @@ .container { display: flex; flex-direction: column; -} - -.radio { - padding: 0; -} + padding: 4px 10px; +} \ No newline at end of file diff --git a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.tsx b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.tsx index da8aad348a..db79800135 100644 --- a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.tsx +++ b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.tsx @@ -59,9 +59,7 @@ export const BooleanValuePresentation: TabContainerPanelComponent editAction.set(firstSelectedCell, true)} @@ -69,9 +67,7 @@ export const BooleanValuePresentation: TabContainerPanelComponent editAction.set(firstSelectedCell, false)} @@ -80,9 +76,7 @@ export const BooleanValuePresentation: TabContainerPanelComponent {nullable && ( editAction.set(firstSelectedCell, null)}