gitfoss | 1583fa79dadd28cc5a58cab58b76c27c78f8a1ac | app/components/DrawerPrimary.tsx ∙ GitFOSS
.ts
TypeScript
(application/typescript)
// 3rd-party
import React from "react";
import styled, { css } from "styled-components";
// import Color from "color";
// app
import { Const } from "../const";
import { Colors, NamedColors } from "../utils/style";
import {
  type RepositoryCountersDTO,
  type CommonViewProps,
  type WithThemeSchemeProp,
} from "../types";
// import { useMediaQuery } from "../utils/hooks/useMediaQuery";
import { buildRouteLink } from "../utils/shared";
import { AppRoute } from "../routes.defs";
// app components
import { Chip } from "./Chip";
import { TextEllipsis } from "./TextEllipsis.styled";
import { SupportIcon } from "./icons/SupportIcon";
import { SettingsIcon } from "./icons/SettingsIcon";
import { FolderIcon } from "./icons/FolderIcon";
import { CommentIcon } from "./icons/CommentIcon";
import { Grid } from "./Grid";
import { GitForkIcon } from "./icons/GitForkIcon";
import { GitPullIcon } from "./icons/GitPullIcon";
import { LikeIcon } from "./icons/LikeIcon";

export const DrawerPrimary = ({
  visible = false,
  commonProps,
  themeScheme,
  orgSlug,
  repoSlug,
  currentRef = Const.DEFAULT_HEAD_REF,
  path = "/",
  counters = {
    pulls: 0,
    tests: 0,
    builds: 0,
    issues: 0,
    apiRefSymbols: 0,
  },
}: WithThemeSchemeProp & {
  visible: boolean;
  commonProps: CommonViewProps;
  orgSlug: string;
  repoSlug: string;
  currentRef?: string;
  path?: string;
  counters?: RepositoryCountersDTO;
}) => {
  const pathRepo = buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
    orgSlug: orgSlug,
    repoSlug: repoSlug,
  });

  const pathRepoTrailing = buildRouteLink(
    AppRoute.REPOSITORY_DETAILS_WITH_TRAILING_SLASH,
    {
      orgSlug: orgSlug,
      repoSlug: repoSlug,
    },
  );

  const pathFiles = buildRouteLink(AppRoute.REPOSITORY_BROWSER, {
    orgSlug: orgSlug,
    repoSlug: repoSlug,
    currentRef: currentRef,
    "*": path,
  });

  const pathPulls = buildRouteLink(AppRoute.REPOSITORY_PULL_REQUESTS, {
    orgSlug: orgSlug,
    repoSlug: repoSlug,
  });

  const pathPipelines = buildRouteLink(AppRoute.REPOSITORY_PIPELINES, {
    orgSlug: orgSlug,
    repoSlug: repoSlug,
  });

  // const isMobile = useMediaQuery("sm");
  // if (isMobile === false) {
  //   visible = true;
  // }

  if (visible === false) {
    return null;
  }

  return (
    <>
      <StyledDrawerPrimary id="drawer" themeScheme={themeScheme}>
        <StyledDrawerHeader>
          <StyledLogoArea themeScheme={themeScheme}>
            <a href={"/"}>
              <h1>{Const.APP_NAME}</h1>
            </a>
          </StyledLogoArea>
        </StyledDrawerHeader>
        <StyledDrawerContent>
          <StyledDrawerListHeader style={{ margin: 0 }}>
            <a
              href={buildRouteLink(AppRoute.ORGANIZATION_DETAILS, { orgSlug })}
            >
              @{orgSlug}
            </a>
            <span>{" / "}</span>
            <a
              href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
                orgSlug,
                repoSlug,
              })}
            >
              <TextEllipsis>{repoSlug}</TextEllipsis>
            </a>
          </StyledDrawerListHeader>
          <StyledDrawerListHeader style={{ height: 32 }}>
            <Grid.Row
              fluid
              nowrap
              gap={8}
              justifyContent={"center"}
              alignItems={"center"}
            >
              <Grid.Row nowrap gap={4} alignItems={"center"}>
                <GitPullIcon
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  size={16}
                />
                <span style={{ fontSize: 11 }}>Watchers</span>
                <Chip
                  themeScheme={themeScheme}
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  style={{
                    padding: "2px 6px",
                    backgroundColor: "rgba(0,0,0,0.1)",
                    fontSize: 11,
                    color: NamedColors.TEXT_MUTED[themeScheme],
                  }}
                >
                  {counters.watchers || "0"}
                </Chip>
              </Grid.Row>
              <Grid.Row nowrap gap={4} alignItems={"center"}>
                <LikeIcon
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  size={16}
                />
                <span style={{ fontSize: 11 }}>Likes</span>
                <Chip
                  themeScheme={themeScheme}
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  style={{
                    padding: "2px 6px",
                    backgroundColor: "rgba(0,0,0,0.1)",
                    fontSize: 11,
                    color: NamedColors.TEXT_MUTED[themeScheme],
                  }}
                >
                  {counters.likes || "0"}
                </Chip>
              </Grid.Row>
              <Grid.Row nowrap gap={4} alignItems={"center"}>
                <GitForkIcon color={Colors.WHITE_01} size={16} />
                <span style={{ fontSize: 11 }}>Forks</span>
                <Chip
                  themeScheme={themeScheme}
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  style={{
                    padding: "2px 6px",
                    backgroundColor: "rgba(0,0,0,0.1)",
                    fontSize: 11,
                    color: NamedColors.TEXT_MUTED[themeScheme],
                  }}
                >
                  {counters.forks || "0"}
                </Chip>
              </Grid.Row>
            </Grid.Row>
          </StyledDrawerListHeader>
          <StyledDrawerList>
            <StyledDrawerListItem
              themeScheme={themeScheme}
              href={pathFiles}
              className={
                ((!commonProps.path!.startsWith(pathPipelines) === false &&
                  commonProps.path!.startsWith(pathFiles)) ||
                  [pathFiles, pathRepo, pathRepoTrailing].some(
                    (p) =>
                      commonProps.path === p || commonProps.path!.startsWith(p),
                  )) &&
                commonProps.path!.startsWith(pathPulls) === false &&
                commonProps.path!.startsWith(pathPipelines) === false
                  ? "active"
                  : undefined
              }
              style={{ paddingRight: 16 }}
            >
              <span>Files</span>
              <FolderIcon
                color={
                  ((!commonProps.path!.startsWith(pathPipelines) === false &&
                    commonProps.path!.startsWith(pathFiles)) ||
                    [pathFiles, pathRepo, pathRepoTrailing].some(
                      (p) =>
                        commonProps.path === p ||
                        commonProps.path!.startsWith(p),
                    )) &&
                  commonProps.path!.startsWith(pathPulls) === false &&
                  commonProps.path!.startsWith(pathPipelines) === false
                    ? NamedColors.TEXT_DEFAULT[themeScheme]
                    : NamedColors.TEXT_MUTED[themeScheme]
                }
                size={16}
              />
            </StyledDrawerListItem>
            <StyledDrawerListItem
              themeScheme={themeScheme}
              href={pathPulls}
              className={
                commonProps.path! === pathPulls ||
                commonProps.path!.startsWith(pathPulls)
                  ? "active"
                  : undefined
              }
            >
              <span>Pull Requests</span>
              <Chip themeScheme={themeScheme}>{counters.pulls || 0}</Chip>
            </StyledDrawerListItem>
            <StyledDrawerListItem
              themeScheme={themeScheme}
              href={pathPipelines}
              className={
                commonProps.path! === pathPipelines ||
                commonProps.path!.startsWith(pathPipelines)
                  ? "active"
                  : undefined
              }
            >
              <span>Pipelines</span>
              <Chip themeScheme={themeScheme}>{counters.builds || 0}</Chip>
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Tests & Coverage</span>
              <Chip themeScheme={themeScheme}>{counters.tests || 0}</Chip>
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Issues</span>
              <Chip themeScheme={themeScheme}>{counters.issues || 0}</Chip>
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>API Reference</span>
              <Chip themeScheme={themeScheme}>
                {counters.apiRefSymbols || 0}
              </Chip>
            </StyledDrawerListItem>
          </StyledDrawerList>
          <StyledDrawerListHeader></StyledDrawerListHeader>
          <StyledDrawerList></StyledDrawerList>
        </StyledDrawerContent>
        <StyledDrawerFooter>
          <StyledDrawerList>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Feedback</span>
              <CommentIcon
                color={NamedColors.TEXT_MUTED[themeScheme]}
                size={20}
              />
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Help Center</span>
              <span style={{ flex: 1 }}></span>
              {counters.helpCenterNotifs! > 0 && (
                <Chip themeScheme={themeScheme}>
                  {counters.helpCenterNotifs}
                </Chip>
              )}
              <SupportIcon
                color={NamedColors.TEXT_MUTED[themeScheme]}
                size={20}
              />
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Settings</span>
              <SettingsIcon
                color={NamedColors.TEXT_MUTED[themeScheme]}
                size={20}
              />
            </StyledDrawerListItem>
          </StyledDrawerList>
        </StyledDrawerFooter>
      </StyledDrawerPrimary>
      <StyledDrawerOverlay href="#?"></StyledDrawerOverlay>
    </>
  );
};

