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 { Divider } from "../mui/Divider";
|
||||
import { Button } from "./styled/index.js";
|
||||
import { Button } from "../mui/Button";
|
||||
import { Typography } from "../mui/Typography";
|
||||
import { Avatar } from "../mui/Avatar";
|
||||
import { Grid } from "../mui/Grid";
|
||||
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 {
|
||||
return <Fragment />;
|
||||
function SignalWifiOffIcon({ ...rest }: any): VNode {
|
||||
return <Icon {...rest} />;
|
||||
}
|
||||
|
||||
function Banner({}: {}) {
|
||||
export function Banner({}: {}) {
|
||||
return (
|
||||
<Fragment>
|
||||
<Paper elevation={0} /*className={classes.paper}*/>
|
||||
<Grid container wrap="nowrap" spacing={16} alignItems="center">
|
||||
<Grid item>
|
||||
<Avatar /*className={classes.avatar}*/>
|
||||
<SignalWifiOffIcon />
|
||||
<Paper elevation={3} /*className={classes.paper}*/>
|
||||
<Grid
|
||||
container
|
||||
// wrap="nowrap"
|
||||
// spacing={10}
|
||||
alignItems="center"
|
||||
columns={3}
|
||||
>
|
||||
<Grid item xs={1}>
|
||||
<Avatar>
|
||||
<SignalWifiOffIcon style={{ backgroundColor: "red" }} />
|
||||
</Avatar>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid item xs={1}>
|
||||
<Typography>
|
||||
You have lost connection to the internet. This app is offline.
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container justify="flex-end" spacing={8}>
|
||||
<Grid item>
|
||||
<Grid container justifyContent="flex-end" spacing={8} columns={3}>
|
||||
<Grid item xs={1}>
|
||||
<Button color="primary">Turn on wifi</Button>
|
||||
</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")`;
|
||||
|
||||
export const NiceSelect = styled.div`
|
||||
|
@ -1,5 +1,53 @@
|
||||
import { css } from "@linaria/core";
|
||||
import { h, Fragment, VNode, ComponentChildren } from "preact";
|
||||
import { theme } from "./style";
|
||||
|
||||
export function Avatar({}: { children: ComponentChildren }): VNode {
|
||||
return <Fragment />;
|
||||
const root = css`
|
||||
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}
|
||||
class={[
|
||||
theme.typography.button,
|
||||
theme.shape.borderRadius,
|
||||
theme.shape.roundBorder,
|
||||
ripple,
|
||||
baseStyle,
|
||||
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;
|
||||
wrap?: string;
|
||||
item?: boolean;
|
||||
spacing?: number;
|
||||
alignItems?: string;
|
||||
justify?: string;
|
||||
|
||||
direction?: "column-reverse" | "column" | "row-reverse" | "row";
|
||||
|
||||
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;
|
||||
}): 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
|
||||
class={[
|
||||
baseStyle,
|
||||
!square && theme.shape.borderRadius,
|
||||
!square && theme.shape.roundBorder,
|
||||
borderVariant[variant],
|
||||
].join(" ")}
|
||||
style={{
|
||||
|
@ -1,9 +1,92 @@
|
||||
import { css } from "@linaria/core";
|
||||
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 {
|
||||
children: ComponentChildren;
|
||||
align?: "center" | "inherit" | "justify" | "left" | "right";
|
||||
gutterBottom?: boolean;
|
||||
noWrap?: boolean;
|
||||
paragraph?: boolean;
|
||||
variant?: VariantEnum;
|
||||
children?: ComponentChildren;
|
||||
}
|
||||
|
||||
export function Typography({ children }: Props): VNode {
|
||||
return <p>{children}</p>;
|
||||
const defaultVariantMapping = {
|
||||
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`;
|
||||
}
|
||||
|
||||
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 ripple = css`
|
||||
@ -117,11 +125,78 @@ function createTheme() {
|
||||
const shadows = createAllShadows();
|
||||
const transitions = createTransitions({});
|
||||
const breakpoints = createBreakpoints({});
|
||||
const spacing = createSpacing();
|
||||
const shape = {
|
||||
borderRadius: css`
|
||||
roundBorder: css`
|
||||
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
|
||||
/////////////////////
|
||||
@ -691,6 +766,7 @@ function createTheme() {
|
||||
shape,
|
||||
transitions,
|
||||
breakpoints,
|
||||
spacing,
|
||||
pxToRem,
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user