Skip to content

Commit

Permalink
feat(Text): allow pass thml attributes durind Box inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaevAlexandr committed May 16, 2024
1 parent fcd2ff3 commit 0909c60
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 19 deletions.
13 changes: 4 additions & 9 deletions src/components/Text/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,13 @@ export interface TextProps<C extends React.ElementType = 'span'>
* Ability to override default html tag
*/
as?: C;
style?: React.CSSProperties;
className?: string;
id?: string;
children?: React.ReactNode;
title?: string;
ellipsisLines?: number;
}

type TextRef<C extends React.ElementType> = React.ComponentPropsWithRef<C>['ref'];

type TextPropsWithoutRef<C extends React.ElementType> = TextProps<C> &
Omit<React.ComponentPropsWithoutRef<C>, keyof TextProps<C>>;
type TextPropsWithTypedAttrs<T extends React.ElementType> = TextProps<T> &
Omit<React.ComponentPropsWithoutRef<T>, keyof TextProps<T>>;

/**
* A component for working with typography.
Expand Down Expand Up @@ -68,7 +63,7 @@ export const Text = React.forwardRef(function Text<C extends React.ElementType =
style: outerStyle,
qa,
...rest
}: TextPropsWithoutRef<C>,
}: TextPropsWithTypedAttrs<C>,
ref?: TextRef<C>,
) {
const Tag: React.ElementType = as || 'span';
Expand Down Expand Up @@ -104,6 +99,6 @@ export const Text = React.forwardRef(function Text<C extends React.ElementType =
}) as (<C extends React.ElementType = 'span'>({
ref,
...props
}: TextPropsWithoutRef<C> & {ref?: TextRef<C>}) => React.ReactElement) & {displayName: string};
}: TextPropsWithTypedAttrs<C> & {ref?: TextRef<C>}) => React.ReactElement) & {displayName: string};

Text.displayName = 'Text';
67 changes: 67 additions & 0 deletions src/components/Text/__tests__/Text.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react';

import {render} from '../../../../test-utils/utils';
import {Button} from '../../Button';
import {Text} from '../Text';

describe('Text', () => {
describe('should return expected html', () => {
test('if no props passed', () => {
const {container} = render(<Text>Hello World!</Text>);

expect(container).toMatchSnapshot();
});

test('if qa attr passed and variant changed', () => {
const {container} = render(
<Text qa="test" variant={'caption-1'}>
Hello World!
</Text>,
);

expect(container).toMatchSnapshot();
});

test('if html attributes passed and changed default html tag and with typed ref', () => {
const ComponentWithRef = () => {
const ref = React.useRef<HTMLLabelElement>(null);

return (
<Text as="label" htmlFor="some-id" ref={ref}>
Hello World!
</Text>
);
};

const {container} = render(<ComponentWithRef />);

expect(container).toMatchSnapshot();
});

test('if passed props what converted to classNames and styles', () => {
const {container} = render(
<Text
style={{width: 200}}
ellipsisLines={2}
ellipsis={true}
whiteSpace="break-spaces"
wordBreak="break-word"
>
Hello World!
</Text>,
);

expect(container).toMatchSnapshot();
});

test('with another component substitution', () => {
const {container} = render(
<Text as={Button} size={'m'} view="action">
Hello World!
</Text>,
);

expect(container).toMatchSnapshot();
});
});
});
59 changes: 59 additions & 0 deletions src/components/Text/__tests__/__snapshots__/Text.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Text should return expected html if html attributes passed and changed default html tag and with typed ref 1`] = `
<div>
<label
class="g-text g-text_variant_body-1"
for="some-id"
>
Hello World!
</label>
</div>
`;

exports[`Text should return expected html if no props passed 1`] = `
<div>
<span
class="g-text g-text_variant_body-1"
>
Hello World!
</span>
</div>
`;

exports[`Text should return expected html if passed props what converted to classNames and styles 1`] = `
<div>
<span
class="g-text g-text_variant_body-1 g-text_ellipsis g-text_ws_break-spaces g-text_wb_break-word g-text_ellipsis-lines"
style="width: 200px;"
>
Hello World!
</span>
</div>
`;

exports[`Text should return expected html if qa attr passed and variant changed 1`] = `
<div>
<span
class="g-text g-text_variant_caption-1"
data-qa="test"
>
Hello World!
</span>
</div>
`;

exports[`Text should return expected html with another component substitution 1`] = `
<div>
<button
class="g-button g-button_view_action g-button_size_m g-button_pin_round-round g-text g-text_variant_body-1"
type="button"
>
<span
class="g-button__text"
>
Hello World!
</span>
</button>
</div>
`;
11 changes: 9 additions & 2 deletions src/components/layout/Box/Box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ export interface BoxProps<T extends React.ElementType = 'div'>
spacing?: SpacingProps;
}

type BoxRef<C extends React.ElementType> = React.ComponentPropsWithRef<C>['ref'];

type BoxPropsWithTypedAttrs<T extends React.ElementType> = BoxProps<T> &
Omit<React.ComponentPropsWithoutRef<T>, keyof BoxProps<T>>;

/**
* Basic block to build other components and for standalone usage as a smart block with build in support of most usable css properties and shortcut `spacing` properties.
* ```tsx
Expand Down Expand Up @@ -63,7 +68,7 @@ export const Box = React.forwardRef(function Box<T extends React.ElementType = '
overflow,
...props
}: BoxProps<T>,
ref?: React.ComponentPropsWithRef<T>['ref'],
ref?: BoxRef<T>,
) {
const Tag: React.ElementType = as || 'div';

Expand All @@ -88,4 +93,6 @@ export const Box = React.forwardRef(function Box<T extends React.ElementType = '
{children}
</Tag>
);
});
}) as (<C extends React.ElementType = 'div'>(
props: BoxPropsWithTypedAttrs<C> & {ref?: BoxRef<C>},
) => React.ReactElement) & {displayName: string};
22 changes: 14 additions & 8 deletions src/components/layout/Flex/Flex.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';

import type {QAProps} from '../../types';
import {block} from '../../utils/cn';
import {Box} from '../Box/Box';
import type {BoxProps} from '../Box/Box';
Expand All @@ -12,7 +11,7 @@ import './Flex.scss';

const b = block('flex');

export interface FlexProps<T extends React.ElementType = 'div'> extends QAProps, BoxProps<T> {
export interface FlexProps<T extends React.ElementType = 'div'> extends BoxProps<T> {
/**
* `flex-direction` property
*/
Expand Down Expand Up @@ -90,6 +89,11 @@ export interface FlexProps<T extends React.ElementType = 'div'> extends QAProps,
space?: Space | MediaPartial<Space>;
}

