feat(styles):定义主题以及全局样式。
This commit is contained in:
parent
fffd3df059
commit
d166f7301e
|
@ -1,16 +1,20 @@
|
|||
import { css } from "@emotion/react";
|
||||
import "normalize.css";
|
||||
import { mq } from "./style-predefines";
|
||||
|
||||
export const globalStyle = css`
|
||||
@import-normalize;
|
||||
|
||||
:root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 62.5%;
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
`;
|
||||
export const globalStyle = (theme) =>
|
||||
css({
|
||||
[":root"]: {
|
||||
colorScheme: "light dark",
|
||||
fontFamily: "Inter, Avenir, Helvetica, Arial, sans-serif",
|
||||
fontSize: 0.625,
|
||||
fontSynthesis: "none",
|
||||
textRendering: "optimizeLegibility",
|
||||
WebkitFontSmoothing: "antialiased",
|
||||
MozOsxFontSmoothing: "grayscale",
|
||||
WebkitTextSizeAdjust: "100%",
|
||||
backgroundColor: theme.backgroundColor.light,
|
||||
[mq.dark]: {
|
||||
backgroundColor: theme.backgroundColor.dark,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
104
src/style-predefines.tsx
Normal file
104
src/style-predefines.tsx
Normal file
|
@ -0,0 +1,104 @@
|
|||
import { css, Elevation, FontSizeUnit, MeasureUnit, Theme } from "@emotion/react";
|
||||
import chroma from "chroma-js";
|
||||
import type { Property } from "csstype";
|
||||
|
||||
export function generatePalette(lightest: string, darkest: string): ColorPalette {
|
||||
return chroma.scale([lightest, darkest]).mode("lch").colors(10, "hex");
|
||||
}
|
||||
|
||||
export const mq = {
|
||||
dark: `@media (prefers-color-scheme: dark)`,
|
||||
[576]: `@media (min-width: 576px)`,
|
||||
[768]: `@media (min-width: 768px)`,
|
||||
[992]: `@media (min-width: 992px)`,
|
||||
[1200]: `@media (min-width: 1200px)`,
|
||||
};
|
||||
|
||||
function transformShadowDefine(
|
||||
shadow: Elevation,
|
||||
shadowColor?: chroma.Color = chroma.hsl(0, 0, 0)
|
||||
): string[] {
|
||||
return [
|
||||
`${shadow.offset.width}px`,
|
||||
`${shadow.offset.height}px`,
|
||||
`${shadow.blur}px`,
|
||||
shadowColor.alpha(shadow.opacity).hex(),
|
||||
];
|
||||
}
|
||||
|
||||
export function elevation(theme: Theme, level: MeasureUnit) {
|
||||
return css({ boxShadow: transformShadowDefine(theme.elevations[level]) });
|
||||
}
|
||||
|
||||
export function flex(
|
||||
theme: Theme,
|
||||
direction: Property.FlexDirection = "row",
|
||||
justify: Property.JustifyContent = "flex-start",
|
||||
align: Property.AlignItems = "start",
|
||||
wrap: Property.FlexWrap = "nowrap",
|
||||
gap: MeasureUnit = "none"
|
||||
) {
|
||||
return css({
|
||||
display: "flex",
|
||||
flexDirection: direction,
|
||||
justifyContent: justify,
|
||||
alignItems: align,
|
||||
flexWrap: wrap,
|
||||
gap: `${theme.spacings[gap]}px`,
|
||||
});
|
||||
}
|
||||
|
||||
export function paddingHorizontal(theme: Theme, padding: MeasureUnit | number = "none") {
|
||||
switch (typeof padding) {
|
||||
case "number":
|
||||
return css({ paddingLeft: padding, paddingRight: padding });
|
||||
case "string":
|
||||
return css({
|
||||
paddingLeft: theme.spacings[padding],
|
||||
paddingRight: theme.spacings[padding],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function paddingVertical(theme: Theme, padding: MeasureUnit | number = "none") {
|
||||
switch (typeof padding) {
|
||||
case "number":
|
||||
return css({ paddingTop: padding, paddingBottom: padding });
|
||||
case "string":
|
||||
return css({
|
||||
paddingTop: theme.spacings[padding],
|
||||
paddingBottom: theme.spacings[padding],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function marginHorizontal(theme: Theme, margin: MeasureUnit | number = "none") {
|
||||
switch (typeof margin) {
|
||||
case "number":
|
||||
return css({ marginLeft: margin, marginRight: margin });
|
||||
case "string":
|
||||
return css({
|
||||
marginLeft: theme.spacings[margin],
|
||||
marginRight: theme.spacings[margin],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function marginVertical(theme: Theme, margin: MeasureUnit | number = "none") {
|
||||
switch (typeof margin) {
|
||||
case "number":
|
||||
return css({ marginTop: margin, marginBottom: margin });
|
||||
case "string":
|
||||
return css({
|
||||
marginTop: theme.spacings[margin],
|
||||
marginBottom: theme.spacings[margin],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function Typography(theme: Theme, fontSize: FontSizeUnit, lineHeightRatio: number = 1.3) {
|
||||
return css({
|
||||
fontSize: theme.fontSizes[fontSize],
|
||||
lineHeight: theme.fontSizes[fontSize] * lineHeightRatio,
|
||||
});
|
||||
}
|
142
src/theme.tsx
Normal file
142
src/theme.tsx
Normal file
|
@ -0,0 +1,142 @@
|
|||
import type { Theme } from "@emotion/react";
|
||||
import { generatePalette } from "./style-predefines";
|
||||
|
||||
const colors: Theme["colors"] = {
|
||||
dark: generatePalette("#c9c9c9", "#141414"),
|
||||
gray: generatePalette("#f8f9fa", "#212529"),
|
||||
red: generatePalette("#fff5f5", "#c92a2a"),
|
||||
pink: generatePalette("#fff0f6", "#a61e4d"),
|
||||
grape: generatePalette("#f8f0fc", "#862e9c"),
|
||||
violet: generatePalette("#f3f0ff", "#5f3dc4"),
|
||||
indigo: generatePalette("#edf2ff", "#364fc7"),
|
||||
bllue: generatePalette("#e7f5ff", "#1864ab"),
|
||||
cyan: generatePalette("#e3fafc", "#0b7285"),
|
||||
teal: generatePalette("#e6fcf5", "#087f5b"),
|
||||
green: generatePalette("#ebfbee", "#2b8a3e"),
|
||||
lime: generatePalette("#f4fce3", "#5c940d"),
|
||||
yellow: generatePalette("#fff9db", "#e67700"),
|
||||
orange: generatePalette("#fff4e6", "#d9480f"),
|
||||
};
|
||||
|
||||
export const theme: Partial<Theme> = {
|
||||
colors,
|
||||
white: "#ffffff",
|
||||
black: "#000000",
|
||||
foregroundColor: {
|
||||
light: chroma.hsl(0, 0, 0.06).hex(),
|
||||
dark: chroma.hsl(0, 0, 0.88).hex(),
|
||||
},
|
||||
backgroundColor: {
|
||||
light: chroma.hsl(0, 0, 0.96).hex(),
|
||||
dark: chroma.hsl(0, 0, 0.18).hex(),
|
||||
},
|
||||
successColor: {
|
||||
light: colors.green[5],
|
||||
dark: colors.green[7],
|
||||
},
|
||||
warnColor: {
|
||||
light: colors.yellow[5],
|
||||
dark: colors.yellow[7],
|
||||
},
|
||||
dangerColor: {
|
||||
light: colors.red[5],
|
||||
dark: colors.red[7],
|
||||
},
|
||||
infoColor: {
|
||||
light: colors.blue[5],
|
||||
dark: colors.blue[7],
|
||||
},
|
||||
spacings: {
|
||||
none: 0,
|
||||
xxs: 2,
|
||||
xs: 4,
|
||||
sm: 8,
|
||||
md: 16,
|
||||
lg: 24,
|
||||
xl: 32,
|
||||
xxl: 40,
|
||||
},
|
||||
radius: {
|
||||
none: 0,
|
||||
xxs: 1,
|
||||
xs: 2,
|
||||
sm: 4,
|
||||
md: 8,
|
||||
lg: 16,
|
||||
xl: 24,
|
||||
xxl: 32,
|
||||
},
|
||||
fontSizes: {
|
||||
fp: 56,
|
||||
fps: 48,
|
||||
f1: 34.7,
|
||||
f1s: 32,
|
||||
f2: 29.3,
|
||||
f2s: 24,
|
||||
f3: 21.3,
|
||||
f3s: 20,
|
||||
f4: 18.7,
|
||||
f4s: 16,
|
||||
f5: 14,
|
||||
f5s: 12,
|
||||
f6: 10,
|
||||
f6s: 8.7,
|
||||
f7: 7.3,
|
||||
f7s: 6.7,
|
||||
},
|
||||
paragraphFontSize: 14,
|
||||
titleFontSize: {
|
||||
h1: 56,
|
||||
h2: 34.7,
|
||||
h3: 29.3,
|
||||
h4: 21.3,
|
||||
h5: 18.7,
|
||||
h6: 14,
|
||||
},
|
||||
elevationColor: {
|
||||
light: chroma.hsl(0, 0, 0).alpha(0.2).hex(),
|
||||
dark: chroma.hsl(0, 0, 0).alpha(0.2).hex(),
|
||||
},
|
||||
elevations: {
|
||||
none: {
|
||||
offset: { width: 0, height: 0 },
|
||||
blur: 0,
|
||||
opacity: 0,
|
||||
},
|
||||
xxs: {
|
||||
offset: { width: 1, height: 1 },
|
||||
blur: 2,
|
||||
opacity: 0.2,
|
||||
},
|
||||
xs: {
|
||||
offset: { width: 2, height: 2 },
|
||||
blur: 4,
|
||||
opacity: 0.2,
|
||||
},
|
||||
sm: {
|
||||
offset: { width: 3, height: 3 },
|
||||
blur: 6,
|
||||
opacity: 0.2,
|
||||
},
|
||||
md: {
|
||||
offset: { width: 4, height: 4 },
|
||||
blur: 8,
|
||||
opacity: 0.2,
|
||||
},
|
||||
lg: {
|
||||
offset: { width: 5, height: 5 },
|
||||
blur: 10,
|
||||
opacity: 0.2,
|
||||
},
|
||||
xl: {
|
||||
offset: { width: 6, height: 6 },
|
||||
blur: 12,
|
||||
opacity: 0.2,
|
||||
},
|
||||
xxl: {
|
||||
offset: { width: 7, height: 7 },
|
||||
blur: 14,
|
||||
opacity: 0.2,
|
||||
},
|
||||
},
|
||||
};
|
69
src/typings/theme.d.ts
vendored
Normal file
69
src/typings/theme.d.ts
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
import "@emotion/react";
|
||||
|
||||
declare module "@emotion/react" {
|
||||
export type ColorName =
|
||||
| "dark"
|
||||
| "gray"
|
||||
| "red"
|
||||
| "pink"
|
||||
| "grape"
|
||||
| "violet"
|
||||
| "indigo"
|
||||
| "blue"
|
||||
| "cyan"
|
||||
| "teal"
|
||||
| "green"
|
||||
| "lime"
|
||||
| "yellow"
|
||||
| "orange";
|
||||
export type ColorScheme = "light" | "dark";
|
||||
export type MeasureUnit = "none" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
|
||||
export type FontSizeUnit =
|
||||
| "fp"
|
||||
| "fps"
|
||||
| "f1"
|
||||
| "f1s"
|
||||
| "f2"
|
||||
| "f2s"
|
||||
| "f3"
|
||||
| "f3s"
|
||||
| "f4"
|
||||
| "f4s"
|
||||
| "f5"
|
||||
| "f5s"
|
||||
| "f6"
|
||||
| "f6s"
|
||||
| "f7"
|
||||
| "f7s";
|
||||
export type TitleLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
||||
export type ColorPalette = Array<string>;
|
||||
export type Elevation = {
|
||||
offset: {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
blur: number;
|
||||
opacity: number;
|
||||
};
|
||||
|
||||
export interface Theme {
|
||||
colors: Record<ColorName, ColorPalette>;
|
||||
black: string;
|
||||
white: string;
|
||||
primaryColor: Record<ColorScheme, ColorPalette>;
|
||||
secondaryColor: Record<ColorScheme, ColorPalette>;
|
||||
backgroundColor: Record<ColorScheme, string>;
|
||||
foregroundColor: Record<ColorScheme, string>;
|
||||
successColor: Record<ColorScheme, string>;
|
||||
warnColor: Record<ColorScheme, string>;
|
||||
dangerColor: Record<ColorScheme, string>;
|
||||
infoColor: Record<ColorScheme, string>;
|
||||
spacings: Record<MeasureUnit, number>;
|
||||
radius: Record<MeasureUnit, number>;
|
||||
fontSizes: Record<FontSizeUnit, number>;
|
||||
paragraphFontSize: number;
|
||||
titleFontSize: Record<TitleLevel, number>;
|
||||
elevations: Record<MeasureUnit, Elevation>;
|
||||
elevationColor: Record<ColorScheme, string>;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user