const StyledDrawerOverlay = styled.a`
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  width: 100vw;
  height: 100vh;
  z-index: 21000;
  pointer-events: none;
  user-select: none;
  background: rgba(0, 0, 0, 0.4);
  filter: blur(8px);
  opacity: 0;
  transition: opacity 140ms ease-in-out 140ms;
`;

const StyledDrawerPrimary = styled.aside<
  WithThemeSchemeProp & { color?: string }
>`
  ${({ themeScheme }) => css`
    min-width: 300px;
    max-width: 320px;
    height: 100vh;

    display: flex;
    flex-flow: column nowrap;
    align-items: center;
    justify-content: center;

    position: sticky;
    top: 0;
    left: 0;
    bottom: 0;

    background: ${NamedColors.HEADER[themeScheme]};
    border-right: 1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]};

    transition: transform 140ms cubic-bezier(0, 0, 0.2, 1);

    @media only screen and (max-width: 768px) {
      & {
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        z-index: 10000;
        width: 85vw;
        max-width: 320px;
        transition: transform 140ms cubic-bezier(0, 0, 0.2, 1);
        transform: translateX(-100%);
      }

      &:target {
        transform: translateX(0);
      }

      &:target ~ ${StyledDrawerOverlay} {
        display: flex;
        pointer-events: auto;
        opacity: 1;
        z-index: 8000;
      }
    }
  `};
`;

