Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Spacing): add css variables support #7955

Merged
merged 3 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { ComponentPlayground, type ComponentPlaygroundProps } from '@vkui-e2e/playground-helpers';
import { type SpacingSize, spacingSizeClassNames } from '../../lib/spacings/sizes';
import { type CSSCustomProperties } from '../../types';
import { Separator, type SeparatorProps } from './Separator';

const sizes = Object.keys(spacingSizeClassNames) as SpacingSize[];
const divStyle: CSSCustomProperties = {
'--my-custom-var': '20px',
};

export const SeparatorPlayground = (props: ComponentPlaygroundProps) => {
return (
Expand Down Expand Up @@ -33,10 +37,14 @@ export const SeparatorPlayground = (props: ComponentPlaygroundProps) => {
align: ['start', 'center', 'end'],
size: ['3xl'],
},
{
direction: ['horizontal', 'vertical'],
size: ['--my-custom-var'],
},
]}
>
{(props: SeparatorProps) => (
<div style={props.direction === 'vertical' ? { display: 'flex' } : undefined}>
<div style={props.direction === 'vertical' ? { display: 'flex', ...divStyle } : divStyle}>
First Item
<Separator {...props} />
Second Item
Expand Down
52 changes: 32 additions & 20 deletions packages/vkui/src/components/Separator/Separator.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { classNames } from '@vkontakte/vkjs';
import { spacingSizeClassNames, type SpacingSizeProp } from '../../lib/spacings/sizes';
import { resolveSpacingSize, type SpacingSizeProp } from '../../lib/spacings/sizes';
import type { HTMLAttributesWithRootRef } from '../../types';
import { RootComponent } from '../RootComponent/RootComponent';
import styles from './Separator.module.css';
Expand All @@ -21,6 +21,8 @@ export interface SeparatorProps extends HTMLAttributesWithRootRef<HTMLDivElement
direction?: 'horizontal' | 'vertical';
/**
* Размер контейнера, в который вложен разделитель
*
* Принимает значения дизайн-системы, числовые значения и css-переменные
*/
size?: SpacingSizeProp;
/**
Expand Down Expand Up @@ -56,22 +58,32 @@ export const Separator = ({
style,
size,
...restProps
}: SeparatorProps): React.ReactNode => (
<RootComponent
{...restProps}
baseClassName={classNames(
padding && styles.padded,
appearanceClassNames[appearance],
typeof size === 'string' && spacingSizeClassNames[size],
directionClassNames[direction],
size !== undefined && styles.sized,
align !== 'center' && alignClassNames[align],
)}
style={{
...(typeof size === 'number' && { [CUSTOM_CSS_TOKEN_FOR_USER_SIZE]: `${size}px` }),
...style,
}}
>
<hr className={styles.in} />
</RootComponent>
);
}: SeparatorProps): React.ReactNode => {
const [spacingSizeClassName, spacingSizeStyle] = resolveSpacingSize(
CUSTOM_CSS_TOKEN_FOR_USER_SIZE,
size,
);
return (
<RootComponent
{...restProps}
baseClassName={classNames(
padding && styles.padded,
appearanceClassNames[appearance],
directionClassNames[direction],
size !== undefined && styles.sized,
align !== 'center' && alignClassNames[align],
spacingSizeClassName,
)}
style={
spacingSizeStyle
? {
...spacingSizeStyle,
...style,
}
: style
}
>
<hr className={styles.in} />
</RootComponent>
);
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import { ComponentPlayground, type ComponentPlaygroundProps } from '@vkui-e2e/playground-helpers';
import { type SpacingSize, spacingSizeClassNames } from '../../lib/spacings/sizes';
import { type CSSCustomProperties } from '../../types';
import { Div } from '../Div/Div';
import { Separator } from '../Separator/Separator';
import { Spacing, type SpacingProps } from './Spacing';

const sizes = Object.keys(spacingSizeClassNames) as SpacingSize[];
const divStyle: React.CSSProperties & CSSCustomProperties = {
'width': 100,
'--my-custom-var': '8px',
};

export const SpacingPlayground = (props: ComponentPlaygroundProps) => {
return (
<ComponentPlayground
{...props}
propSets={[
{
size: [undefined, ...sizes, 8, 16, 24],
size: [undefined, ...sizes, 8, 16, 24, '--my-custom-var'],
},
]}
>
{({ size }: SpacingProps) => (
<Div style={{ width: 100 }}>
<Div style={divStyle}>
<Separator padding />
<Spacing size={size} />
<Separator padding />
Expand Down
7 changes: 7 additions & 0 deletions packages/vkui/src/components/Spacing/Spacing.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ describe('Spacing', () => {
expect(h.container.firstElementChild).toHaveStyle(`${CUSTOM_CSS_TOKEN_FOR_USER_GAP}: 16px`);
});

it('should use css variable size', () => {
const h = render(<Spacing size="--my-custom-var" />);
expect(h.container.firstElementChild).toHaveStyle(
`${CUSTOM_CSS_TOKEN_FOR_USER_GAP}: var(--my-custom-var)`,
);
});

it('should preserve user style', () => {
const h = render(<Spacing size={16} style={{ fontSize: 12 }} />);
expect(h.container.firstElementChild).toHaveStyle(
Expand Down
25 changes: 16 additions & 9 deletions packages/vkui/src/components/Spacing/Spacing.tsx
inomdzhon marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
import { spacingSizeClassNames, type SpacingSizeProp } from '../../lib/spacings/sizes';
import { resolveSpacingSize, type SpacingSizeProp } from '../../lib/spacings/sizes';
import type { HTMLAttributesWithRootRef } from '../../types';
import { RootComponent } from '../RootComponent/RootComponent';
import styles from './Spacing.module.css';
Expand All @@ -10,6 +10,8 @@ export const CUSTOM_CSS_TOKEN_FOR_USER_GAP = '--vkui_internal--spacing_size';
export interface SpacingProps extends HTMLAttributesWithRootRef<HTMLDivElement> {
/**
* Высота спэйсинга
*
* Принимает значения дизайн-системы, числовые значения и css-переменные
*/
size?: SpacingSizeProp;
/**
Expand All @@ -23,17 +25,22 @@ export interface SpacingProps extends HTMLAttributesWithRootRef<HTMLDivElement>
* @see https://vkcom.github.io/VKUI/#/Spacing
*/
export const Spacing = ({ size = 'm', style, ...restProps }: SpacingProps): React.ReactNode => {
const [spacingSizeClassName, spacingSizeStyle] = resolveSpacingSize(
CUSTOM_CSS_TOKEN_FOR_USER_GAP,
size,
);
return (
<RootComponent
{...restProps}
style={{
...(typeof size === 'number' && { [CUSTOM_CSS_TOKEN_FOR_USER_GAP]: `${size}px` }),
...style,
}}
baseClassName={classNames(
styles.host,
typeof size === 'string' && spacingSizeClassNames[size],
)}
style={
spacingSizeStyle
? {
...spacingSizeStyle,
...style,
}
: style
}
baseClassName={classNames(styles.host, spacingSizeClassName)}
/>
);
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 17 additions & 2 deletions packages/vkui/src/lib/spacings/sizes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LiteralUnion } from '../../types';
import type { CSSCustomProperties, LiteralUnion } from '../../types';
import styles from '../../styles/spacings.module.css';

export type SpacingSize = '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' | '2xl' | '3xl' | '4xl';
Expand All @@ -15,4 +15,19 @@ export const spacingSizeClassNames: Record<SpacingSize, string> = {
'4xl': styles['-spacing--4xl'],
};

export type SpacingSizeProp = LiteralUnion<SpacingSize, number>;
export type SpacingSizeProp = LiteralUnion<SpacingSize | `--${string}`, number>;

export function resolveSpacingSize(
cssVariable: string,
size?: SpacingSizeProp,
): [string | undefined, CSSCustomProperties | undefined] {
if (typeof size === 'string') {
if (size.startsWith('--')) {
return [undefined, { [cssVariable]: `var(${size})` }];
} else {
return [spacingSizeClassNames[size as SpacingSize], undefined];
}
}

return [undefined, typeof size === 'number' ? { [cssVariable]: `${size}px` } : undefined];
}
Loading