mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
* 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>
This commit is contained in:
co-authored by
Copilot
mr-anton-t
parent
7c0d666b0a
commit
dce7797bba
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ export function RadioGroup({ className, children, labelledBy, label, ['aria-labe
|
||||
</div>
|
||||
)}
|
||||
<_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')}
|
||||
>
|
||||
|
||||
@@ -33,10 +33,6 @@
|
||||
composes: theme-switch__thumb from global;
|
||||
}
|
||||
|
||||
.radioRipple {
|
||||
composes: theme-radio_ripple from global;
|
||||
}
|
||||
|
||||
.switchBody {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value' | 'checked'> &
|
||||
type BaseProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, '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<any, any>) {
|
||||
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 (
|
||||
<Field {...layoutProps} className={s(styles, { field: true, menu: mod?.includes('menu') }, className)}>
|
||||
<div
|
||||
className={s(styles, {
|
||||
radio: true,
|
||||
primary: mod?.includes('primary'),
|
||||
small: mod?.includes('small') || mod?.includes('menu'),
|
||||
disabledRadio: rest.disabled,
|
||||
radioNoRipple: !ripple,
|
||||
})}
|
||||
<Field {...layoutProps} className={clsx('radio-field', className)}>
|
||||
<UiKitRadio
|
||||
id={id}
|
||||
name={name}
|
||||
value={value?.toString() ?? ''}
|
||||
checked={checked}
|
||||
onChange={handleChange}
|
||||
{...rest}
|
||||
>
|
||||
<input
|
||||
{...rest}
|
||||
className={s(styles, { input: true, disabledInput: rest.disabled })}
|
||||
type="radio"
|
||||
id={id}
|
||||
name={name}
|
||||
value={value ?? ''}
|
||||
checked={checked}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<div className={s(styles, { radioBackground: true })}>
|
||||
<div className={s(styles, { radioOuterCircle: true })} />
|
||||
<div className={s(styles, { radioInnerCircle: true })} />
|
||||
</div>
|
||||
{ripple && <div className={s(styles, { radioRipple: true })} />}
|
||||
</div>
|
||||
<label className={s(styles, { label: true, disabled: rest.disabled })} htmlFor={id}>
|
||||
{children}
|
||||
</label>
|
||||
</UiKitRadio>
|
||||
</Field>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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<React.ComponentProps<typeof UiKitRadioGroup>> & {
|
||||
name: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
type ControlledProps<T> = BaseProps & {
|
||||
value?: T;
|
||||
@@ -41,6 +42,7 @@ export const RadioGroup: RadioGroupType = observer(function RadioGroup({
|
||||
state,
|
||||
onChange,
|
||||
children,
|
||||
...rest
|
||||
}: ControlledProps<string | number> | ObjectProps<any, any>) {
|
||||
const formContext = useContext(FormContext);
|
||||
const [selfValue, setValue] = useState<string | number>();
|
||||
@@ -72,8 +74,14 @@ export const RadioGroup: RadioGroupType = observer(function RadioGroup({
|
||||
value,
|
||||
onChange: handleChange,
|
||||
}),
|
||||
[value, value, handleChange],
|
||||
[value, handleChange],
|
||||
);
|
||||
|
||||
return <RadioGroupContext.Provider value={context}>{children}</RadioGroupContext.Provider>;
|
||||
return (
|
||||
<RadioGroupContext.Provider value={context}>
|
||||
<UiKitRadioGroup {...rest}>
|
||||
{children}
|
||||
</UiKitRadioGroup>
|
||||
</RadioGroupContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
@import './theme-ripple';
|
||||
@import './ripple';
|
||||
@import './color';
|
||||
@import './radio';
|
||||
@import './switch';
|
||||
@import './placeholder';
|
||||
@import './form-controls';
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -49,7 +49,7 @@ export const MenuActionElement = observer<IMenuActionElementProps>(function Menu
|
||||
>
|
||||
<MenuItemElement
|
||||
label={actionInfo.label}
|
||||
icon={<Radio checked={checked} mod={['primary', 'menu']} ripple={false} />}
|
||||
icon={<Radio checked={checked} size="small" />}
|
||||
tooltip={actionInfo.tooltip}
|
||||
loading={loading}
|
||||
/>
|
||||
|
||||
@@ -106,7 +106,7 @@ export const MenuItemRenderer = observer<IMenuItemRendererProps>(function MenuIt
|
||||
checked={item.checked}
|
||||
onClick={() => onClick()}
|
||||
>
|
||||
<MenuItemElement label={item.label} icon={<Radio checked={item.checked} mod={['primary', 'menu']} ripple={false} />} tooltip={item.tooltip} />
|
||||
<MenuItemElement label={item.label} icon={<Radio size="small" checked={item.checked} />} tooltip={item.tooltip} />
|
||||
</MenuItemRadio>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ const driverConfiguration: IDriverConfiguration[] = [
|
||||
isVisible: driver => driver.configurationTypes.includes(DriverConfigurationType.Url),
|
||||
},
|
||||
];
|
||||
|
||||
export const Options: TabContainerPanelComponent<IConnectionFormProps> = observer(function Options({ formState, tabId }) {
|
||||
const { selected } = useTab(tabId);
|
||||
const isAdmin = usePermission(EAdminPermission.admin);
|
||||
@@ -106,6 +107,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = 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<IConnectionFormProps> = observe
|
||||
{translate('connections_connection_driver')}
|
||||
</Combobox>
|
||||
{configurationTypes.length > 1 && (
|
||||
<FormFieldDescription label={translate('connections_connection_configuration')} tiny>
|
||||
<FormFieldDescription label={configurationTypeLabel} tiny>
|
||||
<Container gap>
|
||||
<RadioGroup name="configurationType" state={optionsPart.state}>
|
||||
<RadioGroup aria-label={configurationTypeLabel} name="configurationType" state={optionsPart.state}>
|
||||
{configurationTypes.map(conf => (
|
||||
<Radio
|
||||
key={conf.value}
|
||||
id={conf.value}
|
||||
value={conf.value}
|
||||
mod={['primary', 'small']}
|
||||
readOnly={readonly || configurationTypes.length < 2}
|
||||
disabled={readonly}
|
||||
small
|
||||
keepSize
|
||||
>
|
||||
{conf.name}
|
||||
|
||||
+2
-5
@@ -9,8 +9,5 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.radio {
|
||||
padding: 0;
|
||||
}
|
||||
padding: 4px 10px;
|
||||
}
|
||||
-6
@@ -59,9 +59,7 @@ export const BooleanValuePresentation: TabContainerPanelComponent<IDataValuePane
|
||||
return (
|
||||
<div className={classes['container']}>
|
||||
<Radio
|
||||
className={classes['radio']}
|
||||
id="true_value"
|
||||
mod={['primary']}
|
||||
checked={value === true}
|
||||
disabled={readonly}
|
||||
onClick={() => editAction.set(firstSelectedCell, true)}
|
||||
@@ -69,9 +67,7 @@ export const BooleanValuePresentation: TabContainerPanelComponent<IDataValuePane
|
||||
TRUE
|
||||
</Radio>
|
||||
<Radio
|
||||
className={classes['radio']}
|
||||
id="false_value"
|
||||
mod={['primary']}
|
||||
checked={value === false}
|
||||
disabled={readonly}
|
||||
onClick={() => editAction.set(firstSelectedCell, false)}
|
||||
@@ -80,9 +76,7 @@ export const BooleanValuePresentation: TabContainerPanelComponent<IDataValuePane
|
||||
</Radio>
|
||||
{nullable && (
|
||||
<Radio
|
||||
className={classes['radio']}
|
||||
id="null_value"
|
||||
mod={['primary']}
|
||||
checked={value === null}
|
||||
disabled={readonly}
|
||||
onClick={() => editAction.set(firstSelectedCell, null)}
|
||||
|
||||
Reference in New Issue
Block a user