const StyledDrawerHeader = styled.header`
  width: 100%;
  height: 64px;

  display: flex;
  justify-content: center;
  align-items: center;
`;

const StyledLogoArea = styled.div<WithThemeSchemeProp>`
  @media only screen and (max-width: 768px) {
    & > a > h1 {
      font-size: 22px;
    }
  }

  & > a {
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    align-items: center;

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

    h1 {
      margin: 0;
    }
  }
`;

const StyledDrawerContent = styled.main`
  width: 100%;
  max-width: 100%;
  min-width: 100%;
  height: 100%;

  flex: 1;

  padding: 12px;
  overflow-y: auto;
`;

const StyledDrawerListHeader = styled.section`
  width: 100%;
  min-height: 40px;

  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  align-items: center;

  font-weight: bold;

  margin-bottom: 12px;

  & > span {
    margin: 0 4px;
  }
`;

const StyledDrawerList = styled.section`
  width: 100%;

  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-start;
  align-items: center;

  gap: 2px;
`;

const StyledDrawerListItem = styled.a<
  WithThemeSchemeProp & { disabled?: boolean }
>`
  ${({ disabled, themeScheme }) => css`
    width: 100%;
    height: 40px;

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

    padding: 0 12px;

    font-weight: normal;
    font-size: 14px;
    color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
    border-radius: 20px;
    text-decoration: none;

    & > span:nth-child(1) {
      flex: 1;
    }

    & > ${Chip} {
      color: ${NamedColors.TEXT_MUTED[themeScheme]};
      background-color: ${NamedColors.CARD_OVERLAY[themeScheme]};
    }

    ${(disabled == null || disabled === false) &&
    css`
      &.active,
      &:not(:disabled):hover {
        color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
        background-color: ${NamedColors.CARD[themeScheme]};
        font-weight: bold;
        font-family: monospace;
      }
    `};

    &:hover {
      text-decoration: none;
    }

    &:disabled {
      color: ${NamedColors.TEXT_MUTED[themeScheme]};
    }

    ${disabled &&
    css`
      color: ${NamedColors.TEXT_MUTED[themeScheme]};

      & > ${Chip} {
        color: ${NamedColors.TEXT_MUTED[themeScheme]};
        opacity: 0.3;
      }
    `}
  `}
`;

const StyledDrawerFooter = styled.footer`
  width: 100%;
  height: 128px;

  display: flex;
  justify-content: flex-start;
  align-items: center;

  margin: 16px 0;
  padding: 0 12px;
`;

