Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
feat(lsg): introduce space component
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexpeschel authored and lkuechler committed Dec 7, 2017
1 parent ce93c6a commit f2accd7
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 0 deletions.
123 changes: 123 additions & 0 deletions src/lsg/patterns/space/demo.tsx
@@ -0,0 +1,123 @@
import { Color, colors } from '../colors';
import Space, { Size } from './index';
import * as React from 'react';
import styled from 'styled-components';

const blue: Color = new Color({displayName: 'Demo Blue', rgb: [91, 177, 255]});
const green: Color = new Color({displayName: 'Demo Green', rgb: [91, 255, 151]});
const violet: Color = new Color({displayName: 'Demo Violet', rgb: [181, 91, 255]});

const DemoTileSpace = styled(Space)`
display: flex;
flex-wrap: wrap;
`;

const DemoRowSpace = styled(Space)`
display: flex;
align-content: stretch;
flex-wrap: wrap;
justify-content: space-between;
`;

const InsetSpace = styled(Space)`
background-color: ${blue.toString()};
width: 250px;
height: 250px;
`;

const StackSpace = styled(Space)`
background-color: ${green.toString()};
`;

const InlineSpace = styled(Space)`
background-color: ${violet.toString()};
`;

const Content = styled.div`
background-color: ${colors.white.toString()};
width: 100%;
height: 100%;
text-align: center;
line-height: 2em;
`;

const SpaceDemo: React.StatelessComponent<void> = (): JSX.Element => (
<div>
<Space>Inset</Space>
<DemoTileSpace size={[Size.L, Size.None]}>
<Space size={Size.XS}>
<InsetSpace size={Size.XS} inside={true}><Content>{Size[Size.XS]}</Content></InsetSpace>
</Space>
<Space size={Size.XS}>
<InsetSpace size={Size.XS} inside={true}><Content>{Size[Size.XS]}</Content></InsetSpace>
</Space>
<Space size={Size.XS}>
<InsetSpace size={Size.S} inside={true}><Content>{Size[Size.S]}</Content></InsetSpace>
</Space>
<Space size={Size.XS}>
<InsetSpace size={Size.M} inside={true}><Content>{Size[Size.L]}</Content></InsetSpace>
</Space>
<Space size={Size.XS}>
<InsetSpace size={Size.L} inside={true}><Content>{Size[Size.L]}</Content></InsetSpace>
</Space>
<Space size={Size.XS}>
<InsetSpace size={Size.XL} inside={true}><Content>{Size[Size.XL]}</Content></InsetSpace>
</Space>
<Space size={Size.XS}>
<InsetSpace size={Size.XXL} inside={true}><Content>{Size[Size.XXL]}</Content></InsetSpace>
</Space>
</DemoTileSpace>

<Space sizeTop={Size.XXL}>Inline</Space>
<DemoRowSpace size={[Size.L, Size.None]}>
<Space size={Size.XS}>
<InlineSpace sizeRight={Size.XS} inside={true}><Content>{Size[Size.XS]}</Content></InlineSpace>
</Space>
<Space size={Size.XS}>
<InlineSpace sizeRight={Size.XS} inside={true}><Content>{Size[Size.XS]}</Content></InlineSpace>
</Space>
<Space size={Size.XS}>
<InlineSpace sizeRight={Size.S} inside={true}><Content>{Size[Size.S]}</Content></InlineSpace>
</Space>
<Space size={Size.XS}>
<InlineSpace sizeRight={Size.M} inside={true}><Content>{Size[Size.L]}</Content></InlineSpace>
</Space>
<Space size={Size.XS}>
<InlineSpace sizeRight={Size.L} inside={true}><Content>{Size[Size.L]}</Content></InlineSpace>
</Space>
<Space size={Size.XS}>
<InlineSpace sizeRight={Size.XL} inside={true}><Content>{Size[Size.XL]}</Content></InlineSpace>
</Space>
<Space size={Size.XS}>
<InlineSpace sizeRight={Size.XXL} inside={true}><Content>{Size[Size.XXL]}</Content></InlineSpace>
</Space>
</DemoRowSpace>

<Space sizeTop={Size.XXL}>Stack</Space>
<Space size={[Size.L, Size.None]}>
<Space size={Size.XS}>
<StackSpace sizeBottom={Size.XS} inside={true}><Content>{Size[Size.XS]}</Content></StackSpace>
</Space>
<Space size={Size.XS}>
<StackSpace sizeBottom={Size.XS} inside={true}><Content>{Size[Size.XS]}</Content></StackSpace>
</Space>
<Space size={Size.XS}>
<StackSpace sizeBottom={Size.S} inside={true}><Content>{Size[Size.S]}</Content></StackSpace>
</Space>
<Space size={Size.XS}>
<StackSpace sizeBottom={Size.M} inside={true}><Content>{Size[Size.L]}</Content></StackSpace>
</Space>
<Space size={Size.XS}>
<StackSpace sizeBottom={Size.L} inside={true}><Content>{Size[Size.L]}</Content></StackSpace>
</Space>
<Space size={Size.XS}>
<StackSpace sizeBottom={Size.XL} inside={true}><Content>{Size[Size.XL]}</Content></StackSpace>
</Space>
<Space size={Size.XS}>
<StackSpace sizeBottom={Size.XXL} inside={true}><Content>{Size[Size.XXL]}</Content></StackSpace>
</Space>
</Space>
</div>
);

