mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
103 create radio and radio group components (#3313)
* refactor: rename css variable in order to be more descriptive and stick to the naming convention * refactor: unify controls, add new global control css variables * feat: add radio component * docs: add radio stories * docs: add input docs story * docs: add simple form story * refactor: change default radio dot size * refactor: change class name for radio children wrapper * refactor: don't reexport inner radio elements * refactor: simplify RadioGroup interface by removing items props, make label(any) required The radiogroup must have an accessible name either by a visible label referenced by aria-labelledby or has a label specified with aria-label. https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/radiogroup_role * refactor: use label wrapper for input component to simplify structure * refactor: add classname for radio group container
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
--dbv-kit-btn-background: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-btn-background-hover: var(--dbv-kit-color-primary-700);
|
||||
--dbv-kit-btn-background-active: var(--dbv-kit-color-primary-800);
|
||||
--dbv-kit-btn-outline-color: var(--dbv-kit-color-outline);
|
||||
--dbv-kit-btn-outline-color: var(--dbv-kit-control-outline-color);
|
||||
|
||||
--dbv-kit-btn-border-width: var(--dbv-kit-control-border-width);
|
||||
--dbv-kit-btn-border-color: transparent;
|
||||
|
||||
@@ -11,13 +11,12 @@
|
||||
line-height: var(--dbv-kit-checkbox-height);
|
||||
font-size: var(--dbv-kit-checkbox-font-size);
|
||||
color: var(--dbv-kit-checkbox-foreground);
|
||||
outline: var(--dbv-kit-color-outline);
|
||||
outline: var(--dbv-kit-control-outline-color);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
.dbv-kit-checkbox__check {
|
||||
border-color: var(--dbv-kit-checkbox-border-color-checked);
|
||||
box-shadow: 0 0 0 2px var(--dbv-kit-checkbox-hover-shadow-color);
|
||||
}
|
||||
}
|
||||
@@ -33,11 +32,12 @@
|
||||
}
|
||||
|
||||
.dbv-kit-checkbox__check {
|
||||
--check-size: round(calc(var(--dbv-kit-checkbox-height) * var(--dbv-kit-checkbox-check-size)), 2px);
|
||||
margin-top: calc(var(--dbv-kit-checkbox-height) * (calc(1 - var(--dbv-kit-checkbox-check-size)) / 2));
|
||||
height: calc(var(--dbv-kit-checkbox-height) * var(--dbv-kit-checkbox-check-size));
|
||||
line-height: calc(var(--dbv-kit-checkbox-height) * var(--dbv-kit-checkbox-check-size));
|
||||
width: calc(var(--dbv-kit-checkbox-height) * var(--dbv-kit-checkbox-check-size));
|
||||
min-width: calc(var(--dbv-kit-checkbox-height) * var(--dbv-kit-checkbox-check-size));
|
||||
height: var(--check-size);
|
||||
line-height: var(--check-size);
|
||||
width: var(--check-size);
|
||||
min-width: var(--check-size);
|
||||
border-radius: var(--dbv-kit-checkbox-border-radius);
|
||||
background-color: var(--dbv-kit-checkbox-background);
|
||||
border-color: var(--dbv-kit-checkbox-border-color);
|
||||
@@ -46,7 +46,7 @@
|
||||
color: var(--dbv-kit-checkbox-icon-color);
|
||||
outline-offset: var(--dbv-kit-control-outline-offset);
|
||||
outline-width: var(--dbv-kit-control-outline-width);
|
||||
outline-color: var(--dbv-kit-color-outline);
|
||||
outline-color: var(--dbv-kit-control-outline-color);
|
||||
transition-property: stroke-dashoffset;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
@@ -57,10 +57,6 @@
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: var(--dbv-kit-checkbox-border-color-checked);
|
||||
}
|
||||
|
||||
&[data-checked='true'],
|
||||
&[data-indeterminate='true'] {
|
||||
background-color: var(--dbv-kit-checkbox-background-checked);
|
||||
|
||||
@@ -3,22 +3,21 @@
|
||||
/* Checkbox sizes */
|
||||
--dbv-kit-checkbox-height: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-checkbox-gap: calc(var(--tw-spacing) * 1.25);
|
||||
--dbv-kit-checkbox-check-size: 0.75;
|
||||
--dbv-kit-checkbox-check-size: 0.5625;
|
||||
|
||||
/* Checkbox colors */
|
||||
--dbv-kit-checkbox-foreground: var(--tw-color-black);
|
||||
--dbv-kit-checkbox-background: transparent;
|
||||
--dbv-kit-checkbox-background-checked: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-checkbox-background-active: var(--dbv-kit-color-primary-800);
|
||||
|
||||
--dbv-kit-checkbox-hover-shadow-color: var(--dbv-kit-color-primary-100);
|
||||
--dbv-kit-checkbox-hover-shadow-color: var(--dbv-kit-color-primary-200);
|
||||
--dbv-kit-checkbox-icon-color: var(--tw-color-white);
|
||||
|
||||
/* Checkbox border */
|
||||
--dbv-kit-checkbox-border-width: var(--dbv-kit-control-border-width);
|
||||
--dbv-kit-checkbox-border-width: calc(var(--dbv-kit-control-border-width) * 2);
|
||||
--dbv-kit-checkbox-border-radius: var(--dbv-kit-control-border-radius);
|
||||
--dbv-kit-checkbox-border-style: solid;
|
||||
--dbv-kit-checkbox-border-color: var(--tw-color-gray-300);
|
||||
--dbv-kit-checkbox-border-color: var(--dbv-kit-color-control-inactive);
|
||||
--dbv-kit-checkbox-border-color-checked: var(--dbv-kit-color-primary-600);
|
||||
|
||||
/* Checkbox label font */
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
:root {
|
||||
/* Small checkbox */
|
||||
--dbv-kit-checkbox-small-font-size: calc(var(--dbv-kit-checkbox-font-size) * 0.875);
|
||||
--dbv-kit-checkbox-small-height: calc(var(--dbv-kit-control-height-small) * 0.875);
|
||||
--dbv-kit-checkbox-small-height: var(--dbv-kit-control-height-small);
|
||||
--dbv-kit-checkbox-small-gap: calc(var(--dbv-kit-checkbox-gap) * 0.5);
|
||||
|
||||
/* Medium checkbox */
|
||||
--dbv-kit-checkbox-medium-font-size: var(--dbv-kit-checkbox-font-size);
|
||||
--dbv-kit-checkbox-medium-height: calc(var(--dbv-kit-control-height-medium) * 0.75);
|
||||
--dbv-kit-checkbox-medium-height: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-checkbox-medium-gap: var(--dbv-kit-checkbox-gap);
|
||||
|
||||
/* Large checkbox */
|
||||
--dbv-kit-checkbox-large-font-size: calc(var(--dbv-kit-checkbox-font-size) * 1.125);
|
||||
--dbv-kit-checkbox-large-height: calc(var(--dbv-kit-control-height-large) * 0.75);
|
||||
--dbv-kit-checkbox-large-height: var(--dbv-kit-control-height-large);
|
||||
--dbv-kit-checkbox-large-gap: calc(var(--dbv-kit-checkbox-gap) * 1.25);
|
||||
|
||||
/* Extra large checkbox */
|
||||
--dbv-kit-checkbox-xlarge-font-size: calc(var(--dbv-kit-checkbox-font-size) * 1.25);
|
||||
--dbv-kit-checkbox-xlarge-height: calc(var(--dbv-kit-control-height-xlarge) * 0.75);
|
||||
--dbv-kit-checkbox-xlarge-height: var(--dbv-kit-control-height-xlarge);
|
||||
--dbv-kit-checkbox-xlarge-gap: calc(var(--dbv-kit-checkbox-gap) * 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,21 +15,44 @@
|
||||
border-width: var(--dbv-kit-input-border-width);
|
||||
border-style: var(--dbv-kit-input-border-style);
|
||||
color: var(--dbv-kit-input-foreground);
|
||||
padding: var(--dbv-kit-input-padding);
|
||||
padding-inline: var(--dbv-kit-input-padding);
|
||||
font-size: var(--dbv-kit-input-font-size);
|
||||
height: var(--dbv-kit-input-height);
|
||||
|
||||
&:not(:disabled):hover {
|
||||
border-color: var(--dbv-kit-color-control-hover);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: var(--dbv-kit-control-disabled-opacity);
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: var(--dbv-kit-input-placeholder-foreground);
|
||||
}
|
||||
|
||||
&:focus-visible,
|
||||
&[data-focus-visible] {
|
||||
outline: var(--dbv-kit-control-outline-width) solid var(--dbv-kit-color-outline);
|
||||
outline: var(--dbv-kit-control-outline-width) solid var(--dbv-kit-control-outline-color);
|
||||
outline-offset: var(--dbv-kit-control-outline-offset);
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-input__title {
|
||||
color: var(--dbv-kit-input-label-foreground);
|
||||
padding-inline-start: var(--dbv-kit-input-label-padding);
|
||||
margin-block-end: var(--tw-spacing);
|
||||
}
|
||||
|
||||
.dbv-kit-input__title--required {
|
||||
&:after {
|
||||
content: '*';
|
||||
color: var(--dbv-kit-color-control-required);
|
||||
margin-inline-start: 0.125rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
/* Sizes */
|
||||
|
||||
|
||||
@@ -6,18 +6,20 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import type { ComponentPropsWithRef } from 'react';
|
||||
import { type ComponentPropsWithRef } from 'react';
|
||||
import './Input.css';
|
||||
|
||||
export interface InputProps extends Omit<ComponentPropsWithRef<'input'>, 'size'> {
|
||||
size?: 'small' | 'medium' | 'large' | 'xlarge';
|
||||
label?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Input: React.FC<InputProps> = function Input({ size, className, ...props }) {
|
||||
const classNameToApply = `dbv-kit-input dbv-kit-input--${size ?? 'medium'} ${className}`.trim();
|
||||
const classNameToApply = `dbv-kit-input dbv-kit-input--${size ?? 'medium'} ${className ?? ''}`.trim();
|
||||
return (
|
||||
<div className="dbv-kit-input-wrapper">
|
||||
<label className="dbv-kit-input-wrapper">
|
||||
{props.label && <div className={`dbv-kit-input__title ${props.required ? 'dbv-kit-input__title--required' : ''}`}>{props.label}</div>}
|
||||
<input className={classNameToApply} {...props} />
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,12 +3,16 @@
|
||||
--dbv-kit-input-radius: var(--dbv-kit-control-border-radius);
|
||||
--dbv-kit-input-font-size: calc(var(--dbv-kit-font-size-base) * 0.875);
|
||||
--dbv-kit-input-background: var(--dbv-kit-color-background);
|
||||
--dbv-kit-input-border-color: var(--tw-color-gray-300);
|
||||
--dbv-kit-input-border-color: var(--dbv-kit-color-control-inactive);
|
||||
--dbv-kit-input-border-width: var(--dbv-kit-control-border-width);
|
||||
--dbv-kit-input-border-style: solid;
|
||||
--dbv-kit-input-foreground: var(--dbv-kit-color-foreground);
|
||||
|
||||
--dbv-kit-input-label-foreground: var(--dbv-kit-color-control-label);
|
||||
--dbv-kit-input-label-padding: var(--tw-spacing);
|
||||
|
||||
--dbv-kit-input-height: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-input-padding: calc(var(--tw-spacing) * 1.1);
|
||||
--dbv-kit-input-padding: calc(var(--tw-spacing) * 2.5);
|
||||
--dbv-kit-input-placeholder-foreground: var(--tw-color-gray-500);
|
||||
--dbv-kit-input-option-active-background: var(--dbv-kit-color-primary-200);
|
||||
--dbv-kit-input-option-active-border: var(--dbv-kit-color-primary-500);
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
@import './_base.css';
|
||||
@import './_sizes.css';
|
||||
|
||||
@layer base {
|
||||
.dbv-kit-radio {
|
||||
display: inline-flex;
|
||||
align-items: start;
|
||||
gap: var(--dbv-kit-radio-gap);
|
||||
cursor: pointer;
|
||||
height: var(--dbv-kit-radio-height);
|
||||
|
||||
&:hover .dbv-kit-radio__input:not([aria-disabled='true']) ~ .dbv-kit-radio__control {
|
||||
background-color: var(--dbv-kit-radio-inactive-hover-background);
|
||||
box-shadow: 0 0 0 var(--dbv-kit-control-outline-offset) var(--dbv-kit-radio-hover-shadow-color);
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-radio--small {
|
||||
--dbv-kit-radio-font-size: var(--dbv-kit-radio-small-font-size);
|
||||
--dbv-kit-radio-gap: var(--dbv-kit-radio-small-gap);
|
||||
--dbv-kit-radio-height: var(--dbv-kit-radio-small-height);
|
||||
--dbv-kit-radio-dot-size: var(--dbv-kit-radio-small-dot-size);
|
||||
}
|
||||
|
||||
.dbv-kit-radio--medium {
|
||||
--dbv-kit-radio-font-size: var(--dbv-kit-radio-medium-font-size);
|
||||
--dbv-kit-radio-gap: var(--dbv-kit-radio-medium-gap);
|
||||
--dbv-kit-radio-height: var(--dbv-kit-radio-medium-height);
|
||||
--dbv-kit-radio-dot-size: var(--dbv-kit-radio-medium-dot-size);
|
||||
}
|
||||
|
||||
.dbv-kit-radio--large {
|
||||
--dbv-kit-radio-font-size: var(--dbv-kit-radio-large-font-size);
|
||||
--dbv-kit-radio-gap: var(--dbv-kit-radio-large-gap);
|
||||
--dbv-kit-radio-height: var(--dbv-kit-radio-large-height);
|
||||
--dbv-kit-radio-dot-size: var(--dbv-kit-radio-large-dot-size);
|
||||
}
|
||||
|
||||
.dbv-kit-radio--xlarge {
|
||||
--dbv-kit-radio-font-size: var(--dbv-kit-radio-xlarge-font-size);
|
||||
--dbv-kit-radio-gap: var(--dbv-kit-radio-xlarge-gap);
|
||||
--dbv-kit-radio-height: var(--dbv-kit-radio-xlarge-height);
|
||||
--dbv-kit-radio-dot-size: var(--dbv-kit-radio-xlarge-dot-size);
|
||||
}
|
||||
|
||||
.dbv-kit-radio__input {
|
||||
border: 0px;
|
||||
clip: rect(0px, 0px, 0px, 0px);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0px;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
|
||||
&[aria-checked='true'] + .dbv-kit-radio__control {
|
||||
border-color: var(--dbv-kit-radio-active-border);
|
||||
background-color: var(--dbv-kit-radio-active-background);
|
||||
|
||||
&::after {
|
||||
scale: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-focus-visible='true'] ~ .dbv-kit-radio__control {
|
||||
outline: var(--dbv-kit-control-outline-width) solid var(--dbv-kit-control-outline-color);
|
||||
outline-offset: var(--dbv-kit-control-outline-offset);
|
||||
box-shadow: 0 0 0 var(--dbv-kit-control-outline-offset) var(--dbv-kit-radio-hover-shadow-color);
|
||||
}
|
||||
|
||||
&[aria-disabled='true'] ~ .dbv-kit-radio__text,
|
||||
&[aria-disabled='true'] ~ .dbv-kit-radio__control {
|
||||
opacity: var(--dbv-kit-control-disabled-opacity);
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-radio__control {
|
||||
--ring-size: round(calc(var(--dbv-kit-radio-height) * var(--dbv-kit-radio-ring-size)), 2px);
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: var(--ring-size);
|
||||
height: var(--ring-size);
|
||||
margin-top: calc((var(--dbv-kit-radio-height) - (var(--ring-size))) * 0.5);
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--dbv-kit-radio-inactive-border);
|
||||
background-color: var(--dbv-kit-radio-inactive-background);
|
||||
transition:
|
||||
background-color 0.3s,
|
||||
border-color 0.3s;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: round(calc(var(--dbv-kit-radio-height) * var(--dbv-kit-radio-dot-size)), 2px);
|
||||
height: round(calc(var(--dbv-kit-radio-height) * var(--dbv-kit-radio-dot-size)), 2px);
|
||||
border-radius: 50%;
|
||||
background-color: var(--dbv-kit-radio-active-foreground);
|
||||
scale: 0;
|
||||
|
||||
transition-property: scale;
|
||||
transition-timing-function: var(--tw-ease-in-out);
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-radio__title {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: var(--dbv-kit-radio-height);
|
||||
font-size: var(--dbv-kit-radio-font-size);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import type { ControlSize } from '../types/controls.js';
|
||||
import { _Radio, type RadioProps as _RadioProps } from './index.js';
|
||||
import './Radio.css';
|
||||
|
||||
export interface RadioProps extends Omit<_RadioProps, 'size'> {
|
||||
size?: ControlSize;
|
||||
}
|
||||
|
||||
export function Radio({ children, className, size = 'medium', ...props }: RadioProps) {
|
||||
return (
|
||||
<label className={`dbv-kit-radio dbv-kit-radio--${size} ${className || ''}`}>
|
||||
<_Radio className="dbv-kit-radio__input" {...props} />
|
||||
<div className="dbv-kit-radio__control" />
|
||||
<span className="dbv-kit-radio__title">{children}</span>
|
||||
</label>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
@layer base {
|
||||
.dbv-kit-radio-group {
|
||||
display: flex;
|
||||
|
||||
&.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);
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-radio-group__label {
|
||||
display: block;
|
||||
color: var(--dbv-kit-select-label-foreground);
|
||||
padding-inline-start: var(--dbv-kit-select-label-padding-inline);
|
||||
margin-block-end: var(--tw-spacing);
|
||||
}
|
||||
|
||||
.dbv-kit-radio-group__label--required::after {
|
||||
content: '*';
|
||||
color: var(--dbv-kit-color-control-required);
|
||||
margin-inline-start: 0.125rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { useId } from 'react';
|
||||
import './RadioGroup.css';
|
||||
import { _RadioGroup, _RadioProvider, type RadioProviderProps } from './index.js';
|
||||
|
||||
type LabelProps =
|
||||
| {
|
||||
labelledBy: string;
|
||||
label?: never;
|
||||
['aria-label']?: never;
|
||||
}
|
||||
| {
|
||||
labelledBy?: never;
|
||||
label: React.ReactNode;
|
||||
['aria-label']?: never;
|
||||
}
|
||||
| {
|
||||
labelledBy?: never;
|
||||
label?: never;
|
||||
['aria-label']: string;
|
||||
};
|
||||
|
||||
type RadioGroupProps = Pick<RadioProviderProps, 'value' | 'setValue' | 'store' | 'setActiveId' | 'rtl' | 'defaultValue'> &
|
||||
LabelProps & {
|
||||
required?: boolean;
|
||||
className?: string;
|
||||
vertical?: boolean;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export function RadioGroup({ className, children, labelledBy, label, ['aria-label']: ariaLabel, ...props }: RadioGroupProps) {
|
||||
const labelId = useId();
|
||||
const labelledById = label ? labelId : labelledBy;
|
||||
return (
|
||||
<_RadioProvider {...props}>
|
||||
<div className="dbv-kit-radio-group__container">
|
||||
{label && (
|
||||
<div id={labelId} className={`dbv-kit-radio-group__label ${props.required ? 'dbv-kit-radio-group__label--required' : ''}`}>
|
||||
{label}
|
||||
</div>
|
||||
)}
|
||||
<_RadioGroup
|
||||
aria-labelledby={labelledById}
|
||||
aria-label={ariaLabel}
|
||||
className={`dbv-kit-radio-group ${className ?? ''} ${props.vertical ? 'dbv-kit-radio-group--vertical' : ''}`}
|
||||
>
|
||||
{children}
|
||||
</_RadioGroup>
|
||||
</div>
|
||||
</_RadioProvider>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
@layer base {
|
||||
:root {
|
||||
--dbv-kit-radio-inactive-hover-background: transparent;
|
||||
--dbv-kit-radio-inactive-hover-border: var(--tw-color-gray-400);
|
||||
--dbv-kit-radio-inactive-background: transparent;
|
||||
--dbv-kit-radio-inactive-foreground: var(--dbv-kit-color-control-inactive);
|
||||
--dbv-kit-radio-inactive-border: var(--dbv-kit-color-control-inactive);
|
||||
--dbv-kit-radio-active-background: transparent;
|
||||
--dbv-kit-radio-active-border: var(--dbv-kit-color-primary-500);
|
||||
--dbv-kit-radio-active-foreground: var(--dbv-kit-color-primary-500);
|
||||
--dbv-kit-radio-hover-shadow-color: var(--dbv-kit-color-primary-200);
|
||||
|
||||
--dbv-kit-radio-height: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-radio-ring-size: 0.5625;
|
||||
--dbv-kit-radio-dot-size: 0.25;
|
||||
--dbv-kit-radio-font-size: calc(var(--dbv-kit-font-size-base) * 0.875);
|
||||
--dbv-kit-radio-gap: var(--tw-spacing);
|
||||
|
||||
--dbv-kit-select-label-foreground: var(--dbv-kit-color-control-label);
|
||||
--dbv-kit-select-label-padding-inline: var(--tw-spacing);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
@layer base {
|
||||
:root {
|
||||
/* Small radio */
|
||||
--dbv-kit-radio-small-gap: calc(var(--dbv-kit-radio-gap) * 0.5);
|
||||
--dbv-kit-radio-small-font-size: calc(var(--dbv-kit-radio-font-size) * 0.875);
|
||||
--dbv-kit-radio-small-height: var(--dbv-kit-control-height-small);
|
||||
--dbv-kit-radio-small-dot-size: 0.25;
|
||||
|
||||
/* Medium radio */
|
||||
--dbv-kit-radio-medium-gap: var(--dbv-kit-radio-gap);
|
||||
--dbv-kit-radio-medium-font-size: var(--dbv-kit-radio-font-size);
|
||||
--dbv-kit-radio-medium-height: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-radio-medium-dot-size: 0.25;
|
||||
|
||||
/* Large radio */
|
||||
--dbv-kit-radio-large-gap: calc(var(--dbv-kit-radio-gap) * 1.25);
|
||||
--dbv-kit-radio-large-font-size: calc(var(--dbv-kit-radio-font-size) * 1.125);
|
||||
--dbv-kit-radio-large-height: var(--dbv-kit-control-height-large);
|
||||
--dbv-kit-radio-large-dot-size: 0.25;
|
||||
|
||||
/* Extra large radio */
|
||||
--dbv-kit-radio-xlarge-gap: calc(var(--dbv-kit-radio-gap) * 1.5);
|
||||
--dbv-kit-radio-xlarge-font-size: calc(var(--dbv-kit-radio-font-size) * 1.25);
|
||||
--dbv-kit-radio-xlarge-height: var(--dbv-kit-control-height-xlarge);
|
||||
--dbv-kit-radio-xlarge-dot-size: 0.3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
Radio as _Radio,
|
||||
RadioGroup as _RadioGroup,
|
||||
RadioProvider as _RadioProvider,
|
||||
type RadioGroupProps,
|
||||
type RadioProviderProps,
|
||||
type RadioProps,
|
||||
useRadioContext,
|
||||
useRadioStore,
|
||||
} from '@ariakit/react';
|
||||
export { RadioGroup } from './RadioGroup.js';
|
||||
export { Radio } from './Radio.js';
|
||||
@@ -21,7 +21,11 @@
|
||||
font-size: var(--dbv-kit-select-font-size);
|
||||
outline-width: var(--dbv-kit-control-outline-width);
|
||||
outline-offset: var(--dbv-kit-control-outline-offset);
|
||||
outline-color: var(--dbv-kit-color-outline);
|
||||
outline-color: var(--dbv-kit-control-outline-color);
|
||||
|
||||
&:hover {
|
||||
border-color: var(--dbv-kit-color-control-hover);
|
||||
}
|
||||
|
||||
&[aria-disabled='true'] {
|
||||
opacity: var(--dbv-kit-control-disabled-opacity);
|
||||
@@ -30,11 +34,6 @@
|
||||
&:focus-visible {
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&[data-active] {
|
||||
padding-top: 0.125rem;
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-select__label {
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import {
|
||||
SelectProvider as AriaSelectProvider,
|
||||
Select as AriaSelect,
|
||||
@@ -23,27 +31,27 @@ export function SelectProvider({ children, ...props }: SelectProviderProps) {
|
||||
return <AriaSelectProvider {...props}>{children}</AriaSelectProvider>;
|
||||
}
|
||||
|
||||
export function Select({ className, ref, ...props }: SelectProps) {
|
||||
return <AriaSelect ref={ref} className={`dbv-kit-select ${className || ''}`} {...props} />;
|
||||
export function Select({ className, ...props }: SelectProps) {
|
||||
return <AriaSelect className={`dbv-kit-select ${className || ''}`} {...props} />;
|
||||
}
|
||||
|
||||
export function SelectPopover({ children, ref, className, ...props }: SelectPopoverProps) {
|
||||
export function SelectPopover({ children, className, ...props }: SelectPopoverProps) {
|
||||
return (
|
||||
<AriaSelectPopover ref={ref} className={`dbv-kit-select__popover ${className || ''}`} sameWidth={props.sameWidth ?? true} {...props}>
|
||||
<AriaSelectPopover className={`dbv-kit-select__popover ${className || ''}`} sameWidth={props.sameWidth ?? true} {...props}>
|
||||
{children}
|
||||
</AriaSelectPopover>
|
||||
);
|
||||
}
|
||||
|
||||
export function SelectItem({ children, ref, className, ...props }: SelectItemProps) {
|
||||
export function SelectItem({ children, className, ...props }: SelectItemProps) {
|
||||
return (
|
||||
<AriaSelectItem ref={ref} className={`dbv-kit-select__item ${className || ''}`} {...props}>
|
||||
<AriaSelectItem className={`dbv-kit-select__item ${className || ''}`} {...props}>
|
||||
{children}
|
||||
</AriaSelectItem>
|
||||
);
|
||||
}
|
||||
|
||||
export function SelectLabel({ children, ref, className, ...props }: SelectLabelProps) {
|
||||
export function SelectLabel({ children, className, ...props }: SelectLabelProps) {
|
||||
return (
|
||||
<AriaSelectLabel className={`dbv-kit-select__label ${className || ''}`} {...props}>
|
||||
{children}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
.dbv-kit-select__label--required {
|
||||
&:after {
|
||||
content: '*';
|
||||
color: var(--tw-color-red-600);
|
||||
color: var(--dbv-kit-color-control-required);
|
||||
margin-left: 0.125rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
import { SelectProvider, Select, SelectPopover, SelectItem, SelectLabel } from './Select.js';
|
||||
import './SelectField.css';
|
||||
@@ -40,6 +48,8 @@ export interface SelectFieldProps<T, ItemType = SelectItem<T>> {
|
||||
|
||||
description?: React.ReactNode;
|
||||
|
||||
name?: string;
|
||||
|
||||
disabled?: boolean;
|
||||
|
||||
required?: boolean;
|
||||
@@ -77,6 +87,7 @@ export function SelectField<T, ItemType extends {} = SelectItem<T>>({
|
||||
className,
|
||||
selectedRender,
|
||||
arrowIcon,
|
||||
name,
|
||||
}: SelectFieldProps<T, ItemType>) {
|
||||
const getItemValue = (item: ItemType): T =>
|
||||
getValueByPath<ItemType, T>(item, itemValue, i => ('value' in i ? (i as unknown as SelectItem<T>).value : (i as unknown as T)));
|
||||
@@ -112,7 +123,7 @@ export function SelectField<T, ItemType extends {} = SelectItem<T>>({
|
||||
<SelectProvider value={currentValue as any} setValue={val => handleChange(val as T)}>
|
||||
{label && <SelectLabel className={labelClassName}>{label}</SelectLabel>}
|
||||
|
||||
<Select disabled={disabled}>
|
||||
<Select name={name} disabled={disabled}>
|
||||
{displayValue}
|
||||
{arrowIcon ?? <Select.Arrow />}
|
||||
</Select>
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
--dbv-kit-select-background: var(--dbv-kit-color-background);
|
||||
|
||||
--dbv-kit-select-border-width: var(--dbv-kit-control-border-width);
|
||||
--dbv-kit-select-border-color: var(--tw-color-gray-400);
|
||||
--dbv-kit-select-border-color: var(--dbv-kit-color-control-inactive);
|
||||
--dbv-kit-select-border-style: solid;
|
||||
--dbv-kit-select-border-radius: var(--dbv-kit-control-border-radius);
|
||||
|
||||
--dbv-kit-select-font-weight: var(--tw-font-weight-normal);
|
||||
--dbv-kit-select-font-size: calc(var(--dbv-kit-font-size-base) * 0.875);
|
||||
|
||||
--dbv-kit-select-label-foreground: var(--tw-color-gray-600);
|
||||
--dbv-kit-select-label-foreground: var(--dbv-kit-color-control-label);
|
||||
--dbv-kit-select-label-padding-inline: var(--tw-spacing);
|
||||
|
||||
--dbv-kit-select-popover-background: var(--dbv-kit-color-background);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
--dbv-kit-control-disabled-opacity: 0.5;
|
||||
|
||||
/* Outline */
|
||||
--dbv-kit-color-outline: var(--tw-color-blue-500);
|
||||
--dbv-kit-control-outline-color: var(--tw-color-blue-500);
|
||||
--dbv-kit-control-outline-width: 2px;
|
||||
--dbv-kit-control-outline-offset: 2px;
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
/* Colors */
|
||||
--dbv-kit-color-foreground: var(--tw-color-gray-900);
|
||||
--dbv-kit-color-background: var(--tw-color-gray-50);
|
||||
--dbv-kit-color-control-inactive: var(--tw-color-gray-300);
|
||||
--dbv-kit-color-control-hover: var(--tw-color-gray-400);
|
||||
--dbv-kit-color-control-label: var(--tw-color-gray-600);
|
||||
--dbv-kit-color-control-required: var(--tw-color-red-600);
|
||||
|
||||
--dbv-kit-color-primary-50: var(--tw-color-blue-50);
|
||||
--dbv-kit-color-primary-100: var(--tw-color-blue-100);
|
||||
|
||||
@@ -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.
|
||||
@@ -21,3 +21,4 @@ export {
|
||||
type SelectItemProps,
|
||||
} from './Select/Select.js';
|
||||
export { SelectField, type SelectFieldProps, type SelectItem } from './Select/SelectField.js';
|
||||
export { Radio, RadioGroup, useRadioContext, useRadioStore, type RadioProviderProps, type RadioProps, type RadioGroupProps } from './Radio/index.js';
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Button } from '../../Button/Button.js';
|
||||
import { Checkbox } from '../../Checkbox/Checkbox.js';
|
||||
import { Input } from '../../Input/Input.js';
|
||||
import { Radio } from '../../Radio/index.js';
|
||||
import { RadioGroup } from '../../Radio/RadioGroup.js';
|
||||
import { SelectField } from '../../Select/SelectField.js';
|
||||
|
||||
export const SimpleForm = () => {
|
||||
return (
|
||||
<form className="tw:flex tw:flex-col tw:gap-2" onSubmit={e => (e.preventDefault(), console.log('submit'))}>
|
||||
<Input placeholder="John" name="first-name" label="First Name" />
|
||||
<Input placeholder="Snow" name="last-name" label="Last Name" />
|
||||
<SelectField
|
||||
label="Country"
|
||||
name="Country"
|
||||
items={[
|
||||
{ value: 'USA', label: 'USA' },
|
||||
{ value: 'Canada', label: 'Canada' },
|
||||
{ value: 'UK', label: 'UK' },
|
||||
]}
|
||||
/>
|
||||
|
||||
<RadioGroup vertical label="Marital Status">
|
||||
<Radio name="status" value={'single'}>
|
||||
Single
|
||||
</Radio>
|
||||
<Radio name="status" value={'married'}>
|
||||
Married
|
||||
</Radio>
|
||||
<Radio name="status" value={'divorced'}>
|
||||
Divorced
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
|
||||
<RadioGroup vertical label="Children">
|
||||
<Radio value="Yes">Have children</Radio>
|
||||
<Radio value="No">No</Radio>
|
||||
</RadioGroup>
|
||||
<div>
|
||||
<Checkbox className="tw:flex-row-reverse">Veteran of the console.war</Checkbox>
|
||||
</div>
|
||||
<Button type="submit">Submit</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -76,7 +76,7 @@ export const States = () => {
|
||||
};
|
||||
|
||||
export const Sizes = () => (
|
||||
<div className="tw:flex tw:flex-col tw:space-y-4">
|
||||
<div className="tw:flex tw:flex-col">
|
||||
<Checkbox size="small"> Small </Checkbox>
|
||||
<Checkbox size="medium"> Medium </Checkbox>
|
||||
<Checkbox size="large"> Large </Checkbox>
|
||||
@@ -136,10 +136,6 @@ export const Tokens = () => {
|
||||
<code>--dbv-kit-checkbox-background-hover:</code> var(--dbv-kit-color-primary-100);{' '}
|
||||
<span className="comment"> Checkbox background color on hover</span>
|
||||
</div>
|
||||
<div>
|
||||
<code>--dbv-kit-checkbox-background-active:</code> var(--dbv-kit-color-primary-800);{' '}
|
||||
<span className="comment"> Checkbox background color when active</span>
|
||||
</div>
|
||||
<h3>Borders</h3>
|
||||
<div>
|
||||
<code>--dbv-kit-checkbox-border-width:</code> var(--dbv-kit-control-border-width); <span className="comment"> Checkbox border width</span>
|
||||
|
||||
@@ -8,7 +8,133 @@
|
||||
import { Button } from '../../../Button/Button.js';
|
||||
import { Input } from '../../../Input/Input.js';
|
||||
|
||||
export const InputExample = () => {
|
||||
export const Documentation = () => {
|
||||
return (
|
||||
<section>
|
||||
<h2>Input Component Documentation</h2>
|
||||
<p>
|
||||
The Input component is a customizable form control that allows users to enter text. It can be configured with various sizes and states, and
|
||||
can include labels with optional required indicators.
|
||||
</p>
|
||||
|
||||
<h2>CSS Classes</h2>
|
||||
|
||||
<h3>Input Wrapper</h3>
|
||||
<p>
|
||||
<code>.dbv-kit-input-wrapper</code> - The container that wraps the input and its label. Controls the layout and positioning.
|
||||
</p>
|
||||
|
||||
<h3>Main Input Element</h3>
|
||||
<p>
|
||||
<code>.dbv-kit-input</code> - The main class for the input component. Controls the appearance including size, colors, and borders.
|
||||
</p>
|
||||
|
||||
<h3>Size Variants</h3>
|
||||
<p>
|
||||
<code>.dbv-kit-input--small</code> - Smaller size variant of the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>.dbv-kit-input--medium</code> - Default size variant of the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>.dbv-kit-input--large</code> - Larger size variant of the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>.dbv-kit-input--xlarge</code> - Extra large size variant of the input.
|
||||
</p>
|
||||
|
||||
<h3>Label</h3>
|
||||
<p>
|
||||
<code>.dbv-kit-input__title</code> - Applied to the label element of the input component.
|
||||
</p>
|
||||
<p>
|
||||
<code>.dbv-kit-input__title--required</code> - Applied to the label when the input is required, adds an asterisk indicator.
|
||||
</p>
|
||||
|
||||
<h2>CSS Variables</h2>
|
||||
|
||||
<h3>Base Input Variables</h3>
|
||||
<p>
|
||||
<code>--dbv-kit-input-radius</code> - Controls the border radius of the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-font-size</code> - Sets the default font size of the input text.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-background</code> - Sets the background color of the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-border-color</code> - Defines the default border color of the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-border-width</code> - Sets the width of the border around the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-border-style</code> - Defines the style of the border (solid, dashed, etc.).
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-foreground</code> - Sets the text color of the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-height</code> - Controls the height of the input field.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-padding</code> - Sets the horizontal padding inside the input.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-placeholder-foreground</code> - Controls the color of placeholder text.
|
||||
</p>
|
||||
|
||||
<h3>Label Variables</h3>
|
||||
<p>
|
||||
<code>--dbv-kit-input-label-foreground</code> - Sets the text color of the label.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-label-padding</code> - Controls the padding of the label.
|
||||
</p>
|
||||
|
||||
<h3>Size Variables</h3>
|
||||
<p>
|
||||
<code>--dbv-kit-input-small-padding</code> - Controls the padding for small inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-small-font-size</code> - Sets the font size for small inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-small-height</code> - Controls the height for small inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-medium-padding</code> - Controls the padding for medium inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-medium-font-size</code> - Sets the font size for medium inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-medium-height</code> - Controls the height for medium inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-large-padding</code> - Controls the padding for large inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-large-font-size</code> - Sets the font size for large inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-large-height</code> - Controls the height for large inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-xlarge-padding</code> - Controls the padding for extra large inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-xlarge-font-size</code> - Sets the font size for extra large inputs.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-input-xlarge-height</code> - Controls the height for extra large inputs.
|
||||
</p>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputText = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
@@ -19,3 +145,134 @@ export const InputExample = () => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputNumber = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
<Input type="number" label="Age" defaultValue={18} />
|
||||
<Button>Enter</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputEmail = () => {
|
||||
return (
|
||||
<>
|
||||
<datalist id="ice-cream-emails">
|
||||
<option value="Chocolate@gmail.com"></option>
|
||||
<option value="Coconut@gmail.com"></option>
|
||||
<option value="Mint@gmail.com"></option>
|
||||
<option value="Strawberry@gmail.com"></option>
|
||||
<option value="Vanilla@gmail.com"></option>
|
||||
</datalist>
|
||||
<div className="tw:space-y-2">
|
||||
<Input list="ice-cream-emails" type="email" label="E-mail" placeholder="john@gmail.com" />
|
||||
<Button>Send</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputMonth = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
<Input type="month" label="Month" />
|
||||
<Button>Set</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputWeek = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
<Input type="week" label="Week" />
|
||||
<Button>Set</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputDate = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
<Input label="Birth date" type="date" />
|
||||
<Button>Set</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputTime = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
<Input type="time" label="Time" />
|
||||
<Button>Set</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputRange = () => {
|
||||
return (
|
||||
<>
|
||||
This is not a custom component, but a native HTML input range element.
|
||||
<div className="tw:space-y-2">
|
||||
<Input type="range" label="Range" min={1} max={100} />
|
||||
<Button>Set</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputSearch = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
<Input type="search" label="Search" />
|
||||
<Button>Find</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputTel = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
<Input type="tel" label="Phone" />
|
||||
<Button>Call</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputDisabled = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="tw:space-y-2">
|
||||
<Input label="Username" value="John" disabled />
|
||||
<Input label="E-mail" value="john@google.com" disabled />
|
||||
<div className="tw:mt-2"> To change this fields, please ask your administrator</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const InputRequired = () => {
|
||||
return (
|
||||
<form>
|
||||
<div className="tw:space-y-2">
|
||||
<Input label="Username" required />
|
||||
<Input label="E-mail" required />
|
||||
<Button type="submit">Register</Button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { _Radio, Radio, _RadioProvider, _RadioGroup } from '../../../Radio/index.js';
|
||||
import { RadioGroup } from '../../../Radio/RadioGroup.js';
|
||||
|
||||
export const Documentation = () => {
|
||||
return (
|
||||
<section>
|
||||
<h1>Radio Component Documentation</h1>
|
||||
<p>
|
||||
The Radio component is a customizable radio button that allows users to select one option from a set. The appearance can be customized using
|
||||
CSS classes and variables.
|
||||
</p>
|
||||
<h2>Props</h2>
|
||||
Accept all props from the underlying{' '}
|
||||
<a target="_blank" href="https://ariakit.org/reference/radio">
|
||||
{' '}
|
||||
Radio
|
||||
</a>{' '}
|
||||
component.
|
||||
<h3>Other properties</h3>
|
||||
<p>
|
||||
<code>size</code> - Size of the radio button. Default is 'medium'.
|
||||
</p>
|
||||
<h2>CSS Classes</h2>
|
||||
<h3>Main Radio Element</h3>
|
||||
<p>
|
||||
<code>.dbv-kit-radio</code> - The main container class for the radio component. Controls the overall appearance including size, colors, and
|
||||
borders.
|
||||
</p>
|
||||
<h3>Control</h3>
|
||||
<p>
|
||||
<code>.dbv-kit-radio__control</code> - Applied to the control element of the radio component.
|
||||
</p>
|
||||
<h3>Text</h3>
|
||||
<p>
|
||||
<code>.dbv-kit-radio__title</code> - Applied to the visible title element of the radio component.
|
||||
</p>
|
||||
<h2>CSS Variables</h2>
|
||||
<h3>Radio Component Variables</h3>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-height</code> - Controls the height of the radio component.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-gap</code> - Sets the gap between the radio button and the text.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-inactive-background</code> - Sets the background color of the inactive radio button.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-inactive-border</code> - Sets the border color of the inactive radio button.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-active-background</code> - Sets the background color of the active radio button.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-active-border</code> - Sets the border color of the active radio button.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-active-foreground</code> - Sets the foreground color of the active radio button.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-hover-shadow-color</code> - Defines the shadow color when hovering over the radio button.
|
||||
</p>
|
||||
<h3>Size Variables</h3>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-small-height</code> - Controls the height of the small radio button.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-medium-height</code> - Controls the height of the medium radio button.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-large-height</code> - Controls the height of the large radio button.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-radio-xlarge-height</code> - Controls the height of the extra-large radio button.
|
||||
</p>
|
||||
<h2>RadioGroup Component</h2>
|
||||
<p>
|
||||
The RadioGroup component is used to group multiple Radio components together. It supports both controlled and uncontrolled modes, and can be
|
||||
displayed vertically or horizontally. By default, you should use the RadioGroup component to use Radio components.
|
||||
</p>
|
||||
<h3>Props</h3>
|
||||
<p>
|
||||
Basically, RadioGroup accepts a list of underlying{' '}
|
||||
<a target="_blank" href="https://ariakit.org/reference/radio-provider">
|
||||
{' '}
|
||||
RadioProvider
|
||||
</a>{' '}
|
||||
component props such as 'value' | 'setValue' | 'store' | 'setActiveId' | 'rtl' | 'defaultValue'.{' '}
|
||||
</p>
|
||||
<h4 className="tw:underline">Other properties</h4>
|
||||
<p>
|
||||
<code>vertical</code> - Boolean to display the radio buttons vertically.
|
||||
</p>
|
||||
<p>
|
||||
<code>labelledBy</code> - ID of the element that labels the radio group, if you don't use label prop.
|
||||
</p>
|
||||
<p>
|
||||
<code>label</code> - React node to display as the label for the radio group. Rendered inside a label element and should respect HTML label
|
||||
semantics.
|
||||
</p>
|
||||
<p>
|
||||
<code>required</code> - Boolean to mark the radio group as required.
|
||||
</p>
|
||||
<p>
|
||||
<code>className</code> - Additional CSS classes to apply to the radio group.
|
||||
</p>
|
||||
<p>
|
||||
<code>items</code> - Array of objects with 'value' and 'label' properties to render radio buttons. Cannot be used together with children.
|
||||
</p>
|
||||
<p>
|
||||
<code>name</code> - Name of the radio group. Recommended to always provide a name to radio groups if children Radio components don't.
|
||||
</p>
|
||||
<p>
|
||||
<code>size</code> - Size of the radio buttons.
|
||||
</p>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export const RadioGroupControlled = () => {
|
||||
const [value, setValue] = useState('2');
|
||||
|
||||
useEffect(() => {
|
||||
const intervalId = setInterval(() => {
|
||||
const randomValue = Math.floor(Math.random() * 3 + 1).toString();
|
||||
setValue(randomValue);
|
||||
}, 2000);
|
||||
|
||||
return () => clearInterval(intervalId);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<RadioGroup aria-label="Controlled radio group" value={value} setValue={val => setValue(val as string)}>
|
||||
<Radio value={'1'}>Item 1</Radio>
|
||||
<Radio value={'2'}>Item 2</Radio>
|
||||
<Radio value={'3'}>Item 3</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export const RadioGroupUncontrolled = () => (
|
||||
<RadioGroup label="Uncontrolled">
|
||||
<Radio value={'1'}>Item 1</Radio>
|
||||
<Radio value={'2'}>Item 2</Radio>
|
||||
<Radio value={'3'}>Item 3</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
export const Vertical = () => (
|
||||
<RadioGroup label="Vertical" vertical>
|
||||
<Radio value={'1'}>Item 1</Radio>
|
||||
<Radio value={'2'}>Item 2</Radio>
|
||||
<Radio value={'3'}>Item 3</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
export const Required = () => (
|
||||
<RadioGroup label="Required" required>
|
||||
<Radio value={'1'}>Item 1</Radio>
|
||||
<Radio value={'2'}>Item 2</Radio>
|
||||
<Radio value={'3'}>Item 3</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
export const LabelsReactComponents = () => (
|
||||
<RadioGroup label="" vertical>
|
||||
<Radio value={'1'}>
|
||||
<div className="tw:flex tw:hover:bg-orange-100 tw:transition tw:duration-300 tw:ease-in-out">
|
||||
<div className="tw:bg-orange-500 tw:text-white tw:px-2">Orange</div>
|
||||
<div className="tw:ml-2 tw:text-gray-500">Juicy</div>
|
||||
</div>
|
||||
</Radio>
|
||||
<Radio value={'2'}>
|
||||
<div className="tw:flex tw:hover:bg-green-100">
|
||||
<div className="tw:bg-green-300 tw:text-green-900 tw:px-2">Apple</div>
|
||||
<div className="tw:ml-2 tw:text-gray-500">Vital</div>
|
||||
</div>
|
||||
</Radio>
|
||||
<Radio value={'3'}>
|
||||
<div className="tw:flex tw:hover:bg-rose-100">
|
||||
<div className="tw:bg-rose-400 tw:text-white tw:px-2">Peach</div>
|
||||
<div className="tw:ml-2 tw:text-gray-500">Silky</div>
|
||||
</div>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
export const GroupWithCustomLabel = () => (
|
||||
<div>
|
||||
<div id="fruits-radio" className="tw:text-lg">
|
||||
Pick a fruit
|
||||
</div>
|
||||
<RadioGroup labelledBy="fruits-radio">
|
||||
<Radio value={'1'}>Apple</Radio>
|
||||
<Radio value={'2'}>Banana</Radio>
|
||||
<Radio value={'3'}>Cherry</Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Sizes = () => (
|
||||
<div className="tw:space-y-4">
|
||||
<RadioGroup label="Small">
|
||||
<Radio size="small" value={'1'}>
|
||||
Small
|
||||
</Radio>
|
||||
<Radio size="small" value={'2'}>
|
||||
Small
|
||||
</Radio>
|
||||
<Radio size="small" value={'3'}>
|
||||
Small
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
<RadioGroup label="Medium">
|
||||
<Radio size="medium" value={'1'}>
|
||||
Medium
|
||||
</Radio>
|
||||
<Radio size="medium" value={'2'}>
|
||||
Medium
|
||||
</Radio>
|
||||
<Radio size="medium" value={'3'}>
|
||||
Medium
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
<RadioGroup label="Large">
|
||||
<Radio size="large" value={'1'}>
|
||||
Large
|
||||
</Radio>
|
||||
<Radio size="large" value={'2'}>
|
||||
Large
|
||||
</Radio>
|
||||
<Radio size="large" value={'3'}>
|
||||
Large
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
<RadioGroup label="Extra Large">
|
||||
<Radio size="xlarge" value={'1'}>
|
||||
Extra Large
|
||||
</Radio>
|
||||
<Radio size="xlarge" value={'2'}>
|
||||
Extra Large
|
||||
</Radio>
|
||||
<Radio size="xlarge" value={'3'}>
|
||||
Extra Large
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const RadioDisabled = () => (
|
||||
<RadioGroup label="Disabled">
|
||||
<Radio value={'1'} disabled>
|
||||
Disabled
|
||||
</Radio>
|
||||
<Radio value={'2'}>Enabled</Radio>
|
||||
<Radio value={'3'} disabled>
|
||||
Disabled
|
||||
</Radio>
|
||||
<Radio value={'4'}>Enabled</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Select } from '../../../Select/Select.js';
|
||||
|
||||
export const Docs = () => {
|
||||
@@ -69,7 +77,7 @@ export const Docs = () => {
|
||||
<code>--dbv-kit-control-outline-width</code> - Defines the width of the focus outline.
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-color-outline</code> - Sets the color of the focus outline.
|
||||
<code>--dbv-kit-control-outline-color</code> - Sets the color of the focus outline.
|
||||
</p>
|
||||
|
||||
<h3>Label Variables</h3>
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const GlobalTokens = () => {
|
||||
return (
|
||||
<div className="tw:p-4 tw:my-4">
|
||||
@@ -99,8 +107,8 @@ export const GlobalTokens = () => {
|
||||
<span className="color-sample" style={{ backgroundColor: 'var(--dbv-kit-color-primary-900)' }}></span>
|
||||
</p>
|
||||
<p>
|
||||
<code>--dbv-kit-color-outline:</code> Default control outline color used for focused elements{' '}
|
||||
<span className="color-sample" style={{ backgroundColor: 'var(--dbv-kit-color-outline)' }}></span>
|
||||
<code>--dbv-kit-control-outline-color:</code> Default control outline color used for focused elements{' '}
|
||||
<span className="color-sample" style={{ backgroundColor: 'var(--dbv-kit-control-outline-color)' }}></span>
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
|
||||
Reference in New Issue
Block a user