.ts
TypeScript
(application/typescript)
// 3rd-party
import React from "react";
import styled, { css } from "styled-components";
// import Color from "color";
// app
import { Const } from "../const";
import { Colors, NamedColors } from "../utils/style";
import {
  type RepositoryCountersDTO,
  type CommonViewProps,
  type WithThemeSchemeProp,
} from "../types";
// import { useMediaQuery } from "../utils/hooks/useMediaQuery";
import { buildRouteLink } from "../utils/shared";
import { AppRoute } from "../routes.defs";
// app components
import { Chip } from "./Chip";
import { TextEllipsis } from "./TextEllipsis.styled";
import { SupportIcon } from "./icons/SupportIcon";
import { SettingsIcon } from "./icons/SettingsIcon";
import { FolderIcon } from "./icons/FolderIcon";
import { CommentIcon } from "./icons/CommentIcon";
import { Grid } from "./Grid";
import { GitForkIcon } from "./icons/GitForkIcon";
import { GitPullIcon } from "./icons/GitPullIcon";
import { LikeIcon } from "./icons/LikeIcon";

export const DrawerPrimary = ({
  visible = false,
  commonProps,
  themeScheme,
  orgSlug,
  repoSlug,
  currentRef = Const.DEFAULT_HEAD_REF,
  path = "/",
  counters = {
    pulls: 0,
    tests: 0,
    builds: 0,
    issues: 0,
    apiRefSymbols: 0,
  },
}: WithThemeSchemeProp & {
  visible: boolean;
  commonProps: CommonViewProps;
  orgSlug: string;
  repoSlug: string;
  currentRef?: string;
  path?: string;
  counters?: RepositoryCountersDTO;
}) => {
  const pathRepo = buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
    orgSlug: orgSlug,
    repoSlug: repoSlug,
  });

  const pathRepoTrailing = buildRouteLink(
    AppRoute.REPOSITORY_DETAILS_WITH_TRAILING_SLASH,
    {
      orgSlug: orgSlug,
      repoSlug: repoSlug,
    },
  );

  const pathFiles = buildRouteLink(AppRoute.REPOSITORY_BROWSER, {
    orgSlug: orgSlug,
    repoSlug: repoSlug,
    currentRef: currentRef,
    "*": path,
  });

  const pathPulls = buildRouteLink(AppRoute.REPOSITORY_PULL_REQUESTS, {
    orgSlug: orgSlug,
    repoSlug: repoSlug,
  });

  const pathPipelines = buildRouteLink(AppRoute.REPOSITORY_PIPELINES, {
    orgSlug: orgSlug,
    repoSlug: repoSlug,
  });

  // const isMobile = useMediaQuery("sm");
  // if (isMobile === false) {
  //   visible = true;
  // }

  if (visible === false) {
    return null;
  }

  return (
    <>
      <StyledDrawerPrimary id="drawer" themeScheme={themeScheme}>
        <StyledDrawerHeader>
          <StyledLogoArea themeScheme={themeScheme}>
            <a href={"/"}>
              <h1>{Const.APP_NAME}</h1>
            </a>
          </StyledLogoArea>
        </StyledDrawerHeader>
        <StyledDrawerContent>
          <StyledDrawerListHeader style={{ margin: 0 }}>
            <a
              href={buildRouteLink(AppRoute.ORGANIZATION_DETAILS, { orgSlug })}
            >
              @{orgSlug}
            </a>
            <span>{" / "}</span>
            <a
              href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
                orgSlug,
                repoSlug,
              })}
            >
              <TextEllipsis>{repoSlug}</TextEllipsis>
            </a>
          </StyledDrawerListHeader>
          <StyledDrawerListHeader style={{ height: 32 }}>
            <Grid.Row
              fluid
              nowrap
              gap={8}
              justifyContent={"center"}
              alignItems={"center"}
            >
              <Grid.Row nowrap gap={4} alignItems={"center"}>
                <GitPullIcon
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  size={16}
                />
                <span style={{ fontSize: 11 }}>Watchers</span>
                <Chip
                  themeScheme={themeScheme}
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  style={{
                    padding: "2px 6px",
                    backgroundColor: "rgba(0,0,0,0.1)",
                    fontSize: 11,
                    color: NamedColors.TEXT_MUTED[themeScheme],
                  }}
                >
                  {counters.watchers || "0"}
                </Chip>
              </Grid.Row>
              <Grid.Row nowrap gap={4} alignItems={"center"}>
                <LikeIcon
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  size={16}
                />
                <span style={{ fontSize: 11 }}>Likes</span>
                <Chip
                  themeScheme={themeScheme}
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  style={{
                    padding: "2px 6px",
                    backgroundColor: "rgba(0,0,0,0.1)",
                    fontSize: 11,
                    color: NamedColors.TEXT_MUTED[themeScheme],
                  }}
                >
                  {counters.likes || "0"}
                </Chip>
              </Grid.Row>
              <Grid.Row nowrap gap={4} alignItems={"center"}>
                <GitForkIcon color={Colors.WHITE_01} size={16} />
                <span style={{ fontSize: 11 }}>Forks</span>
                <Chip
                  themeScheme={themeScheme}
                  color={NamedColors.TEXT_MUTED[themeScheme]}
                  style={{
                    padding: "2px 6px",
                    backgroundColor: "rgba(0,0,0,0.1)",
                    fontSize: 11,
                    color: NamedColors.TEXT_MUTED[themeScheme],
                  }}
                >
                  {counters.forks || "0"}
                </Chip>
              </Grid.Row>
            </Grid.Row>
          </StyledDrawerListHeader>
          <StyledDrawerList>
            <StyledDrawerListItem
              themeScheme={themeScheme}
              href={pathFiles}
              className={
                ((!commonProps.path!.startsWith(pathPipelines) === false &&
                  commonProps.path!.startsWith(pathFiles)) ||
                  [pathFiles, pathRepo, pathRepoTrailing].some(
                    (p) =>
                      commonProps.path === p || commonProps.path!.startsWith(p),
                  )) &&
                commonProps.path!.startsWith(pathPulls) === false &&
                commonProps.path!.startsWith(pathPipelines) === false
                  ? "active"
                  : undefined
              }
              style={{ paddingRight: 16 }}
            >
              <span>Files</span>
              <FolderIcon
                color={
                  ((!commonProps.path!.startsWith(pathPipelines) === false &&
                    commonProps.path!.startsWith(pathFiles)) ||
                    [pathFiles, pathRepo, pathRepoTrailing].some(
                      (p) =>
                        commonProps.path === p ||
                        commonProps.path!.startsWith(p),
                    )) &&
                  commonProps.path!.startsWith(pathPulls) === false &&
                  commonProps.path!.startsWith(pathPipelines) === false
                    ? NamedColors.TEXT_DEFAULT[themeScheme]
                    : NamedColors.TEXT_MUTED[themeScheme]
                }
                size={16}
              />
            </StyledDrawerListItem>
            <StyledDrawerListItem
              themeScheme={themeScheme}
              href={pathPulls}
              className={
                commonProps.path! === pathPulls ||
                commonProps.path!.startsWith(pathPulls)
                  ? "active"
                  : undefined
              }
            >
              <span>Pull Requests</span>
              <Chip themeScheme={themeScheme}>{counters.pulls || 0}</Chip>
            </StyledDrawerListItem>
            <StyledDrawerListItem
              themeScheme={themeScheme}
              href={pathPipelines}
              className={
                commonProps.path! === pathPipelines ||
                commonProps.path!.startsWith(pathPipelines)
                  ? "active"
                  : undefined
              }
            >
              <span>Pipelines</span>
              <Chip themeScheme={themeScheme}>{counters.builds || 0}</Chip>
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Tests & Coverage</span>
              <Chip themeScheme={themeScheme}>{counters.tests || 0}</Chip>
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Issues</span>
              <Chip themeScheme={themeScheme}>{counters.issues || 0}</Chip>
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>API Reference</span>
              <Chip themeScheme={themeScheme}>
                {counters.apiRefSymbols || 0}
              </Chip>
            </StyledDrawerListItem>
          </StyledDrawerList>
          <StyledDrawerListHeader></StyledDrawerListHeader>
          <StyledDrawerList></StyledDrawerList>
        </StyledDrawerContent>
        <StyledDrawerFooter>
          <StyledDrawerList>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Feedback</span>
              <CommentIcon
                color={NamedColors.TEXT_MUTED[themeScheme]}
                size={20}
              />
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Help Center</span>
              <span style={{ flex: 1 }}></span>
              {counters.helpCenterNotifs! > 0 && (
                <Chip themeScheme={themeScheme}>
                  {counters.helpCenterNotifs}
                </Chip>
              )}
              <SupportIcon
                color={NamedColors.TEXT_MUTED[themeScheme]}
                size={20}
              />
            </StyledDrawerListItem>
            <StyledDrawerListItem themeScheme={themeScheme} disabled>
              <span>Settings</span>
              <SettingsIcon
                color={NamedColors.TEXT_MUTED[themeScheme]}
                size={20}
              />
            </StyledDrawerListItem>
          </StyledDrawerList>
        </StyledDrawerFooter>
      </StyledDrawerPrimary>
      <StyledDrawerOverlay href="#?"></StyledDrawerOverlay>
    </>
  );
};

