Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/vkui/src/lib/layouts/layoutProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const CSS_INTRINSIC_KEYWORDS: CSSIntrinsicSizingKeywords[] = [
const CSS_GLOBAL_KEYWORDS: CSSGlobalValue[] = ['inherit', 'initial', 'unset'];

const CSS_KEYWORDS = [...CSS_INTRINSIC_KEYWORDS, ...CSS_GLOBAL_KEYWORDS];
const PADDING_VALUES = [...DESIGN_SYSTEM_SIZES, ...CSS_GLOBAL_KEYWORDS];
const PADDING_VALUES = [...DESIGN_SYSTEM_SIZES, ...CSS_GLOBAL_KEYWORDS, 'system'];
const SIZE_VALUES = CSS_KEYWORDS;
const MINMAX_SIZE_VALUES = [...CSS_KEYWORDS.filter((opt) => opt !== 'auto')];
const FLEX_VALUES = CSS_GLOBAL_KEYWORDS;
Expand Down
104 changes: 104 additions & 0 deletions packages/vkui/src/lib/layouts/resolveLayoutProps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,108 @@ describe('resolveLayoutProps', () => {
'data-testid': 'test',
});
});

it('should handle padding="system"', () => {
const props = { padding: 'system' };
const result = resolveLayoutProps(props);

expect(result).toEqual({
className: 'vkui-padding-block vkui-padding-inline',
style: {
'--vkui_internal--padding-block': 'var(--vkui--size_base_padding_vertical--regular)',
'--vkui_internal--padding-inline': 'var(--vkui--size_base_padding_horizontal--regular)',
},
});
});

it('should handle paddingBlock="system"', () => {
const props = { paddingBlock: 'system' };
const result = resolveLayoutProps(props);

expect(result).toEqual({
className: 'vkui-padding-block',
style: {
'--vkui_internal--padding-block': 'var(--vkui--size_base_padding_vertical--regular)',
},
});
});

it('should handle paddingInline="system"', () => {
const props = { paddingInline: 'system' };
const result = resolveLayoutProps(props);

expect(result).toEqual({
className: 'vkui-padding-inline',
style: {
'--vkui_internal--padding-inline': 'var(--vkui--size_base_padding_horizontal--regular)',
},
});
});

it('should handle paddingBlockStart="system"', () => {
const props = { paddingBlockStart: 'system' };
const result = resolveLayoutProps(props);

expect(result).toEqual({
className: 'vkui-padding-block-start',
style: {
'--vkui_internal--padding-block-start': 'var(--vkui--size_base_padding_vertical--regular)',
},
});
});

it('should handle paddingBlockEnd="system"', () => {
const props = { paddingBlockEnd: 'system' };
const result = resolveLayoutProps(props);

expect(result).toEqual({
className: 'vkui-padding-block-end',
style: {
'--vkui_internal--padding-block-end': 'var(--vkui--size_base_padding_vertical--regular)',
},
});
});

it('should handle paddingInlineStart="system"', () => {
const props = { paddingInlineStart: 'system' };
const result = resolveLayoutProps(props);

expect(result).toEqual({
className: 'vkui-padding-inline-start',
style: {
'--vkui_internal--padding-inline-start':
'var(--vkui--size_base_padding_horizontal--regular)',
},
});
});

it('should handle paddingInlineEnd="system"', () => {
const props = { paddingInlineEnd: 'system' };
const result = resolveLayoutProps(props);

expect(result).toEqual({
className: 'vkui-padding-inline-end',
style: {
'--vkui_internal--padding-inline-end': 'var(--vkui--size_base_padding_horizontal--regular)',
},
});
});

