@devseed-ui/theme-provider
Version:
devseed UI Kit Theme
191 lines (162 loc) • 4.1 kB
JavaScript
import React from 'react';
import { createGlobalStyle, css, ThemeProvider } from 'styled-components';
import { themeVal } from './utils';
import { theme } from './theme';
import { unscrollableY, unscrollableX } from './helpers';
// Global styles for these components are included here for performance reasons.
// This way they're only rendered when absolutely needed.
const baseStyles = css`
/**
* Based on
* https://hankchizljaw.com/wrote/a-modern-css-reset/
*/
/* Box sizing rules */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Set core root defaults */
html:focus-within {
scroll-behavior: smooth;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
/* Set default line-height */
* {
line-height: ${themeVal('type.base.line')};
}
/* Remove default margin */
body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol,
li,
figure,
blockquote,
dl,
dd {
margin: 0;
}
/* Remove list styles on ul, ol elements with a list role, which suggests
default styling will be removed */
ul[role='list'],
ol[role='list'] {
list-style: none;
padding: 0;
}
/* Set core <body> defaults */
body {
background-color: ${themeVal('color.background')};
color: ${themeVal('type.base.color')};
font-size: ${themeVal('type.base.size')};
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
font-family: ${themeVal('type.base.family')};
text-transform: ${themeVal('type.base.case')};
font-weight: ${themeVal('type.base.weight')};
font-style: ${themeVal('type.base.style')};
font-variation-settings: ${themeVal('type.base.settings')};
min-width: ${themeVal('layout.min')};
min-height: 100vh;
text-rendering: optimizeSpeed;
${({ theme }) =>
theme.type.base.antialiasing &&
css`
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
`}
}
/* Apply some default styles to <a> elements without a class */
a:not([class]) {
cursor: pointer;
color: ${themeVal('color.link')};
text-decoration: none;
transition: opacity 0.24s ease 0s;
&:visited {
color: ${themeVal('color.link')};
}
&:hover {
opacity: 0.64;
}
&:active {
transform: translate(0, 1px);
}
}
/* Make images easier to work with */
img,
picture {
max-width: 100%;
display: block;
}
/* Inherit fonts for <input> and <button> */
input,
button,
textarea,
select {
font: inherit;
}
/* Text-level semantics */
b,
strong {
font-weight: ${themeVal('type.base.bold')};
}
/* Remove all animations and transitions for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
html:focus-within {
scroll-behavior: auto;
}
*,
*::before,
*::after {
animation-duration: 0.01ms ;
animation-iteration-count: 1 ;
transition-duration: 0.01ms ;
scroll-behavior: auto ;
}
}
/* Misc */
::selection {
background-color: ${themeVal('color.base-400a')};
color: ${themeVal('color.surface')};
}
.tether-element {
z-index: 1000;
}
.unscrollable-y {
${unscrollableY()}
}
.unscrollable-x {
${unscrollableX()}
}
`;
const GlobalStyles = createGlobalStyle`
${baseStyles}
`;
/* eslint-disable react/prop-types */
const DevseedUiThemeProvider = ({
children,
theme: providedTheme,
...rest
}) => {
// If the user provided a function, pass the ui library theme to allow
// overrides. The resulting theme will be the used one.
const newTheme =
typeof providedTheme === 'function'
? providedTheme(theme.main)
: // If it's not a function, the provided theme is used,
// defaulting to the ui-library.
providedTheme || theme.main;
return (
<ThemeProvider theme={newTheme} {...rest}>
<GlobalStyles />
{children}
</ThemeProvider>
);
};
/* eslint-enable react/prop-types */
export { GlobalStyles, DevseedUiThemeProvider };