diff --git a/CHANGELOG.md b/CHANGELOG.md index f9187d3e7e..a690cf7e0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,45 @@ # Changelog +## [4.11.1](https://github.com/gravity-ui/uikit/compare/v4.11.0...v4.11.1) (2023-05-12) + + +### Bug Fixes + +* **Select:** align items by baseline for label and values ([#661](https://github.com/gravity-ui/uikit/issues/661)) ([b25734f](https://github.com/gravity-ui/uikit/commit/b25734f94a0837f2c5857f3609e45e317fbcb99b)) + +## [4.11.0](https://github.com/gravity-ui/uikit/compare/v4.10.0...v4.11.0) (2023-05-11) + + +### Features + +* **TextInput:** add rightContent props ([#649](https://github.com/gravity-ui/uikit/issues/649)) ([fd29127](https://github.com/gravity-ui/uikit/commit/fd29127d30df8659da3785fc1417cae778846842)) +* **UserAvatar:** add `srcset` support ([#641](https://github.com/gravity-ui/uikit/issues/641)) ([fe05925](https://github.com/gravity-ui/uikit/commit/fe05925d6b47ff9cc0d4786c5cb435089e3a7987)) + + +### Bug Fixes + +* **Tooltip:** increase selector specificity ([#660](https://github.com/gravity-ui/uikit/issues/660)) ([1f53d8d](https://github.com/gravity-ui/uikit/commit/1f53d8dbd75b01c3c621d4696e4d0317d06b3a82)) + +## [4.10.0](https://github.com/gravity-ui/uikit/compare/v4.9.0...v4.10.0) (2023-04-26) + + +### Features + +* **Popover:** let action and cancel buttons to wrap on long text ([#631](https://github.com/gravity-ui/uikit/issues/631)) ([f22f9b5](https://github.com/gravity-ui/uikit/commit/f22f9b5ed2b864fbccb19118b142b6e03285296a)) + +## [4.9.0](https://github.com/gravity-ui/uikit/compare/v4.8.1...v4.9.0) (2023-04-20) + + +### Features + +* **Select:** remove pointer cursor for disabled option ([#638](https://github.com/gravity-ui/uikit/issues/638)) ([d1dd601](https://github.com/gravity-ui/uikit/commit/d1dd60117b03c5c3c6c55ca38f9cee6a6c44e7fc)) +* **Text:** add reference ([#628](https://github.com/gravity-ui/uikit/issues/628)) ([922b390](https://github.com/gravity-ui/uikit/commit/922b390d92747d55b9ca2521f4de78a5754ca263)) + + +### Bug Fixes + +* **Card:** update border-radius ([#639](https://github.com/gravity-ui/uikit/issues/639)) ([a05df9e](https://github.com/gravity-ui/uikit/commit/a05df9e1c8ddc4f697634296b10aac9aa264b204)) + ## [4.8.1](https://github.com/gravity-ui/uikit/compare/v4.8.0...v4.8.1) (2023-04-17) diff --git a/package-lock.json b/package-lock.json index f4b666486e..2a6fe47ab4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@gravity-ui/uikit", - "version": "4.8.1", + "version": "4.11.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -15030,13 +15030,6 @@ "integrity": "sha512-yI7FwUqU4TVb+7t6PaQ3spT/42r/KLEi8mtdGoQo2li/kFzmu9URmalTvw7xCCJtSOyhBxscvEAmvjeN9iHARg==", "requires": { "tabbable": "^6.1.1" - }, - "dependencies": { - "tabbable": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.1.1.tgz", - "integrity": "sha512-4kl5w+nCB44EVRdO0g/UGoOp3vlwgycUVtkk/7DPyeLZUCuNFFKCFG6/t/DgHLrUPHjrZg6s5tNm+56Q2B0xyg==" - } } }, "for-each": { @@ -26175,9 +26168,9 @@ "dev": true }, "tabbable": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.0.1.tgz", - "integrity": "sha512-SYJSIgeyXW7EuX1ytdneO5e8jip42oHWg9xl/o3oTYhmXusZVgiA+VlPvjIN+kHii9v90AmzTZEBcsEvuAY+TA==" + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.1.1.tgz", + "integrity": "sha512-4kl5w+nCB44EVRdO0g/UGoOp3vlwgycUVtkk/7DPyeLZUCuNFFKCFG6/t/DgHLrUPHjrZg6s5tNm+56Q2B0xyg==" }, "table": { "version": "6.8.0", diff --git a/package.json b/package.json index 80e07c98ac..e12e4e7215 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gravity-ui/uikit", - "version": "4.8.1", + "version": "4.11.1", "description": "Gravity UI base styling and components", "license": "MIT", "repository": { @@ -87,7 +87,7 @@ "react-virtualized-auto-sizer": "1.0.7", "react-window": "1.8.8", "resize-observer-polyfill": "1.5.1", - "tabbable": "6.0.1", + "tabbable": "6.1.1", "tslib": "2.3.1", "utility-types": "3.10.0" }, diff --git a/src/components/Button/Button.scss b/src/components/Button/Button.scss index 18caab4636..d7909252f6 100644 --- a/src/components/Button/Button.scss +++ b/src/components/Button/Button.scss @@ -85,6 +85,30 @@ $block: '.#{variables.$ns}button'; } &_size { + &_xs { + --yc-button-height: 20px; + + font-size: 13px; + + #{$block}__text { + margin: 0 6px; + } + + #{$block}__icon { + width: var(--yc-button-height); + + &_side_left ~ #{$block}__text { + margin-left: 18px; + } + + &_side_right ~ #{$block}__text { + margin-right: 18px; + } + } + + --yc-button-border-radius: var(--yc-border-radius-xs); + } + &_s { --yc-button-height: 24px; diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 7d9ba1eb4a..a87e2a6fa5 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -23,7 +23,7 @@ export type ButtonView = | 'outlined-contrast' // outlined button appearance with contrast background | 'flat-contrast'; // flat button appearance with contrast background -export type ButtonSize = 's' | 'm' | 'l' | 'xl'; +export type ButtonSize = 'xs' | 's' | 'm' | 'l' | 'xl'; export type ButtonPin = | 'round-round' diff --git a/src/components/Button/README.md b/src/components/Button/README.md index 43814fe9ba..aaeacff4e8 100644 --- a/src/components/Button/README.md +++ b/src/components/Button/README.md @@ -82,7 +82,7 @@ type ButtonView = | 'outlined-contrast' | 'flat-contrast'; -type ButtonSize = 's' | 'm' | 'l' | 'xl'; +type ButtonSize = 'xs' | 's' | 'm' | 'l' | 'xl'; type ButtonPin = | 'round-round' diff --git a/src/components/Button/__stories__/Button.new.stories.tsx b/src/components/Button/__stories__/Button.new.stories.tsx index 52159efd5c..57d1028e54 100644 --- a/src/components/Button/__stories__/Button.new.stories.tsx +++ b/src/components/Button/__stories__/Button.new.stories.tsx @@ -29,7 +29,7 @@ export default { defaultValue: 'normal', }, size: { - options: ['s', 'm', 'l', 'xl'], + options: ['xs', 's', 'm', 'l', 'xl'], control: {type: 'radio'}, defaultValue: 'm', }, diff --git a/src/components/Button/__stories__/Button.stories.tsx b/src/components/Button/__stories__/Button.stories.tsx index 20822854fe..74233c2556 100644 --- a/src/components/Button/__stories__/Button.stories.tsx +++ b/src/components/Button/__stories__/Button.stories.tsx @@ -15,6 +15,10 @@ export const Default = DefaultTemplate.bind({}); const SizeTemplate: Story = (args) => ( <> + + diff --git a/src/components/Button/__stories__/ButtonShowcase.tsx b/src/components/Button/__stories__/ButtonShowcase.tsx index 6e30ccef93..e795d907b0 100644 --- a/src/components/Button/__stories__/ButtonShowcase.tsx +++ b/src/components/Button/__stories__/ButtonShowcase.tsx @@ -16,6 +16,8 @@ export function ButtonShowcase() { {renderViewGrid()}

