aboutsummaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/Box/index.tsx18
-rw-r--r--components/Breadcrumbs/index.tsx12
-rw-r--r--components/Button/index.tsx39
-rw-r--r--components/Input/index.tsx22
-rw-r--r--components/Markdown/index.tsx4
-rw-r--r--components/TextArea/index.tsx22
-rw-r--r--components/Typography/index.tsx47
-rw-r--r--components/Typography/typo.module.scss64
-rw-r--r--components/ViewPort/index.tsx3
-rw-r--r--components/utils/inputElementStyle.tsx16
-rw-r--r--components/utils/systemProps.tsx107
11 files changed, 348 insertions, 6 deletions
diff --git a/components/Box/index.tsx b/components/Box/index.tsx
new file mode 100644
index 0000000..32866b2
--- /dev/null
+++ b/components/Box/index.tsx
@@ -0,0 +1,18 @@
+import { getSystemStyle, SystemProps } from '../utils/systemProps';
+
+interface BoxProps extends SystemProps {
+ style?: React.CSSProperties;
+ children?: React.ReactNode;
+};
+
+const Box: React.FC<BoxProps> = ({ style, children, ...props}) => {
+ const systemStyle = getSystemStyle(props, style);
+
+ return (
+ <div style={systemStyle}>
+ { children }
+ </div>
+ );
+};
+
+export default Box;
diff --git a/components/Breadcrumbs/index.tsx b/components/Breadcrumbs/index.tsx
index c5a17b8..d773b33 100644
--- a/components/Breadcrumbs/index.tsx
+++ b/components/Breadcrumbs/index.tsx
@@ -6,6 +6,7 @@ import clsx from 'clsx';
export type BreadcrumbsProps = {
className?: string;
style?: object;
+ children: React.ReactNode;
};
const Breadcrumbs : FC<BreadcrumbsProps> = ({children, className, ...props}) => (
@@ -25,7 +26,11 @@ const Breadcrumbs : FC<BreadcrumbsProps> = ({children, className, ...props}) =>
</span>
);
-const Crumb : FC = ({children, ...props}) => (
+export type CrumbProps = {
+ children: React.ReactNode;
+};
+
+const Crumb : FC<CrumbProps> = ({children, ...props}) => (
<span className={styles.crumb} {...props}>
{children}
</span>
@@ -33,12 +38,13 @@ const Crumb : FC = ({children, ...props}) => (
export type LinkCrumbProps = {
href: string;
+ children: React.ReactNode;
}
const LinkCrumb : FC<LinkCrumbProps> = ({children, href, ...props}) => (
<Crumb>
<Link href={href}>
- <a>{children}</a>
+ {children}
</Link>
</Crumb>
);
@@ -47,4 +53,4 @@ export {
Crumb,
Breadcrumbs,
LinkCrumb
-}; \ No newline at end of file
+};
diff --git a/components/Button/index.tsx b/components/Button/index.tsx
new file mode 100644
index 0000000..9eb2e95
--- /dev/null
+++ b/components/Button/index.tsx
@@ -0,0 +1,39 @@
+import React, { TextareaHTMLAttributes } from 'react';
+import { getSystemStyle, SystemProps } from '../utils/systemProps';
+
+interface ButtonProps
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
+ SystemProps
+{ }
+
+const Button: React.FC<ButtonProps> = ({ style, ...props }) => {
+ style = {
+ margin: '0.25rem 0.125rem',
+ cursor: 'pointer',
+ padding: '0.375rem 0.75rem',
+ borderRadius: '0.25rem',
+ textAlign: 'center',
+ verticalAlign: 'middle',
+ display: 'inline-block',
+ userSelect: 'none',
+
+ fontFamily: 'inherit',
+ fontSize: '.95rem',
+ lineHeight: '1.15',
+
+ // Color
+ color: '#fff',
+ backgroundColor: '#1473ff',
+ border: '1px solid #1473ff',
+ boxSizing: 'border-box',
+
+ transition: 'color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out',
+ ...style,
+ };
+
+ const systemStyle = getSystemStyle(props, style);
+
+ return (<button style={systemStyle} {...props} />);
+};
+
+export default Button;
diff --git a/components/Input/index.tsx b/components/Input/index.tsx
new file mode 100644
index 0000000..69f64fa
--- /dev/null
+++ b/components/Input/index.tsx
@@ -0,0 +1,22 @@
+import React, { TextareaHTMLAttributes, ForwardRefRenderFunction } from 'react';
+import { getSystemStyle, SystemProps } from '../utils/systemProps';
+import inputElStyle from '../utils/inputElementStyle';
+
+interface InputProps
+ extends React.InputHTMLAttributes<HTMLInputElement>,
+ SystemProps
+{ }
+
+const Input: ForwardRefRenderFunction<HTMLInputElement, InputProps> =
+ ({ style, ...props }, ref) => {
+ style = {
+ ...inputElStyle,
+ ...style,
+ };
+
+ const systemStyle = getSystemStyle(props, style);
+
+ return <input ref={ref} style={systemStyle} {...props} />;
+ };
+
+export default React.forwardRef(Input);
diff --git a/components/Markdown/index.tsx b/components/Markdown/index.tsx
index 4bb6c79..1a71330 100644
--- a/components/Markdown/index.tsx
+++ b/components/Markdown/index.tsx
@@ -11,7 +11,7 @@ interface MarkdownProps {
const Markdown : FC<MarkdownProps> = ({md, className, ...props}) => (
<div
className={clsx(styles.markdownContainer, className)}
-
+
dangerouslySetInnerHTML={{
__html: md
}}
@@ -24,4 +24,4 @@ export type {
MarkdownProps
};
-export default Markdown; \ No newline at end of file
+export default Markdown;
diff --git a/components/TextArea/index.tsx b/components/TextArea/index.tsx
new file mode 100644
index 0000000..c40efed
--- /dev/null
+++ b/components/TextArea/index.tsx
@@ -0,0 +1,22 @@
+import React, { TextareaHTMLAttributes, ForwardRefRenderFunction } from 'react';
+import { getSystemStyle, SystemProps } from '../utils/systemProps';
+import inputElStyle from '../utils/inputElementStyle';
+
+interface TextAreaProps
+ extends TextareaHTMLAttributes<HTMLTextAreaElement>,
+ SystemProps
+{ }
+
+const TextArea: ForwardRefRenderFunction<HTMLTextAreaElement, TextAreaProps> =
+ ({ style, ...props }, ref) => {
+ style = {
+ ...inputElStyle,
+ ...style,
+ };
+
+ const systemStyle = getSystemStyle(props, style);
+
+ return <textarea ref={ref} style={systemStyle} {...props} />;
+ };
+
+export default React.forwardRef(TextArea);
diff --git a/components/Typography/index.tsx b/components/Typography/index.tsx
new file mode 100644
index 0000000..b9babc0
--- /dev/null
+++ b/components/Typography/index.tsx
@@ -0,0 +1,47 @@
+import React from 'react';
+import styles from './typo.module.scss';
+import clsx from 'clsx';
+
+
+type Variant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'body';
+type Align = 'inherit' | 'left' | 'center' | 'right';
+
+interface TypographyProps extends React.HTMLAttributes<HTMLElement> {
+ variant?: Variant;
+ align?: Align;
+ gutter?: boolean;
+}
+
+const variantTagMap: Record<Variant, keyof JSX.IntrinsicElements> = {
+ h1: 'h1',
+ h2: 'h2',
+ h3: 'h3',
+ h4: 'h4',
+ h5: 'h5',
+ h6: 'h6',
+ body: 'p'
+};
+
+const Typography: React.FC<TypographyProps> = ({
+ variant = 'body',
+ align = 'inherit',
+ gutter = false,
+ className,
+ ...props
+}) => {
+ const Tag = variantTagMap[variant] as keyof React.ReactHTML;
+
+ const typographyClassName = clsx(
+ styles[`typo-${variant}`],
+ {
+ [`align-${align}`]: align !== 'inherit',
+ [styles['typo-gutter']]: gutter
+ },
+ className
+ );
+
+ return <Tag className={typographyClassName} {...props} />;
+};
+
+export default Typography;
+
diff --git a/components/Typography/typo.module.scss b/components/Typography/typo.module.scss
new file mode 100644
index 0000000..934333d
--- /dev/null
+++ b/components/Typography/typo.module.scss
@@ -0,0 +1,64 @@
+.typo-h1 {
+ font-size: 2.8rem;
+ font-weight: 300;
+ line-height: 1.167;
+ letter-spacing: -0.01562em;
+ // margin-top: 1.0rem;
+ // margin-bottom: 1rem;
+
+ padding-bottom: 0.4rem;
+ border-bottom: 0.12rem solid rgb(53, 53, 53);
+}
+
+.typo-h2 {
+ font-size: 2.3rem;
+ font-weight: 300;
+ line-height: 1.2;
+ letter-spacing: -0.00833em;
+
+ // margin-top: 1.6rem;
+ // margin-bottom: 0.8rem;
+}
+
+.typo-h3 {
+ font-size: 1.3rem;
+ font-weight: 400;
+ line-height: 1.167;
+ letter-spacing: 0em;
+
+ // margin-top: 1.3rem;
+ // margin-bottom: 0.5rem;
+}
+
+.typo-h4 {
+ font-size: 1.25rem;
+}
+
+.typo-h5 {
+ font-size: 1.15rem;
+}
+
+.typo-h6 {
+ font-size: 1.10rem;
+}
+
+.typo-h4, .typo-h5, .typo-h6 {
+ // margin-top: 0.8rem;
+ // margin-bottom: 0.6rem;
+}
+
+.typo-p {
+ font-size: 1rem;
+ letter-spacing: 0.00938em;
+ font-weight: 300;
+}
+
+.typo-p {
+ font-size: 1rem;
+ line-height: 1.5;
+ // margin-bottom: 1em;
+}
+
+.typo-gutter {
+ margin-bottom: 0.35em;
+}
diff --git a/components/ViewPort/index.tsx b/components/ViewPort/index.tsx
index 665ee00..29191a1 100644
--- a/components/ViewPort/index.tsx
+++ b/components/ViewPort/index.tsx
@@ -5,6 +5,7 @@ import clsx from 'clsx';
export type Props = {
size?: "sm" | "md" | "lg";
className?: string;
+ children?: React.ReactNode;
};
const Viewport : FC<Props> = ({children, className, size}) => {
@@ -20,4 +21,4 @@ const Viewport : FC<Props> = ({children, className, size}) => {
)
};
-export default Viewport; \ No newline at end of file
+export default Viewport;
diff --git a/components/utils/inputElementStyle.tsx b/components/utils/inputElementStyle.tsx
new file mode 100644
index 0000000..c784e85
--- /dev/null
+++ b/components/utils/inputElementStyle.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+
+export default {
+ backgroundColor: '#fff',
+ border: '1px solid #ced4da',
+ padding: '0.375rem 0.75rem',
+ width: '100%',
+ borderRadius: '0.25rem',
+ resize: 'vertical',
+ fontFamily: 'inherit',
+ margin: '0',
+ display: 'block',
+ fontSize: '1em',
+ boxSizing: 'border-box',
+ lineHeight: '1.5rem',
+} as React.CSSProperties;
diff --git a/components/utils/systemProps.tsx b/components/utils/systemProps.tsx
new file mode 100644
index 0000000..8fc0317
--- /dev/null
+++ b/components/utils/systemProps.tsx
@@ -0,0 +1,107 @@
+import React from 'react';
+
+export type SystemProps = {
+ // Margin
+ mt?: number;
+ mb?: number;
+ ml?: number;
+ mr?: number;
+ mx?: number;
+ my?: number;
+ m?: number;
+
+ // Padding
+ pt?: number;
+ pb?: number;
+ pl?: number;
+ pr?: number;
+ px?: number;
+ py?: number;
+ p?: number;
+
+ // Arbitrary style
+ sx?: React.CSSProperties;
+};
+
+const calculateStyleValue = (multiplier: number, spacer: number = 1): string => {
+ return `${multiplier * spacer}em`;
+};
+
+const getSystemStyle = (
+ systemProps: SystemProps,
+ userStyle: React.CSSProperties = {}
+): React.CSSProperties => {
+ const spacer = 1; // 1em
+
+ let style: React.CSSProperties = {};
+
+ // Margin
+ const { mt, mb, ml, mr, mx, my, m } = systemProps;
+
+ if (m !== undefined) {
+ const value = calculateStyleValue(m, spacer);
+ style.marginTop = value;
+ style.marginBottom = value;
+ style.marginLeft = value;
+ style.marginRight = value;
+ }
+
+ if (mx !== undefined) {
+ const value = calculateStyleValue(mx, spacer);
+ style.marginLeft = value;
+ style.marginRight = value;
+ }
+
+ if (my !== undefined) {
+ const value = calculateStyleValue(my, spacer);
+ style.marginTop = value;
+ style.marginBottom = value;
+ }
+
+ if (mt !== undefined) style.marginTop = calculateStyleValue(mt, spacer);
+ if (mb !== undefined) style.marginBottom = calculateStyleValue(mb, spacer);
+ if (ml !== undefined) style.marginLeft = calculateStyleValue(ml, spacer);
+ if (mr !== undefined) style.marginRight = calculateStyleValue(mr, spacer);
+
+ // Padding
+ const { pt, pb, pl, pr, px, py, p } = systemProps;
+
+ if (p !== undefined) {
+ const value = calculateStyleValue(p, spacer);
+ style.paddingTop = value;
+ style.paddingBottom = value;
+ style.paddingLeft = value;
+ style.paddingRight = value;
+ }
+
+ if (px !== undefined) {
+ const value = calculateStyleValue(px, spacer);
+ style.paddingLeft = value;
+ style.paddingRight = value;
+ }
+
+ if (py !== undefined) {
+ const value = calculateStyleValue(py, spacer);
+ style.paddingTop = value;
+ style.paddingBottom = value;
+ }
+
+ if (pt !== undefined) style.paddingTop = calculateStyleValue(pt, spacer);
+ if (pb !== undefined) style.paddingBottom = calculateStyleValue(pb, spacer);
+ if (pl !== undefined) style.paddingLeft = calculateStyleValue(pl, spacer);
+ if (pr !== undefined) style.paddingRight = calculateStyleValue(pr, spacer);
+
+ // Merge with arbitrary styles (sx)
+ if (systemProps.sx) {
+ style = { ...style, ...systemProps.sx };
+ }
+
+ // Override with user-defined style
+ style = { ...style, ...userStyle };
+
+ return style;
+};
+
+export {
+ getSystemStyle
+};