const StyledDrawerOverlay = styled.a`
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  width: 100vw;
  height: 100vh;
  z-index: 21000;
  pointer-events: none;
  user-select: none;
  background: rgba(0, 0, 0, 0.4);
  filter: blur(8px);
  opacity: 0;
  transition: opacity 140ms ease-in-out 140ms;
`;

const StyledDrawerPrimary = styled.aside<
  WithThemeSchemeProp & { color?: string }
>`
  ${({ themeScheme }) => css`
    min-width: 300px;
    max-width: 320px;
    height: 100vh;

    display: flex;
    flex-flow: column nowrap;
    align-items: center;
    justify-content: center;

    position: sticky;
    top: 0;
    left: 0;
    bottom: 0;

    background: ${NamedColors.HEADER[themeScheme]};
    border-right: 1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]};

    transition: transform 140ms cubic-bezier(0, 0, 0.2, 1);

    @media only screen and (max-width: 768px) {
      & {
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        z-index: 10000;
        width: 85vw;
        max-width: 320px;
        transition: transform 140ms cubic-bezier(0, 0, 0.2, 1);
        transform: translateX(-100%);
      }

      &:target {
        transform: translateX(0);
      }

      &:target ~ ${StyledDrawerOverlay} {
        display: flex;
        pointer-events: auto;
        opacity: 1;
        z-index: 8000;
      }
    }
  `};
`;