export default SpaceDemo;
115 changes: 115 additions & 0 deletions src/lsg/patterns/space/index.tsx
@@ -0,0 +1,115 @@
import * as React from 'react';
import styled from 'styled-components';

export interface SpaceProps {
className?: string;
inside?: boolean;
size?: Size | Size[];
sizeBottom?: Size;
sizeLeft?: Size;
sizeRight?: Size;
sizeTop?: Size;
}

export interface StyledSpaceProps {
inside: boolean;
// Redefine `size` as `spaceSize` property for styled components to avoid collision
// with `size` property on `React.HTMLAttributes` interface.
spaceSize: Size[];
}

export enum Size {
// Explicity set enum values to indicate that they will be used later on as
// array indicies.
None = 0,
XS = 6,
S = 12,
M = 15,
L = 18,
XL = 24,
XXL = 32
}

export enum PageInset {
// Defines global page gutter used in header and footer components
XS = 24,
S = 42,
M = 60,
L = 78,
XL = 96
}

/**
* Calculates the actual value for the given size and breakpoint, based on the
* given growth mapping.
* @param size The size used for calculation.
*/
export function getSpace(size: Size): number {
if (undefined !== size) {
return size;
}
return 0;
}

function expand<T>(source: T[] | T): T[] {
const values: T[] = Array.isArray(source) ? source : [source];

switch (values.length) {
case 1: // [a] => [a, a, a, a]
return [values[0], values[0], values[0], values[0]];
case 2: // [a, b] => [a, b, a, b]
return [...values, ...values];
case 3: // [a, b, c] => [a, b, c, b]
return [...values, values[1]];
case 4: // [a, b, c, d] => [a, b, c, d]
default:
return values.slice(0, 4);
}
}

function merge<T>(shorthand: T | T[], top?: T, right?: T, bottom?: T, left?: T): T[] {
const expanded = expand<T>(shorthand);

return [
top === undefined ? expanded[0] : top,
right === undefined ? expanded[1] : right,
bottom === undefined ? expanded[2] : bottom,
left === undefined ? expanded[3] : left
];
}

function calculate(property: string, space: Size[]): string {
const values = space.map<string>((value, index) => `${getSpace(value)}px`);

const result = `${property}: ${values.join(' ')};`;

return result;
}

const StyledSpace = styled.div`
${(props: StyledSpaceProps) =>
calculate(props.inside
? 'padding'
: 'margin'
, props.spaceSize
)
}
`;

const Space: React.StatelessComponent<SpaceProps> = props => {
const size = merge<number>(
props.size || 0,
props.sizeTop,
props.sizeRight,
props.sizeBottom,
props.sizeLeft
);

return (
<StyledSpace className={props.className} spaceSize={size} inside={Boolean(props.inside)}>
{props.children}
</StyledSpace>
);
};

export default Space;
7 changes: 7 additions & 0 deletions src/lsg/patterns/space/pattern.json
@@ -0,0 +1,7 @@
{
"name": "space",
"displayName": "Space",
"flag": "alpha",
"version": "1.0.0",
"tags": ["space"]
}

0 comments on commit f2accd7

Please sign in to comment.