Parcourir la source

Make dialogs look better on mobile (#908)

* Standardize mobile media query

* Refactor & add mobile support to dialogs

* back & close icons
Jed Fox il y a 5 ans
Parent
commit
668f8ec4a6

+ 1 - 0
src/_variables.scss

@@ -0,0 +1 @@
+$media-query: "(max-width: 600px), (max-height: 500px) and (max-width: 1000px)";

+ 49 - 0
src/components/Dialog.scss

@@ -0,0 +1,49 @@
+@import "../_variables";
+
+.Dialog__title {
+  --metric: calc(var(--space-factor) * 4);
+  display: grid;
+  align-items: center;
+  margin-top: 0;
+  grid-template-columns: 1fr calc(var(--space-factor) * 7);
+  grid-gap: var(--metric);
+}
+
+.Dialog__titleContent {
+  flex: 1;
+}
+
+.Dialog .Modal__close {
+  margin: 0;
+}
+
+@media #{$media-query} {
+  .Dialog__title {
+    grid-template-columns: calc(var(--space-factor) * 7) 1fr calc(
+        var(--space-factor) * 7
+      );
+    position: sticky;
+    top: calc(-1 * var(--metric));
+    margin: calc(-1 * var(--metric));
+    margin-bottom: var(--metric);
+    padding: calc(var(--space-factor) * 2) var(--metric);
+    background: white;
+    font-size: 1.25em;
+
+    box-sizing: border-box;
+    border-bottom: 1px solid #ccc;
+    z-index: 1;
+  }
+  .Dialog__titleContent {
+    text-align: center;
+  }
+  .Dialog .Island {
+    height: 100%;
+    box-sizing: border-box;
+    overflow-y: auto;
+  }
+
+  .Dialog .Modal__close {
+    order: -1;
+  }
+}

+ 41 - 0
src/components/Dialog.tsx

@@ -0,0 +1,41 @@
+import React from "react";
+import { Modal } from "./Modal";
+import { Island } from "./Island";
+import { t } from "../i18n";
+import useIsMobile from "../is-mobile";
+import { back, close } from "./icons";
+
+import "./Dialog.scss";
+
+export function Dialog(props: {
+  children: React.ReactNode;
+  className?: string;
+  maxWidth?: number;
+  onCloseRequest(): void;
+  closeButtonRef?: React.Ref<HTMLButtonElement>;
+  title: React.ReactNode;
+}) {
+  return (
+    <Modal
+      className={`${props.className ?? ""} Dialog`}
+      labelledBy="dialog-title"
+      maxWidth={props.maxWidth}
+      onCloseRequest={props.onCloseRequest}
+    >
+      <Island padding={4}>
+        <h2 id="dialog-title" className="Dialog__title">
+          <span className="Dialog__titleContent">{props.title}</span>
+          <button
+            className="Modal__close"
+            onClick={props.onCloseRequest}
+            aria-label={t("buttons.close")}
+            ref={props.closeButtonRef}
+          >
+            {useIsMobile() ? back : close}
+          </button>
+        </h2>
+        {props.children}
+      </Island>
+    </Modal>
+  );
+}

+ 25 - 0
src/components/ExportDialog.css → src/components/ExportDialog.scss

@@ -1,3 +1,5 @@
+@import "../_variables";
+
 .ExportDialog__preview {
   --preview-padding: calc(var(--space-factor) * 4);
 
@@ -25,3 +27,26 @@
   align-items: baseline;
   justify-content: flex-end;
 }
+
+@media #{$media-query} {
+  .ExportDialog__preview canvas {
+    max-height: 30vh;
+  }
+  .ExportDialog__dialog,
+  .ExportDialog__dialog .Island {
+    height: 100%;
+    box-sizing: border-box;
+  }
+  .ExportDialog__dialog .Island {
+    overflow-y: auto;
+  }
+  .ExportDialog__actions {
+    flex-direction: column;
+  }
+  .ExportDialog__actions > * {
+    margin-bottom: calc(var(--space-factor) * 3);
+  }
+  .ExportDialog__scales {
+    justify-content: flex-start;
+  }
+}

+ 77 - 87
src/components/ExportDialog.tsx

@@ -1,11 +1,9 @@
-import "./ExportDialog.css";
+import "./ExportDialog.scss";
 
 import React, { useState, useEffect, useRef } from "react";
 
