Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breakpoint, MediaQuery, spacing, radius tokens #559

Merged
merged 9 commits into from
Sep 20, 2024
47 changes: 47 additions & 0 deletions src/theme/breakpoint/media-query-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { BreakpointValues } from "./theme-helper";
import { StyledComponentProps } from "../helpers";

// Typings for MedaiQuery
type MaxWidthBreakpoints = "xxs" | "xs" | "sm" | "md" | "lg" | "xl";
type MinWidthBreakpoints = MaxWidthBreakpoints | "xxl";
type MediaQueryMinMax = "max-width" | "min-width";
type MediaQuerySpec<T extends string> = Record<
T,
(props: StyledComponentProps) => string
>;

const createMediaQueryFunction = <T extends string>(
type: MediaQueryMinMax,
key: T
) => {
const mappedKey = type === "max-width" ? `${key}-max` : `${key}-min`;
const breakpointFunction =
BreakpointValues[mappedKey as keyof typeof BreakpointValues];

return (props: StyledComponentProps) => {
const value = breakpointFunction(props);
return `@media screen and (${type}: ${value}px)`;
};
};

const getMediaQuerySpec = <T extends string>(
type: "max-width" | "min-width"
): MediaQuerySpec<T> => {
// Conditional breakpoints for max and min widths
const breakpoints = (
type === "max-width"
? ["xxs", "xs", "sm", "md", "lg", "xl"]
: ["xxs", "xs", "sm", "md", "lg", "xl", "xxl"]
) as T[];

return breakpoints.reduce((accumulator, key) => {
accumulator[key] = createMediaQueryFunction(type, key);
return accumulator;
}, {} as MediaQuerySpec<T>);
};

// Export with typing
export const MediaQuery = {
MaxWidth: getMediaQuerySpec<MaxWidthBreakpoints>("max-width"),
MinWidth: getMediaQuerySpec<MinWidthBreakpoints>("min-width"),
};
41 changes: 41 additions & 0 deletions src/theme/breakpoint/specs/lifesg-breakpoint-set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { BreakpointSet } from "../types";

export const LifeSgBreakpointSet: BreakpointSet = {
"xxs-min": 0,
"xxs-max": 320,
"xs-min": 321,
"xs-max": 375,
"sm-min": 376,
"sm-max": 420,
"md-min": 421,
"md-max": 767,
"lg-min": 768,
"lg-max": 1023,
"xl-min": 1024,
"xl-max": 1440,
"xxl-min": 1441,

"xxs-column": 8,
"xs-column": 8,
"sm-column": 8,
"md-column": 8,
"lg-column": 12,
"xl-column": 12,
"xxl-column": 12,

"xxs-gutter": 16,
"xs-gutter": 16,
"sm-gutter": 16,
"md-gutter": 16,
"lg-gutter": 32,
"xl-gutter": 32,
"xxl-gutter": 32,

"xxs-margin": 24,
"xs-margin": 24,
"sm-margin": 24,
"md-margin": 24,
"lg-margin": 48,
"xl-margin": 48,
"xxl-margin": 48,
};
74 changes: 74 additions & 0 deletions src/theme/breakpoint/theme-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { StyledComponentProps, getCollection, getValue } from "../helpers";
import { BreakpointScheme, ThemeCollectionSpec } from "../types";
import { LifeSgBreakpointSet } from "./specs/lifesg-breakpoint-set";
import { BreakpointCollectionsMap, BreakpointSet } from "./types";

const BreakpointSpec: ThemeCollectionSpec<
BreakpointCollectionsMap,
BreakpointScheme
> = {
collections: {
lifesg: LifeSgBreakpointSet,
},
defaultValue: "lifesg",
};

export const getBreakpoint = (key: keyof BreakpointSet) => {
return (props: StyledComponentProps): number => {
const theme = props.theme;
const breakpointSet: BreakpointSet = getCollection(
BreakpointSpec,
theme?.breakpointScheme
);

let value: number | undefined;

if (theme?.overrides?.breakpoint) {
value = getValue(breakpointSet, key, theme.overrides.breakpoint);
} else {
value = breakpointSet[key];
}

return value;
};
};

