Skip to content

Commit

Permalink
feat(Label): added value prop for "key:value" labels (#665)
Browse files Browse the repository at this point in the history
Co-authored-by: sunduckcow <[email protected]>
  • Loading branch information
sunduckcow and sunduckcow authored Jun 9, 2023
1 parent e84f7c0 commit 5c979aa
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 115 deletions.
193 changes: 80 additions & 113 deletions src/components/Label/Label.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -26,22 +40,72 @@ $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;
position: relative;
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;
text-overflow: ellipsis;
overflow: hidden;
}

&__value {
display: flex;
opacity: 0.7;
}

&__separator {
margin: 0 4px;
}

// & selector added to up priority over button styles
& &__addon {
display: flex;
Expand Down Expand Up @@ -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));
}
}

Expand Down Expand Up @@ -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)
);
}
}
}
17 changes: 15 additions & 2 deletions src/components/Label/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -81,6 +83,7 @@ export const Label = React.forwardRef<HTMLDivElement, LabelProps>(function Label
closeButtonLabel,
copyButtonLabel,
interactive = false,
value,
onCopy,
onClick,
} = props;
Expand All @@ -98,7 +101,17 @@ export const Label = React.forwardRef<HTMLDivElement, LabelProps>(function Label
const leftIcon = icon && (
<div className={b('addon', {side: hasContent ? 'left' : undefined})}>{icon}</div>
);
const content = hasContent && <div className={b('text')}>{children}</div>;
const content = hasContent && (
<div className={b('text')}>
<div className={b('content')}>{children}</div>
{Boolean(value) && (
<div className={b('value')}>
<div className={b('separator')}>:</div>
<div className={b('key')}>{value}</div>
</div>
)}
</div>
);

const handleCloseClick = (event: React.MouseEvent<HTMLButtonElement>) => {
if (hasOnClick) {
Expand Down
14 changes: 14 additions & 0 deletions src/components/Label/__stories__/Label.stories.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
60 changes: 60 additions & 0 deletions src/components/Label/__stories__/Label.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export default {
children: {
control: {type: 'text'},
},
copyText: {
control: {type: 'text'},
defaultValue: '',
},
},
} as Meta;

Expand Down Expand Up @@ -64,6 +68,9 @@ const ThemeTemplate: StoryFn<LabelProps> = (args) => {
<Label {...args} theme="unknown">
unknown
</Label>
<Label {...args} theme="clear">
clear
</Label>
</div>
);
};
Expand Down Expand Up @@ -173,3 +180,56 @@ export const Interactions: StoryFn<LabelProps> = (args) => (
</div>
</div>
);

type WithKey<T> = 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<LabelProps>) => <Label {...args}></Label>;

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<LabelProps> = (args) => (
<div className="label-stories">
<div className="grid" style={{gridTemplateColumns: `repeat(${1 + themes.length}, 1fr)`}}>
<div></div>
{themes.map((theme) => (
<h1 key={`${theme}-header`}>{theme}</h1>
))}
{sizes.map((size) => (
<React.Fragment key={size}>
<h1>{size}</h1>
{themes.map((theme) => (
<div key={theme} className="section">
{section({theme, size, ...args})}
</div>
))}
</React.Fragment>
))}
</div>
</div>
);

export const Showcase = KeyValuesTemplate.bind({});

Showcase.args = {
interactive: true,
};

0 comments on commit 5c979aa

Please sign in to comment.