const StyledDrawerHeader = styled.header`
  width: 100%;
  height: 64px;

  display: flex;
  justify-content: center;
  align-items: center;
`;

const StyledLogoArea = styled.div<WithThemeSchemeProp>`
  @media only screen and (max-width: 768px) {
    & > a > h1 {
      font-size: 22px;
    }
  }

  & > a {
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    align-items: center;

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

    h1 {
      margin: 0;
    }
  }
`;

const StyledDrawerContent = styled.main`
  width: 100%;
  max-width: 100%;
  min-width: 100%;
  height: 100%;

  flex: 1;

  padding: 12px;
  overflow-y: auto;
`;

const StyledDrawerListHeader = styled.section`
  width: 100%;
  min-height: 40px;

  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  align-items: center;

  font-weight: bold;

  margin-bottom: 12px;

  & > span {
    margin: 0 4px;
  }
`;

const StyledDrawerList = styled.section`
  width: 100%;

  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-start;
  align-items: center;

  gap: 2px;
`;

const StyledDrawerListItem = styled.a<
  WithThemeSchemeProp & { disabled?: boolean }
>`
  ${({ disabled, themeScheme }) => css`
    width: 100%;
    height: 40px;

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

    padding: 0 12px;

    font-weight: normal;
    font-size: 14px;
    color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
    border-radius: 20px;
    text-decoration: none;

    & > span:nth-child(1) {
      flex: 1;
    }

    & > ${Chip} {
      color: ${NamedColors.TEXT_MUTED[themeScheme]};
      background-color: ${NamedColors.CARD_OVERLAY[themeScheme]};
    }

    ${(disabled == null || disabled === false) &&
    css`
      &.active,
      &:not(:disabled):hover {
        color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
        background-color: ${NamedColors.CARD[themeScheme]};
        font-weight: bold;
        font-family: monospace;
      }
    `};

    &:hover {
      text-decoration: none;
    }

    &:disabled {
      color: ${NamedColors.TEXT_MUTED[themeScheme]};
    }

    ${disabled &&
    css`
      color: ${NamedColors.TEXT_MUTED[themeScheme]};

      & > ${Chip} {
        color: ${NamedColors.TEXT_MUTED[themeScheme]};
        opacity: 0.3;
      }
    `}
  `}
`;

const StyledDrawerFooter = styled.footer`
  width: 100%;
  height: 128px;

  display: flex;
  justify-content: flex-start;
  align-items: center;

  margin: 16px 0;
  padding: 0 12px;
`;

GitFOSS • v0.2.0 (#50a2553) • MIT License