export const BreakpointValues = {
"xxs-min": getBreakpoint("xxs-min"),
"xxs-max": getBreakpoint("xxs-max"),
"xs-min": getBreakpoint("xs-min"),
"xs-max": getBreakpoint("xs-max"),
"sm-min": getBreakpoint("sm-min"),
"sm-max": getBreakpoint("sm-max"),
"md-min": getBreakpoint("md-min"),
"md-max": getBreakpoint("md-max"),
"lg-min": getBreakpoint("lg-min"),
"lg-max": getBreakpoint("lg-max"),
"xl-min": getBreakpoint("xl-min"),
"xl-max": getBreakpoint("xl-max"),
"xxl-min": getBreakpoint("xxl-min"),

"xxs-column": getBreakpoint("xxs-column"),
"xs-column": getBreakpoint("xs-column"),
"sm-column": getBreakpoint("sm-column"),
"md-column": getBreakpoint("md-column"),
"lg-column": getBreakpoint("lg-column"),
"xl-column": getBreakpoint("xl-column"),
"xxl-column": getBreakpoint("xxl-column"),

"xxs-gutter": getBreakpoint("xxs-gutter"),
"xs-gutter": getBreakpoint("xs-gutter"),
"sm-gutter": getBreakpoint("sm-gutter"),
"md-gutter": getBreakpoint("md-gutter"),
"lg-gutter": getBreakpoint("lg-gutter"),
"xl-gutter": getBreakpoint("xl-gutter"),
"xxl-gutter": getBreakpoint("xxl-gutter"),

"xxs-margin": getBreakpoint("xxs-margin"),
"xs-margin": getBreakpoint("xs-margin"),
"sm-margin": getBreakpoint("sm-margin"),
"md-margin": getBreakpoint("md-margin"),
"lg-margin": getBreakpoint("lg-margin"),
"xl-margin": getBreakpoint("xl-margin"),
"xxl-margin": getBreakpoint("xxl-margin"),
};
45 changes: 45 additions & 0 deletions src/theme/breakpoint/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { StyledComponentProps } from "../helpers";
import { BreakpointScheme } from "../types";

export interface BreakpointSet {
"xxs-min": number;
"xxs-max": number;
"xs-min": number;
"xs-max": number;
"sm-min": number;
"sm-max": number;
"md-min": number;
"md-max": number;
"lg-min": number;
"lg-max": number;
"xl-min": number;
"xl-max": number;
"xxl-min": number;
"xxs-column": number;
"xs-column": number;
"sm-column": number;
"md-column": number;
"lg-column": number;
"xl-column": number;
"xxl-column": number;
"xxs-gutter": number;
"xs-gutter": number;
"sm-gutter": number;
"md-gutter": number;
"lg-gutter": number;
"xl-gutter": number;
"xxl-gutter": number;
"xxs-margin": number;
"xs-margin": number;
"sm-margin": number;
"md-margin": number;
"lg-margin": number;
"xl-margin": number;
"xxl-margin": number;
}

export type BreakpointCollectionsMap = {
[key in BreakpointScheme]: BreakpointSet;
};

export type BreakpointSetOptions = Partial<BreakpointSet>;
24 changes: 24 additions & 0 deletions src/theme/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { BreakpointValues } from "./breakpoint/theme-helper";
import { AnimationValues } from "./animation/theme-helper";
import { BorderValues } from "./border/theme-helper";
import { PrimitiveColour } from "./colour-primitive/theme-helper";
import { ColourSemantic } from "./colour-semantic/theme-helper";
import { FontValues } from "./font/theme-helper";
import { RadiusValues } from "./radius/theme-helper";
import { SpacingValues } from "./spacing/theme-helper";
import { ThemeSpec } from "./types";
import { TypographyValues } from "./typography/theme-helper";

Expand All @@ -19,37 +22,58 @@ export const Animation = AnimationValues;

export const Border = BorderValues;

export const Spacing = SpacingValues;

export const Radius = RadiusValues;

export const Breakpoint = BreakpointValues;