+ + diff --git a/src/components/Button/__stories__/examples/ButtonExampleView/ButtonExampleView.tsx b/src/components/Button/__stories__/examples/ButtonExampleView/ButtonExampleView.tsx index 266af18a3b..ff44910699 100644 --- a/src/components/Button/__stories__/examples/ButtonExampleView/ButtonExampleView.tsx +++ b/src/components/Button/__stories__/examples/ButtonExampleView/ButtonExampleView.tsx @@ -238,6 +238,7 @@ export function ButtonExampleState() { export function ButtonExampleSize() { return ( + diff --git a/src/components/Button/__tests__/Button.test.tsx b/src/components/Button/__tests__/Button.test.tsx index b9204269b4..389879a8f8 100644 --- a/src/components/Button/__tests__/Button.test.tsx +++ b/src/components/Button/__tests__/Button.test.tsx @@ -48,12 +48,15 @@ describe('Button', () => { expect(button).not.toBeDisabled(); }); - test.each(new Array('s', 'm', 'l', 'xl'))('render with given "%s" size', (size) => { - render( + ); +}; diff --git a/src/components/TextInput/README.md b/src/components/TextInput/README.md index 5e37bd59a4..60bd809fb9 100644 --- a/src/components/TextInput/README.md +++ b/src/components/TextInput/README.md @@ -91,6 +91,10 @@ export interface TextInputProps extends DOMProps, QAProps { * Maximum number of rows in textarea when the hight is autogenerated. */ maxRows?: number; + /** + * User`s node rendered after input and clear button + */ + rightContent?: React.ReactNode; onUpdate?: (value: string) => void; onChange?: React.ChangeEventHandler; onFocus?: React.FocusEventHandler; diff --git a/src/components/TextInput/TextInput.scss b/src/components/TextInput/TextInput.scss index 39fe4885ef..9a0936a29e 100644 --- a/src/components/TextInput/TextInput.scss +++ b/src/components/TextInput/TextInput.scss @@ -1,24 +1,30 @@ @use '../variables'; @use '../../../styles/mixins'; +$sHeight: 24px; +$mHeight: 28px; +$lHeight: 36px; +$xlHeight: 44px; +$borderWidth: 1px; + @mixin block_style($size: s, $type: control) { @if $size == 's' { - height: 24px; + height: #{$sHeight - $borderWidth * 2}; padding: 4px 8px; @include mixins.text-body-short; } @if $size == 'm' { - height: 28px; + height: #{$mHeight - $borderWidth * 2}; padding: 6px 8px; @include mixins.text-body-short; } @if $size == 'l' { - height: 36px; + height: #{$lHeight - $borderWidth * 2}; padding: 10px 12px; @include mixins.text-body-short; } @if $size == 'xl' { - height: 44px; + height: #{$xlHeight - $borderWidth * 2}; padding: 12px; @include mixins.text-body-2; } @@ -32,14 +38,20 @@ $block: '.#{variables.$ns}text-input'; #{$block} { - box-sizing: border-box; display: inline-block; width: 100%; position: relative; + &__content { + box-sizing: border-box; + display: flex; + width: 100%; + } + &__control { box-sizing: border-box; display: inline-block; + flex-grow: 1; vertical-align: top; position: relative; margin: 0; @@ -49,6 +61,7 @@ $block: '.#{variables.$ns}text-input'; font-family: var(--yc-text-body-font-family); color: var(--yc-color-text-primary); background-color: transparent; + border: none; &::placeholder { color: var(--yc-color-text-hint); @@ -91,25 +104,35 @@ $block: '.#{variables.$ns}text-input'; margin-top: 2px; } - /* increase css specificity to rewrite Button styles */ - &__clear[class] { - --yc-button-background-color: transparent; - --yc-button-background-color-hover: transparent; + &__clear { + /* increase css specificity to rewrite Button styles */ + &[class] { + --yc-button-background-color: transparent; + --yc-button-background-color-hover: transparent; - position: absolute; - top: 0; - right: 0; - color: var(--yc-color-text-hint); + color: var(--yc-color-text-hint); - &:hover { - color: var(--yc-color-text-primary); + &:hover { + color: var(--yc-color-text-primary); + } + } + + &_textarea { + position: absolute; + top: 0; + right: 0; } - &:not(#{$block}__clear_visible) { - display: none; + &:not(#{&}_textarea) { + margin: -1px; } } + &__additional-content { + display: flex; + align-items: center; + } + &_size { &_s { #{$block}__control { @@ -120,10 +143,9 @@ $block: '.#{variables.$ns}text-input'; @include block_style(s, label); } - &#{$block}_has-clear { - #{$block}__control { - padding-right: 26px; - } + #{$block}__additional-content { + height: #{$sHeight - $borderWidth * 2}; + padding-right: 1px; } --yc-text-input-border-radius: var(--yc-border-radius-s); @@ -138,10 +160,9 @@ $block: '.#{variables.$ns}text-input'; @include block_style(m, label); } - &#{$block}_has-clear { - #{$block}__control { - padding-right: 26px; - } + #{$block}__additional-content { + height: #{$mHeight - $borderWidth * 2}; + padding-right: 1px; } --yc-text-input-border-radius: var(--yc-border-radius-m); @@ -156,10 +177,9 @@ $block: '.#{variables.$ns}text-input'; @include block_style(l, label); } - &#{$block}_has-clear { - #{$block}__control { - padding-right: 36px; - } + #{$block}__additional-content { + height: #{$lHeight - $borderWidth * 2}; + padding-right: 3px; } --yc-text-input-border-radius: var(--yc-border-radius-l); @@ -174,10 +194,9 @@ $block: '.#{variables.$ns}text-input'; @include block_style(xl, label); } - &#{$block}_has-clear { - #{$block}__control { - padding-right: 36px; - } + #{$block}__additional-content { + height: #{$xlHeight - $borderWidth * 2}; + padding-right: 3px; } --yc-text-input-border-radius: var(--yc-border-radius-xl); @@ -186,26 +205,28 @@ $block: '.#{variables.$ns}text-input'; &_view { &_normal { - #{$block}__control { + #{$block}__content { border: 1px solid var(--yc-color-line-generic); &:hover { - border: 1px solid var(--yc-color-line-generic-hover); + border-color: var(--yc-color-line-generic-hover); } - &:focus { - border: 1px solid var(--yc-color-line-generic-active); + &:focus-within { + border-color: var(--yc-color-line-generic-active); } } } &_clear { - #{$block}__control { + & #{$block}__content { border: 1px solid transparent; border-left: 0; border-right: 0; border-radius: 0; + } + & #{$block}__control { padding-left: 0; padding-right: 0; } @@ -214,13 +235,13 @@ $block: '.#{variables.$ns}text-input'; @include mixins.pin( $block, - #{$block}__control, + #{$block}__content, var(--yc-text-input-border-radius), $append: false ); &_disabled { - #{$block}__control { + #{$block}__content { background-color: var(--yc-color-base-generic-accent-disabled); color: var(--yc-color-text-hint); border-color: transparent; @@ -230,6 +251,10 @@ $block: '.#{variables.$ns}text-input'; } } + #{$block}__control { + color: var(--yc-color-text-hint); + } + #{$block}__label { color: var(--yc-color-text-hint); } @@ -241,25 +266,31 @@ $block: '.#{variables.$ns}text-input'; } } + &_has-right-content { + #{$block}__control { + padding-right: 2px; + } + } + &_state { &_error { &#{$block}_view_normal { - #{$block}__control { + #{$block}__content { border-color: var(--yc-color-line-danger); &:hover, - &:focus { + &:focus-within { border-color: var(--yc-color-line-danger); } } } &#{$block}_view_clear { - #{$block}__control { + #{$block}__content { border-bottom: 1px solid var(--yc-color-line-danger); &:hover, - &:focus { + &:focus-within { border-bottom: 1px solid var(--yc-color-line-danger); } } diff --git a/src/components/TextInput/TextInput.tsx b/src/components/TextInput/TextInput.tsx index 49c0d1ddfb..77f76885fc 100644 --- a/src/components/TextInput/TextInput.tsx +++ b/src/components/TextInput/TextInput.tsx @@ -1,15 +1,13 @@ import React from 'react'; -import {block} from '../utils/cn'; +import {block, modsClassName} from '../utils/cn'; import {useForkRef} from '../utils/useForkRef'; import {useElementSize} from '../utils/useElementSize'; import {useUniqId} from '../utils/useUniqId'; -import {TextAreaControl} from './TextAreaControl/TextAreaControl'; import {InputControl} from './InputControl/InputControl'; -import {Button} from '../Button'; -import {Icon} from '../Icon'; -import {CrossIcon} from '../icons/CrossIcon'; +import {TextAreaControl} from './TextAreaControl/TextAreaControl'; +import {ClearAction} from './ClearAction/ClearAction'; +import {AdditionalContent} from './AdditionalContent/AdditionalContent'; import {TextInputProps, TextInputView, TextInputSize, TextInputPin, TextInputState} from './types'; -import i18n from './i18n'; import './TextInput.scss'; @@ -33,6 +31,7 @@ const prepareAutoComplete = (autoComplete: TextInputProps['autoComplete']): stri } }; +// eslint-disable-next-line complexity export const TextInput = React.forwardRef(function TextInput( props, ref, @@ -58,6 +57,7 @@ export const TextInput = React.forwardRef(funct className, qa, controlProps: originalControlProps, + rightContent, } = props; const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue ?? ''); const innerControlRef = React.useRef(null); @@ -120,6 +120,7 @@ export const TextInput = React.forwardRef(funct const isErrorMsgVisible = typeof error === 'string'; const isClearControlVisible = Boolean(hasClear && !disabled && inputValue); + const isRightContentVisible = Boolean(rightContent && !multiline); const controlProps: TextInputProps['controlProps'] = { ...originalControlProps, @@ -157,38 +158,38 @@ export const TextInput = React.forwardRef(funct { view, size, - pin: view === 'clear' ? undefined : pin, disabled, state, - 'has-clear': hasClear, + pin: view === 'clear' ? undefined : pin, + 'has-right-content': + (isClearControlVisible || isRightContentVisible) && !multiline, 'has-scrollbar': hasVerticalScrollbar, }, className, )} data-qa={qa} > - {isLabelVisible && ( - - )} - {multiline ? ( - - ) : ( - - )} - + + {isLabelVisible && ( + + )} + {multiline ? ( + + ) : ( + + )} + {isClearControlVisible && ( + + )} + {isRightContentVisible && {rightContent}} + {isErrorMsgVisible &&

{error}
} - {hasClear && ( - - )}
); }); diff --git a/src/components/TextInput/__stories__/TextInputShowcase.scss b/src/components/TextInput/__stories__/TextInputShowcase.scss index 3b56bfc34a..f3acc7c642 100644 --- a/src/components/TextInput/__stories__/TextInputShowcase.scss +++ b/src/components/TextInput/__stories__/TextInputShowcase.scss @@ -1,10 +1,4 @@ .text-input-showcase { - display: grid; - grid-template: - 'text-input' auto - 'text-input-label' auto - 'text-area' auto / auto; - &__text-input-examples { grid-area: text-input; display: grid; diff --git a/src/components/TextInput/__stories__/TextInputShowcase.tsx b/src/components/TextInput/__stories__/TextInputShowcase.tsx index eee8f63c5a..0f8f1d45f9 100644 --- a/src/components/TextInput/__stories__/TextInputShowcase.tsx +++ b/src/components/TextInput/__stories__/TextInputShowcase.tsx @@ -1,6 +1,9 @@ import React from 'react'; import block from 'bem-cn-lite'; import {Checkbox} from '../../Checkbox'; +import {Button} from '../../Button'; +import {Icon} from '../../Icon'; +import {GearIcon} from '../../icons'; import {TextInput} from '../TextInput'; import {TextInputProps} from '../types'; import './TextInputShowcase.scss'; @@ -10,6 +13,25 @@ const b = block('text-input-showcase'); const LABEL = 'Label:'; const LONG_LABEL = 'Very very long label is limited by 50% width of the input control size'; +const RightContent = (props: {size: TextInputProps['size']; disabled?: boolean}) => { + const {size, disabled} = props; + const [selected, setSelected] = React.useState(false); + + const handleClick = () => setSelected(!selected); + + return ( + + ); +}; + export const TextInputShowcase: React.FC = () => { const [value, setValue] = React.useState(''); const [isErrorMessageVisible, setErrorMessageVisibility] = React.useState(false); @@ -112,6 +134,74 @@ export const TextInputShowcase: React.FC = () => { +
+

TextInput (with right content)

+ +
+

Sizes:

+ + } + /> + } + /> + } + /> + } + /> +
+ +
+

States:

+ +
+ } + /> + +
+ } + disabled + /> + } + hasClear + /> + } + /> +
+
+

