theme-ui#useThemeUI JavaScript Examples
The following examples show how to use
theme-ui#useThemeUI.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: invert-wrapper.jsx From MDXP with MIT License | 6 votes |
InvertWrapper = ({children}) => {
const {theme} = useThemeUI();
return (
<ThemeProvider theme={{colors: {background: theme.colors.text, text: theme.colors.background}}}>
{children}
</ThemeProvider>
);
}
Example #2
Source File: image.js From proof-of-humanity-web with MIT License | 6 votes |
Image = forwardRef((props, ref) => {
const { theme } = useThemeUI();
const { width, height } = theme.images?.[props.variant] ?? {};
return props.src ? (
<_Image ref={ref} {...props} />
) : (
<ReactLoadingSkeleton
circle={props.variant === "avatar"}
{...props}
width={props.width || width}
height={props.height || height}
/>
);
})
Example #3
Source File: flex.jsx From MDXP with MIT License | 5 votes |
Flex = ({
children,
sx = {},
variant,
display,
width,
height,
flexDirection,
flexWrap,
flexFlow,
justifyContent,
alignItems,
alignContent,
...props
}) => {
const {theme} = useThemeUI();
// Setup variant
let variantValue = {};
if ((typeof variant === 'string' || variant instanceof String)) {
variant = 'mdxp.flex.' + variant;
variantValue = variant.split('.').reduce((acc, val) => acc?.[val], theme) || {};
}
if (sx.variant && (typeof sx.variant === 'string' || sx.variant instanceof String)) {
variantValue = sx.variant.split('.').reduce((acc, val) => acc?.[val], theme) || {};
}
// Default values
display = display ?? variantValue.display ?? 'flex';
width = width ?? variantValue.width ?? '100%';
return (
<Block
sx={{
variant,
display,
width,
height,
flexDirection,
flexWrap,
flexFlow,
justifyContent,
alignItems,
alignContent,
...sx
}}
{...props}
>
{children}
</Block>
);
}
Example #4
Source File: grid.jsx From MDXP with MIT License | 4 votes |
Grid = ({
children,
sx = {},
variant,
display,
width,
height,
grid,
gridTemplateColumns,
gridTemplateRows,
gridTemplateAreas,
gridTemplate,
gridColumnGap,
gridRowGap,
gridGap,
justifyItems,
alignItems,
placeItems,
justifyContent,
alignContent,
placeContent,
gridAutoColumns,
gridAutoRows,
gridAutoFlow,
...props
}) => {
const {theme} = useThemeUI();
// Setup variant
let variantValue = {};
if ((typeof variant === 'string' || variant instanceof String)) {
variant = 'mdxp.grid.' + variant;
variantValue = variant.split('.').reduce((acc, val) => acc?.[val], theme) || {};
}
if (sx.variant && (typeof sx.variant === 'string' || sx.variant instanceof String)) {
variantValue = sx.variant.split('.').reduce((acc, val) => acc?.[val], theme) || {};
}
// Default values
display = display ?? variantValue.display ?? 'grid';
width = width ?? variantValue.width ?? '100%';
height = height ?? variantValue.height ?? '100%';
if (Array.isArray(gridTemplateAreas)) {
gridTemplateAreas = '"' + gridTemplateAreas.join('" "') + '"';
} else if (gridTemplateAreas && !gridTemplateAreas.match(/^['"].*['"]$/)) {
gridTemplateAreas = '"' + gridTemplateAreas + '"';
}
return (
<Block
sx={{
variant,
display,
width,
height,
grid,
gridTemplateColumns,
gridTemplateRows,
gridTemplateAreas,
gridTemplate,
gridColumnGap,
gridRowGap,
gridGap,
justifyItems,
alignItems,
placeItems,
justifyContent,
alignContent,
placeContent,
gridAutoColumns,
gridAutoRows,
gridAutoFlow,
...sx
}}
{...props}
>
{children}
</Block>
);
}
Example #5
Source File: presenter-tools.jsx From MDXP with MIT License | 4 votes |
NavigationButtons = ({sx = {}, ...props}) => {
const {theme} = useThemeUI();
const color = theme?.mdxp?.presenter?.color ?? 'white';
const deck = useDeck();
const {next, nextSlide, previous, previousSlide, navigate} = useNavigation();
return (
<div
sx={{
variant: 'mdxp.presenter',
display: 'flex',
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
'& > button': {
width: 'auto',
height: '75%',
mx: '5px',
cursor: 'hand',
bg: 'transparent',
border: 'none'
},
'& > span': {
mx: '30px'
},
...sx
}}
{...props}
>
<button
onClick={() => navigate({slide: 0, step: 0, mode: deckModes.PRESENTER})}
onMouseDown={e => e.preventDefault()}
>
<svg
xmlns="http://www.w3.org/2000/svg"
sx={{height: '100%', width: 'auto'}}
width="66px" height="66px" viewBox="0 0 66 66"
fill="none"
>
<circle r="30.5" transform="matrix(-1 0 0 1 33 33)" stroke={color} strokeWidth="5"/>
<path d="M33.2078 32.8312l12.3094-6.7115v-5.8898L27.0637 30.3735v4.9789l18.4535 10.1648v-5.911l-12.3094-6.775zM20.2299 45.5172h4.0459V20.2299h-4.0459v25.2873z" fill={color}/>
</svg>
</button>
<button onClick={() => previousSlide()} onMouseDown={e => e.preventDefault()}>
<svg
xmlns="http://www.w3.org/2000/svg"
sx={{height: '100%', width: 'auto'}}
width="66px" height="66px" viewBox="0 0 66 66"
fill="none"
>
<circle r="30.5" transform="matrix(-1 0 0 1 33 33)" stroke={color} strokeWidth="5"/>
<path d="M40.5412 32.8312l12.3094-6.7115v-5.8898L34.3971 30.3735v4.9789l18.4535 10.1648v-5.911l-12.3094-6.775zM20.3113 32.8312l12.3094-6.7115v-5.8898L14.1672 30.3735v4.9789l18.4535 10.1648v-5.911l-12.3094-6.775z" fill={color}/>
</svg>
</button>
<button onClick={() => previous()} onMouseDown={e => e.preventDefault()}>
<svg
xmlns="http://www.w3.org/2000/svg"
sx={{height: '100%', width: 'auto'}}
width="66px" height="66px" viewBox="0 0 66 66"
fill="none"
>
<circle r="30.125" transform="matrix(-1 0 0 1 32.625 32.625)" stroke={color} strokeWidth="5"/>
<path d="M29.0805 32.4581L41.25 25.8229V20L23.0062 30.0284v4.9223L41.25 45v-5.8439l-12.1695-6.698z" fill={color} />
</svg>
</button>
<span>{deck.slideIndex + 1} / {deck.slideLength}</span>
<button onClick={() => next()} onMouseDown={e => e.preventDefault()}>
<svg
xmlns="http://www.w3.org/2000/svg"
sx={{height: '100%', width: 'auto'}}
width="66px" height="66px" viewBox="0 0 66 66"
fill="none"
>
<circle cx="32.625" cy="32.625" r="30.125" stroke={color} strokeWidth="5"/>
<path d="M36.1695 32.4581L24 25.8229V20l18.2438 10.0284v4.9223L24 45v-5.8439l12.1695-6.698z" fill={color} />
</svg>
</button>
<button onClick={() => nextSlide()} onMouseDown={e => e.preventDefault()}>
<svg
xmlns="http://www.w3.org/2000/svg"
sx={{height: '100%', width: 'auto'}}
width="66px" height="66px" viewBox="0 0 66 66"
fill="none"
>
<circle cx="32.625" cy="32.625" r="30.125" stroke={color} strokeWidth="5"/>
<path d="M26.1695 32.4581L14 25.8229V20l18.2438 10.0284v4.9223L14 45v-5.8439l12.1695-6.698zm20 0L34 25.8229V20l18.2438 10.0284v4.9223L34 45v-5.8439l12.1695-6.698z" fill={color} />
</svg>
</button>
<button
onClick={() => navigate({slide: -1, step: -1, mode: deckModes.PRESENTER})}
onMouseDown={e => e.preventDefault()}
>
<svg
xmlns="http://www.w3.org/2000/svg"
sx={{height: '100%', width: 'auto'}}
width="66px" height="66px" viewBox="0 0 66 66"
fill="none"
>
<circle cx="32.625" cy="32.625" r="30.125" stroke={color} strokeWidth="5"/>
<path d="M32.1695 32.4581L20 25.8229V20l18.2438 10.0284v4.9223L20 45v-5.8439l12.1695-6.698zM45 45h-4V20h4v25z" fill={color} />
</svg>
</button>
</div>
);
}
Example #6
Source File: presenter-tools.jsx From MDXP with MIT License | 4 votes |
Time = ({sx = {}, keyboardTarget, ...props}) => {
const {theme} = useThemeUI();
const color = theme?.mdxp?.presenter?.color || 'white';
const [timer, setTimer] = useState(0);
const [play, setPlay] = useState(false);
const [datetime, setDatetime] = useState('00:00');
useLayoutEffect(() => {
const date = new Date();
setDatetime(hhmmss(date.getHours(), date.getMinutes()));
const dateUpdate = setInterval(() => {
const date = new Date();
setDatetime(hhmmss(date.getHours(), date.getMinutes()));
}, 5000);
return () => clearInterval(dateUpdate);
}, []);
useEffect(() => {
if (play) {
const timerUpdate = setInterval(() => {
setTimer(t => t + 1);
}, 1000);
return () => clearInterval(timerUpdate);
}
}, [play]);
const handleKeyboard = e => {
const {metaKey, ctrlKey, altKey} = e;
if (metaKey || ctrlKey) {
return;
}
if (altKey) {
if (e.keyCode === 84) {
setPlay(s => !s);
} else if (e.keyCode === 82) {
setPlay(false);
setTimer(0);
}
}
};
useEffect(() => {
const currentTarget = (keyboardTarget && keyboardTarget.hasOwnProperty('current')) ? keyboardTarget.current : keyboardTarget;
if (currentTarget) {
currentTarget.addEventListener('keydown', handleKeyboard);
}
return () => {
if (currentTarget) {
currentTarget.removeEventListener('keydown', handleKeyboard);
}
};
}, [keyboardTarget]);
return (
<div
sx={{
variant: 'mdxp.presenter',
width: '100%',
height: '100%',
display: 'flex',
flexFlow: 'column nowrap',
justifyContent: 'flex-end',
'&>div:first-child': {
fontWeight: '300'
},
'&>div:last-child': {
width: '100%',
display: 'flex',
fontSize: '2em',
alignItems: 'baseline',
justifyContent: 'flex-start',
'&>button': {
bg: 'transparent',
border: 'none',
cursor: 'hand',
mx: '5px'
},
'& div:first-child': {
mr: '10px'
}
},
...sx
}}
{...props}
>
<div>{datetime}</div>
<div>
<div>{hhmmss(...toHMS(timer), ' : ')}</div>
<button onClick={() => setPlay(!play)} onMouseDown={e => e.preventDefault()}>
<svg height="2em" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
{play ?
(<path fillRule="evenodd" clipRule="evenodd" d="M7 25V0h3.3333v25H7zm8.6667 0V0H19v25h-3.3333z" fill={color} />) :
(<path d="M1 23.3333V1.5702l21.7631 10.1561L1 23.3333z" stroke={color} strokeWidth="2"/>)
}
</svg>
</button>
<button
onClick={() => {
setPlay(false);
setTimer(0);
}}
onMouseDown={e => e.preventDefault()}
>
<svg height="2em" viewBox="0 0 22 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.41177 4.41176L11.0294 0v2.94118c2.1814 0 4.3138.64686 6.1276 1.85879 1.8138 1.21192 3.2275 2.93448 4.0623 4.94984.8347 2.01539 1.0532 4.23299.6276 6.37249-.4256 2.1395-1.476 4.1048-3.0185 5.6473-1.5425 1.5424-3.5078 2.5929-5.6473 3.0185-2.1395.4255-4.3571.2071-6.37246-.6277-2.01536-.8348-3.73792-2.2484-4.94985-4.0622C.646864 18.2844 0 16.152 0 13.9706h2c0 1.7858.52957 3.5316 1.52173 5.0165.99216 1.4848 2.40237 2.6422 4.05227 3.3256 1.64991.6834 3.4654.8622 5.217.5138 1.7515-.3484 3.3604-1.2084 4.6232-2.4712 1.2628-1.2627 2.1227-2.8716 2.4711-4.6232.3484-1.7515.1696-3.567-.5138-5.2169-.6834-1.64993-1.8407-3.06013-3.3256-4.05229-1.4849-.99217-3.2306-1.52173-5.0165-1.52173v3.88235L4.41177 4.41176z" fill={color} />
</svg>
</button>
</div>
</div>
);
}
Example #7
Source File: Header.jsx From nextjs-prismic-blog-starter with MIT License | 4 votes |
Header = () => {
const {theme, colorMode, setColorMode} = useThemeUI()
return (
<Headroom disableInlineStyles upTolerance={10} downTolerance={10}>
<header style={{background: `${theme.colors.muted}`}} className='header'>
<div className='header-content'>
<div>
<Styled.h1 style={{margin: '0'}}>
<NextLink href='/' passHref>
<Styled.a
style={{
textDecoration: 'none',
fontFamily: 'Damion',
letterSpacing: '0.15rem',
}}
onClick={() =>
trackGAEvent('logo', `clicked on site logo`, 'link click')
}
rel='noreferrer noopener'>
Blog
</Styled.a>
</NextLink>
</Styled.h1>
</div>
<div className='header-links'>
{/* <Styled.h2 style={{ margin: "0 1rem" }}>
<Styled.a as={Link} to="/">
Tags
</Styled.a>
</Styled.h2> */}
{/* <p>
<GoSearch
title="Search"
style={{
fontSize: "1.2rem",
verticalAlign: "middle",
marginTop: "0.2rem",
}}
/>
</p> */}
<p>
{colorMode === 'light' ? (
<span
title='Switch to Dark Mode'
aria-label='Switch to Dark Mode'>
<FiSun
className='theme-icon'
onClick={() => {
setColorMode('dark')
trackGAEvent(
'toggle theme',
`enabled dark theme`,
'icon click'
)
}}
/>
</span>
) : (
<span
title='Switch to Light Mode'
aria-label='Switch to Light Mode'>
<FiMoon
className='theme-icon'
onClick={() => {
setColorMode('light')
trackGAEvent(
'toggle theme',
`enabled light theme`,
'icon click'
)
}}
/>
</span>
)}
</p>
</div>
</div>
</header>
</Headroom>
)
}
Example #8
Source File: Listing.jsx From nextjs-prismic-blog-starter with MIT License | 4 votes |
Listing = ({articles}) => {
const {theme} = useThemeUI()
const GridLayout = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, 325px);
grid-template-rows: auto;
grid-gap: 1.25rem;
justify-content: center;
margin: auto;
@media (max-width: ${theme.breakpoints[0]}) {
grid-template-columns: 1fr;
}
`
const ArticleCard = styled.div`
display: grid;
grid-template-columns: 325px;
grid-template-rows: 200px auto;
grid-gap: 0;
margin: 0 auto;
border-radius: 25px;
box-shadow: inset -5px -5px 12px ${theme.colors.shade1},
inset 5px 5px 12px ${theme.colors.shade2};
`
return (
<GridLayout>
{articles.map((article) => (
<ArticleCard
aria-label={`Read article ${article.uid}`}
title={article.uid}
key={article.uid}>
<div style={{overflow: 'hidden'}}>
<NextLink
href={hrefResolver(article)}
as={linkResolver(article)}
passHref>
<a>
<Image
src={article.data.article_image.url}
alt={article.data.article_image.alt}
title={article.data.article_image.alt}
layout='responsive'
width={article.data.article_image.dimensions.width}
height={article.data.article_image.dimensions.height}
className='article-image'
/>
</a>
</NextLink>
</div>
<div
sx={{
px: 3,
py: 2,
'@media (max-width: 30rem)': {
px: 3,
},
}}>
<h2
sx={{
m: 0,
pt: 0,
minHeight: '5rem',
fontSize: [2, 3],
'@media (max-width: 30rem)': {
pt: 0,
height: 'auto',
},
}}>
<NextLink
href={hrefResolver(article)}
as={linkResolver(article)}
passHref>
<a
sx={{
color: 'inherit',
textDecoration: 'none',
':hover,:focus': {
color: 'secondary',
textDecoration: 'underline',
cursor: 'pointer',
},
}}
onClick={() =>
trackGAEvent(
'home',
`clicked on ${article.uid} article title`,
'text click'
)
}
rel='noreferrer noopener'>
{RichText.asText(article.data.title)}
</a>
</NextLink>
</h2>
<p
sx={{
my: 0,
fontSize: [1, 2],
height: '5.5rem',
'@media screen and (max-width: 30rem)': {
height: 'auto',
},
}}>
{truncateText(`${RichText.asText(article.data.excerpt)}`)}
<NextLink
href={hrefResolver(article)}
as={linkResolver(article)}
passHref>
<a
sx={{variant: 'styles.a'}}
aria-label={`Read the article on ${RichText.asText(
article.data.title
)}`}
title={`Read the article on ${RichText.asText(
article.data.title
)}`}
onClick={() =>
trackGAEvent(
'home',
`clicked on ${article.uid} read full article`,
'link click'
)
}
rel='noreferrer noopener'>
Read Full Article
</a>
</NextLink>
</p>
<div
sx={{
display: 'flex',
flexFlow: 'row wrap',
justifyContent: 'flex-start',
alignItems: 'center',
margin: '0 auto 0 -0.25rem',
}}>
{article.data.categories.map(({slug}, index) => {
return (
slug && (
<Chip
name={slug}
slug={slug}
type='category'
page='listing'
key={index}
onClick={() =>
trackGAEvent('home', `clicked on ${slug}`, 'chip click')
}
/>
)
)
})}
</div>
<p
sx={{
fontSize: 0,
mb: 1,
py: 1,
}}>
<em
title={`Article posted on ${formatDate(article.data.created)}`}
aria-label={`Article posted on ${formatDate(
article.data.created
)}`}>
{formatDate(article.data.created)}
</em>
<span sx={{mx: 2, fontSize: '10px'}}>|</span>
<em
title='Time to read the article'
aria-label='Time to read the article'>
<FiClock style={{marginBottom: '-0.15rem'}} />
{article.data.read_time} min read
</em>
</p>
</div>
</ArticleCard>
))}
</GridLayout>
)
}
Example #9
Source File: Code.jsx From nextjs-prismic-blog-starter with MIT License | 4 votes |
Code = ({data: {primary}}) => {
const {theme, colorMode} = useThemeUI()
const [copied, setCopied] = useState(false)
/**
* Toast
* language of the block copied to clipboard
* @param {String} lang
*/
const copyText = (lang) => {
// remove older toast and copied state
toast.dismiss()
setCopied(false)
// new toast and copied state
toast.info(`${lang.toUpperCase()} block copied to clipboard`, {
onOpen: () => {
setCopied(true)
},
onClose: () => {
setCopied(false)
},
})
}
const Button = styled.button`
color: ${theme.colors.text};
background: ${theme.colors.shade2};
padding: 0.25rem;
border: none;
font-family: ${theme.fonts.body};
letter-spacing: 1px;
cursor: pointer;
&:hover {
color: ${theme.colors.accent};
background: ${theme.colors.text};
}
`
return (
<Fragment>
<Highlight
{...defaultProps}
theme={colorMode === 'light' ? light : dark}
code={RichText.asText(primary.code)}
language={primary.lang}>
{({className, style, tokens, getLineProps, getTokenProps}) => (
<pre
className={className}
style={{
...style,
backgroundColor: theme.colors.code,
marginLeft: primary.type === 'List' ? '2.5rem' : null,
borderWidth: '1px',
borderStyle: 'solid',
borderColor: theme.colors.shade2,
borderRadius: '0.25rem',
}}>
<div
className={className}
style={{
...style,
margin: '-0.25rem auto 0.5rem auto',
textAlign: 'right',
color: theme.colors.accent,
backgroundColor: theme.colors.code,
}}>
<span>{primary.lang.toUpperCase()}</span>
<CopyToClipboard
text={primary.code.text}
onCopy={() => copyText(primary.lang)}
style={{margin: '0 0.5rem'}}>
{copied ? <span>Copied</span> : <Button>Copy</Button>}
</CopyToClipboard>
</div>
{tokens.map((line, i) => (
<div {...getLineProps({line, key: i})}>
{line.map((token, key) => (
<span {...getTokenProps({token, key})} />
))}
</div>
))}
</pre>
)}
</Highlight>
<ToastContainer
autoClose={2500}
closeOnClick
newestOnTop
pauseOnHover
transition={Slide}
draggable
role='alert'
/>
</Fragment>
)
}
Example #10
Source File: Gallery.jsx From nextjs-prismic-blog-starter with MIT License | 4 votes |
Gallery = ({data: {items}}) => {
const [modalIsOpen, setModalIsOpen] = useState(false)
const {theme} = useThemeUI()
const toggleModal = () => {
setModalIsOpen(!modalIsOpen)
}
const images = items.map(({image}) => {
return {
caption: image.alt,
alt: image.alt,
source: image.url,
}
})
const navigationStyle = {
backgroundColor: theme.colors.highlight,
color: theme.colors.text,
':hover': {
backgroundColor: theme.colors.gray,
},
}
const galleryStyles = {
header: (base, state) => ({
...base,
padding: 20,
}),
navigationPrev: (base) => ({
...base,
...navigationStyle,
}),
navigationNext: (base) => ({
...base,
...navigationStyle,
}),
view: () => ({
height: 'auto',
width: '100%',
margin: '0 auto -1rem auto',
backgroundColor: theme.colors.accent,
}),
footer: (base, state) => {
const opacity = state.interactionIsIdle ? 0 : 1
const transition = 'opacity 300ms'
return {
...base,
opacity,
transition,
fontFamily: theme.fonts.body,
fontSize: theme.fontSizes[(3, 4)],
}
},
}
return (
<Fragment>
<ModalGateway>
{modalIsOpen ? (
<Modal onClose={toggleModal}>
<Carousel views={images} styles={galleryStyles} />
</Modal>
) : null}
</ModalGateway>
<div
style={{
position: 'relative',
margin: '0 auto 2rem auto',
cursor: 'pointer',
borderRadius: '25px',
boxShadow: `inset -5px -5px 12px ${theme.colors.shade1},
inset 5px 5px 12px ${theme.colors.shade2}`,
overflow: 'hidden',
}}
onClick={toggleModal}>
{items && (
<Image
src={items[0].image.url}
alt={items[0].image.alt}
title={items[0].image.alt}
layout='responsive'
width={items[0].image.dimensions.width}
height={items[0].image.dimensions.height}
/>
)}
<p
style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 15,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#fff',
backgroundColor: 'rgba(0,0,0,0.3)',
borderWidth: '1px',
borderStyle: 'solid',
borderColor: '#f7f8f9',
borderRadius: '25px',
width: '200px',
height: '40px',
padding: '0.5rem',
margin: '0 auto 0 auto',
cursor: 'pointer',
zIndex: 10,
}}
onClick={toggleModal}>
View Gallery
</p>
</div>
</Fragment>
)
}