diff --git a/apps/blueprints/src/components/Button.tsx b/apps/blueprints/src/components/Button.tsx index 5b99637..3880b6a 100644 --- a/apps/blueprints/src/components/Button.tsx +++ b/apps/blueprints/src/components/Button.tsx @@ -15,12 +15,13 @@ export const Button: React.FC = ({ primary, className, children, .. }; const StyledButton = styled.button` + display: inline-flex; + align-items: center; background-color: #8e8e8e; padding: 10px 12px; text-align: left; color: #000; font-weight: 600; - display: inline-block; border: none; line-height: 100%; vertical-align: middle; @@ -58,7 +59,6 @@ const StyledButton = styled.button` position: relative; padding-top: 12px; padding-bottom: 8px; - vertical-align: -2px; box-shadow: inset 0 10px 2px -8px #000, inset 0 9px 2px -8px #000, inset 8px 0 4px -8px #563a10, inset 8px 0 4px -8px #563a10, inset -8px 0 4px -8px #563a10, inset -8px 0 4px -8px #563a10, inset 0 9px 2px -8px #563a10, inset 0 -9px 2px -8px #563a10, inset 0 -8.5px 0 -8px #563a10, diff --git a/apps/blueprints/src/components/CopyButton.tsx b/apps/blueprints/src/components/CopyButton.tsx index d585438..4a51a0b 100644 --- a/apps/blueprints/src/components/CopyButton.tsx +++ b/apps/blueprints/src/components/CopyButton.tsx @@ -5,9 +5,9 @@ import { Button, ButtonProps } from "../components/Button"; const SUCCESS_ICON_DURATION = 2000; -export const CopyButton: React.FC< - Omit & { content: string; label?: string } -> = ({ content, label, ...props }) => { +export type CopyButtonProps = Omit & { content: string; label?: string }; + +export const CopyButton: React.FC = ({ content, label, ...props }) => { const [loading, setLoading] = useState(false); const [iconType, setIconType] = useState<"success" | "error" | null>(null); diff --git a/apps/blueprints/src/components/CopyButtonDropdown.tsx b/apps/blueprints/src/components/CopyButtonDropdown.tsx new file mode 100644 index 0000000..87b90fd --- /dev/null +++ b/apps/blueprints/src/components/CopyButtonDropdown.tsx @@ -0,0 +1,36 @@ +import React, { useState } from "react"; +import { AiFillCaretDown } from "react-icons/ai"; +import { Button } from "../components/Button"; +import { CopyButton } from "../components/CopyButton"; +import { Box } from "@chakra-ui/layout"; +import styled from "@emotion/styled"; + +const Wrapper = styled(Box)` + position: relative; +`; + +const DropdownBox = styled(Box)` + position: absolute; + transform: translateY(100%); + bottom: -0.5rem; + right: 40px; + z-index: 3; +`; + +export const CopyButtonDropdown: React.FC = (props) => { + const [dropdownOpen, setDropdownOpen] = useState(false); + console.log({ dropdownOpen }); + return ( + + + {dropdownOpen && ( + + + + )} + + + ); +}; diff --git a/apps/blueprints/src/components/Markdown.tsx b/apps/blueprints/src/components/Markdown.tsx index 0d5bdcb..82feb5c 100644 --- a/apps/blueprints/src/components/Markdown.tsx +++ b/apps/blueprints/src/components/Markdown.tsx @@ -2,7 +2,7 @@ import { css } from "@emotion/react"; import ReactMarkdown from "react-markdown"; const markdownStyle = css` - overflow: hidden; + overflow: auto; img { max-width: 100%; } @@ -16,8 +16,8 @@ const markdownStyle = css` } `; -export const Markdown: React.FC<{ children: string }> = ({ children }) => ( -
+export const Markdown: React.FC<{ children: string }> = ({ children, ...props }) => ( +
{children}
); diff --git a/apps/blueprints/src/components/Panel.tsx b/apps/blueprints/src/components/Panel.tsx index 529d8cf..902af65 100644 --- a/apps/blueprints/src/components/Panel.tsx +++ b/apps/blueprints/src/components/Panel.tsx @@ -1,8 +1,9 @@ -import { css, SerializedStyles } from "@emotion/react"; +import React, { ReactNode } from "react"; import { Box, BoxProps } from "@chakra-ui/react"; -import { ReactNode } from "react"; +import styled from "@emotion/styled"; +import clsx from "clsx"; -const panelStyles = css` +const StyledPanel = styled(Box)` display: flex; flex-direction: column; padding: 12px; @@ -22,31 +23,36 @@ const panelStyles = css` display: flex; align-items: center; } -`; -const panelInsetStyles = css` - padding: 4px; - box-shadow: inset 0 0 3px 0 #000, 0 -2px 2px -1px #000, -2px 0 2px -2px #28221f, - -2px 0 2px -2px #28221f, 2px 0 2px -2px #28221f, 2px 0 2px -2px #28221f, 0 3px 3px -3px #8f8c8b, - 0 2px 2px -2px #8f8c8b, 0 1px 1px -1px #8f8c8b; - background-color: #242324; - margin-top: 12px; -`; -const boxShadow = `inset 0 0 3px 0 #000, 0 -2px 2px -1px #000, -2px 0 2px -2px #28221f, --2px 0 2px -2px #28221f, 2px 0 2px -2px #28221f, 2px 0 2px -2px #28221f, -0 3px 3px -3px #8f8c8b, 0 2px 2px -2px #8f8c8b, 0 1px 1px -1px #8f8c8b`; -export const Panel: React.FC< - Omit & { - title?: ReactNode; - css?: SerializedStyles; - bottom?: ReactNode; + .panel-content { + color: white; + height: 100%; + padding: 12px; + background: #414040; + box-shadow: inset 0 0 3px 0 #000, 0 -2px 2px -1px #000, -2px 0 2px -2px #28221f, + -2px 0 2px -2px #28221f, 2px 0 2px -2px #28221f, 2px 0 2px -2px #28221f, + 0 3px 3px -3px #8f8c8b, 0 2px 2px -2px #8f8c8b, 0 1px 1px -1px #8f8c8b; } -> = ({ children, title, bottom, css: prop_css, ...props }) => ( - + + .panel-inset { + padding: 4px; + box-shadow: inset 0 0 3px 0 #000, 0 -2px 2px -1px #000, -2px 0 2px -2px #28221f, + -2px 0 2px -2px #28221f, 2px 0 2px -2px #28221f, 2px 0 2px -2px #28221f, + 0 3px 3px -3px #8f8c8b, 0 2px 2px -2px #8f8c8b, 0 1px 1px -1px #8f8c8b; + background-color: #242324; + margin-top: 12px; + } +`; + +interface PanelProps extends Omit { + title?: ReactNode; + bottom?: ReactNode; +} + +export const Panel: React.FC = ({ title, bottom, children, className, ...props }) => ( + {title &&

{title}

} - - {children} - - {bottom && {bottom}} -
+
{children}
+ {bottom &&
{bottom}
} + ); diff --git a/apps/blueprints/src/hooks/url.hook.ts b/apps/blueprints/src/hooks/url.hook.ts new file mode 100644 index 0000000..4ebebb2 --- /dev/null +++ b/apps/blueprints/src/hooks/url.hook.ts @@ -0,0 +1,15 @@ +import { useEffect, useState } from "react"; + +/** + * Get URL safely without SSR-Hydration problems + * @returns + */ +export function useUrl() { + const [url, setUrl] = useState(null); + + useEffect(() => { + setUrl(new URL(window.location.href)); + }, []); + + return url; +} diff --git a/apps/blueprints/src/pages/_app.tsx b/apps/blueprints/src/pages/_app.tsx index 9f81300..2ef5c7d 100644 --- a/apps/blueprints/src/pages/_app.tsx +++ b/apps/blueprints/src/pages/_app.tsx @@ -44,10 +44,11 @@ const globalStyles = css` } main { display: flex; - margin: 1rem; + padding: 1rem; .container { max-width: 1400px; margin: 0 auto; + width: 100%; } } `; diff --git a/apps/blueprints/src/pages/blueprint/[blueprintId].tsx b/apps/blueprints/src/pages/blueprint/[blueprintId].tsx index 9e24c6a..2661db9 100644 --- a/apps/blueprints/src/pages/blueprint/[blueprintId].tsx +++ b/apps/blueprints/src/pages/blueprint/[blueprintId].tsx @@ -2,7 +2,9 @@ import React, { useEffect, useState } from "react"; import { NextPage } from "next"; import Link from "next/link"; import BBCode from "bbcode-to-react"; -import { Grid, Image, Box } from "@chakra-ui/react"; +import { Image, Box, Grid } from "@chakra-ui/react"; +import styled from "@emotion/styled"; +import clsx from "clsx"; import { getBlueprintBookById, getBlueprintById, @@ -29,10 +31,92 @@ import { CopyButton } from "../../components/CopyButton"; import { ImageEditor } from "../../components/ImageEditor"; import { useAuth } from "../../providers/auth"; import { pageHandler } from "../../utils/page-handler"; -import styled from "@emotion/styled"; -import { css } from "@emotion/react"; import { AiOutlineHeart, AiFillHeart } from "react-icons/ai"; import { Button } from "../../components/Button"; +import { useUrl } from "../../hooks/url.hook"; + +const StyledBlueptintPage = styled(Grid)` + grid-gap: 16px; + + .title { + position: relative; + width: 100%; + + .text { + white-space: nowrap; + width: calc(100% - 120px); + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + } + } + + .panel { + &.image { + height: 579px; + } + &.child-tree { + overflow: hidden; + height: 579px; + position: relative; + .child-tree-wrapper { + height: 483px; + overflow: auto; + } + } + &.info { + dl { + display: flex; + dt { + width: 65%; + font-weight: 600; + } + dd { + width: 35%; + text-align: right; + } + } + + hr { + margin-left: -64px; + margin-right: -64px; + border: none; + height: 2px; + margin: 12px auto; + box-shadow: inset 0 1px 1px 0 #131313, inset 0 -1px 1px 0 #838383, 0 0 4px 0 #392f2e; + } + } + + &.tags { + text-align: left; + + .tag { + display: inline-block; + margin: 3px; + padding: 0 3px; + background: #313131; + border-radius: 3px; + } + } + + &.entities table { + td { + border: 1px solid #909090; + } + td:not(.no-padding) { + padding: 5px 10px; + } + } + + .description { + max-height: 600px; + } + } +`; + +const StyledMarkdown = styled(Markdown)` + max-height: 600px; +`; type Selected = | { type: "blueprint"; data: Pick } @@ -46,29 +130,6 @@ interface IndexProps { favorite: boolean; } -const BlueprintStyles = css` - .title { - position: relative; - width: 100%; - - .text { - white-space: nowrap; - width: calc(100% - 120px); - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - } - } -`; -const StyledTable = styled.table` - td { - border: 1px solid #909090; - } - td:not(.no-padding) { - padding: 5px 10px; - } -`; - export const Index: NextPage = ({ selected, blueprint, @@ -77,6 +138,7 @@ export const Index: NextPage = ({ favorite, }) => { const auth = useAuth(); + const url = useUrl(); const [selectedBlueprintString, setSelectedBlueprintString] = useState(null); const [bookChildTreeData, setBookChildTreeData] = useState( null @@ -84,8 +146,10 @@ export const Index: NextPage = ({ const [selectedData, setSelectedData] = useState(null); const [showDetails, setShowDetails] = useState<"string" | "json" | "none">("none"); const [isFavorite, setIsFavorite] = useState(favorite); - const selectedHash = selected.data.blueprint_hash; + const isBlueprintBook = Boolean(blueprint_book); + // const isBlueprintBookChild = isBlueprintBook && selected.type === "blueprint"; + const showEntities = selected.type === "blueprint" && selectedData?.blueprint; useEffect(() => { const hash = blueprint_book ? blueprint_book.blueprint_hash : blueprint?.blueprint_hash; @@ -145,16 +209,85 @@ export const Index: NextPage = ({ }; return ( - + {isBlueprintBook && ( + + {blueprint_page.title} + {auth && ( + + )} +
+ } + gridColumn="1" + gridRow="1" + > + {bookChildTreeData && ( +
+ +
+ )} + + )} + - {blueprint_page.title} - {auth && ( + Image + Factorio blueprint editor + + {selectedBlueprintString && ( + + )} + {selected.data.blueprint_hash && url && ( + + )} + + + } + > + {selectedBlueprintString && } + + + + {isBlueprintBook ? "Description" : blueprint_page.title} + {auth && !isBlueprintBook && (