TextInput (multiline)

diff --git a/src/components/TextInput/__tests__/TextInput.input.test.tsx b/src/components/TextInput/__tests__/TextInput.input.test.tsx index 1ab297e59d..f23f917c3e 100644 --- a/src/components/TextInput/__tests__/TextInput.input.test.tsx +++ b/src/components/TextInput/__tests__/TextInput.input.test.tsx @@ -29,10 +29,15 @@ describe('TextInput input', () => { expect(container.querySelector('.yc-text-input__error')).not.toBeInTheDocument(); }); - test('render clear button with hasClear prop', () => { + test('check clear button visibility with hasClear prop', async () => { render(); - - expect(screen.getByRole('button', {name: 'Clear input value'})).toBeInTheDocument(); + const user = userEvent.setup(); + const input = screen.getByRole('textbox'); + let clearButton = screen.queryByRole('button', {name: 'Clear input value'}); + expect(clearButton).not.toBeInTheDocument(); + await user.type(input, 'abc'); + clearButton = screen.queryByRole('button', {name: 'Clear input value'}); + expect(clearButton).toBeInTheDocument(); }); test('do not render clear button without hasClear prop', () => { @@ -66,6 +71,8 @@ describe('TextInput input', () => { const onChangeFn = jest.fn(); const user = userEvent.setup(); render(); + const input = screen.getByRole('textbox'); + await user.type(input, 'abc'); const clear = screen.getByRole('button', {name: 'Clear input value'}); if (clear) { @@ -74,19 +81,6 @@ describe('TextInput input', () => { expect(onChangeFn).toBeCalled(); }); - - test('call onUpdate with emply value when click to clean button', async () => { - const onUpdateFn = jest.fn(); - const user = userEvent.setup(); - render(); - const clear = screen.getByRole('button', {name: 'Clear input value'}); - - if (clear) { - await user.click(clear); - } - - expect(onUpdateFn).toBeCalledWith(''); - }); }); describe('autocomplete', () => { diff --git a/src/components/TextInput/types.ts b/src/components/TextInput/types.ts index d32b252449..a0f5583daf 100644 --- a/src/components/TextInput/types.ts +++ b/src/components/TextInput/types.ts @@ -75,6 +75,10 @@ export interface TextInputProps extends DOMProps, QAProps { * Maximum number of rows in textarea when the hight is autogenerated. */ maxRows?: number; + /** + * User`s node rendered after input and clear button + */ + rightContent?: React.ReactNode; onUpdate?: (value: string) => void; onChange?: React.ChangeEventHandler; onFocus?: React.FocusEventHandler; diff --git a/src/components/Tooltip/Tooltip.scss b/src/components/Tooltip/Tooltip.scss index ebbaac3dd5..5fca2e39e4 100644 --- a/src/components/Tooltip/Tooltip.scss +++ b/src/components/Tooltip/Tooltip.scss @@ -6,11 +6,14 @@ $block: '.#{variables.$ns}tooltip'; // prevent glitch between two nearby tooltip refs pointer-events: none; - --yc-popup-border-width: 0; - --yc-popup-background-color: var(--yc-color-base-float-heavy); - &__content { padding: 6px 12px; color: var(--yc-color-text-light-primary); } } + +// [class] for increasing specificity +#{$block}[class] { + --yc-popup-border-width: 0; + --yc-popup-background-color: var(--yc-color-base-float-heavy); +} diff --git a/src/components/UserAvatar/README.md b/src/components/UserAvatar/README.md index 8f19f308b1..086f2e550d 100644 --- a/src/components/UserAvatar/README.md +++ b/src/components/UserAvatar/README.md @@ -8,5 +8,7 @@ Component for displaying user avatar. | :-------- | :--------------- | :------- | :------ | :--------------------------------------------------------- | | imgUrl | `string` | | | Link to image | | size | `UserAvatarSize` | | 'm' | Component size. Possible values: `xs`, `s`, `m`, `l`, `xl` | +| srcSet | `string` | | | `srcSet` attribute of the image | +| sizes | `string` | | | `sizes` attribute of the image | | title | `string` | | | Tooltip text on hover | | className | `string` | | | Class name | diff --git a/src/components/UserAvatar/UserAvatar.scss b/src/components/UserAvatar/UserAvatar.scss index 639118e167..7e18f9be27 100644 --- a/src/components/UserAvatar/UserAvatar.scss +++ b/src/components/UserAvatar/UserAvatar.scss @@ -3,13 +3,16 @@ $block: '.#{variables.$ns}user-avatar'; #{$block} { - box-sizing: border-box; display: inline-block; + overflow: hidden; + + box-sizing: border-box; + + border-radius: 50%; background-color: var(--yc-color-base-background); background-repeat: no-repeat; background-position: center; background-size: cover; - border-radius: 50%; &_size { &_xs { @@ -37,4 +40,8 @@ $block: '.#{variables.$ns}user-avatar'; height: 50px; } } + + &__figure { + object-fit: cover; + } } diff --git a/src/components/UserAvatar/UserAvatar.tsx b/src/components/UserAvatar/UserAvatar.tsx index 3b101e53b2..994f66f125 100644 --- a/src/components/UserAvatar/UserAvatar.tsx +++ b/src/components/UserAvatar/UserAvatar.tsx @@ -1,28 +1,42 @@ import React from 'react'; import {block} from '../utils/cn'; +import {SIZES} from './constants'; +import type {UserAvatarSize} from './types'; import './UserAvatar.scss'; -export type UserAvatarSize = 'xs' | 's' | 'm' | 'l' | 'xl'; - export interface UserAvatarProps { imgUrl?: string; size?: UserAvatarSize; + srcSet?: string; + sizes?: string; title?: string; className?: string; + /** @deprecated Use appropriate component, like `