export const LifeSGTheme: ThemeSpec = {
colourScheme: "lifesg",
fontScheme: "lifesg",
animationScheme: "lifesg",
borderScheme: "lifesg",
spacingScheme: "lifesg",
radiusScheme: "lifesg",
breakpointScheme: "lifesg",
};

export const BookingSGTheme: ThemeSpec = {
colourScheme: "bookingsg",
fontScheme: "bookingsg",
animationScheme: "lifesg",
borderScheme: "lifesg",
spacingScheme: "lifesg",
radiusScheme: "lifesg",
breakpointScheme: "lifesg",
};

export const CcubeTheme: ThemeSpec = {
colourScheme: "ccube",
fontScheme: "ccube",
animationScheme: "lifesg",
borderScheme: "lifesg",
spacingScheme: "lifesg",
radiusScheme: "lifesg",
breakpointScheme: "lifesg",
};

export const MyLegacyTheme: ThemeSpec = {
colourScheme: "mylegacy",
fontScheme: "mylegacy",
animationScheme: "lifesg",
borderScheme: "lifesg",
spacingScheme: "lifesg",
radiusScheme: "lifesg",
breakpointScheme: "lifesg",
};

export const RBSTheme: ThemeSpec = {
colourScheme: "rbs",
fontScheme: "rbs",
animationScheme: "lifesg",
borderScheme: "lifesg",
spacingScheme: "lifesg",
radiusScheme: "lifesg",
breakpointScheme: "lifesg",
};
10 changes: 10 additions & 0 deletions src/theme/radius/specs/lifesg-radius-set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { RadiusSet } from "../types";

export const LifeSgRadiusSet: RadiusSet = {
none: 0,
xs: 2,
sm: 4,
md: 8,
lg: 12,
full: 9999,
};
36 changes: 36 additions & 0 deletions src/theme/radius/theme-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { StyledComponentProps, getCollection, getValue } from "../helpers";
import { RadiusScheme, ThemeCollectionSpec } from "../types";
import { LifeSgRadiusSet } from "./specs/lifesg-radius-set";
import { RadiusCollectionsMap, RadiusSet } from "./types";

const RadiusSpec: ThemeCollectionSpec<RadiusCollectionsMap, RadiusScheme> = {
collections: {
lifesg: LifeSgRadiusSet,
},
defaultValue: "lifesg",
};

export const getRadius = (key: keyof RadiusSet) => {
return (props: StyledComponentProps): string => {
const theme = props.theme;
const radiusSet: RadiusSet = getCollection(
RadiusSpec,
theme.radiusScheme
);

if (theme.overrides && theme.overrides.radius) {
return `${getValue(radiusSet, key, theme.overrides.radius)}px`;
} else {
return `${radiusSet[key]}px`;
}
};
};

export const RadiusValues = {
none: getRadius("none"),
xs: getRadius("xs"),
sm: getRadius("sm"),
md: getRadius("md"),
lg: getRadius("lg"),
full: getRadius("full"),
};
16 changes: 16 additions & 0 deletions src/theme/radius/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { RadiusScheme } from "../types";

export type RadiusSet = {
none: number;
xs: number;
sm: number;
md: number;
lg: number;
full: number;
};

export type RadiusSetOptions = Partial<RadiusSet>;

export type RadiusCollectionsMap = {
[key in RadiusScheme]: RadiusSet;
};
24 changes: 24 additions & 0 deletions src/theme/spacing/specs/lifesg-spacing-set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { SpacingSet } from "../types";

export const LifeSgSpacingSet: SpacingSet = {
"spacing-0": 0,
"spacing-4": 4,
"spacing-8": 8,
"spacing-12": 12,
"spacing-16": 16,
"spacing-20": 20,
"spacing-24": 24,
"spacing-32": 32,
"spacing-40": 40,
"spacing-48": 48,
"spacing-64": 64,
"spacing-72": 72,

"layout-xs": 8,
"layout-sm": 16,
"layout-md": 24,
"layout-lg": 32,
"layout-xl": 48,
"layout-xxl": 64,
"layout-xxxl": 128,
};
Loading
Loading