Everything goes through <Box>
// src/client/MyButton.tsx
import React from 'react';
import { Box } from 'pu2';
// Renders a <div> element with a button role
export const MyButton = ({ children, onClick }) => (
<Box
role="button"
cursor="pointer"
display="flex"
alignItems="center"
justifyContent="center"
onClick={onClick}
>
{children}
</Box>
);
// Renders a <button> element with some icon
export const MyButton2 = ({ children, icon, onClick }) => (
<Box as="button" onClick={onClick}>
{icon}
{children}
</Box>
);
// Passing some css as a prop will override style props (renders a black button with white text)
const css = { color: 'white', background: 'black' };
export const MyButton4 = ({ children, onClick }) => (
<Box color="orange" css={css} onClick={onClick}>
{children}
</Box>
);
// Get fancy. Generate classnames on-the-fly, including media queries and sub-selectors.
const css = {
color: 'lightblue',
// Match descendent children (notice the space before the selector)
' span': {
color: 'green',
'[data-value]': { color: 'silver' }, // Match attribute
'.x': { color: 'wheat' } // Match classname (no space before the selector)
},
' .b': { color: 'orange' },
// Match immediate children
'>span': { color: 'blue' },
'>.b': {
color: 'yellow',
':hover': { color: 'cyan' } // Match element state
},
// Match a media query
'@media screen and (max-width: 600px)': {
color: 'magenta',
'>span': { color: 'red' }
}
}
export const MyButton5 = ({ onClick, prefix }) => (
<Box css={css} onClick={onClick}>
lightblue...or magenta when <=600px screen width
<Box className="a">black</Box>
<Box as="span">
blue...or red when <=600px screen width
<Box className="b">orange</Box>
</Box>
<Box className="b">
yellow...or cyan when hovering
<Box as="span">green</Box>
<Box as="span" data-value="10">silver</Box>
<Box as="span" className="x">wheat</Box>
</Box>
<Box className="b">
</Box>
)
// src/client/App.ts
import React from 'react';
import { Box } from 'pu2/style-lib';
export const App = () => (
<Box background="blue" p="16px">
<Box color="red" background="white" p="8px">
Text
</Box>
</Box>
);
// src/client/main.client.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserStyleProvider } from 'pu2/style-lib';
import { App } from './App';
ReactDOM.hydrate(
<BrowserStyleProvider>
<App />
</BrowserStyleProvider>,
document.body
)
// src/server/main.server.ts
import React from 'react';
import express from 'express';
import { renderToString } from 'react-dom/server';
import { SSRStyleProvider, SSRStyleCollector } from 'pu2/style-lib/server';
import { App } from '../client/App';
const renderSSR = ({ appHtml, styleHtml }) => `
<!DOCTYPE html>
<html lang="en">
<head>
<title>My App</title>
${styleHtml}
</head>
<body>
${appHtml}
</body>
</html>
`;
const server = express();
server.get('/', async (req, res) => {
const collector = new SSRStyleCollector();
const appHtml = renderToString(
<SSRStyleProvider collector={collector}>
<App />
</SSRStyleProvider>
);
const styleHtml = collector.getHtml();
res.status(200)
.set({ 'Content-Type': 'text/html' })
.end(renderSSR({ appHtml, styleHtml }));
});
server.listen(3000);