diff --git a/src/components/experimental/Label/Label.tsx b/src/components/experimental/Label/Label.tsx new file mode 100644 index 00000000..0d49821c --- /dev/null +++ b/src/components/experimental/Label/Label.tsx @@ -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 ( + + {children} + + ); +} + +export { Label, LabelProps }; diff --git a/src/components/experimental/Label/docs/Label.stories.tsx b/src/components/experimental/Label/docs/Label.stories.tsx new file mode 100644 index 00000000..e1d60e92 --- /dev/null +++ b/src/components/experimental/Label/docs/Label.stories.tsx @@ -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; + +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 {children}; + } +}; diff --git a/src/essentials/experimental/cssVariables.ts b/src/essentials/experimental/cssVariables.ts index def980b5..381d42d5 100644 --- a/src/essentials/experimental/cssVariables.ts +++ b/src/essentials/experimental/cssVariables.ts @@ -53,6 +53,12 @@ export const getSemanticValue = (token: SemanticColorToken): ReadCssVariable => `var(--${DS_PREFIX}-color-${token}-hsl)`; +export const getBareValue = (token: BareColorToken): ReadCssVariable => + `var(--${DS_PREFIX}-palette-${token})`; + +export const getBareHslValue = (token: BareColorToken): ReadCssVariable => + `var(--${DS_PREFIX}-palette-${token}-hsl)`; + export const generateCssVariables = (tokens: TokenObject, namespace: NameSpace): ReadonlyArray => { const entries = generateCssVariableEntries(tokens); const hslComponentsEntries = generateHslComponentsCssVariableEntries(entries); diff --git a/src/essentials/experimental/globalStyles.ts b/src/essentials/experimental/globalStyles.ts index 47a53403..3d81d74f 100644 --- a/src/essentials/experimental/globalStyles.ts +++ b/src/essentials/experimental/globalStyles.ts @@ -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, @@ -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} } diff --git a/src/essentials/experimental/index.ts b/src/essentials/experimental/index.ts index a70bf365..6224ff08 100644 --- a/src/essentials/experimental/index.ts +++ b/src/essentials/experimental/index.ts @@ -1,2 +1,4 @@ export * from './theme'; export { createGlobalStyle, ColorPalette } from './Colors'; +export { darkTheme } from './globalStyles'; +export { getSemanticValue, getBareValue, getBareHslValue, getSemanticHslValue } from './cssVariables';