type FlexRef<C extends React.ElementType> = React.ComponentPropsWithRef<C>['ref'];

type FlexPropsWithTypedAttrs<T extends React.ElementType> = FlexProps<T> &
Omit<React.ComponentPropsWithoutRef<T>, keyof FlexProps<T>>;

/**
* Flexbox model utility component.
*
Expand Down Expand Up @@ -124,11 +128,9 @@ export interface FlexProps<T extends React.ElementType = 'div'> extends QAProps,
* ---
* Storybook - https://preview.gravity-ui.com/uikit/?path=/docs/layout--playground#flex
*/
export const Flex = React.forwardRef(function Flex<T extends React.ElementType = 'div'>(
props: FlexProps<T>,
ref: React.ComponentPropsWithRef<T>['ref'],
) {
export const Flex = function Flex<T extends React.ElementType = 'div'>(props: FlexProps<T>) {
const {
as: propsAs,
direction,
grow,
basis,
Expand All @@ -151,6 +153,8 @@ export const Flex = React.forwardRef(function Flex<T extends React.ElementType =
...restProps
} = props;

const as: React.ElementType = propsAs || 'div';

const {
getClosestMediaProps,
theme: {spaceBaseSize},
Expand All @@ -174,6 +178,7 @@ export const Flex = React.forwardRef(function Flex<T extends React.ElementType =

return (
<Box
as={as}
className={b(
{
'center-content': centerContent,
Expand All @@ -198,7 +203,6 @@ export const Flex = React.forwardRef(function Flex<T extends React.ElementType =
justifySelf: applyMediaProps(justifySelf),
...style,
}}
ref={ref}
{...restProps}
>
{space
Expand All @@ -209,4 +213,6 @@ export const Flex = React.forwardRef(function Flex<T extends React.ElementType =
: children}
</Box>
);
});
} as (<C extends React.ElementType = 'div'>(
props: FlexPropsWithTypedAttrs<C> & {ref?: FlexRef<C>},
) => React.ReactElement) & {displayName: string};

0 comments on commit 0909c60

Please sign in to comment.