diff options
| author | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2023-08-28 21:33:44 -0500 | 
|---|---|---|
| committer | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2023-08-28 21:33:44 -0500 | 
| commit | f0c03a9b8e15387c4defd0a0e3e0298324406fae (patch) | |
| tree | 564011d0265666953b17258954ff68614ff6566a /components | |
| parent | 2f0439621cff059e414d67f6ce43a7a6c4de13bc (diff) | |
| download | homepage-f0c03a9b8e15387c4defd0a0e3e0298324406fae.tar.xz homepage-f0c03a9b8e15387c4defd0a0e3e0298324406fae.zip | |
Add wg2nd
Diffstat (limited to 'components')
| -rw-r--r-- | components/Box/index.tsx | 18 | ||||
| -rw-r--r-- | components/Breadcrumbs/index.tsx | 12 | ||||
| -rw-r--r-- | components/Button/index.tsx | 39 | ||||
| -rw-r--r-- | components/Input/index.tsx | 22 | ||||
| -rw-r--r-- | components/Markdown/index.tsx | 4 | ||||
| -rw-r--r-- | components/TextArea/index.tsx | 22 | ||||
| -rw-r--r-- | components/Typography/index.tsx | 47 | ||||
| -rw-r--r-- | components/Typography/typo.module.scss | 64 | ||||
| -rw-r--r-- | components/ViewPort/index.tsx | 3 | ||||
| -rw-r--r-- | components/utils/inputElementStyle.tsx | 16 | ||||
| -rw-r--r-- | components/utils/systemProps.tsx | 107 | 
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 +}; | 