it('should handle multiple system padding props', () => {
const props = {
paddingBlock: 'system',
paddingInline: 'system',
paddingBlockStart: 'system',
};
const result = resolveLayoutProps(props);

expect(result).toEqual({
className: 'vkui-padding-block vkui-padding-inline vkui-padding-block-start',
style: {
'--vkui_internal--padding-block': 'var(--vkui--size_base_padding_vertical--regular)',
'--vkui_internal--padding-inline': 'var(--vkui--size_base_padding_horizontal--regular)',
'--vkui_internal--padding-block-start': 'var(--vkui--size_base_padding_vertical--regular)',
},
});
});
});
34 changes: 32 additions & 2 deletions packages/vkui/src/lib/layouts/resolveLayoutProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ import { classNames } from '@vkontakte/vkjs';
import { mergeStyle } from '../../helpers/mergeStyle';
import { generateConstantClassName, generateVariable, generateVariableClassName } from './helpers';
import { LAYOUT_PROPS, type LayoutPropKeys } from './layoutProps';
import type { LayoutProps } from './types';

export type ComponentProps = {
const SYSTEM_PADDING_VERTICAL = 'var(--vkui--size_base_padding_vertical--regular)';
const SYSTEM_PADDING_HORIZONTAL = 'var(--vkui--size_base_padding_horizontal--regular)';

export type ComponentProps = Partial<LayoutProps> & {
className?: string;
style?: React.CSSProperties;
} & {
[key: string]: unknown;
};

Expand All @@ -21,12 +26,37 @@ export function resolveLayoutProps<T extends ComponentProps>(
let resolvedClassName: string | undefined;
let resolvedStyle: React.CSSProperties | undefined;

if (outProps.padding === 'system') {
outProps.paddingBlock = SYSTEM_PADDING_VERTICAL;
outProps.paddingInline = SYSTEM_PADDING_HORIZONTAL;
delete outProps.padding;
}

for (const key in LAYOUT_PROPS) {
if (key in outProps && outProps[key] !== undefined) {
const propDef = LAYOUT_PROPS[key as LayoutPropKeys];
const value = outProps[key];
const cssProperty = key.replace(/([A-Z])/g, '-$1').toLowerCase();
if (typeof value === 'string' && (propDef as string[]).includes(value)) {

if (value === 'system' && key.startsWith('padding')) {
let systemValue: string;
if (key === 'paddingBlock' || key === 'paddingBlockStart' || key === 'paddingBlockEnd') {
systemValue = SYSTEM_PADDING_VERTICAL;
} else if (
key === 'paddingInline' ||
key === 'paddingInlineStart' ||
key === 'paddingInlineEnd'
) {
systemValue = SYSTEM_PADDING_HORIZONTAL;
} else {
systemValue = value;
}

resolvedClassName = classNames(resolvedClassName, generateVariableClassName(cssProperty));
resolvedStyle = mergeStyle(resolvedStyle, {
[generateVariable(cssProperty)]: systemValue,
});
} else if (typeof value === 'string' && (propDef as string[]).includes(value)) {
resolvedClassName = classNames(
resolvedClassName,
generateConstantClassName(cssProperty, value),
Expand Down
5 changes: 4 additions & 1 deletion packages/vkui/src/lib/layouts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ export type PositionValue = 'static' | 'relative' | 'absolute' | 'fixed' | 'stic
export type OverflowValue = 'visible' | 'hidden' | 'clip' | 'scroll' | 'auto' | CSSGlobalValue;

// Тип для отступов
export type PaddingProp = LiteralUnion<DesignSystemSize | CSSGlobalValue, number | string>;
export type PaddingProp = LiteralUnion<
DesignSystemSize | CSSGlobalValue | 'system',
number | string
>;

// Типы для параметров позиционирования
export type InsetProp = LiteralUnion<DesignSystemSize | CSSGlobalValue | 'auto', number | string>;
Expand Down
1 change: 1 addition & 0 deletions website/content/components/box.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ description: Универсальный компонент для создани

- токены дизайн-системы VKUI (`'2xs', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl', '4xl'`);
- стандартные CSS-значения (`'inherit'`, `'initial'`, `'unset'`);
- специальное значение `'system'` — автоматически устанавливает системные отступы VKUI (эквивалентно использованию `--vkui--size_base_padding_vertical--regular` и `--vkui--size_base_padding_horizontal--regular`);
- числовые значения (будут преобразованы в пиксели);
- любое валидное строковое значение (`"2rem", "10%"`, CSS-переменные).

Expand Down
Loading