-import { Modal } from "./Modal";
 import { ToolButton } from "./ToolButton";
 import { clipboard, exportFile, link } from "./icons";
-import { Island } from "./Island";
 import { ExcalidrawElement } from "../element/types";
 import { AppState } from "../types";
 import { exportToCanvas } from "../scene/export";
@@ -18,6 +16,7 @@ import { KEYS } from "../keys";
 import { probablySupportsClipboardBlob } from "../clipboard";
 import { getSelectedElements, isSomeElementSelected } from "../scene";
 import useIsMobile from "../is-mobile";
+import { Dialog } from "./Dialog";
 
 const scales = [1, 2, 3];
 const defaultScale = scales.includes(devicePixelRatio) ? devicePixelRatio : 1;
@@ -36,7 +35,7 @@ function ExportModal({
   onExportToSvg,
   onExportToClipboard,
   onExportToBackend,
-  onCloseRequest,
+  closeButton,
 }: {
   appState: AppState;
   elements: readonly ExcalidrawElement[];
@@ -47,6 +46,7 @@ function ExportModal({
   onExportToClipboard: ExportCB;
   onExportToBackend: ExportCB;
   onCloseRequest: () => void;
+  closeButton: React.RefObject<HTMLButtonElement>;
 }) {
   const someElementIsSelected = isSomeElementSelected(elements, appState);
   const [scale, setScale] = useState(defaultScale);
@@ -54,7 +54,6 @@ function ExportModal({
   const previewRef = useRef<HTMLDivElement>(null);
   const { exportBackground, viewBackgroundColor } = appState;
   const pngButton = useRef<HTMLButtonElement>(null);
-  const closeButton = useRef<HTMLButtonElement>(null);
   const onlySelectedInput = useRef<HTMLInputElement>(null);
 
   const exportedElements = exportSelected
@@ -113,92 +112,80 @@ function ExportModal({
 
   return (
     <div onKeyDown={handleKeyDown}>
-      <Island padding={4}>
-        <button
-          className="Modal__close"
-          onClick={onCloseRequest}
-          aria-label={t("buttons.close")}
-          ref={closeButton}
-        >
-          ╳
-        </button>
-        <h2 id="export-title">{t("buttons.export")}</h2>
-        <div className="ExportDialog__preview" ref={previewRef}></div>
-        <div className="ExportDialog__actions">
-          <Stack.Col gap={1}>
-            <Stack.Row gap={2}>
-              <ToolButton
-                type="button"
-                label="PNG"
-                title={t("buttons.exportToPng")}
-                aria-label={t("buttons.exportToPng")}
-                onClick={() => onExportToPng(exportedElements, scale)}
-                ref={pngButton}
-              />
+      <div className="ExportDialog__preview" ref={previewRef}></div>
+      <div className="ExportDialog__actions">
+        <Stack.Col gap={1}>
+          <Stack.Row gap={2}>
+            <ToolButton
+              type="button"
+              label="PNG"
+              title={t("buttons.exportToPng")}
+              aria-label={t("buttons.exportToPng")}
+              onClick={() => onExportToPng(exportedElements, scale)}
+              ref={pngButton}
+            />
+            <ToolButton
+              type="button"
+              label="SVG"
+              title={t("buttons.exportToSvg")}
+              aria-label={t("buttons.exportToSvg")}
+              onClick={() => onExportToSvg(exportedElements, scale)}
+            />
+            {probablySupportsClipboardBlob && (
               <ToolButton
                 type="button"
-                label="SVG"
-                title={t("buttons.exportToSvg")}
-                aria-label={t("buttons.exportToSvg")}
-                onClick={() => onExportToSvg(exportedElements, scale)}
+                icon={clipboard}
+                title={t("buttons.copyToClipboard")}
+                aria-label={t("buttons.copyToClipboard")}
+                onClick={() => onExportToClipboard(exportedElements, scale)}
               />
-              {probablySupportsClipboardBlob && (
+            )}
+            <ToolButton
+              type="button"
+              icon={link}
+              title={t("buttons.getShareableLink")}
+              aria-label={t("buttons.getShareableLink")}
+              onClick={() => onExportToBackend(exportedElements)}
+            />
+          </Stack.Row>
+        </Stack.Col>
+        {actionManager.renderAction("changeProjectName")}
+        <Stack.Col gap={1}>
+          <div className="ExportDialog__scales">
+            <Stack.Row gap={2} align="baseline">
+              {scales.map(s => (
                 <ToolButton
-                  type="button"
-                  icon={clipboard}
-                  title={t("buttons.copyToClipboard")}
-                  aria-label={t("buttons.copyToClipboard")}
-                  onClick={() => onExportToClipboard(exportedElements, scale)}
+                  key={s}
+                  size="s"
+                  type="radio"
+                  icon={`x${s}`}
+                  name="export-canvas-scale"
+                  aria-label={`Scale ${s} x`}
+                  id="export-canvas-scale"
+                  checked={s === scale}
+                  onChange={() => setScale(s)}
                 />
-              )}
-              <ToolButton
-                type="button"
-                icon={link}
-                title={t("buttons.getShareableLink")}
-                aria-label={t("buttons.getShareableLink")}
-                onClick={() => onExportToBackend(exportedElements)}
-              />
+              ))}
             </Stack.Row>
-          </Stack.Col>
-
-          {actionManager.renderAction("changeProjectName")}
-          <Stack.Col gap={1}>
-            <div className="ExportDialog__scales">
-              <Stack.Row gap={2} align="baseline">
-                {scales.map(s => (
-                  <ToolButton
-                    key={s}
-                    size="s"
-                    type="radio"
-                    icon={`x${s}`}
-                    name="export-canvas-scale"
-                    aria-label={`Scale ${s} x`}
-                    id="export-canvas-scale"
-                    checked={s === scale}
-                    onChange={() => setScale(s)}
-                  />
-                ))}
-              </Stack.Row>
+          </div>
+          {actionManager.renderAction("changeExportBackground")}
+          {someElementIsSelected && (
+            <div>
+              <label>
+                <input
+                  type="checkbox"
+                  checked={exportSelected}
+                  onChange={event =>
+                    setExportSelected(event.currentTarget.checked)
+                  }
+                  ref={onlySelectedInput}
+                />{" "}
+                {t("labels.onlySelected")}
+              </label>
             </div>
-            {actionManager.renderAction("changeExportBackground")}
-            {someElementIsSelected && (
-              <div>
-                <label>
-                  <input
-                    type="checkbox"
-                    checked={exportSelected}
-                    onChange={event =>
-                      setExportSelected(event.currentTarget.checked)
-                    }
-                    ref={onlySelectedInput}
-                  />{" "}
-                  {t("labels.onlySelected")}
-                </label>
-              </div>
-            )}
-          </Stack.Col>
-        </div>
-      </Island>
+          )}
+        </Stack.Col>
+      </div>
     </div>
   );
 }
@@ -224,6 +211,7 @@ export function ExportDialog({
 }) {
   const [modalIsShown, setModalIsShown] = useState(false);
   const triggerButton = useRef<HTMLButtonElement>(null);
+  const closeButton = useRef<HTMLButtonElement>(null);
 
   const handleClose = React.useCallback(() => {
     setModalIsShown(false);
@@ -242,10 +230,11 @@ export function ExportDialog({
         ref={triggerButton}
       />
       {modalIsShown && (
-        <Modal
+        <Dialog
           maxWidth={800}
           onCloseRequest={handleClose}
-          labelledBy="export-title"
+          title={t("buttons.export")}
+          closeButtonRef={closeButton}
         >
           <ExportModal
             elements={elements}
@@ -257,8 +246,9 @@ export function ExportDialog({
             onExportToClipboard={onExportToClipboard}
             onExportToBackend={onExportToBackend}
             onCloseRequest={handleClose}
+            closeButton={closeButton}
           />
-        </Modal>
+        </Dialog>
       )}
     </>
   );

+ 9 - 10
src/components/HintViewer.css → src/components/HintViewer.scss

@@ -1,3 +1,5 @@
+@import "../_variables";
+
 .HintViewer {
   color: #868e96; /* OC: GRAY 6*/
   font-size: 0.8rem;
@@ -6,19 +8,16 @@
   position: absolute;
   top: 54px;
   transform: translateX(calc(-50% - 16px)); /* 16px is half of lock icon */
-}
-
-.HintViewer > span {
-  background-color: rgba(255, 255, 255, 0.88);
-  padding: 0.2rem 0.4rem;
-  border-radius: 3px;
-}
-
-@media (max-width: 600px), (max-height: 500px) and (max-width: 1000px) {
-  .HintViewer {
+  @media #{$media-query} {
     position: static;
     transform: none;
     margin-top: 0.5rem;
     text-align: center;
   }
+
+  > span {
+    background-color: rgba(255, 255, 255, 0.88);
+    padding: 0.2rem 0.4rem;
+    border-radius: 3px;
+  }
 }

+ 1 - 1
src/components/HintViewer.tsx

@@ -3,7 +3,7 @@ import { t } from "../i18n";
 import { ExcalidrawElement } from "../element/types";
 import { getSelectedElements } from "../scene";
 
-import "./HintViewer.css";
+import "./HintViewer.scss";
 import { AppState } from "../types";
 
 interface Hint {

+ 5 - 4
src/components/Island.tsx

@@ -4,13 +4,14 @@ import React from "react";
 
 type IslandProps = { children: React.ReactNode; padding?: number };
 
-export function Island({ children, padding }: IslandProps) {
-  return (
+export const Island = React.forwardRef<HTMLDivElement, IslandProps>(
+  ({ children, padding }, ref) => (
     <div
       className="Island"
       style={{ "--padding": padding } as React.CSSProperties}
+      ref={ref}
     >
       {children}
     </div>
-  );
-}
+  ),
+);

+ 25 - 1
src/components/Modal.css → src/components/Modal.scss

@@ -1,3 +1,5 @@
+@import "../_variables";
+
 .Modal {
   position: fixed;
   top: 0;
@@ -44,9 +46,31 @@
     transform: translateY(0);
   }
 }
-
 .Modal__close {
+  width: calc(var(--space-factor) * 7);
+  height: calc(var(--space-factor) * 7);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  svg {
+    height: calc(var(--space-factor) * 5);
+  }
+}
+.Modal__close--floating {
   position: absolute;
   right: calc(var(--space-factor) * 5);
   top: calc(var(--space-factor) * 5);
 }
+
+@media #{$media-query} {
+  .Modal {
+    padding: 0;
+  }
+  .Modal__content {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+  }
+}

+ 3 - 2
src/components/Modal.tsx

@@ -1,10 +1,11 @@
-import "./Modal.css";
+import "./Modal.scss";
 
 import React, { useEffect, useState } from "react";
 import { createPortal } from "react-dom";
 import { KEYS } from "../keys";
 
 export function Modal(props: {
+  className?: string;
   children: React.ReactNode;
   maxWidth?: number;
   onCloseRequest(): void;
@@ -20,7 +21,7 @@ export function Modal(props: {
   };
   return createPortal(
     <div
-      className="Modal"
+      className={`Modal ${props.className ?? ""}`}
       role="dialog"
       aria-modal="true"
       onKeyDown={handleKeydown}

+ 1 - 1
src/components/ProjectName.css

@@ -1,7 +1,7 @@
 .ProjectName {
   display: inline-block;
   cursor: pointer;
-  border: none;
+  border: 1.5px solid #eee;
   height: 2.5rem;
   line-height: 2.5rem;
   padding: 0 0.5rem;

+ 65 - 78
src/components/RoomDialog.tsx

@@ -1,21 +1,19 @@
 import React, { useState, useEffect, useRef } from "react";
 import { ToolButton } from "./ToolButton";
-import { Island } from "./Island";
 import { t } from "../i18n";
 import useIsMobile from "../is-mobile";
 import { users, clipboard, start, stop } from "./icons";
-import { Modal } from "./Modal";
+
+import "./RoomDialog.scss";
 import { copyTextToSystemClipboard } from "../clipboard";
+import { Dialog } from "./Dialog";
 import { AppState } from "../types";
-import "./RoomDialog.scss";
 
 function RoomModal({
-  onCloseRequest,
   activeRoomLink,
   onRoomCreate,
   onRoomDestroy,
 }: {
-  onCloseRequest: () => void;
   activeRoomLink: string;
   onRoomCreate: () => void;
   onRoomDestroy: () => void;
@@ -36,75 +34,65 @@ function RoomModal({
 
   return (
     <div className="RoomDialog-modal">
-      <Island padding={4}>
-        <button
-          className="Modal__close"
-          onClick={onCloseRequest}
-          aria-label={t("buttons.close")}
-        >
-          ╳
-        </button>
-        <h2 id="export-title">{t("labels.createRoom")}</h2>
-        {!activeRoomLink && (
-          <>
-            <p>{t("roomDialog.desc_intro")}</p>
-            <p>{`🔒 ${t("roomDialog.desc_privacy")}`}</p>
-            <p>{t("roomDialog.desc_start")}</p>
-            <div className="RoomDialog-sessionStartButtonContainer">
-              <ToolButton
-                className="RoomDialog-startSession"
-                type="button"
-                icon={start}
-                title={t("roomDialog.button_startSession")}
-                aria-label={t("roomDialog.button_startSession")}
-                showAriaLabel={true}
-                onClick={onRoomCreate}
-              />
-            </div>
-          </>
-        )}
-        {activeRoomLink && (
-          <>
-            <p>{t("roomDialog.desc_inProgressIntro")}</p>
-            <p>{t("roomDialog.desc_shareLink")}</p>
-            <div className="RoomDialog-linkContainer">
-              <ToolButton
-                type="button"
-                icon={clipboard}
-                title={t("labels.copy")}
-                aria-label={t("labels.copy")}
-                onClick={copyRoomLink}
-              />
-              <input
-                value={activeRoomLink}
-                readOnly={true}
-                className="RoomDialog-link"
-                ref={roomLinkInput}
-                onPointerDown={selectInput}
-              />
-            </div>
-            <p>{`🔒 ${t("roomDialog.desc_privacy")}`}</p>
-            <p>
-              <span role="img" aria-hidden="true">
-                ⚠️
-              </span>{" "}
-              {t("roomDialog.desc_persistenceWarning")}
-            </p>
-            <p>{t("roomDialog.desc_exitSession")}</p>
-            <div className="RoomDialog-sessionStartButtonContainer">
-              <ToolButton
-                className="RoomDialog-stopSession"
-                type="button"
-                icon={stop}
-                title={t("roomDialog.button_stopSession")}
-                aria-label={t("roomDialog.button_stopSession")}
-                showAriaLabel={true}
-                onClick={onRoomDestroy}
-              />
-            </div>
-          </>
-        )}
-      </Island>
+      {!activeRoomLink && (
+        <>
+          <p>{t("roomDialog.desc_intro")}</p>
+          <p>{`🔒 ${t("roomDialog.desc_privacy")}`}</p>
+          <p>{t("roomDialog.desc_start")}</p>
+          <div className="RoomDialog-sessionStartButtonContainer">
+            <ToolButton
+              className="RoomDialog-startSession"
+              type="button"
+              icon={start}
+              title={t("roomDialog.button_startSession")}
+              aria-label={t("roomDialog.button_startSession")}
+              showAriaLabel={true}
+              onClick={onRoomCreate}
+            />
+          </div>
+        </>
+      )}
+      {activeRoomLink && (
+        <>
+          <p>{t("roomDialog.desc_inProgressIntro")}</p>
+          <p>{t("roomDialog.desc_shareLink")}</p>
+          <div className="RoomDialog-linkContainer">
+            <ToolButton
+              type="button"
+              icon={clipboard}
+              title={t("labels.copy")}
+              aria-label={t("labels.copy")}
+              onClick={copyRoomLink}
+            />
+            <input
+              value={activeRoomLink}
+              readOnly={true}
+              className="RoomDialog-link"
+              ref={roomLinkInput}
+              onPointerDown={selectInput}
+            />
+          </div>
+          <p>{`🔒 ${t("roomDialog.desc_privacy")}`}</p>
+          <p>
+            <span role="img" aria-hidden="true">
+              ⚠️
+            </span>{" "}
+            {t("roomDialog.desc_persistenceWarning")}
+          </p>
+          <p>{t("roomDialog.desc_exitSession")}</p>
+          <div className="RoomDialog-sessionStartButtonContainer">
+            <ToolButton
+              className="RoomDialog-stopSession"
+              type="button"
+              icon={stop}
+              title={t("roomDialog.button_stopSession")}
+              aria-label={t("roomDialog.button_stopSession")}
+              showAriaLabel={true}
+              onClick={onRoomDestroy}
+            />
+          </div>
+        </>
+      )}
     </div>
   );
 }
@@ -155,18 +143,17 @@ export function RoomDialog({
         )}
       </ToolButton>
       {modalIsShown && (
-        <Modal
+        <Dialog
           maxWidth={800}
-          labelledBy="room-title"
           onCloseRequest={handleClose}
+          title={t("labels.createRoom")}
         >
           <RoomModal
-            onCloseRequest={handleClose}
             activeRoomLink={activeRoomLink}
             onRoomCreate={onRoomCreate}
             onRoomDestroy={onRoomDestroy}
           />
-        </Modal>
+        </Dialog>
       )}
     </>
   );

+ 2 - 0
src/components/ToolIcon.scss

@@ -13,6 +13,8 @@
   cursor: pointer;
   background-color: var(--button-gray-1);
   -webkit-tap-highlight-color: transparent;
+
+  border-radius: var(--space-factor);
 }
 
 .ToolIcon__icon {

+ 18 - 12
src/components/icons.tsx

@@ -11,12 +11,14 @@ const createIcon = (
   d: string | React.ReactNode,
   width = 512,
   height = width,
+  style?: React.CSSProperties,
 ) => (
   <svg
     aria-hidden="true"
     focusable="false"
     role="img"
     viewBox={`0 0 ${width} ${height}`}
+    style={style}
   >
     {typeof d === "string" ? <path fill="currentColor" d={d} /> : d}
   </svg>
@@ -183,24 +185,28 @@ export const sendToBack = createIcon(
 );
 
 export const users = createIcon(
-  <path
-    fill="currentColor"
-    d="M192 256c61.9 0 112-50.1 112-112S253.9 32 192 32 80 82.1 80 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C51.6 288 0 339.6 0 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zM480 256c53 0 96-43 96-96s-43-96-96-96-96 43-96 96 43 96 96 96zm48 32h-3.8c-13.9 4.8-28.6 8-44.2 8s-30.3-3.2-44.2-8H432c-20.4 0-39.2 5.9-55.7 15.4 24.4 26.3 39.7 61.2 39.7 99.8v38.4c0 2.2-.5 4.3-.6 6.4H592c26.5 0 48-21.5 48-48 0-61.9-50.1-112-112-112z"
-  ></path>,
+  "M192 256c61.9 0 112-50.1 112-112S253.9 32 192 32 80 82.1 80 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C51.6 288 0 339.6 0 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zM480 256c53 0 96-43 96-96s-43-96-96-96-96 43-96 96 43 96 96 96zm48 32h-3.8c-13.9 4.8-28.6 8-44.2 8s-30.3-3.2-44.2-8H432c-20.4 0-39.2 5.9-55.7 15.4 24.4 26.3 39.7 61.2 39.7 99.8v38.4c0 2.2-.5 4.3-.6 6.4H592c26.5 0 48-21.5 48-48 0-61.9-50.1-112-112-112z",
   640,
   512,
 );
 
 export const start = createIcon(
-  <path
-    fill="currentColor"
-    d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm115.7 272l-176 101c-15.8 8.8-35.7-2.5-35.7-21V152c0-18.4 19.8-29.8 35.7-21l176 107c16.4 9.2 16.4 32.9 0 42z"
-  ></path>,
+  "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm115.7 272l-176 101c-15.8 8.8-35.7-2.5-35.7-21V152c0-18.4 19.8-29.8 35.7-21l176 107c16.4 9.2 16.4 32.9 0 42z",
 );
 
 export const stop = createIcon(
-  <path
-    fill="currentColor"
-    d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm96 328c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h160c8.8 0 16 7.2 16 16v160z"
-  ></path>,
+  "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm96 328c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h160c8.8 0 16 7.2 16 16v160z",
+);
+
+export const close = createIcon(
+  "M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z",
+  352,
+  512,
+);
+
+export const back = createIcon(
+  "M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z",
+  320,
+  512,
+  { marginLeft: "-0.2rem" },
 );

+ 2 - 1
src/styles.scss

@@ -1,4 +1,5 @@
 @import "./theme.css";
+@import "./_variables";
 
 body {
   margin: 0;
@@ -359,7 +360,7 @@ button,
   padding: 10px 20px;
 }
 
-@media (max-width: 600px), (max-height: 500px) and (max-width: 1000px) {
+@media #{$media-query} {
   aside {
     display: none;
   }