William Nemenchainitial commit
86fb32e9/11/2022, 1:13:39 AM
.ts
TypeScript
(application/typescript)
// 3rd-party
import { removeCommentsAndSpacing } from "@ethicdevs/react-monolith";
import React, { FC } from "react";
import styled, { css } from "styled-components";

// app
import type { SectionsWithPages, WithThemeSchemeProp } from "../types";
import { NamedColors } from "../utils/style";

import InstantRouterIndicator from "../islands/InstantRouterIndicator";
import SideMenu from "../islands/SideMenu";
import { PageHeader } from "./PageHeader";

interface LayoutProps {
  foo?: boolean;
  currentPageSlug?: string;
  currentSectionSlug?: string;
  menuDefinition?: SectionsWithPages;
  showSideExamples?: boolean;
  showSideMenu?: boolean;
}

const BRANDLINE_HEIGHT = 4;
const HEADER_HEIGHT = 72;
const SIDE_MENU_WIDTH = 320;
const SIDE_EXAMPLES_WIDTH = 490;

export const Layout: FC<LayoutProps & WithThemeSchemeProp> = ({
  children,
  menuDefinition,
  currentPageSlug = undefined,
  currentSectionSlug = undefined,
  showSideExamples = false,
  showSideMenu = menuDefinition != null,
  themeScheme,
}) => {
  const sharedProps = {
    themeScheme,
  };

  return (
    <>
      <style
        dangerouslySetInnerHTML={{
          __html: removeCommentsAndSpacing(`
            html,
            body {
              margin: 0;
              padding: 0;
              font-family: sans-serif;
              font-size: 16px;
              background-color: ${NamedColors.BRAND_LINE[themeScheme]};
            }
            html {
              /* so anchor are not hidden behind sticky header */
              scroll-padding-top: ${HEADER_HEIGHT + 16}px;
            }
            body {
              overflow-x: hidden;
              overflow-y: scroll;
            }
            * { box-sizing: border-box; }
            a > * {
              pointer-events: none;
            }
          `),
        }}
      />
      <StyledLayoutWrapper {...sharedProps}>
        <div data-islandid={`${InstantRouterIndicator.name}$$0`}>
          <InstantRouterIndicator />
        </div>
        {/*<StyledBrandLine {...sharedProps} />*/}
        <StyledPageHeaderWrapper {...sharedProps}>
          <PageHeader themeScheme={themeScheme} />
        </StyledPageHeaderWrapper>
        <StyledPageWrapper>
          {menuDefinition && showSideMenu && (
            <StyledSideMenuWrapper
              data-islandid={`${SideMenu.name}$$0`}
              {...sharedProps}
            >
              <SideMenu
                currentSectionSlug={currentSectionSlug}
                currentPageSlug={currentPageSlug}
                menuDefinition={menuDefinition}
                themeScheme={themeScheme}
              />
            </StyledSideMenuWrapper>
          )}
          <StyledChildrenWrapper {...sharedProps}>
            {children}
          </StyledChildrenWrapper>
          {showSideExamples && (
            <StyledSideExamplesWrapper {...sharedProps}>
              <div style={{ width: "100%" }}>
                <h3>Examples</h3>
              </div>
            </StyledSideExamplesWrapper>
          )}
        </StyledPageWrapper>
        {/*<StyledPageFooterWrapper>
        <h4>Footer</h4>
      </StyledPageFooterWrapper>*/}
      </StyledLayoutWrapper>
    </>
  );
};

const StyledLayoutWrapper = styled.div<WithThemeSchemeProp>`
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-start;
  align-items: flex-start;

  min-height: 100vh;
  min-width: 100%;
  max-width: 100%;

  ${({ themeScheme }) => css`
    background-color: ${NamedColors.BACKGROUND[themeScheme]};
    color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
  `};
`;

/*const StyledBrandLine = styled.div<WithThemeSchemeProp>`
  display: flex;
  width: 100%;
  height: ${BRANDLINE_HEIGHT}px;

  ${({ themeScheme }) => css`
    background-color: ${NamedColors.BRAND_LINE[themeScheme]};
    background-image: linear-gradient(90deg, #1a8f97 0%, #23024d 100%);
  `};
`;*/

const StyledPageHeaderWrapper = styled.div<WithThemeSchemeProp>`
  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-start;
  align-items: center;

  width: 100%;
  min-height: ${HEADER_HEIGHT}px;
  height: ${HEADER_HEIGHT}px;
  max-height: ${HEADER_HEIGHT}px;

  position: sticky;
  top: 0;
  z-index: 11000;

  gap: 20px;
  padding: 0 20px;

  ${({ themeScheme }) => css`
    background-color: ${NamedColors.HEADER[themeScheme]};
    border-bottom: 1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]};

    & > a > h1 {
      color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
      margin: 0;
      margin-left: 16px;
    }
  `};

  & > a {
    text-decoration: unset;

    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    align-items: center;
  }
`;

const StyledPageWrapper = styled.div`
  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-start;
  align-items: stretch;

  position: relative;

  flex: 1;
  width: 100%;
  min-height: calc(100% - ${BRANDLINE_HEIGHT + HEADER_HEIGHT}px);
`;

const StyledSideMenuWrapper = styled.aside<WithThemeSchemeProp>`
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-start;
  align-items: flex-start;

  width: ${SIDE_MENU_WIDTH}px;
  min-height: calc(100% - ${BRANDLINE_HEIGHT + HEADER_HEIGHT}px);
  max-height: calc(100vh - ${BRANDLINE_HEIGHT + HEADER_HEIGHT}px);

  position: sticky;
  top: ${HEADER_HEIGHT}px;

  overflow-y: auto;

  padding: 8px 0 16px 0;

  ${({ themeScheme }) => css`
    background-color: ${NamedColors.SIDE_MENU[themeScheme]};
    border-right: 1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]};
  `};
`;

const StyledChildrenWrapper = styled.div`
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-start;
  align-items: flex-start;

  flex: 1;
  width: 100%;
`;

const StyledSideExamplesWrapper = styled.aside<WithThemeSchemeProp>`
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-start;
  align-items: flex-start;

  width: ${SIDE_EXAMPLES_WIDTH}px;
  min-height: calc(100% - ${BRANDLINE_HEIGHT + HEADER_HEIGHT}px);

  position: sticky;
  top: ${HEADER_HEIGHT}px;

  padding: 24px;
  gap: 24px;

  ${({ themeScheme }) => css`
    background-color: ${NamedColors.SIDE_EXAMPLES[themeScheme]};
    border-left: 1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]};
  `};
`;