grid implementation
This commit is contained in:
parent
60a50babd1
commit
2150f3d96b
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2021 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Banner } from "./Banner";
|
||||||
|
import { Fragment, h } from "preact";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "mui/banner",
|
||||||
|
component: Banner,
|
||||||
|
};
|
||||||
|
|
||||||
|
function Wrapper({ children }: any) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
backgroundColor: "lightgray",
|
||||||
|
padding: 10,
|
||||||
|
width: "100%",
|
||||||
|
// width: 400,
|
||||||
|
// height: 400,
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ flexGrow: 1 }}>{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BasicExample = () => (
|
||||||
|
<Fragment>
|
||||||
|
<Wrapper>
|
||||||
|
<Banner />
|
||||||
|
</Wrapper>
|
||||||
|
</Fragment>
|
||||||
|
);
|
@ -1,33 +1,58 @@
|
|||||||
import { h, Fragment, VNode } from "preact";
|
import { h, Fragment, VNode } from "preact";
|
||||||
import { Divider } from "../mui/Divider";
|
import { Divider } from "../mui/Divider";
|
||||||
import { Button } from "./styled/index.js";
|
import { Button } from "../mui/Button";
|
||||||
import { Typography } from "../mui/Typography";
|
import { Typography } from "../mui/Typography";
|
||||||
import { Avatar } from "../mui/Avatar";
|
import { Avatar } from "../mui/Avatar";
|
||||||
import { Grid } from "../mui/Grid";
|
import { Grid } from "../mui/Grid";
|
||||||
import { Paper } from "../mui/Paper";
|
import { Paper } from "../mui/Paper";
|
||||||
|
import { Icon } from "./styled";
|
||||||
|
import settingsIcon from "../../static/img/settings_black_24dp.svg";
|
||||||
|
// & > a > div.settings-icon {
|
||||||
|
// mask: url(${settingsIcon}) no-repeat center;
|
||||||
|
// background-color: white;
|
||||||
|
// width: 24px;
|
||||||
|
// height: 24px;
|
||||||
|
// margin-left: auto;
|
||||||
|
// margin-right: 8px;
|
||||||
|
// padding: 4px;
|
||||||
|
// }
|
||||||
|
// & > a.active {
|
||||||
|
// background-color: #f8faf7;
|
||||||
|
// color: #0042b2;
|
||||||
|
// font-weight: bold;
|
||||||
|
// }
|
||||||
|
// & > a.active > div.settings-icon {
|
||||||
|
// background-color: #0042b2;
|
||||||
|
// }
|
||||||
|
|
||||||
function SignalWifiOffIcon(): VNode {
|
function SignalWifiOffIcon({ ...rest }: any): VNode {
|
||||||
return <Fragment />;
|
return <Icon {...rest} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Banner({}: {}) {
|
export function Banner({}: {}) {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Paper elevation={0} /*className={classes.paper}*/>
|
<Paper elevation={3} /*className={classes.paper}*/>
|
||||||
<Grid container wrap="nowrap" spacing={16} alignItems="center">
|
<Grid
|
||||||
<Grid item>
|
container
|
||||||
<Avatar /*className={classes.avatar}*/>
|
// wrap="nowrap"
|
||||||
<SignalWifiOffIcon />
|
// spacing={10}
|
||||||
|
alignItems="center"
|
||||||
|
columns={3}
|
||||||
|
>
|
||||||
|
<Grid item xs={1}>
|
||||||
|
<Avatar>
|
||||||
|
<SignalWifiOffIcon style={{ backgroundColor: "red" }} />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item xs={1}>
|
||||||
<Typography>
|
<Typography>
|
||||||
You have lost connection to the internet. This app is offline.
|
You have lost connection to the internet. This app is offline.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container justify="flex-end" spacing={8}>
|
<Grid container justifyContent="flex-end" spacing={8} columns={3}>
|
||||||
<Grid item>
|
<Grid item xs={1}>
|
||||||
<Button color="primary">Turn on wifi</Button>
|
<Button color="primary">Turn on wifi</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -826,6 +826,16 @@ export const NavigationHeader = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const Icon = styled.div`
|
||||||
|
mask: url(${settingsIcon}) no-repeat center;
|
||||||
|
background-color: gray;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: 8px;
|
||||||
|
padding: 4px;
|
||||||
|
`;
|
||||||
|
|
||||||
const image = `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`;
|
const image = `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`;
|
||||||
|
|
||||||
export const NiceSelect = styled.div`
|
export const NiceSelect = styled.div`
|
||||||
|
@ -1,5 +1,53 @@
|
|||||||
|
import { css } from "@linaria/core";
|
||||||
import { h, Fragment, VNode, ComponentChildren } from "preact";
|
import { h, Fragment, VNode, ComponentChildren } from "preact";
|
||||||
|
import { theme } from "./style";
|
||||||
|
|
||||||
export function Avatar({}: { children: ComponentChildren }): VNode {
|
const root = css`
|
||||||
return <Fragment />;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
font-family: ${theme.typography.fontFamily};
|
||||||
|
font-size: ${theme.typography.pxToRem(20)};
|
||||||
|
line-height: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
user-select: none;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const colorStyle = css`
|
||||||
|
color: ${theme.palette.background.default};
|
||||||
|
background-color: ${theme.palette.mode === "light"
|
||||||
|
? theme.palette.grey[400]
|
||||||
|
: theme.palette.grey[600]};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const avatarImageStyle = css`
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
object-fit: cover;
|
||||||
|
color: transparent;
|
||||||
|
text-indent: 10000;
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
variant?: "circular" | "rounded" | "square";
|
||||||
|
children?: ComponentChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Avatar({ variant, children, ...rest }: Props): VNode {
|
||||||
|
const borderStyle =
|
||||||
|
variant === "square"
|
||||||
|
? theme.shape.squareBorder
|
||||||
|
: variant === "rounded"
|
||||||
|
? theme.shape.roundBorder
|
||||||
|
: theme.shape.circularBorder;
|
||||||
|
return (
|
||||||
|
<div class={[root, borderStyle].join(" ")} {...rest}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ export function Button({
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
class={[
|
class={[
|
||||||
theme.typography.button,
|
theme.typography.button,
|
||||||
theme.shape.borderRadius,
|
theme.shape.roundBorder,
|
||||||
ripple,
|
ripple,
|
||||||
baseStyle,
|
baseStyle,
|
||||||
button,
|
button,
|
||||||
|
192
packages/taler-wallet-webextension/src/mui/Grid.stories.tsx
Normal file
192
packages/taler-wallet-webextension/src/mui/Grid.stories.tsx
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2021 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Grid } from "./Grid";
|
||||||
|
import { Fragment, h } from "preact";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "mui/grid",
|
||||||
|
component: Grid,
|
||||||
|
};
|
||||||
|
|
||||||
|
function Item({ children }: any) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: "white",
|
||||||
|
textAlign: "center",
|
||||||
|
color: "back",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Wrapper({ children }: any) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
backgroundColor: "lightgray",
|
||||||
|
padding: 10,
|
||||||
|
width: "100%",
|
||||||
|
// width: 400,
|
||||||
|
// height: 400,
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ flexGrow: 1 }}>{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BasicExample = () => (
|
||||||
|
<Fragment>
|
||||||
|
<Wrapper>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={8}>
|
||||||
|
<Item>xs=8</Item>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<Item>xs=4</Item>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<Item>xs=4</Item>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={8}>
|
||||||
|
<Item>xs=8</Item>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
<Wrapper>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={6} md={8}>
|
||||||
|
<Item>xs=6 md=8</Item>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} md={4}>
|
||||||
|
<Item>xs=6 md=4</Item>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} md={4}>
|
||||||
|
<Item>xs=6 md=4</Item>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} md={8}>
|
||||||
|
<Item>xs=6 md=8</Item>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Responsive12ColumnsSize = () => (
|
||||||
|
<Fragment>
|
||||||
|
<Wrapper>
|
||||||
|
<p>Item size is responsive: xs=6 sm=4 md=2</p>
|
||||||
|
<Grid container spacing={1} columns={12}>
|
||||||
|
{Array.from(Array(6)).map((_, index) => (
|
||||||
|
<Grid item xs={6} sm={4} md={2} key={index}>
|
||||||
|
<Item>item {index}</Item>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
<Wrapper>
|
||||||
|
<p>Item size is fixed</p>
|
||||||
|
<Grid container spacing={1} columns={12}>
|
||||||
|
{Array.from(Array(6)).map((_, index) => (
|
||||||
|
<Grid item xs={6} key={index}>
|
||||||
|
<Item>item {index}</Item>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Responsive12Spacing = () => (
|
||||||
|
<Fragment>
|
||||||
|
<Wrapper>
|
||||||
|
<p>Item space is responsive: xs=1 sm=2 md=3</p>
|
||||||
|
<Grid container spacing={{ xs: 2, sm: 4, md: 6 }} columns={12}>
|
||||||
|
{Array.from(Array(6)).map((_, index) => (
|
||||||
|
<Grid item xs={6} key={index}>
|
||||||
|
<Item>item {index}</Item>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
<Wrapper>
|
||||||
|
<p>Item space is fixed</p>
|
||||||
|
<Grid container spacing={1} columns={12}>
|
||||||
|
{Array.from(Array(6)).map((_, index) => (
|
||||||
|
<Grid item xs={6} key={index}>
|
||||||
|
<Item>item {index}</Item>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
|
||||||
|
<Wrapper>
|
||||||
|
<p>Item row space is responsive: xs=6 sm=4 md=1</p>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
rowSpacing={{ xs: 6, sm: 3, md: 1 }}
|
||||||
|
columnSpacing={1}
|
||||||
|
columns={12}
|
||||||
|
>
|
||||||
|
{Array.from(Array(6)).map((_, index) => (
|
||||||
|
<Grid item xs={6} key={index}>
|
||||||
|
<Item>item {index}</Item>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
<Wrapper>
|
||||||
|
<p>Item col space is responsive: xs=6 sm=3 md=1</p>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
columnSpacing={{ xs: 6, sm: 3, md: 1 }}
|
||||||
|
rowSpacing={1}
|
||||||
|
columns={12}
|
||||||
|
>
|
||||||
|
{Array.from(Array(6)).map((_, index) => (
|
||||||
|
<Grid item xs={6} key={index}>
|
||||||
|
<Item>item {index}</Item>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Example = () => (
|
||||||
|
<Wrapper>
|
||||||
|
<p>Item row space is responsive: xs=6 sm=4 md=1</p>
|
||||||
|
<Grid container rowSpacing={3} columnSpacing={1} columns={12}>
|
||||||
|
{Array.from(Array(6)).map((_, index) => (
|
||||||
|
<Grid item xs={6} key={index}>
|
||||||
|
<Item>item {index}</Item>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Wrapper>
|
||||||
|
);
|
@ -1,13 +1,241 @@
|
|||||||
import { h, Fragment, VNode, ComponentChildren } from "preact";
|
import { css } from "@linaria/core";
|
||||||
|
import { h, Fragment, VNode, ComponentChildren, createContext } from "preact";
|
||||||
|
import { useContext } from "preact/hooks";
|
||||||
|
import { theme } from "./style";
|
||||||
|
|
||||||
export function Grid({}: {
|
type ResponsiveKeys = "xs" | "sm" | "md" | "lg" | "xl";
|
||||||
|
|
||||||
|
export type ResponsiveSize = {
|
||||||
|
xs: number;
|
||||||
|
sm: number;
|
||||||
|
md: number;
|
||||||
|
lg: number;
|
||||||
|
xl: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const root = css`
|
||||||
|
box-sizing: border-box;
|
||||||
|
`;
|
||||||
|
const containerStyle = css`
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
const itemStyle = css`
|
||||||
|
margin: 0;
|
||||||
|
`;
|
||||||
|
const zeroMinWidthStyle = css`
|
||||||
|
min-width: 0px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
type GridSizes = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||||
|
type SpacingSizes = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
columns?: number | Partial<ResponsiveSize>;
|
||||||
container?: boolean;
|
container?: boolean;
|
||||||
wrap?: string;
|
|
||||||
item?: boolean;
|
item?: boolean;
|
||||||
spacing?: number;
|
|
||||||
alignItems?: string;
|
direction?: "column-reverse" | "column" | "row-reverse" | "row";
|
||||||
justify?: string;
|
|
||||||
|
lg?: GridSizes | "auto" | "true";
|
||||||
|
md?: GridSizes | "auto" | "true";
|
||||||
|
sm?: GridSizes | "auto" | "true";
|
||||||
|
xl?: GridSizes | "auto" | "true";
|
||||||
|
xs?: GridSizes | "auto" | "true";
|
||||||
|
|
||||||
|
wrap?: "nowrap" | "wrap-reverse" | "wrap";
|
||||||
|
spacing?: SpacingSizes | Partial<ResponsiveSize>;
|
||||||
|
columnSpacing?: SpacingSizes | Partial<ResponsiveSize>;
|
||||||
|
rowSpacing?: SpacingSizes | Partial<ResponsiveSize>;
|
||||||
|
|
||||||
|
alignItems?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline";
|
||||||
|
justifyContent?:
|
||||||
|
| "flex-start"
|
||||||
|
| "flex-end"
|
||||||
|
| "center"
|
||||||
|
| "space-around"
|
||||||
|
| "space-between"
|
||||||
|
| "space-evenly";
|
||||||
|
|
||||||
|
zeroMinWidth?: boolean;
|
||||||
children: ComponentChildren;
|
children: ComponentChildren;
|
||||||
}): VNode {
|
}
|
||||||
return <Fragment />;
|
theme.breakpoints.up;
|
||||||
|
|
||||||
|
function getOffset(val: number | string) {
|
||||||
|
if (typeof val === "number") `${val}px`;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnGapVariant = css`
|
||||||
|
${theme.breakpoints.up("xs")} {
|
||||||
|
width: calc(100% + var(--space-col-xs));
|
||||||
|
margin-left: calc(-1 * var(--space-col-xs));
|
||||||
|
& > div {
|
||||||
|
padding-left: var(--space-col-xs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${theme.breakpoints.up("sm")} {
|
||||||
|
width: calc(100% + var(--space-col-sm));
|
||||||
|
margin-left: calc(-1 * var(--space-col-sm));
|
||||||
|
& > div {
|
||||||
|
padding-left: var(--space-col-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${theme.breakpoints.up("md")} {
|
||||||
|
width: calc(100% + var(--space-col-md));
|
||||||
|
margin-left: calc(-1 * var(--space-col-md));
|
||||||
|
& > div {
|
||||||
|
padding-left: var(--space-col-md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const rowGapVariant = css`
|
||||||
|
${theme.breakpoints.up("xs")} {
|
||||||
|
margin-top: calc(-1 * var(--space-row-xs));
|
||||||
|
& > div {
|
||||||
|
padding-top: var(--space-row-xs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${theme.breakpoints.up("sm")} {
|
||||||
|
margin-top: calc(-1 * var(--space-row-sm));
|
||||||
|
& > div {
|
||||||
|
padding-top: var(--space-row-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${theme.breakpoints.up("md")} {
|
||||||
|
margin-top: calc(-1 * var(--space-row-md));
|
||||||
|
& > div {
|
||||||
|
padding-top: var(--space-row-md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const sizeVariant = css`
|
||||||
|
${theme.breakpoints.up("xs")} {
|
||||||
|
flex-basis: var(--relation-col-vs-xs);
|
||||||
|
flex-grow: 0;
|
||||||
|
max-width: var(--relation-col-vs-xs);
|
||||||
|
}
|
||||||
|
${theme.breakpoints.up("sm")} {
|
||||||
|
flex-basis: var(--relation-col-vs-sm);
|
||||||
|
flex-grow: 0;
|
||||||
|
max-width: var(--relation-col-vs-sm);
|
||||||
|
}
|
||||||
|
${theme.breakpoints.up("md")} {
|
||||||
|
flex-basis: var(--relation-col-vs-md);
|
||||||
|
flex-grow: 0;
|
||||||
|
max-width: var(--relation-col-vs-md);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const GridContext = createContext<ResponsiveSize>(toResponsive(12));
|
||||||
|
|
||||||
|
function toResponsive(v: number | Partial<ResponsiveSize>): ResponsiveSize {
|
||||||
|
const p = typeof v === "number" ? { xs: v } : v;
|
||||||
|
const xs = p.xs || 12;
|
||||||
|
const sm = p.sm || xs;
|
||||||
|
const md = p.md || sm;
|
||||||
|
const lg = p.lg || md;
|
||||||
|
const xl = p.xl || lg;
|
||||||
|
return {
|
||||||
|
xs,
|
||||||
|
sm,
|
||||||
|
md,
|
||||||
|
lg,
|
||||||
|
xl,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Grid({
|
||||||
|
columns: cp,
|
||||||
|
container = false,
|
||||||
|
item = false,
|
||||||
|
direction = "row",
|
||||||
|
lg,
|
||||||
|
md,
|
||||||
|
sm,
|
||||||
|
xl,
|
||||||
|
xs,
|
||||||
|
wrap = "wrap",
|
||||||
|
spacing = 0,
|
||||||
|
columnSpacing: csp,
|
||||||
|
rowSpacing: rsp,
|
||||||
|
alignItems,
|
||||||
|
justifyContent,
|
||||||
|
zeroMinWidth = false,
|
||||||
|
children,
|
||||||
|
}: Props): VNode {
|
||||||
|
const cc = useContext(GridContext);
|
||||||
|
const columns = !cp ? cc : toResponsive(cp);
|
||||||
|
|
||||||
|
const rowSpacing = rsp ? toResponsive(rsp) : toResponsive(spacing);
|
||||||
|
const columnSpacing = csp ? toResponsive(csp) : toResponsive(spacing);
|
||||||
|
|
||||||
|
const ssize = toResponsive({ xs, md, lg, xl, sm } as any);
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
console.log(rowSpacing);
|
||||||
|
console.log(columnSpacing);
|
||||||
|
}
|
||||||
|
const spacingStyles = !container
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
"--space-col-xs": getOffset(theme.spacing(columnSpacing.xs)),
|
||||||
|
"--space-col-sm": getOffset(theme.spacing(columnSpacing.sm)),
|
||||||
|
"--space-col-md": getOffset(theme.spacing(columnSpacing.md)),
|
||||||
|
"--space-col-lg": getOffset(theme.spacing(columnSpacing.lg)),
|
||||||
|
"--space-col-xl": getOffset(theme.spacing(columnSpacing.xl)),
|
||||||
|
|
||||||
|
"--space-row-xs": getOffset(theme.spacing(rowSpacing.xs)),
|
||||||
|
"--space-row-sm": getOffset(theme.spacing(rowSpacing.sm)),
|
||||||
|
"--space-row-md": getOffset(theme.spacing(rowSpacing.md)),
|
||||||
|
"--space-row-lg": getOffset(theme.spacing(rowSpacing.lg)),
|
||||||
|
"--space-row-xl": getOffset(theme.spacing(rowSpacing.xl)),
|
||||||
|
};
|
||||||
|
const relationStyles = !item
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
"--relation-col-vs-sm": relation(columns, ssize, "sm"),
|
||||||
|
"--relation-col-vs-lg": relation(columns, ssize, "lg"),
|
||||||
|
"--relation-col-vs-xs": relation(columns, ssize, "xs"),
|
||||||
|
"--relation-col-vs-xl": relation(columns, ssize, "xl"),
|
||||||
|
"--relation-col-vs-md": relation(columns, ssize, "md"),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GridContext.Provider value={columns}>
|
||||||
|
<div
|
||||||
|
id={container ? "container" : "item"}
|
||||||
|
class={[
|
||||||
|
root,
|
||||||
|
container && containerStyle,
|
||||||
|
item && itemStyle,
|
||||||
|
zeroMinWidth && zeroMinWidthStyle,
|
||||||
|
sizeVariant,
|
||||||
|
container && columnGapVariant,
|
||||||
|
container && rowGapVariant,
|
||||||
|
].join(" ")}
|
||||||
|
style={{
|
||||||
|
...relationStyles,
|
||||||
|
...spacingStyles,
|
||||||
|
justifyContent,
|
||||||
|
alignItems,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</GridContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function relation(
|
||||||
|
cols: ResponsiveSize,
|
||||||
|
values: ResponsiveSize,
|
||||||
|
size: ResponsiveKeys,
|
||||||
|
) {
|
||||||
|
const colsNum = typeof cols === "number" ? cols : cols[size] || 12;
|
||||||
|
return (
|
||||||
|
String(Math.round(((values[size] || 1) / colsNum) * 10e7) / 10e5) + "%"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ export function Paper({
|
|||||||
<div
|
<div
|
||||||
class={[
|
class={[
|
||||||
baseStyle,
|
baseStyle,
|
||||||
!square && theme.shape.borderRadius,
|
!square && theme.shape.roundBorder,
|
||||||
borderVariant[variant],
|
borderVariant[variant],
|
||||||
].join(" ")}
|
].join(" ")}
|
||||||
style={{
|
style={{
|
||||||
|
@ -1,9 +1,92 @@
|
|||||||
|
import { css } from "@linaria/core";
|
||||||
import { h, Fragment, VNode, ComponentChildren } from "preact";
|
import { h, Fragment, VNode, ComponentChildren } from "preact";
|
||||||
|
|
||||||
|
type VariantEnum =
|
||||||
|
| "body1"
|
||||||
|
| "body2"
|
||||||
|
| "button"
|
||||||
|
| "caption"
|
||||||
|
| "h1"
|
||||||
|
| "h2"
|
||||||
|
| "h3"
|
||||||
|
| "h4"
|
||||||
|
| "h5"
|
||||||
|
| "h6"
|
||||||
|
| "inherit"
|
||||||
|
| "overline"
|
||||||
|
| "subtitle1"
|
||||||
|
| "subtitle2";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: ComponentChildren;
|
align?: "center" | "inherit" | "justify" | "left" | "right";
|
||||||
|
gutterBottom?: boolean;
|
||||||
|
noWrap?: boolean;
|
||||||
|
paragraph?: boolean;
|
||||||
|
variant?: VariantEnum;
|
||||||
|
children?: ComponentChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Typography({ children }: Props): VNode {
|
const defaultVariantMapping = {
|
||||||
return <p>{children}</p>;
|
h1: "h1",
|
||||||
|
h2: "h2",
|
||||||
|
h3: "h3",
|
||||||
|
h4: "h4",
|
||||||
|
h5: "h5",
|
||||||
|
h6: "h6",
|
||||||
|
subtitle1: "h6",
|
||||||
|
subtitle2: "h6",
|
||||||
|
body1: "p",
|
||||||
|
body2: "p",
|
||||||
|
inherit: "p",
|
||||||
|
};
|
||||||
|
|
||||||
|
const root = css`
|
||||||
|
margin: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const noWrapStyle = css`
|
||||||
|
overflow: "hidden";
|
||||||
|
text-overflow: "ellipsis";
|
||||||
|
white-space: "nowrap";
|
||||||
|
`;
|
||||||
|
const gutterBottomStyle = css`
|
||||||
|
margin-bottom: 0.35em;
|
||||||
|
`;
|
||||||
|
const paragraphStyle = css`
|
||||||
|
margin-bottom: 16px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function Typography({
|
||||||
|
align,
|
||||||
|
gutterBottom = false,
|
||||||
|
noWrap = false,
|
||||||
|
paragraph = false,
|
||||||
|
variant = "body1",
|
||||||
|
children,
|
||||||
|
}: Props): VNode {
|
||||||
|
const cmp = paragraph
|
||||||
|
? "p"
|
||||||
|
: defaultVariantMapping[variant as "h1"] || "span";
|
||||||
|
|
||||||
|
const alignStyle =
|
||||||
|
align == "inherit"
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
textAlign: align,
|
||||||
|
};
|
||||||
|
return h(
|
||||||
|
cmp,
|
||||||
|
{
|
||||||
|
class: [
|
||||||
|
root,
|
||||||
|
noWrap && noWrapStyle,
|
||||||
|
gutterBottom && gutterBottomStyle,
|
||||||
|
paragraph && paragraphStyle,
|
||||||
|
].join(" "),
|
||||||
|
style: {
|
||||||
|
...alignStyle,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@ export function pxToRem(size: number): string {
|
|||||||
return `${(size / htmlFontSize) * coef}rem`;
|
return `${(size / htmlFontSize) * coef}rem`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Spacing {
|
||||||
|
(): string;
|
||||||
|
(value: number): string;
|
||||||
|
(topBottom: number, rightLeft: number): string;
|
||||||
|
(top: number, rightLeft: number, bottom: number): string;
|
||||||
|
(top: number, right: number, bottom: number, left: number): string;
|
||||||
|
}
|
||||||
|
|
||||||
export const theme = createTheme();
|
export const theme = createTheme();
|
||||||
|
|
||||||
export const ripple = css`
|
export const ripple = css`
|
||||||
@ -117,11 +125,78 @@ function createTheme() {
|
|||||||
const shadows = createAllShadows();
|
const shadows = createAllShadows();
|
||||||
const transitions = createTransitions({});
|
const transitions = createTransitions({});
|
||||||
const breakpoints = createBreakpoints({});
|
const breakpoints = createBreakpoints({});
|
||||||
|
const spacing = createSpacing();
|
||||||
const shape = {
|
const shape = {
|
||||||
borderRadius: css`
|
roundBorder: css`
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
`,
|
`,
|
||||||
|
squareBorder: css`
|
||||||
|
border-radius: 0px;
|
||||||
|
`,
|
||||||
|
circularBorder: css`
|
||||||
|
border-radius: 50%;
|
||||||
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
///////////////////// SPACING
|
||||||
|
/////////////////////
|
||||||
|
|
||||||
|
function createUnaryUnit(theme: { spacing: number }, defaultValue: number) {
|
||||||
|
const themeSpacing = theme.spacing || defaultValue;
|
||||||
|
|
||||||
|
if (typeof themeSpacing === "number") {
|
||||||
|
return (abs: number | string) => {
|
||||||
|
if (typeof abs === "string") {
|
||||||
|
return abs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return themeSpacing * abs;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(themeSpacing)) {
|
||||||
|
return (abs: number | string) => {
|
||||||
|
if (typeof abs === "string") {
|
||||||
|
return abs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return themeSpacing[abs];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof themeSpacing === "function") {
|
||||||
|
return themeSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (a: string | number) => "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function createUnarySpacing(theme: { spacing: number }) {
|
||||||
|
return createUnaryUnit(theme, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSpacing(spacingInput: number = 8): Spacing {
|
||||||
|
// Material Design layouts are visually balanced. Most measurements align to an 8dp grid, which aligns both spacing and the overall layout.
|
||||||
|
// Smaller components, such as icons, can align to a 4dp grid.
|
||||||
|
// https://material.io/design/layout/understanding-layout.html#usage
|
||||||
|
const transform = createUnarySpacing({
|
||||||
|
spacing: spacingInput,
|
||||||
|
});
|
||||||
|
|
||||||
|
const spacing = (...argsInput: ReadonlyArray<number | string>): string => {
|
||||||
|
const args = argsInput.length === 0 ? [1] : argsInput;
|
||||||
|
|
||||||
|
return args
|
||||||
|
.map((argument) => {
|
||||||
|
const output = transform(argument);
|
||||||
|
return typeof output === "number" ? `${output}px` : output;
|
||||||
|
})
|
||||||
|
.join(" ");
|
||||||
|
};
|
||||||
|
|
||||||
|
return spacing;
|
||||||
|
}
|
||||||
/////////////////////
|
/////////////////////
|
||||||
///////////////////// BREAKPOINTS
|
///////////////////// BREAKPOINTS
|
||||||
/////////////////////
|
/////////////////////
|
||||||
@ -691,6 +766,7 @@ function createTheme() {
|
|||||||
shape,
|
shape,
|
||||||
transitions,
|
transitions,
|
||||||
breakpoints,
|
breakpoints,
|
||||||
|
spacing,
|
||||||
pxToRem,
|
pxToRem,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user