vcc-ui
Version:
A React library for building user interfaces at Volvo Cars
357 lines (356 loc) • 10.7 kB
TypeScript
import * as CSS from 'csstype';
import { IRenderer } from 'fela';
import { ComponentType, ReactNode } from 'react';
import { IconColor, IconType } from '../components/icon';
import { ThreeElements } from './three-element-types';
export type ValueOf<T> = T[keyof T];
/**
* CSS object where values can be strings or numbers.
*/
export type CSSPropertiesBase = CSS.Properties<string | number>;
export type CSSCustomPropertyType = `${string}var(--${string})${string}`;
export type CSSCalcType = `${string}calc(${string})${string}`;
export type CSSPropertiesDefault = {
[key in keyof CSSPropertiesBase]: CSSPropertiesBase[key] | CSSCustomPropertyType | CSSCalcType;
};
/**
* CSS object with pseudo selectors.
*/
export type CSSPseudos<Theme> = {
[K in CSS.Pseudos]?: ExtendCSSObject<Theme>;
};
export interface CustomCSSProperties {
/**
* #### `foreground.primary`
* Use for primary text and icons.
*
* > ⚪: `#141414` | ⚫: `#ffffff`
*
*
* #### `foreground.secondary`
* Use for secondary text and icons.
*
* > ⚪: `#707070` | ⚫: `#a3a3a3`
*
*
* #### `foreground.inverted`
* Use for inverted text and icons.
*
* > ⚪: `#ffffff` | ⚫: `#000000`
*
*
* #### `foreground.alert`
* Use for highlighting errors, invalid data, and destructive actions.
*
* > ⚪: `#bf2012` | ⚫: `#ea2c1a`
*
*
* #### `foreground.action`
* Use for links and other interactive elements.
*
* > ⚪: `#1c6bba` | ⚫: `#1c6bba`
*
**/
color?: `foreground.${keyof DesignSystemColors['foreground']}` | Omit<string, ''>;
/**
* #### `background.primary`
* Primary background
*
* > ⚪: `#ffffff` | ⚫: `#0a0a0a`
*
*
* #### `background.secondary`
* Secondary background
*
* > ⚪: `#fafafa` | ⚫: `#141414`
*
**/
backgroundColor?: `background.${keyof DesignSystemColors['background']}` | Omit<string, ''>;
}
export type CSSProperties = CSSPropertiesDefault & CustomCSSProperties;
export type ExtendPropValue<Theme, Props = {}> = ExtendCSSObject<Theme, Props> | ((args: {
theme: Theme;
} & Props) => ExtendCSSObject<Theme, Props>) | ExtendPropValue<Theme, Props>[] | FelaExtend<Theme> | undefined;
export interface FelaExtend<Theme> {
extend?: {
condition?: boolean;
style: ExtendCSSObject<Theme>;
} | {
condition?: boolean;
style: ExtendCSSObject<Theme>;
}[];
}
/**
* CSS object with properties, breakpoints, child selectors and pseudo selectors.
*/
export interface ExtendCSSObject<Theme, Props = {}> extends FelaExtend<Theme>, CSSProperties, CSSPseudos<Theme> {
[key: string]: ExtendCSSObject<Theme, Props> | ExtendPropValue<Theme, Props> | string | boolean | number | undefined;
}
export type ResponsiveProp<T> = T | [T] | [T, T] | [T, T, T] | [T, T, T, T] | Record<ThemeBreakpointName | 'default', T> | {
[mediaQuery: string]: T;
};
export type TypeVariants =
/**
* * Amundsen (action text) - 14px
*/
'amundsen'
/**
* * Bates - 12px
*/
| 'bates'
/**
* * Columbus (default) - 16px
*/
| 'columbus'
/**
* * Cook - 32px / 36px / 40px
*/
| 'cook'
/**
* * Hillary - 20px
*/
| 'hillary'
/**
* * Ootah - 24px / 28px / 32px
*/
| 'ootah'
/**
* * Peary - 48px / 52px / 56px
*/
| 'peary'
/**
* * Yang (brand statement) - 40px / 72px / 72px
*/
| 'yang'
/**
* * Kelly - 14px
*/
| 'kelly'
/**
* * Meir - 8px
*/
| 'meir';
export interface DesignSystemColors {
brand: {
/**
* The primary brand color, used sparingly to create brand associated UI components.
*
* * Light Theme: #284e80
* * Dark Theme: #284e80
*/
primary: string;
};
foreground: {
/**
* Use for primary text and icons.
*
* * Light Theme: #141414
* * Dark Theme: #ffffff
*/
primary: string;
/**
* Use for secondary text and icons.
*
* * Light Theme: #707070
* * Dark Theme: #a3a3a3
*/
secondary: string;
/**
* Use for inverted text and icons.
*
* * Light Theme: #ffffff
* * Dark Theme: #000000
*/
inverted: string;
/**
* Use to highlight positive actions or events.
*
* * Light Theme: #058A22
* * Dark Theme: #08B42E
*/
positive: string;
/**
* Use to highlight destructive actions.
*
* * Light Theme: #bf2012
* * Dark Theme: #ea2c1a
*/
alert: string;
/**
* Use for links and other interactive elements.
*
* * Light Theme: #1c6bba
* * Dark Theme: #1c6bba
*/
action: string;
};
background: {
/**
* Primary background.
*
* * Light Theme: #ffffff
* * Dark Theme: #0a0a0a
*/
primary: string;
/**
* Secondary background.
*
* * Light Theme: #fafafa
* * Dark Theme: #141414
* */
secondary: string;
};
ornament: {
/**
* Use to visually group or separate UI elements.
*
* * Light Theme: #d5d5d5
* * Dark Theme: #707070
*/
border: string;
/**
* Use to visually group or separate UI elements.
*
* * Light Theme: #ebebeb
* * Dark Theme: #292929
*/
divider: string;
/**
* Use to highlight selected and focus states.
*
* * Light Theme: #1c6bba
* * Dark Theme: #1c6bba
*/
highlight: string;
/**
* Use to highlight successful states.
*
* * Light Theme: #058A22
* * Dark Theme: #08B42E
*/
positive: string;
/**
* Use to highlight errors and invalid states.
*
* * Light Theme: #bf2012
* * Dark Theme: #ea2c1a
*/
alert: string;
};
primitive: {
black: string;
white: string;
blue: string;
accentBlue: string;
greenPositive: string;
red: string;
grey100: string;
grey200: string;
grey300: string;
grey400: string;
grey500: string;
};
}
export interface ThemeBreakpoints {
/** \< 480 (identical to untilM) */
onlyS: '@media (max-width: 479px)';
/** \< 480 */
untilM: '@media (max-width: 479px)';
/** \> 480 */
fromM: '@media (min-width: 480px)';
/** \>= 480 && < 1024 */
onlyM: '@media (min-width: 480px) and (max-width: 1023px)';
/** \< 1024 */
untilL: '@media (max-width: 1023px)';
/** \>= 1024 */
fromL: '@media (min-width: 1024px)';
/** \>= 1024 && < 1600 */
onlyL: '@media (min-width: 1024px) and (max-width: 1599px)';
/** \< 1600 */
untilXL: '@media (max-width: 1599px)';
/** \>= 1600 */
fromXL: '@media (min-width: 1600px)';
/** \>= 1600 (identical to fromXL) */
onlyXL: '@media (min-width: 1600px)';
}
export type ThemeBreakpointName = keyof ThemeBreakpoints;
export type Direction = 'ltr' | 'rtl';
/** Volvo Theme */
export interface CurrentTheme {
name: 'volvo' | 'volvo-dark' | 'light' | 'dark';
color: DesignSystemColors;
direction: Direction;
baselineGrid: 8;
baselineSubGrid: 4;
breakpoints: ThemeBreakpoints;
icons: readonly ('account' | 'email' | 'facebook' | 'globe' | 'instagram' | 'linkedin' | 'pinterest' | 'search' | 'twitter' | 'vkontakte' | 'wechat' | 'weibo' | 'youku' | 'youtube')[];
getIcon(type: IconType, color?: IconColor): string;
fonts: any;
font: {
family: {
'volvo-novum': 'Volvo Novum, sans-serif';
'volvo-serif': 'Volvo Serif Pro, serif';
'volvo-broad': 'Volvo Broad Pro, sans-serif';
};
weight: {
'semi-light': 300;
regular: 400;
medium: 500;
};
};
fontsPath: string;
fontTypes: any;
iconsPath: string;
tokens: {
[key: string]: any;
};
logoImagesPath: string;
typeScale: Record<TypeVariants, any>;
states: {
focus: {
outlineOffset: number;
outlineWidth: number;
outlineColor: string;
outlineStyle: string;
};
};
}
export type Extendable<Props = {}> = {
/** A CSS object or a function returning a CSS object, or an array of them */
extend?: ExtendPropValue<CurrentTheme, Props>;
};
/** All intrinsic elements except react-three-fiber related ones */
export type OmittedIntrinsicElements = Omit<JSX.IntrinsicElements, ThreeElements>;
/** A React component, or a string specifying a name for an HTML element */
export type AsProp = keyof OmittedIntrinsicElements | ComponentType<any>;
export type PropsWithExtend<Props> = Props & Extendable<Props>;
export type ExtendCSS<Props = {}> = ExtendPropValue<CurrentTheme, Props>;
type As<Props = any> = Exclude<React.ElementType<Props>, ThreeElements>;
export type PropsWithAs<Props = {}, Type extends As = As, ExtendedRefType = undefined> = Props & Omit<React.ComponentProps<Type>, 'as' | keyof Props | 'ref'> & {
as?: Type;
ref?: React.ComponentProps<Type>['ref'] | ExtendedRefType;
};
export type ComponentWithAs<Props, DefaultType extends As, ExtendedRefType = undefined> = {
<Type extends As>(props: PropsWithAs<Props, Type, ExtendedRefType> & {
as: Type;
}): JSX.Element;
(props: PropsWithAs<Props, DefaultType, ExtendedRefType>): JSX.Element;
};
/** Changes the rendered element from `<button>` to `<a>`,
* and based on that change the allowed props
*/
type HrefProp = any;
export type PropsWithHref<Props = {}, Href extends HrefProp = undefined, NoHrefElementType extends 'button' | 'div' = 'button'> = Props & React.ComponentProps<Href extends undefined ? NoHrefElementType : 'a'> & {
href?: Href;
};
export type ComponentWithHref<Props, DefaultHref extends HrefProp, NoHrefElementType extends 'button' | 'div' = 'button'> = {
<Href extends HrefProp>(props: PropsWithHref<Props, Href, NoHrefElementType> & {
href: Href;
}): JSX.Element;
(props: PropsWithHref<Props, DefaultHref, NoHrefElementType>): JSX.Element;
};
export type Theme = ComponentType<{
children: (theme: CurrentTheme) => ReactNode;
}>;
export type renderStyles = (renderer: IRenderer) => React.DetailedReactHTMLElement<any, HTMLElement>[];
export {};