diff --git a/app/public/index.html b/app/public/index.html index c8d2c9daaa..fff4bbe40e 100644 --- a/app/public/index.html +++ b/app/public/index.html @@ -33,7 +33,7 @@ <% } %> - + diff --git a/app/src/common/AppHeader.tsx b/app/src/common/AppHeader.tsx index 3a8f06a7b8..407c303a6b 100644 --- a/app/src/common/AppHeader.tsx +++ b/app/src/common/AppHeader.tsx @@ -205,7 +205,7 @@ export function AppHeader() { target="_blank" href="https://forms.office.com/e/9iEvJUKdeM" > - Take part in UUI survey + Take part in UUI survey ), }, diff --git a/app/src/index.tsx b/app/src/index.tsx index d62a641904..03658162a4 100644 --- a/app/src/index.tsx +++ b/app/src/index.tsx @@ -18,7 +18,6 @@ import '@epam/internal/styles.css'; import '@epam/assets/theme/theme_vanilla_thunder.scss'; import '@epam/assets/theme/theme_loveship_dark.scss'; import '@epam/assets/theme/theme_electric.scss'; -import '@epam/assets/theme/theme_6px.scss'; import './index.module.scss'; const router6 = createBrowserRouter([ diff --git a/epam-assets/theme/theme_6px.scss b/epam-assets/theme/theme_6px.scss index 21cbb92efc..39ac4a937e 100644 --- a/epam-assets/theme/theme_6px.scss +++ b/epam-assets/theme/theme_6px.scss @@ -1,13 +1,25 @@ -.uui-6px-grid { +@mixin uui-6px-grid { --uui-focus-outline-width: 2px; --uui-focus-outline-offset: 2px; --uui-focus-radius: 2px; - --uui-border-radius: 3px; + //--uui-border-radius: 3px; // TODO: ????? --uui-y-inner-padding: calc((var(--uui-size) - var(--uui-line-height) - (var(--uui-border-width) * 2)) / 2); --uui-tab-line-width: 3px; --uui-notify-size: 6px; - .uui-size-18, .uui-size-24.uui-picker-toggler .uui-tag.uui-size-inherit { + + .uui-size-12 { + --uui-size: 12px; + --uui-border-width: 1px; + --uui-x-outer-padding: 6px; + --uui-x-inner-padding: 6px; + --uui-icon-size: 12px; + --uui-line-height: 12px; + --uui-font-size: 12px; + + } + + .uui-size-18 { --uui-size: 18px; --uui-border-width: 1px; --uui-x-outer-padding: 3px; @@ -18,7 +30,7 @@ } - .uui-size-24, .uui-size-30.uui-picker-toggler .uui-tag.uui-size-inherit { + .uui-size-24 { --uui-size: 24px; --uui-border-width: 1px; --uui-x-outer-padding: 6px; @@ -29,7 +41,7 @@ --uui-font-size: 12px; } - .uui-size-30, .uui-size-36.uui-picker-toggler .uui-tag.uui-size-inherit { + .uui-size-30 { --uui-size: 30px; --uui-border-width: 1px; --uui-x-outer-padding: 6px; @@ -40,7 +52,7 @@ --uui-font-size: 14px; } - .uui-size-36, .uui-size-42.uui-picker-toggler .uui-tag.uui-size-inherit { + .uui-size-36 { --uui-size: 36px; --uui-border-width: 1px; --uui-x-outer-padding: 6px; @@ -51,7 +63,7 @@ --uui-font-size: 14px; } - .uui-size-42, .uui-size-48.uui-picker-toggler .uui-tag.uui-size-inherit { + .uui-size-42 { --uui-size: 42px; --uui-border-width: 1px; --uui-x-outer-padding: 12px; @@ -81,7 +93,7 @@ --uui-y-outer-padding: 3px; --uui-icon-size: 24px; --uui-line-height: 24px; - --uui-font-size: 16px; + --uui-font-size: 20px; } .uui-input-box { @@ -94,17 +106,20 @@ } } - .uui-tab-button { - &.uui-size-36, &.uui-size-48, &.uui-size-60 { - --uui-x-outer-padding: 9px; - --uui-x-inner-padding: 3px; - --uui-icon-size: 18px; - --uui-line-height: 18px; - --uui-font-size: 14px; - } + .uui-tab-button:is(.uui-size-36, .uui-size-48, .uui-size-60) { + --uui-x-outer-padding: 9px; + --uui-x-inner-padding: 3px; + --uui-icon-size: 18px; + --uui-line-height: 18px; + --uui-font-size: 14px; } .uui-tag { + &.uui-size-18 { + --uui-font-size: 12px; + --uui-line-height: 14px; + } + &.uui-size-18, &.uui-size-24, &.uui-size-30, @@ -117,20 +132,20 @@ &.uui-size-30 { --uui-x-outer-padding: 3px; } + + &.uui-size-42, + &.uui-size-48 { + --uui-x-outer-padding: 6px; + } } - .uui-size-24.uui-picker-toggler, - .uui-size-30.uui-picker-toggler, - .uui-size-36.uui-picker-toggler, - .uui-size-42.uui-picker-toggler { + .uui-picker-toggler:is(.uui-size-24, .uui-size-30, .uui-size-36, .uui-size-42) { .uui-tag.uui-size-inherit { --uui-x-inner-padding: 3px; } } - .uui-size-24.uui-picker-toggler, - .uui-size-30.uui-picker-toggler, - .uui-size-36.uui-picker-toggler { + .uui-picker-toggler:is(.uui-size-24, .uui-size-30, .uui-size-36) { .uui-tag.uui-size-inherit { --uui-x-outer-padding: 3px; } @@ -141,4 +156,39 @@ --uui-x-outer-padding: 6px; } } + + .uui-checkbox-container { + &.uui-size-18 { + --uui-x-inner-padding: 12px; + --uui-line-height: 18px; + --uui-font-size: 14px; + } + } + + .uui-switch { + &.uui-size-18 { + --uui-x-inner-padding: 12px; + --uui-line-height: 18px; + --uui-font-size: 14px; + } + + &.uui-size-24 { + --uui-x-inner-padding: 12px; + --uui-line-height: 24px; + --uui-font-size: 16px; + } + } + + .uui-picker-body:is(.uui-size-30, .uui-size-36) .uui-switch.uui-size-inherit { + --uui-x-inner-padding: 12px; + --uui-line-height: 18px; + --uui-font-size: 14px; + + } + + .uui-picker-body:is(.uui-size-42, .uui-size-48) .uui-switch.uui-size-inherit { + --uui-x-inner-padding: 12px; + --uui-line-height: 24px; + --uui-font-size: 16px; + } } diff --git a/epam-assets/theme/theme_electric.scss b/epam-assets/theme/theme_electric.scss index 165b7d7a6d..c22ad97fd6 100644 --- a/epam-assets/theme/theme_electric.scss +++ b/epam-assets/theme/theme_electric.scss @@ -1,4 +1,5 @@ @use './tokens/_theme_electric.scss' as tokens; +@use './theme_6px' as *; @import '../scss/electric/font-faces'; /* Name convention */ @@ -537,5 +538,6 @@ } .uui-theme-electric { + @include uui-6px-grid(); @include theme-electric(); } diff --git a/epam-assets/theme/theme_loveship.scss b/epam-assets/theme/theme_loveship.scss index 6506bde267..686572352e 100644 --- a/epam-assets/theme/theme_loveship.scss +++ b/epam-assets/theme/theme_loveship.scss @@ -1,4 +1,5 @@ @use '../scss/loveship/font-faces'; +@use './theme_6px' as *; @use './tokens/_theme_loveship.scss' as tokens; /* Name convention */ /* --uui-'component name or group of components name'-'styled part name'-'states(optional)'-'hover/active/focus(optional)' */ @@ -624,5 +625,6 @@ } .uui-theme-loveship { + @include uui-6px-grid(); @include theme-loveship(); } diff --git a/epam-assets/theme/theme_loveship_dark.scss b/epam-assets/theme/theme_loveship_dark.scss index 31bd62cc8b..061db61fe3 100644 --- a/epam-assets/theme/theme_loveship_dark.scss +++ b/epam-assets/theme/theme_loveship_dark.scss @@ -1,4 +1,5 @@ @use '../scss/loveship/font-faces'; +@use './theme_6px' as *; @use './tokens/_theme_loveship_dark.scss' as tokens; /* Name convention */ /* --uui-'component name or group of components name'-'styled part name'-'states(optional)'-'hover/active/focus(optional)' */ @@ -824,5 +825,6 @@ } .uui-theme-loveship_dark { + @include uui-6px-grid(); @include theme-loveship_dark(); } diff --git a/epam-assets/theme/theme_promo.scss b/epam-assets/theme/theme_promo.scss index 4cef34d449..cb53f707d1 100644 --- a/epam-assets/theme/theme_promo.scss +++ b/epam-assets/theme/theme_promo.scss @@ -1,4 +1,5 @@ @use '../scss/promo/font-faces'; +@use './theme_6px' as *; @use './tokens/_theme_promo.scss' as tokens; /* Name convention */ /* --uui-'component name or group of components name'-'styled part name'-'states(optional)'-'hover/active/focus(optional)' */ @@ -636,6 +637,7 @@ } .uui-theme-promo { + @include uui-6px-grid(); @include theme-promo(); } diff --git a/epam-assets/theme/theme_vanilla_thunder.scss b/epam-assets/theme/theme_vanilla_thunder.scss index a9db2d9b22..12d370a09f 100644 --- a/epam-assets/theme/theme_vanilla_thunder.scss +++ b/epam-assets/theme/theme_vanilla_thunder.scss @@ -1,6 +1,9 @@ +@use './theme_6px' as *; + /* Name convention */ /* --uui-'component name or group of components name'-'styled part name'-'states(optional)'-'hover/active/focus(optional)' */ .uui-theme-vanilla_thunder { + @include uui-6px-grid(); --uui-font: var(--font-inter); --uui-font-mono: 'Roboto Mono', monospace; @@ -478,4 +481,4 @@ } } } -} \ No newline at end of file +} diff --git a/uui-components/src/buttons/IconButton.tsx b/uui-components/src/buttons/IconButton.tsx index f309ab1ef8..baf82437a1 100644 --- a/uui-components/src/buttons/IconButton.tsx +++ b/uui-components/src/buttons/IconButton.tsx @@ -12,7 +12,7 @@ export type IconButtonProps = ClickableComponentProps & Omit((props, ref) => { - const size = props.size && Number(props.size); return ( - + { props.showDropdownIcon && ( - + ) } ); diff --git a/uui-components/src/layout/IconContainer.tsx b/uui-components/src/layout/IconContainer.tsx index a59a38da76..f55c099d46 100644 --- a/uui-components/src/layout/IconContainer.tsx +++ b/uui-components/src/layout/IconContainer.tsx @@ -17,7 +17,7 @@ export interface ControlIconProps extends IHasCX, IDisableable, IHasRawProps((props, ref) => { diff --git a/uui-components/src/widgets/Avatar.tsx b/uui-components/src/widgets/Avatar.tsx index 36920880e7..d72a20d211 100644 --- a/uui-components/src/widgets/Avatar.tsx +++ b/uui-components/src/widgets/Avatar.tsx @@ -38,15 +38,13 @@ function AvatarComponent(props: AvatarProps, ref: React.ForwardedRef { return { dropdownIcon: props.dropdownIcon || systemIcons.foldingArrow, - size: props.size && Number(props.size), }; }, applyIconButtonMods, diff --git a/uui/components/buttons/LinkButton.module.scss b/uui/components/buttons/LinkButton.module.scss index 8610719bcf..4e1f9605d5 100644 --- a/uui/components/buttons/LinkButton.module.scss +++ b/uui/components/buttons/LinkButton.module.scss @@ -1,20 +1,33 @@ @use '../../assets/styles/index' as *; .root { + // colors --uui-link_btn-text: var(--uui-color-50); --uui-link_btn-text-hover: var(--uui-color-60); --uui-link_btn-text-active: var(--uui-color-70); --uui-link_btn-text-disabled: var(--uui-text-disabled); + // fonts --uui-link-button-font: var(--uui-font); --uui-link-button-font-weight: 600; + // sizes + --uui-link-button-min-height: var(--uui-size); + --uui-link-button-min-width: var(--uui-size); + --uui-link-button-inner-gap: var(--uui-x-inner-padding); + --uui-link-button-caption-padding: calc((var(--uui-link-button-min-height) - var(--uui-link-button-line-height)) / 2); + --uui-link-button-icon-height: var(--uui-icon-size); + --uui-link-button-line-height: var(--uui-line-height); + --uui-link-button-font-size: var(--uui-font-size); + @include clickable-styles(); + min-width: var(--uui-link-button-min-width); &:global(.uui-button-box) { background-color: transparent; color: var(--uui-link_btn-text); fill: var(--uui-link_btn-text); + min-height: var(--uui-link-button-min-height); min-width: auto; &:global(.-clickable:not(.uui-disabled)) { @@ -56,32 +69,24 @@ :global(.uui-caption) { font-family: var(--uui-link-button-font); font-weight: var(--uui-link-button-font-weight, normal); - } + line-height: var(--uui-link-button-line-height); + font-size: var(--uui-link-button-font-size); + padding-top: var(--uui-link-button-caption-padding); + padding-bottom: var(--uui-link-button-caption-padding); - // Sizes - &:global { - &.uui-size-18 { - @include link-button-layout(18px); + &:not(:first-child) { + padding-left: var(--uui-link-button-inner-gap); } - &.uui-size-24 { - @include link-button-layout(24px); - } - - &.uui-size-30 { - @include link-button-layout(30px); - } - - &.uui-size-36 { - @include link-button-layout(36px); - } - - &.uui-size-42 { - @include link-button-layout(42px); + &:not(:last-child) { + padding-right: var(--uui-link-button-inner-gap); } + } - &.uui-size-48 { - @include link-button-layout(48px); + :global(.uui-icon) { + svg { + height: var(--uui-link-button-icon-height); + width: inherit; } } } diff --git a/uui/components/buttons/LinkButton.tsx b/uui/components/buttons/LinkButton.tsx index bf0d7b5c2c..144dc3ab6b 100644 --- a/uui/components/buttons/LinkButton.tsx +++ b/uui/components/buttons/LinkButton.tsx @@ -3,10 +3,10 @@ import { CX, cx, devLogger, Icon, IDropdownToggler, IHasCaption, IHasIcon, uuiEl import { Clickable, ClickableComponentProps, IconContainer } from '@epam/uui-components'; import * as types from '../types'; import { systemIcons } from '../../icons/icons'; +import { settings } from '../../settings'; import { getIconClass } from './helper'; import css from './LinkButton.module.scss'; -const DEFAULT_SIZE = '36'; const DEFAULT_COLOR = 'primary'; interface LinkButtonMods { @@ -40,7 +40,7 @@ function applyLinkButtonMods(mods: LinkButtonProps) { return [ 'uui-link_button', css.root, - `uui-size-${mods.size || DEFAULT_SIZE}`, + `uui-size-${mods.size || settings.sizes.defaults.linkButton}`, ...getIconClass(mods), `uui-color-${mods.color || DEFAULT_COLOR}`, ]; diff --git a/uui/components/buttons/TabButton.tsx b/uui/components/buttons/TabButton.tsx index 110e53e22a..6e80fef9b9 100644 --- a/uui/components/buttons/TabButton.tsx +++ b/uui/components/buttons/TabButton.tsx @@ -4,6 +4,7 @@ import { Clickable, ClickableComponentProps, IconContainer } from '@epam/uui-com import { getIconClass } from './helper'; import { CountIndicator } from '../widgets'; import { systemIcons } from '../../icons/icons'; +import { settings } from '../../settings'; import css from './TabButton.module.scss'; type TabButtonMods = { @@ -16,8 +17,6 @@ type TabButtonMods = { withNotify?: boolean; }; -const DEFAULT_SIZE = '48'; - /** Represents the properties of a TabButton component. */ export type TabButtonProps = TabButtonMods & ClickableComponentProps & IDropdownToggler & IHasIcon & IHasCaption & { /** Call to clear toggler value */ @@ -39,7 +38,7 @@ function applyTabButtonMods(mods: TabButtonProps) { return [ css.root, 'uui-tab-button', - `uui-size-${mods.size || DEFAULT_SIZE}`, + `uui-size-${mods.size || settings.sizes.defaults.tabButton}`, mods.withNotify && css.withNotify, ...getIconClass(mods), ]; diff --git a/uui/components/datePickers/DatePicker.tsx b/uui/components/datePickers/DatePicker.tsx index 53e6fde002..a5450daf7c 100644 --- a/uui/components/datePickers/DatePicker.tsx +++ b/uui/components/datePickers/DatePicker.tsx @@ -3,7 +3,7 @@ import { Dropdown } from '@epam/uui-components'; import { DropdownBodyProps, IDropdownToggler, cx, devLogger, isFocusReceiverInsideFocusLock, useUuiContext, uuiMod, } from '@epam/uui-core'; -import { TextInput } from '../inputs'; +import { TextInput, TextInputProps } from '../inputs'; import { EditMode } from '../types'; import { systemIcons } from '../../icons/icons'; import { DropdownContainer } from '../overlays'; @@ -12,6 +12,7 @@ import { defaultFormat, isValidDate, toCustomDateFormat, toValueDateFormat, } from './helpers'; import { DatePickerBody } from './DatePickerBody'; +import { settings } from '../../settings'; const defaultMode = EditMode.FORM; const modifiers = [{ @@ -84,7 +85,7 @@ export function DatePickerComponent(props: DatePickerProps, ref: React.Forwarded icon={ props.mode !== EditMode.CELL && systemIcons.calendar ? systemIcons.calendar : undefined } iconPosition={ props.iconPosition || 'left' } placeholder={ props.placeholder ? props.placeholder : format } - size={ props.size || '36' } + size={ props.size || settings.sizes.defaults.datePicker as TextInputProps['size'] } value={ inputValue || undefined } onValueChange={ (v) => { setInputValue(v || ''); diff --git a/uui/components/datePickers/RangeDatePicker.module.scss b/uui/components/datePickers/RangeDatePicker.module.scss index 39d83c9913..abb032d519 100644 --- a/uui/components/datePickers/RangeDatePicker.module.scss +++ b/uui/components/datePickers/RangeDatePicker.module.scss @@ -8,33 +8,9 @@ min-width: 0; padding: 0 5px; - &:global(.uui-focus) { - border: 1px solid var(--uui-control-border-focus); - } - - &.size-24 { - @include control-box-layout(22px, 0); - @include scalable-icon-size(24); - } - - &.size-30 { - @include control-box-layout(28px, 0); - @include scalable-icon-size(30); - } - - &.size-36 { - @include control-box-layout(34px, 0); - @include scalable-icon-size(36); - } - - &.size-42 { - @include control-box-layout(40px, 0); - @include scalable-icon-size(42); - } - - &.size-48 { - @include control-box-layout(46px, 0); - @include scalable-icon-size(48); + &:global(.uui-input-box) { + border-width: 0; + min-height: calc(var(--uui-size) - 2px); } } @@ -45,6 +21,16 @@ border: 1px solid var(--uui-control-border); border-radius: var(--uui-border-radius); + > :first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + > :last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .separator { display: flex; flex-shrink: 0; diff --git a/uui/components/datePickers/RangeDatePickerInput.tsx b/uui/components/datePickers/RangeDatePickerInput.tsx index d83c5cd41a..0d2d9997ca 100644 --- a/uui/components/datePickers/RangeDatePickerInput.tsx +++ b/uui/components/datePickers/RangeDatePickerInput.tsx @@ -5,7 +5,7 @@ import { uuiDayjs } from '../../helpers/dayJsHelper'; import { IEditable, devLogger, cx, uuiMod, IHasCX, IClickable, IHasRawProps, } from '@epam/uui-core'; -import { TextInput } from '../inputs'; +import { TextInput, TextInputProps } from '../inputs'; import { SizeMod } from '../types'; import { RangeDatePickerInputType, RangeDatePickerProps, RangeDatePickerValue, @@ -16,6 +16,7 @@ import css from './RangeDatePicker.module.scss'; import { defaultRangeValue, isValidRange, toCustomDateRangeFormat, toValueDateRangeFormat, } from './helpers'; +import { settings } from '../../settings'; /** * Represents RangeDatePickerInputProps @@ -150,8 +151,8 @@ export const RangeDatePickerInput = forwardRef onInputChange(v || '', 'from') } @@ -166,9 +167,9 @@ export const RangeDatePickerInput = forwardRef
{ onValueChange(defaultRangeValue); diff --git a/uui/components/filters/FilterPickerBody.tsx b/uui/components/filters/FilterPickerBody.tsx index 1189616fa2..24f261b751 100644 --- a/uui/components/filters/FilterPickerBody.tsx +++ b/uui/components/filters/FilterPickerBody.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import * as React from 'react'; import { DataRowProps, DataSourceListProps, DataSourceState, DropdownBodyProps, isMobile, PickerFilterConfig, usePrevious } from '@epam/uui-core'; import { PickerBodyBaseProps, PickerInputBaseProps, usePickerInput } from '@epam/uui-components'; import { DataPickerRow, PickerItem, DataPickerBody, DataPickerFooter, PickerInputProps } from '../pickers'; @@ -9,7 +9,7 @@ type FilterPickerBodyProps = DropdownBodyProps & PickerInputBaseProp showSearch?: boolean; }; -export function FilterPickerBody({ +export function FilterPickerBody({ highlightSearchMatches = true, ...restProps }: FilterPickerBodyProps) { @@ -33,14 +33,14 @@ export function FilterPickerBody({ const prevOpened = usePrevious(props.isOpen); React.useLayoutEffect(() => { - if (prevOpened === props.isOpen && props.isOpen + if (prevOpened === props.isOpen && props.isOpen && prevValue !== props.value && props.value !== props.emptyValue && props.selectionMode === 'single' ) { props.onClose(); } }, [props.value]); - + const getSubtitle = ({ path }: DataRowProps, { search }: DataSourceState) => { if (!search) return; @@ -59,7 +59,7 @@ export function FilterPickerBody({ highlightSearchMatches={ highlightSearchMatches } { ...(flattenSearchResults ? { subtitle: getSubtitle(rowProps, dsState) } : {}) } dataSourceState={ dsState } - size="36" + size="36" { ...rowProps } /> ); diff --git a/uui/components/filters/FiltersPanelItem.tsx b/uui/components/filters/FiltersPanelItem.tsx index d6e254fccd..ce09ffd579 100644 --- a/uui/components/filters/FiltersPanelItem.tsx +++ b/uui/components/filters/FiltersPanelItem.tsx @@ -33,7 +33,7 @@ function useView(props: FiltersToolbarItemProps, value: any) { if (props.type === 'singlePicker') { dataSourceState.selectedId = value; } - + if (props.type === 'multiPicker') { dataSourceState.checked = value; } diff --git a/uui/components/inputs/Checkbox.module.scss b/uui/components/inputs/Checkbox.module.scss index 74c8d90961..35de8ae7cd 100644 --- a/uui/components/inputs/Checkbox.module.scss +++ b/uui/components/inputs/Checkbox.module.scss @@ -1,25 +1,5 @@ @use '../../assets/styles/index.scss' as *; -@mixin icon-sizes($size, $font-size, $line-height) { - :global(.uui-checkbox) { - box-sizing: border-box; - width: $size; - height: $size; - - :global(.uui-icon) { - svg { - height: $size; - width: $size; - } - } - } - - :global(.uui-input-label) { - font-size: $font-size; - line-height: $line-height; - } -} - .root { --uui-checkbox-border: var(--uui-control-border); --uui-checkbox-border-hover: var(--uui-color-60); @@ -37,26 +17,38 @@ --uui-checkbox-label-disabled: var(--uui-text-disabled); --uui-checkbox-label-readonly: var(--uui-text-primary); - --uui-checkbox-border-radius: var(--uui-border-radius); - + // font --uui-checkbox-font: var(--uui-font); --uui-checkbox-font-weight: 400; - //Colors - &:hover, &:active, &:focus-within { - :global(.uui-checkbox) { - border-color: var(--uui-checkbox-border-hover); - } - - :global(.uui-checked) { - background-color: var(--uui-checkbox-bg-checked-hover); - } - } + // size + --uui-checkbox-min-height: var(--uui-size); + --uui-checkbox-min-width: var(--uui-size); + --uui-checkbox-border-radius: var(--uui-border-radius); + --uui-checkbox-border-width: var(--uui-border-width); + --uui-checkbox-inner-gap: var(--uui-x-inner-padding); + --uui-checkbox-line-height: var(--uui-line-height); + --uui-checkbox-font-size: var(--uui-font-size); + //Colors :global(.uui-checkbox) { background-color: var(--uui-checkbox-bg); - border: 1px solid var(--uui-checkbox-border); + border: var(--uui-checkbox-border-width) solid var(--uui-checkbox-border); border-radius: var(--uui-checkbox-border-radius); position: relative; + box-sizing: border-box; + height: var(--uui-checkbox-min-height); + width: var(--uui-checkbox-min-width); + + :global(.uui-icon) { + position: absolute; + top: calc(0px - var(--uui-checkbox-border-width)); + left: calc(0px - var(--uui-checkbox-border-width)); + + svg { + height: var(--uui-checkbox-min-height); + width: var(--uui-checkbox-min-width); + } + } :global(input[type='checkbox']):focus-visible { @include focus-visible-effect(); @@ -67,10 +59,12 @@ } :global(.uui-input-label) { + color: var(--uui-checkbox-label); font-family: var(--uui-checkbox-font); + font-size: var(--uui-checkbox-font-size); font-weight: var(--uui-checkbox-font-weigth); - color: var(--uui-checkbox-label); - margin-left: 12px; + line-height: var(--uui-checkbox-line-height); + margin-left: var(--uui-checkbox-inner-gap); flex-grow: 1; } @@ -80,6 +74,16 @@ fill: var(--uui-checkbox-fill); } + &:hover, &:active, &:focus-within { + :global(.uui-checkbox) { + border-color: var(--uui-checkbox-border-hover); + } + + :global(.uui-checked) { + background-color: var(--uui-checkbox-bg-checked-hover); + } + } + &:global(.uui-disabled), &:global(.uui-readonly) { cursor: default; @@ -144,19 +148,6 @@ } } - //Sizes - &.size-18 { - @include icon-sizes(18px, 14px, 18px); - } - - &.size-12 { - @include icon-sizes(12px, 12px, 12px); - - :global(.uui-input-label) { - margin-left: 6px; - } - } - &.mode-cell { justify-content: center; } diff --git a/uui/components/inputs/Checkbox.tsx b/uui/components/inputs/Checkbox.tsx index 2f1152856a..947eee9073 100644 --- a/uui/components/inputs/Checkbox.tsx +++ b/uui/components/inputs/Checkbox.tsx @@ -2,6 +2,7 @@ import { withMods } from '@epam/uui-core'; import * as uuiComponents from '@epam/uui-components'; import { ReactComponent as Check } from '@epam/assets/icons/notification-done-outline.svg'; import { ReactComponent as PartlySelect } from '@epam/assets/icons/content-minus-outline.svg'; +import { settings } from '../../settings'; import css from './Checkbox.module.scss'; interface CheckboxMods { @@ -23,7 +24,7 @@ export type CheckboxProps = CheckboxMods & uuiComponents.CheckboxProps; function applyCheckboxMods(mods: CheckboxMods) { return [ css.root, - css['size-' + (mods.size || '18')], + `uui-size-${mods.size || settings.sizes.defaults.checkbox}`, css['mode-' + (mods.mode || 'form')], 'uui-color-primary', ]; diff --git a/uui/components/inputs/NumericInput.tsx b/uui/components/inputs/NumericInput.tsx index 39cc60fcc0..90110a310d 100644 --- a/uui/components/inputs/NumericInput.tsx +++ b/uui/components/inputs/NumericInput.tsx @@ -3,9 +3,9 @@ import { NumericInput as uuiNumericInput, NumericInputProps as uuiNumericInputPr import { ControlSize, EditMode, IHasEditMode } from '../types'; import { systemIcons } from '../../icons/icons'; import textInputCss from './TextInput.module.scss'; +import { settings } from '../../settings'; import css from './NumericInput.module.scss'; -const DEFAULT_SIZE = '36'; const DEFAULT_MODE = EditMode.FORM; type NumericInputMods = IHasEditMode & { @@ -21,7 +21,7 @@ function applyNumericInputMods(mods: NumericInputMods) { return [ textInputCss.root, css.root, - `uui-size-${mods.size || DEFAULT_SIZE}`, + `uui-size-${mods.size || settings.sizes.defaults.numericInput}`, textInputCss['mode-' + (mods.mode || DEFAULT_MODE)], ]; } diff --git a/uui/components/inputs/RadioInput.tsx b/uui/components/inputs/RadioInput.tsx index 3dd4f7972d..4e7d771168 100644 --- a/uui/components/inputs/RadioInput.tsx +++ b/uui/components/inputs/RadioInput.tsx @@ -1,7 +1,8 @@ import { withMods } from '@epam/uui-core'; import { RadioInput as uuiRadioInput, RadioInputProps as uuiRadioInputProps } from '@epam/uui-components'; -import css from './RadioInput.module.scss'; import { ReactComponent as RadioPoint } from '@epam/assets/icons/radio_dot-fill.svg'; +import { settings } from '../../settings'; +import css from './RadioInput.module.scss'; type RadioInputMods = { /** @@ -17,7 +18,7 @@ export type RadioInputProps = RadioInputMods & uuiRadioInputProps; function applyRadioInputMods(mods: RadioInputProps) { return [ css.root, - css['size-' + (mods.size || '18')], + css['size-' + (mods.size || settings.sizes.defaults.radioInput)], 'uui-radio-input-container', 'uui-color-primary', ]; diff --git a/uui/components/inputs/Switch.module.scss b/uui/components/inputs/Switch.module.scss index babb669ce5..3fe297c126 100644 --- a/uui/components/inputs/Switch.module.scss +++ b/uui/components/inputs/Switch.module.scss @@ -51,31 +51,60 @@ --uui-switch-label: var(--uui-text-primary); --uui-switch-label-disabled: var(--uui-text-disabled); + // font --uui-switch-font: var(--uui-font); --uui-switch-font-weight: 400; + + // size + --uui-switch-min-height: var(--uui-size); + --uui-switch-min-width: var(--uui-size); + --uui-switch-border-width: var(--uui-border-width); + --uui-switch-inner-gap: var(--uui-x-inner-padding); + --uui-switch-line-height: var(--uui-line-height); + --uui-switch-font-size: var(--uui-font-size); // //Sizes - &.size-12 { - @include control-switch-size(12px); + //&.size-12 { + // @include control-switch-size(12px); + //} + // + //&.size-18 { + // @include control-switch-size(18px); + //} + // + //&.size-24 { + // @include control-switch-size(24px); + //} + + :global(.uui-switch-body) { + height: var(--uui-switch-min-height); + width: calc(var(--uui-switch-min-width) * 2); + } + + :global(.uui-switch-toggler) { + height: var(--uui-switch-min-height); + width: var(--uui-switch-min-width); } - &.size-18 { - @include control-switch-size(18px); + :global(.uui-input-label) { + font-size: var(--uui-switch-font-size); + line-height: var(--uui-switch-line-height); } - &.size-24 { - @include control-switch-size(24px); + :global(.uui-checked) { + :global(.uui-switch-toggler) { + transform: translateX(var(--uui-switch-min-width)); + } } :global(.uui-switch-body) { background-color: var(--uui-switch-bg); - border: 1px solid var(--uui-switch-border); - width: 36px; - border-radius: 18px; + border: var(--uui-switch-border-width) solid var(--uui-switch-border); + border-radius: var(--uui-switch-min-height); box-sizing: border-box; :global(input[type='checkbox']):focus-visible { - @include focus-visible-effect(2px, inherit); + @include focus-visible-effect(var(--uui-focus-outline-offset), inherit); width: inherit; height: inherit; position: absolute; @@ -84,11 +113,11 @@ } :global(.uui-switch-toggler) { - left: -1px; + left: calc(0px - var(--uui-switch-border-width)); border-radius: 50%; box-sizing: border-box; background-color: var(--uui-switch-toggler-bg); - border: 1px solid var(--uui-switch-border); + border: var(--uui-switch-border-width) solid var(--uui-switch-border); transition: 0.1s transform cubic-bezier(0.4, 0, 0.2, 1); } @@ -96,7 +125,7 @@ font-family: var(--uui-switch-font); font-weight: var(--uui-switch-font-weight, normal); color: var(--uui-switch-label); - margin-left: 11px; + margin-left: var(--uui-switch-inner-gap); } //Colors diff --git a/uui/components/inputs/Switch.tsx b/uui/components/inputs/Switch.tsx index 83fc704b77..9a8cb44231 100644 --- a/uui/components/inputs/Switch.tsx +++ b/uui/components/inputs/Switch.tsx @@ -1,5 +1,6 @@ import { withMods } from '@epam/uui-core'; import * as uuiComponents from '@epam/uui-components'; +import { settings } from '../../settings'; import css from './Switch.module.scss'; interface SwitchMods { @@ -15,7 +16,9 @@ export type SwitchProps = uuiComponents.SwitchProps & SwitchMods; function applySwitchMods(mods: SwitchProps) { return [ - css.root, css['size-' + (mods.size || '18')], 'uui-color-primary', + css.root, + `uui-size-${mods.size || settings.sizes.defaults.switch}`, + 'uui-color-primary', ]; } diff --git a/uui/components/inputs/TextInput.tsx b/uui/components/inputs/TextInput.tsx index 7b171b2081..79e15a210f 100644 --- a/uui/components/inputs/TextInput.tsx +++ b/uui/components/inputs/TextInput.tsx @@ -3,9 +3,9 @@ import { withMods, IEditableDebouncer, IEditableDebouncerOptions } from '@epam/u import { TextInput as uuiTextInput, TextInputProps as CoreTextInputProps } from '@epam/uui-components'; import { IHasEditMode, EditMode, ControlSize } from '../types'; import { systemIcons } from '../../icons/icons'; +import { settings } from '../../settings'; import css from './TextInput.module.scss'; -const DEFAULT_SIZE = '36'; const DEFAULT_MODE = EditMode.FORM; type TextInputMods = IHasEditMode & { @@ -19,7 +19,7 @@ type TextInputMods = IHasEditMode & { function applyTextInputMods(mods: CoreTextInputProps & TextInputMods) { return [ css.root, - `uui-size-${mods.size || DEFAULT_SIZE}`, + `uui-size-${mods.size || settings.sizes.defaults.textInput}`, css['mode-' + (mods.mode || DEFAULT_MODE)], ]; } diff --git a/uui/components/pickers/DataPickerBody.tsx b/uui/components/pickers/DataPickerBody.tsx index 65f0428548..5f556e6d8b 100644 --- a/uui/components/pickers/DataPickerBody.tsx +++ b/uui/components/pickers/DataPickerBody.tsx @@ -3,11 +3,12 @@ import { Lens, DataSourceState, isMobile, cx, } from '@epam/uui-core'; import { FlexCell, PickerBodyBase, PickerBodyBaseProps } from '@epam/uui-components'; -import { SearchInput } from '../inputs'; +import { SearchInput, SearchInputProps } from '../inputs'; import { FlexRow, VirtualList } from '../layout'; import { Text } from '../typography'; import { i18n } from '../../i18n'; import { ControlSize } from '../types'; +import { settings } from '../../settings'; import css from './DataPickerBody.module.scss'; export interface DataPickerBodyProps extends PickerBodyBaseProps { @@ -26,15 +27,16 @@ export class DataPickerBody extends PickerBodyBase { return this.props.renderNotFound(); } + // TODO: need fix sizes, how to use variables return ( - - {i18n.dataPickerBody.noRecordsMessage} + + {i18n.dataPickerBody.noRecordsMessage} ); } render() { - const searchSize = isMobile() ? '48' : this.props.searchSize || '36'; + const searchSize = (isMobile() ? settings.sizes.dataPickerBody.searchInput['mobile'] : this.props.searchSize) as SearchInputProps['size']; return ( <> @@ -55,7 +57,7 @@ export class DataPickerBody extends PickerBodyBase { )} { this.props.rowsCount > 0 ? ( - (props: DataPickerCellProps & PickerCellMods) { const ref = React.useRef(); @@ -19,13 +18,13 @@ export function DataPickerCell(props: DataPickerCellProps + ); } else if (props.rowProps.isUnknown) { content = ( - + Unknown ); @@ -36,11 +35,11 @@ export function DataPickerCell(props: DataPickerCellProps {(props.rowProps.isChildrenSelected || props.rowProps.isSelected) && (
-
@@ -66,9 +65,9 @@ export function DataPickerCell(props: DataPickerCellProps diff --git a/uui/components/pickers/DataPickerFooter.tsx b/uui/components/pickers/DataPickerFooter.tsx index e78c9a8de5..65f5ee5ecf 100644 --- a/uui/components/pickers/DataPickerFooter.tsx +++ b/uui/components/pickers/DataPickerFooter.tsx @@ -1,23 +1,17 @@ import React, { PropsWithChildren } from 'react'; import { isMobile, PickerFooterProps } from '@epam/uui-core'; import { i18n } from '../../i18n'; -import { Switch } from '../inputs'; -import { FlexCell, FlexRow, FlexSpacer } from '../layout'; -import { LinkButton } from '../buttons'; +import { Switch, SwitchProps } from '../inputs'; +import { FlexCell, FlexRow, FlexRowProps, FlexSpacer } from '../layout'; +import { LinkButton, LinkButtonProps } from '../buttons'; import { SizeMod } from '../types'; +import { settings } from '../../settings'; type DataPickerFooterProps = PickerFooterProps & SizeMod & { selectionMode: 'single' | 'multi'; }; -const switchSizes = { - 24: '12', - 36: '18', - 42: '24', - 48: '24', -} as const; - function DataPickerFooterImpl(props: PropsWithChildren>) { const { clearSelection, @@ -25,8 +19,7 @@ function DataPickerFooterImpl(props: PropsWithChildren 0; const rowsCount = view.getListProps().rowsCount; const isEmptyRowsAndHasNoSelection = (rowsCount === 0 && !hasSelection); @@ -41,10 +34,10 @@ function DataPickerFooterImpl(props: PropsWithChildren + {!isSinglePicker && ( = (props) => { return ( - {title} + {title} props.close?.() } cx={ css.close } /> ); diff --git a/uui/components/pickers/DataPickerRow.tsx b/uui/components/pickers/DataPickerRow.tsx index 442aaf6d57..88d8aff932 100644 --- a/uui/components/pickers/DataPickerRow.tsx +++ b/uui/components/pickers/DataPickerRow.tsx @@ -2,7 +2,8 @@ import * as React from 'react'; import { DataRowProps } from '@epam/uui-core'; import { DataPickerRow as UUIDataPickerRow } from '@epam/uui-components'; import { DataPickerCell } from './DataPickerCell'; - +import { PickerCellMods } from './types'; +import { settings } from '../../settings'; import css from './DataPickerRow.module.scss'; export interface DataPickerRowProps extends DataRowProps { @@ -17,8 +18,8 @@ export class DataPickerRow extends React.Component>, IDropdownBodyProps { children: ReactNode; @@ -34,7 +35,7 @@ export const MobileDropdownWrapper: React.FC = (pro {props.children} - {isMobileView && props.onClose?.() } cx={ css.done } size="48" />} + {isMobileView && props.onClose?.() } cx={ css.done } size={ settings.sizes.mobileDropdownWrapper.linkButton as LinkButtonProps['size'] } />} ); }; diff --git a/uui/components/pickers/PickerInput.module.scss b/uui/components/pickers/PickerInput.module.scss deleted file mode 100644 index cf8246bc54..0000000000 --- a/uui/components/pickers/PickerInput.module.scss +++ /dev/null @@ -1,39 +0,0 @@ -@use '../../assets/styles/index' as *; - -.footer-wrapper { - border-top: 1px solid var(--uui-divider); - padding: 0 12px; - display: flex; - - &.footer-size-24 { - min-height: 24px; - } - - &.footer-size-30 { - min-height: 30px; - - :global(.uui-caption) { - font-size: 14px; - } - } - - &.footer-size-36 { - min-height: 36px; - } - - &.footer-size-42 { - min-height: 42px; - - :global(.uui-caption) { - font-size: 16px; - } - } - - &.footer-size-48 { - min-height: 48px; - - :global(.uui-caption) { - font-size: 16px; - } - } -} diff --git a/uui/components/pickers/PickerInput.tsx b/uui/components/pickers/PickerInput.tsx index d3932296de..b741148cf6 100644 --- a/uui/components/pickers/PickerInput.tsx +++ b/uui/components/pickers/PickerInput.tsx @@ -7,12 +7,10 @@ import { PickerModal } from './PickerModal'; import { PickerToggler, PickerTogglerMods } from './PickerToggler'; import { MobileDropdownWrapper } from './MobileDropdownWrapper'; import { DataPickerBody } from './DataPickerBody'; -import { DataPickerRow } from './DataPickerRow'; +import { DataPickerRow, DataPickerRowProps } from './DataPickerRow'; import { DataPickerFooter } from './DataPickerFooter'; -import { PickerItem } from './PickerItem'; - -const pickerHeight = 300; -const pickerWidth = 360; +import { PickerItem, PickerItemProps } from './PickerItem'; +import { settings } from '../../settings'; export type PickerInputProps = SizeMod & IHasEditMode & PickerInputBaseProps & { /** @@ -108,10 +106,10 @@ function PickerInputComponent({ highlightSearchMatches = true, ...pr const getRowSize = () => { if (isMobile()) { - return '48'; + return settings.sizes.pickerInput.rowSize.mobile; } - return props.editMode === 'modal' ? '36' : props.size; + return props.editMode === 'modal' ? settings.sizes.pickerInput.rowSize.modal : props.size; }; const getSubtitle = ({ path }: DataRowProps, { search }: DataSourceState) => { @@ -129,7 +127,7 @@ function PickerInputComponent({ highlightSearchMatches = true, ...pr return ( ['size'] } dataSourceState={ dsState } highlightSearchMatches={ highlightSearchMatches } { ...(flattenSearchResults ? { subtitle: getSubtitle(rowProps, dataSourceState) } : {}) } @@ -145,8 +143,8 @@ function PickerInputComponent({ highlightSearchMatches = true, ...pr ['size'] } + padding={ (props.editMode === 'modal' ? settings.sizes.pickerInput.rowSize.padding.modal : settings.sizes.pickerInput.rowSize.padding.default) as DataPickerRowProps['padding'] } renderItem={ (item, itemProps) => renderRowItem(item, itemProps, dsState) } /> ); @@ -154,8 +152,8 @@ function PickerInputComponent({ highlightSearchMatches = true, ...pr const renderBody = (bodyProps: DropdownBodyProps & DataSourceListProps & Omit, rows: DataRowProps[]) => { const renderedDataRows = rows.map((row) => renderRow(row, dataSourceState)); - const bodyHeight = isMobile() ? document.documentElement.clientHeight : props.dropdownHeight || pickerHeight; - const minBodyWidth = props.minBodyWidth || pickerWidth; + const bodyHeight = isMobile() ? document.documentElement.clientHeight : props.dropdownHeight || settings.sizes.pickerInput.height; + const minBodyWidth = props.minBodyWidth || settings.sizes.pickerInput.width; return ( extends DataRowProps, SizeMod { /** Path to the user avatar. @@ -40,7 +39,7 @@ export function PickerItem(props: PickerItemProps) { size, avatarUrl, isLoading, isDisabled, icon, cx, } = props; - const itemSize = size || defaultSize; + const itemSize = size || settings.sizes.defaults.pickerItem as ControlSize; const isMultiline = !!(props.title && props.subtitle); const { search } = props.dataSourceState ?? {}; @@ -50,7 +49,7 @@ export function PickerItem(props: PickerItemProps) { return ( @@ -64,12 +63,12 @@ export function PickerItem(props: PickerItemProps) { { icon && } { title && ( - + { isLoading ? : title } ) } { subtitle && ( - + { isLoading ? : subtitle } ) } @@ -79,6 +78,6 @@ export function PickerItem(props: PickerItemProps) { ); } -function getAvatarSize(size: string, isMultiline: boolean): string | number { - return isMultiline ? size : +size - 6; +function getAvatarSize(size: ControlSize, isMultiline: boolean): string | number { + return settings.sizes.pickerItem.avatar[isMultiline ? 'multiline' : 'rest'][size]; } diff --git a/uui/components/pickers/PickerToggler.tsx b/uui/components/pickers/PickerToggler.tsx index 25805fae2b..db9bfccf10 100644 --- a/uui/components/pickers/PickerToggler.tsx +++ b/uui/components/pickers/PickerToggler.tsx @@ -2,10 +2,10 @@ import * as React from 'react'; import * as types from '../types'; import { PickerToggler as UuiPickerToggler, PickerTogglerProps } from '@epam/uui-components'; import { PickerTogglerTag, PickerTogglerTagProps } from './PickerTogglerTag'; -import css from './PickerToggler.module.scss'; import { systemIcons } from '../../icons/icons'; +import { settings } from '../../settings'; +import css from './PickerToggler.module.scss'; -const defaultSize = '36'; const defaultMode = types.EditMode.FORM; export interface PickerTogglerMods extends types.IHasEditMode { @@ -13,14 +13,14 @@ export interface PickerTogglerMods extends types.IHasEditMode { * Defines component size * @default 36 */ - size?: '24' | '30' | '36' | '42' | '48' | 'inherit'; + size?: '24' | '30' | '36' | '42' | '48'; } function applyPickerTogglerMods(mods: PickerTogglerMods) { return [ 'uui-picker-toggler', css.root, - `uui-size-${mods.size || defaultSize}`, + `uui-size-${mods.size || settings.sizes.defaults.pickerToggler}`, css['mode-' + (mods.mode || defaultMode)], ]; } diff --git a/uui/components/pickers/PickerTogglerTag.tsx b/uui/components/pickers/PickerTogglerTag.tsx index 9b67ffd3d0..0791b64f97 100644 --- a/uui/components/pickers/PickerTogglerTag.tsx +++ b/uui/components/pickers/PickerTogglerTag.tsx @@ -1,16 +1,22 @@ import * as React from 'react'; import { PickerTogglerRenderItemParams } from '@epam/uui-components'; +import * as types from '../types'; import { Tag, TagProps } from '../widgets'; import { Tooltip } from '../overlays'; import { TextPlaceholder } from '../typography'; +import { settings } from '../../settings'; import css from './PickerTogglerTag.module.scss'; -export interface PickerTogglerTagProps extends PickerTogglerRenderItemParams, TagProps {} +export interface PickerTogglerTagProps extends PickerTogglerRenderItemParams, TagProps { + /** Defines component size */ + size?: types.ControlSize; +} export const PickerTogglerTag = React.forwardRef((props: PickerTogglerTagProps, ref: React.Ref) => { const tagProps = { ...props, tabIndex: -1, + size: settings.sizes.pickerToggler.tag[props.size] as TagProps['size'], caption: props.rowProps?.isLoading ? : props.caption, }; @@ -24,10 +30,10 @@ export const PickerTogglerTag = React.forwardRef((props: PickerTogglerTagProps - + ); } else { - return ; + return ; } }); diff --git a/uui/components/typography/Text.tsx b/uui/components/typography/Text.tsx index 67da595c80..10bcd8ad78 100644 --- a/uui/components/typography/Text.tsx +++ b/uui/components/typography/Text.tsx @@ -1,6 +1,7 @@ import { withMods } from '@epam/uui-core'; import { getTextClasses, TextSettings } from '../../helpers'; import * as uuiComponents from '@epam/uui-components'; +import { settings } from '../../settings'; import css from './Text.module.scss'; type TextColor = 'info' | 'warning' | 'critical' | 'success' | 'brand' | 'primary' | 'secondary' | 'tertiary' | 'disabled' | 'white'; @@ -39,7 +40,7 @@ export interface TextProps extends TextCoreProps, TextMods {} function applyTextMods(mods: TextProps) { const textClasses = getTextClasses( { - size: mods.size || '36', + size: mods.size || (settings.sizes.defaults.text as TextSize), lineHeight: mods.lineHeight, fontSize: mods.fontSize, }, diff --git a/uui/components/widgets/CountIndicator.tsx b/uui/components/widgets/CountIndicator.tsx index c06369bf13..46f6e1ac2a 100644 --- a/uui/components/widgets/CountIndicator.tsx +++ b/uui/components/widgets/CountIndicator.tsx @@ -1,6 +1,7 @@ import React, { forwardRef } from 'react'; import cx from 'classnames'; import { IHasCaption, IHasCX } from '@epam/uui-core'; +import { settings } from '../../settings'; import css from './CountIndicator.module.scss'; type CountIndicatorMods = { @@ -15,7 +16,7 @@ export type CountIndicatorCoreProps = IHasCaption & IHasCX & { * Defines component size. * @default '24' */ - size?: '24' | '18' | '12' | 'inherit'; + size?: '24' | '18' | '12'; }; export type CountIndicatorProps = CountIndicatorCoreProps & CountIndicatorMods; @@ -27,7 +28,7 @@ export const CountIndicator = forwardRef((p className={ cx([ css.root, 'uui-count_indicator', - `uui-size-${props.size || 24}`, + `uui-size-${props.size || settings.sizes.defaults.countIndicator}`, props.color && `uui-color-${props.color}`, props.cx, ]) } diff --git a/uui/components/widgets/DataRowAddons.module.scss b/uui/components/widgets/DataRowAddons.module.scss index 51bf1abc88..cf9794196d 100644 --- a/uui/components/widgets/DataRowAddons.module.scss +++ b/uui/components/widgets/DataRowAddons.module.scss @@ -1,5 +1,5 @@ :global(.uui-dr_addons-checkbox) { - padding-right: 12px; + padding-right: calc(var(--uui-x-inner-padding) * 2); } .drag-handle { diff --git a/uui/components/widgets/DataRowAddons.tsx b/uui/components/widgets/DataRowAddons.tsx index 93adfd1dfb..89f838f392 100644 --- a/uui/components/widgets/DataRowAddons.tsx +++ b/uui/components/widgets/DataRowAddons.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { uuiElement, uuiMarkers, DataRowProps } from '@epam/uui-core'; import { IconContainer, DragHandle } from '@epam/uui-components'; -import { Checkbox } from '../inputs'; +import { Checkbox, CheckboxProps } from '../inputs'; import { ControlSize } from '../types'; +import { settings } from '../../settings'; import { ReactComponent as FoldingArrow } from '@epam/assets/icons/navigation-chevron_down-outline.svg'; import css from './DataRowAddons.module.scss'; @@ -12,47 +13,20 @@ import css from './DataRowAddons.module.scss'; export interface DataRowAddonsProps { /** DataRowProps object for the row where an addon is placed. */ rowProps: DataRowProps; - /** HTML tabIndex attribute to set on the cell. */ tabIndex?: React.HTMLAttributes['tabIndex']; - /** Controls size. */ size?: ControlSize | '60'; } export function DataRowAddons(props: DataRowAddonsProps) { const row = props.rowProps; - const additionalItemSize = +props.size < 30 ? '12' : '18'; const getIndent = () => { - switch (props.size) { - case '24': - return (row.indent - 1) * 6; - case '30': - case '36': - return (row.indent - 1) * 12; - case '42': - case '48': - case '60': - return (row.indent - 1) * 24; - default: - return (row.indent - 1) * 24; - } + return (row.indent - 1) * settings.sizes.rowAddons.indentUnit[props.size || 'default']; }; const getWidth = () => { - switch (props.size) { - case '24': - return '12px'; - case '30': - case '36': - return '18px'; - case '42': - case '48': - case '60': - return '24px'; - default: - return '12px'; - } + return settings.sizes.rowAddons.indentWidth[props.size || 'default']; }; return ( @@ -63,7 +37,7 @@ export function DataRowAddons(props: DataRowAddonsProps) key="cb" cx="uui-dr_addons-checkbox" tabIndex={ props.tabIndex } - size={ additionalItemSize } + size={ settings.sizes.rowAddons.checkbox[props.size] as CheckboxProps['size'] } value={ row.isChecked } indeterminate={ !row.isChecked && row.isChildrenChecked } onValueChange={ () => row.onCheck?.(row) } diff --git a/uui/components/widgets/Tag.module.scss b/uui/components/widgets/Tag.module.scss index 27d2f696bb..d46da39b25 100644 --- a/uui/components/widgets/Tag.module.scss +++ b/uui/components/widgets/Tag.module.scss @@ -53,7 +53,7 @@ border: var(--uui-tag-border-width) solid var(--uui-tag-border); :global(.uui-count_indicator):not(:last-child) { - margin-right: 6px; + margin-right: var(--uui-tag-inner-padding); } &:global(.-clickable) { diff --git a/uui/components/widgets/Tag.tsx b/uui/components/widgets/Tag.tsx index df26681bf6..e933904661 100644 --- a/uui/components/widgets/Tag.tsx +++ b/uui/components/widgets/Tag.tsx @@ -3,20 +3,9 @@ import { CX, cx, devLogger, Icon, IDropdownToggler, IHasCaption, IHasIcon, uuiEl import { Clickable, ClickableComponentProps, IconContainer } from '@epam/uui-components'; import { CountIndicator, CountIndicatorProps } from './CountIndicator'; import { systemIcons } from '../../icons/icons'; +import { settings } from '../../settings'; import css from './Tag.module.scss'; -const DEFAULT_SIZE = '36'; - -const mapCountIndicatorSizes: Record = { - 18: '12', - 24: '18', - 30: '18', - 36: '18', - 42: '24', - 48: '24', - inherit: 'inherit', -}; - interface TagMods { /** * Defines component color. @@ -31,7 +20,7 @@ export type TagCoreProps = ClickableComponentProps & IDropdownToggler & IHasIcon * Defines component size. * @default '36' */ - size?: '18' | '24' | '30' | '36' | '42' | '48' | 'inherit'; + size?: '18' | '24' | '30' | '36' | '42' | '48'; /** * Defines component fill style. * @default 'solid' @@ -58,7 +47,7 @@ export type TagProps = TagCoreProps & TagMods; function applyTagMods(props: TagProps) { return [ css.root, - `uui-size-${props.size || DEFAULT_SIZE}`, + `uui-size-${props.size || settings.sizes.defaults.tag as TagProps['size']}`, `uui-color-${props.color || 'neutral'}`, `uui-fill-${props.fill || 'solid'}`, 'uui-tag', @@ -100,7 +89,7 @@ export const Tag = React.forwardRef ) } diff --git a/uui/helpers/textLayout.tsx b/uui/helpers/textLayout.tsx index 8f25cfcf64..3706f2fefb 100644 --- a/uui/helpers/textLayout.tsx +++ b/uui/helpers/textLayout.tsx @@ -1,5 +1,6 @@ -import css from './text-layout.module.scss'; import { ControlSize } from '../components/types'; +import { settings } from '../settings'; +import css from './text-layout.module.scss'; export interface TextSettings { /** Defines text line-height */ @@ -8,16 +9,6 @@ export interface TextSettings { fontSize?: '10' | '12' | '14' | '16' | '18' | '24'; } -const defaultTextSettings = { - 18: { lineHeight: 12, fontSize: 10 }, - 24: { lineHeight: 18, fontSize: 12 }, - 30: { lineHeight: 18, fontSize: 14 }, - 36: { lineHeight: 18, fontSize: 14 }, - 42: { lineHeight: 24, fontSize: 16 }, - 48: { lineHeight: 24, fontSize: 16 }, - 60: { lineHeight: 30, fontSize: 24 }, -}; - export function getTextClasses(props: TextSettings & { size: 'none' | '18' | ControlSize | '60' }, border: boolean) { if (props.size === 'none') { return [css['line-height-' + props.lineHeight], css['font-size-' + props.fontSize]]; @@ -25,8 +16,8 @@ export function getTextClasses(props: TextSettings & { size: 'none' | '18' | Con const setting = { size: props.size, - lineHeight: props.lineHeight || defaultTextSettings[props.size].lineHeight, - fontSize: props.fontSize || defaultTextSettings[props.size].fontSize, + lineHeight: props.lineHeight || settings.sizes.text[props.size].lineHeight, + fontSize: props.fontSize || settings.sizes.text[props.size].fontSize, }; const vPadding = (+setting.size - +setting.lineHeight - (border ? 2 : 0)) / 2; diff --git a/uui/index.tsx b/uui/index.tsx index 0eb439f7b1..7fb3dae380 100644 --- a/uui/index.tsx +++ b/uui/index.tsx @@ -3,3 +3,4 @@ import './assets/styles/typography.scss'; export * from './components'; export * from './i18n'; export * from './helpers'; +export * from './settings'; diff --git a/uui/settings.ts b/uui/settings.ts new file mode 100644 index 0000000000..fb27119316 --- /dev/null +++ b/uui/settings.ts @@ -0,0 +1,171 @@ +export const settings = { + sizes: { + defaults: { + button: '36', + checkbox: '18', + countIndicator: '24', + dataPickerCell: '36', + linkButton: '36', + numericInput: '36', + pickerToggler: '36', + pickerItem: '36', + radioInput: '18', + switch: '18', + tabButton: '42', + tag: '36', + text: '36', + textInput: '36', + rangeDatePicker: '36', + datePicker: '36', + }, + tag: { + countIndicator: { + 18: '12', + 24: '18', + 30: '18', + 36: '18', + 42: '24', + 48: '24', + }, + }, + mobileDropdownWrapper: { + linkButton: '48', + }, + pickerInput: { + height: 300, + width: 360, + rowSize: { + mobile: '48', + modal: '36', + padding: { + modal: '24', + default: '12', + }, + }, + }, + pickerToggler: { + tag: { + 24: '18', + 30: '24', + 36: '30', + 42: '36', + 48: '42', + 60: '48', + }, + }, + dataPickerHeader: { + text: { + fontWeight: '600', + size: '48', + }, + }, + dataPickerBody: { + flexCell: { + default: '36', + }, + searchInput: { + mobile: '48', + }, + }, + pickerItem: { // max 48, setup by row with 60???? + avatar: { + rest: { + 24: '18', + 30: '24', + 36: '30', + 42: '36', + 48: '36', // no design + }, + multiline: { + 24: '30', + 30: '30', + 36: '36', + 42: '42', + 48: '48', // no design + }, + }, + }, + dataPickerCell: { + isBoldIcon: { + 24: true, + }, + padding: { + default: '12', + }, + paddingLeft: { + default: '24', + }, + text: { + 24: '24', + 30: '30', + 36: '36', + 42: '42', + 48: '48', + 60: '48', + }, + }, + dataPickerRow: { // max 60 + padding: { + default: '24', + }, + dataPickerCell: { + default: '36', + }, + }, + dataPickerFooter: { + flexRowPadding: '12', + switch: { + 24: '12', + 30: '18', + 36: '18', + 42: '24', + 48: '24', + }, + linkButton: { + 24: '12', + 30: '18', + 36: '18', + 42: '24', + 48: '24', + mobile: '48', + }, + }, + rowAddons: { + checkbox: { + 24: '12', + 30: '18', + 36: '18', + 42: '18', + 48: '18', + 60: '18', + }, + indentUnit: { + 24: 6, + 30: 12, + 36: 12, + 42: 24, + 48: 24, + 60: 24, + default: 24, + }, + indentWidth: { + 24: 12, + 30: 18, + 36: 18, + 42: 24, + 48: 24, + 60: 24, + default: 12, + }, + }, + text: { + 18: { lineHeight: 12, fontSize: 10 }, + 24: { lineHeight: 18, fontSize: 12 }, + 30: { lineHeight: 18, fontSize: 14 }, + 36: { lineHeight: 18, fontSize: 14 }, + 42: { lineHeight: 24, fontSize: 16 }, + 48: { lineHeight: 24, fontSize: 16 }, + 60: { lineHeight: 30, fontSize: 24 }, + }, + }, +};