diff --git a/src/components/Label/Label.scss b/src/components/Label/Label.scss index e63d82ae2..a176720ca 100644 --- a/src/components/Label/Label.scss +++ b/src/components/Label/Label.scss @@ -2,18 +2,32 @@ $block: '.#{variables.$ns}label'; $disabled: #{$block}_disabled; -$transitionDuration: 0.3s; +$transitionDuration: 0.15s; $transitionTimingFunction: ease-in-out; -@mixin themeState($bgColor, $bgHoverColor, $textColor) { +@mixin themeState($bgColor, $bgHoverColor, $textColor, $borderColor: none) { color: #{$textColor}; background-color: #{$bgColor}; - // hover on interactive label - &:not(#{$disabled})#{$block}_is-interactive:hover { + @if $borderColor != none { + --border-size: 1px; + border: var(--border-size) solid #{$borderColor}; + } + + // hover on interactive label (excluding hover on addon) + &:not(#{$disabled})#{$block}_is-interactive:hover:not( + :has(#{$block}__addon_interactive:hover) + ) { background-color: #{$bgHoverColor}; } + //fallback for old browsers + @supports not selector(:has(*)) { + &:not(#{$disabled})#{$block}_is-interactive:hover { + background-color: #{$bgHoverColor}; + } + } + // hover on action button &:not(#{$disabled}) #{$block}__addon_interactive { --yc-button-background-color-hover: #{$bgHoverColor}; @@ -26,6 +40,42 @@ $transitionTimingFunction: ease-in-out; } } +@mixin sizeState($margin, $mainSize, $rAddon, $lAddon, $borderRadius) { + height: #{$mainSize}; + & #{$block}__text { + line-height: #{$mainSize}; + margin: 0 #{$margin}; + } + + & #{$block}__addon { + --addon-size: calc(#{$mainSize} - var(--border-size) * 2); + width: var(--addon-size); + height: var(--addon-size); + } + + &#{$block}_has-right-addon #{$block}__text { + margin-right: #{$rAddon}; + } + + &#{$block}_has-left-addon #{$block}__text { + margin-left: #{$lAddon}; + } + + &#{$block}_style { + &_default, + &_rounded { + border-radius: #{$borderRadius}; + + & #{$block}__addon { + &_interactive { + --yc-button-height: #{$mainSize}; + --yc-button-border-radius: calc(#{$borderRadius} - var(--border-size)); + } + } + } + } +} + #{$block} { display: inline-flex; align-items: center; @@ -33,8 +83,13 @@ $transitionTimingFunction: ease-in-out; transition-property: opacity, color, background-color; transition-duration: $transitionDuration; transition-timing-function: $transitionTimingFunction; + box-sizing: border-box; + + --border-size: 0px; &__text { + display: flex; + align-items: baseline; width: 100%; text-align: center; white-space: nowrap; @@ -42,6 +97,15 @@ $transitionTimingFunction: ease-in-out; overflow: hidden; } + &__value { + display: flex; + opacity: 0.7; + } + + &__separator { + margin: 0 4px; + } + // & selector added to up priority over button styles & &__addon { display: flex; @@ -75,121 +139,15 @@ $transitionTimingFunction: ease-in-out; &_size { &_xs { - height: 20px; - - & #{$block}__text { - line-height: 20px; - margin: 0 8px; - } - - & #{$block}__addon { - width: 20px; - height: 20px; - } - - &#{$block}_has-right-addon #{$block}__text { - margin-right: 22px; - } - - &#{$block}_has-left-addon #{$block}__text { - margin-left: 24px; - } - - &#{$block}_style { - &_default, - &_rounded { - border-radius: var(--yc-border-radius-xs); - - & #{$block}__addon { - &_interactive { - --yc-button-height: 20px; - --yc-button-border-radius: var(--yc-border-radius-xs); - } - } - } - } + @include sizeState(8px, 20px, 22px, 24px, var(--yc-border-radius-xs)); } &_s { - height: 24px; - - & #{$block}__text { - line-height: 24px; - margin: 0 10px; - } - - & #{$block}__icon { - width: 24px; - height: 24px; - } - - &#{$block}_has-right-addon #{$block}__text { - margin-right: 26px; - } - - &#{$block}_has-left-addon #{$block}__text { - margin-left: 28px; - } - - &#{$block}_style { - &_default, - &_rounded { - border-radius: var(--yc-border-radius-s); - - & #{$block}__addon { - &_interactive { - --yc-button-height: 24px; - --yc-button-border-radius: var(--yc-border-radius-s); - } - } - } - } + @include sizeState(10px, 24px, 26px, 28px, var(--yc-border-radius-s)); } &_m { - height: 28px; - - & #{$block}__text { - line-height: 28px; - margin: 0 12px; - } - - & #{$block}__addon { - width: 28px; - height: 28px; - } - - &#{$block}_has-right-addon #{$block}__text { - margin-right: 32px; - } - - &#{$block}_has-left-addon #{$block}__text { - margin-left: 32px; - } - - &#{$block}_style { - &_default { - border-radius: var(--yc-border-radius-m); - - & #{$block}__addon { - &_interactive { - --yc-button-height: 28px; - --yc-button-border-radius: var(--yc-border-radius-m); - } - } - } - - &_rounded { - border-radius: 24px; - - & #{$block}__addon { - &_interactive { - --yc-button-height: 28px; - --yc-button-border-radius: 24px; - } - } - } - } + @include sizeState(12px, 28px, 32px, 32px, var(--yc-border-radius-m)); } } @@ -250,5 +208,14 @@ $transitionTimingFunction: ease-in-out; var(--yc-color-text-complementary) ); } + + &_clear { + @include themeState( + transparent, + var(--yc-color-base-simple-hover-solid), + var(--yc-color-text-complementary), + var(--yc-color-line-generic) + ); + } } } diff --git a/src/components/Label/Label.tsx b/src/components/Label/Label.tsx index 4ca2ffe68..af15f8283 100644 --- a/src/components/Label/Label.tsx +++ b/src/components/Label/Label.tsx @@ -51,11 +51,13 @@ interface LabelOwnProps { children?: React.ReactNode; /** Display hover */ interactive?: boolean; + /** Label value (shows as "children : value") */ + value?: string; } interface LabelDefaultProps { /** Label color */ - theme: 'normal' | 'info' | 'danger' | 'warning' | 'success' | 'unknown'; + theme: 'normal' | 'info' | 'danger' | 'warning' | 'success' | 'unknown' | 'clear'; /** Label type (plain, with copy text button or with close button) */ type: 'default' | 'copy' | 'close'; /** Label size */ @@ -81,6 +83,7 @@ export const Label = React.forwardRef(function Label closeButtonLabel, copyButtonLabel, interactive = false, + value, onCopy, onClick, } = props; @@ -98,7 +101,17 @@ export const Label = React.forwardRef(function Label const leftIcon = icon && (
{icon}
); - const content = hasContent &&
{children}
; + const content = hasContent && ( +
+
{children}
+ {Boolean(value) && ( +
+
:
+
{value}
+
+ )} +
+ ); const handleCloseClick = (event: React.MouseEvent) => { if (hasOnClick) { diff --git a/src/components/Label/__stories__/Label.stories.scss b/src/components/Label/__stories__/Label.stories.scss index 91682f72b..67ed2f6b9 100644 --- a/src/components/Label/__stories__/Label.stories.scss +++ b/src/components/Label/__stories__/Label.stories.scss @@ -3,4 +3,18 @@ .yc-label { margin-left: 10px; } + .grid { + display: grid; + // grid-template-columns: from js + gap: 30px; + } + .section { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; + & > * { + width: min-content; + margin-left: unset; + } + } } diff --git a/src/components/Label/__stories__/Label.stories.tsx b/src/components/Label/__stories__/Label.stories.tsx index 820faf832..b2bfde425 100644 --- a/src/components/Label/__stories__/Label.stories.tsx +++ b/src/components/Label/__stories__/Label.stories.tsx @@ -32,6 +32,10 @@ export default { children: { control: {type: 'text'}, }, + copyText: { + control: {type: 'text'}, + defaultValue: '', + }, }, } as Meta; @@ -64,6 +68,9 @@ const ThemeTemplate: StoryFn = (args) => { + ); }; @@ -173,3 +180,56 @@ export const Interactions: StoryFn = (args) => ( ); + +type WithKey = T & {key: React.Key}; + +const themes = ['normal', 'info', 'danger', 'warning', 'success', 'unknown', 'clear'] as const; +const sizes = ['xs', 's', 'm'] as const; + +const getLabel = ({...args}: WithKey) => ; + +const section = (args: LabelProps) => { + const cases: LabelProps[] = [ + {children: 'Label', icon: icons['TickIcon'], type: 'default'}, + {children: 'Label', type: 'default'}, + {children: 'Label', icon: icons['TickIcon'], type: 'copy'}, + {children: 'Label', type: 'copy'}, + {children: 'Label', icon: icons['TickIcon'], type: 'close'}, + {children: 'Label', type: 'close'}, + {children: 'Key', value: 'Value', icon: icons['TickIcon'], type: 'default'}, + {children: 'Key', value: 'Value', type: 'default'}, + {children: 'Key', value: 'Value', icon: icons['TickIcon'], type: 'copy'}, + {children: 'Key', value: 'Value', type: 'copy'}, + {children: 'Key', value: 'Value', icon: icons['TickIcon'], type: 'close'}, + {children: 'Key', value: 'Value', type: 'close'}, + {icon: icons['TickIcon']}, + ]; + return cases.map((label, i) => getLabel({key: i, ...args, ...label})); +}; + +const KeyValuesTemplate: StoryFn = (args) => ( +
+
+
+ {themes.map((theme) => ( +

{theme}

+ ))} + {sizes.map((size) => ( + +

{size}

+ {themes.map((theme) => ( +
+ {section({theme, size, ...args})} +
+ ))} +
+ ))} +
+
+); + +export const Showcase = KeyValuesTemplate.bind({}); + +Showcase.args = { + interactive: true, +};