Skip to content

Commit

Permalink
feat(label): add experimental label component (#471)
Browse files Browse the repository at this point in the history
* feat(label): add Label

* feat(essentials): add darkTheme css util

* feat(essentials): add bare color value getters

* docs(label): add examples

* fix(label): add nowrap

---------

Co-authored-by: Lena Rashkovan <lena.rashkovan@free-now.com>
  • Loading branch information
alatielle and Lena Rashkovan committed Sep 20, 2024
1 parent 7ca6245 commit ea608ab
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 3 deletions.
55 changes: 55 additions & 0 deletions src/components/experimental/Label/Label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import styled from 'styled-components';
import { variant } from 'styled-system';
import React, { ComponentPropsWithoutRef, ReactElement } from 'react';
import { textStyles } from '../Text/Text';
import { getSemanticValue } from '../../../essentials/experimental/cssVariables';
import { get } from '../../../utils/experimental/themeGet';

type LabelType = 'default' | 'positive' | 'negative';

interface LabelProps extends ComponentPropsWithoutRef<'span'> {
/**
* Set the appropriate colors for the component with 'default' as a default
*/
type?: LabelType;
}

const variantStyles = variant({
prop: '$type',
variants: {
default: {
color: getSemanticValue('on-surface'),
backgroundColor: getSemanticValue('surface-variant')
},
positive: {
color: getSemanticValue('on-positive-container'),
backgroundColor: getSemanticValue('positive-container')
},
negative: {
color: getSemanticValue('on-negative-container'),
backgroundColor: getSemanticValue('negative-container')
}
}
});

const StyledLabel = styled.span<{ $type: LabelType }>`
display: inline-flex;
box-sizing: border-box;
border-radius: ${get('radii.2')};
padding: ${get('space.1')} ${get('space.2')};
white-space: nowrap;
${textStyles.variants.label2};
${props => variantStyles(props)}
`;

function Label({ children, type = 'default', ...restProps }: LabelProps): ReactElement {
return (
<StyledLabel $type={type} {...restProps}>
{children}
</StyledLabel>
);
}

export { Label, LabelProps };
56 changes: 56 additions & 0 deletions src/components/experimental/Label/docs/Label.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import styled from 'styled-components';
import { StoryObj, Meta } from '@storybook/react';
import { Label } from '../Label';
import { darkTheme, getBareValue } from '../../../../essentials/experimental';

const meta: Meta = {
title: 'Experimental/Components/Label',
component: Label,
parameters: {
layout: 'centered'
},
args: {
children: 'Label Text'
},
argTypes: {
type: {
control: 'radio',
options: ['default', 'positive', 'negative']
}
}
};

export default meta;

type Story = StoryObj<typeof Label>;

export const Default: Story = {};

export const Positive: Story = {
args: {
type: 'positive'
}
};

export const Negative: Story = {
args: {
type: 'negative'
}
};

export const Custom: Story = {
render: ({ children, ...props }) => {
const CustomLabel = styled(Label)`
color: ${getBareValue('neutral-99')};
background-color: ${getBareValue('blue-50')};
${darkTheme`
color: ${getBareValue('neutral-10')};
background-color: ${getBareValue('blue-70')};
`}
`;

return <CustomLabel {...props}>{children}</CustomLabel>;
}
};
6 changes: 6 additions & 0 deletions src/essentials/experimental/cssVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ export const getSemanticValue = (token: SemanticColorToken): ReadCssVariable<Sem
export const getSemanticHslValue = (token: SemanticColorToken): ReadCssVariable<SemanticColorHslTokenCssVariable> =>
`var(--${DS_PREFIX}-color-${token}-hsl)`;

export const getBareValue = (token: BareColorToken): ReadCssVariable<BareColorTokenCssVariable> =>
`var(--${DS_PREFIX}-palette-${token})`;

export const getBareHslValue = (token: BareColorToken): ReadCssVariable<BareColorHslTokenCssVariable> =>
`var(--${DS_PREFIX}-palette-${token}-hsl)`;

export const generateCssVariables = (tokens: TokenObject, namespace: NameSpace): ReadonlyArray<string> => {
const entries = generateCssVariableEntries(tokens);
const hslComponentsEntries = generateHslComponentsCssVariableEntries(entries);
Expand Down
23 changes: 20 additions & 3 deletions src/essentials/experimental/globalStyles.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import { createGlobalStyle } from 'styled-components';
import { createGlobalStyle, css, CSSObject } from 'styled-components';

import { TokenObject } from '../../utils/cssVariables';
import { generateBareCssVariables, generateSemanticCssVariables, getSemanticValue } from './cssVariables';
import { SemanticColorsSchema } from './types';

export const DARK_THEME_CLASS = 'dark-scheme';
export const LIGHT_THEME_CLASS = 'light-scheme';

export const darkTheme: typeof css = (first: CSSObject | TemplateStringsArray, ...interpolations: never[]) => {
const styles = css(first, ...interpolations);

return css`
.${DARK_THEME_CLASS} & {
${styles};
}
@media (prefers-color-scheme: dark) {
${styles}
}
`;
};

export const createThemeGlobalStyle = (
bareVariables: TokenObject,
lightScheme: SemanticColorsSchema,
Expand All @@ -20,12 +37,12 @@ export const createThemeGlobalStyle = (
${semanticCssVariablesForLightTheme}
}
.dark-scheme {
.${DARK_THEME_CLASS} {
color-scheme: dark;
${semanticCssVariablesForDarkTheme}
}
.light-scheme {
.${LIGHT_THEME_CLASS} {
color-scheme: light;
${semanticCssVariablesForLightTheme}
}
Expand Down
2 changes: 2 additions & 0 deletions src/essentials/experimental/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './theme';
export { createGlobalStyle, ColorPalette } from './Colors';
export { darkTheme } from './globalStyles';
export { getSemanticValue, getBareValue, getBareHslValue, getSemanticHslValue } from './cssVariables';

0 comments on commit ea608ab

Please sign in to comment.