diff --git a/apps/blueprints/src/components/Button.tsx b/apps/blueprints/src/components/Button.tsx new file mode 100644 index 0000000..5b99637 --- /dev/null +++ b/apps/blueprints/src/components/Button.tsx @@ -0,0 +1,82 @@ +import React from "react"; +import styled from "@emotion/styled"; +import clsx from "clsx"; + +export interface ButtonProps extends React.ButtonHTMLAttributes { + primary?: boolean; +} + +export const Button: React.FC = ({ primary, className, children, ...props }) => { + return ( + + {children} + + ); +}; + +const StyledButton = styled.button` + 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; + white-space: nowrap; + box-shadow: inset 8px 0 4px -8px #000, inset -8px 0 4px -8px #000, inset 0 10px 2px -8px #e3e3e3, + inset 0 10px 2px -8px #282828, inset 0 -9px 2px -8px #000, 0 0 4px 0 #000; + position: relative; + cursor: pointer; + user-select: none; + height: 36px; + outline: none; + + &.primary { + background-color: #5eb663; + } + + &.danger { + background-color: #fe5a5a; + box-shadow: inset 8px 0 4px -8px #000, inset -8px 0 4px -8px #000, inset 0 10px 2px -8px #fda1a1, + inset 0 10px 2px -8px #8b0101, inset 0 -9px 2px -8px #000, 0 0 4px 0 #000; + } + + &:hover { + color: #000; + text-decoration: none; + outline: 0; + box-shadow: inset 8px 0 4px -8px #000, inset -8px 0 4px -8px #000, inset 0 9px 2px -8px #fff, + inset 0 8px 4px -8px #000, inset 0 -8px 4px -8px #000, inset 0 -9px 2px -8px #432400, + 0 0 4px 0 #000, inset 0 0 4px 2px #f9b44b; + background-color: #e39827; + filter: drop-shadow(0 0 2px #f9b44b); + } + + &:active { + 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, + 0 0 4px 0 #000; + background-color: #f1be64; + filter: none; + outline: 0; + } + + &:disabled { + padding-top: 10px; + padding-bottom: 10px; + cursor: default; + vertical-align: 0; + background-color: #3d3d3d; + color: #818181; + box-shadow: inset 8px 0 4px -8px #000, inset -8px 0 4px -8px #000, inset 0 8px 4px -8px #000, + inset 0 -6px 4px -8px #818181, inset 0 -8px 4px -8px #000, 0 0 4px 0 #000; + filter: none; + } +`; diff --git a/apps/blueprints/src/components/CopyButton.tsx b/apps/blueprints/src/components/CopyButton.tsx index e5d8489..d585438 100644 --- a/apps/blueprints/src/components/CopyButton.tsx +++ b/apps/blueprints/src/components/CopyButton.tsx @@ -1,6 +1,7 @@ import React, { useMemo, useState } from "react"; -import { Button, ButtonProps } from "@chakra-ui/react"; import { MdCheck, MdClose } from "react-icons/md"; +import { IoMdClipboard } from "react-icons/io"; +import { Button, ButtonProps } from "../components/Button"; const SUCCESS_ICON_DURATION = 2000; @@ -8,44 +9,45 @@ export const CopyButton: React.FC< Omit & { content: string; label?: string } > = ({ content, label, ...props }) => { const [loading, setLoading] = useState(false); - const [icon, setIcon] = useState<"red" | "green" | null>(null); + const [iconType, setIconType] = useState<"success" | "error" | null>(null); - const iconProps = useMemo(() => { - if (icon === "green") { - return { - colorScheme: "green", - leftIcon: , - }; - } else if (icon === "red") { - return { - colorScheme: "red", - leftIcon: , - }; - } else { - return { colorScheme: "green" }; + const icon = useMemo(() => { + switch (iconType) { + case "success": + return ; + case "error": + return ; + default: + return ; } - }, [icon]); + }, [iconType]); + + const handleClick = async () => { + setLoading(true); + try { + await navigator.clipboard.writeText(content); + setIconType("success"); + setTimeout(() => setIconType(null), SUCCESS_ICON_DURATION); + setLoading(false); + } catch (err) { + setIconType("error"); + setLoading(false); + } + }; return ( ); diff --git a/apps/blueprints/src/components/Panel.tsx b/apps/blueprints/src/components/Panel.tsx index bb97dbe..529d8cf 100644 --- a/apps/blueprints/src/components/Panel.tsx +++ b/apps/blueprints/src/components/Panel.tsx @@ -23,17 +23,30 @@ const panelStyles = css` 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 } -> = ({ children, title, css: prop_css, ...props }) => ( + Omit & { + title?: ReactNode; + css?: SerializedStyles; + bottom?: ReactNode; + } +> = ({ children, title, bottom, css: prop_css, ...props }) => ( - {title ?

{title}

: null} + {title &&

{title}

} {children} + {bottom && {bottom}}
); diff --git a/apps/blueprints/src/pages/blueprint/[blueprintId].tsx b/apps/blueprints/src/pages/blueprint/[blueprintId].tsx index a44c28d..ddb70e4 100644 --- a/apps/blueprints/src/pages/blueprint/[blueprintId].tsx +++ b/apps/blueprints/src/pages/blueprint/[blueprintId].tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import { NextPage } from "next"; import Link from "next/link"; import BBCode from "bbcode-to-react"; -import { Button, Grid, Image, Box } from "@chakra-ui/react"; +import { Grid, Image, Box } from "@chakra-ui/react"; import { getBlueprintBookById, getBlueprintById, @@ -32,6 +32,7 @@ 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"; type Selected = | { type: "blueprint"; data: Pick } @@ -157,11 +158,13 @@ export const Index: NextPage = ({ {blueprint_page.title} {auth && ( )} @@ -220,21 +223,16 @@ export const Index: NextPage = ({ - - {selected.data.blueprint_hash && typeof window !== "undefined" && ( - + + {selectedBlueprintString && ( + )} - {selectedBlueprintString && ( + {selected.data.blueprint_hash && typeof window !== "undefined" && ( )} @@ -319,16 +317,14 @@ export const Index: NextPage = ({ > diff --git a/apps/blueprints/src/pages/index.tsx b/apps/blueprints/src/pages/index.tsx index da70b1a..e4f3376 100644 --- a/apps/blueprints/src/pages/index.tsx +++ b/apps/blueprints/src/pages/index.tsx @@ -72,7 +72,7 @@ export const Index: NextPage = ({ borderRight: "1px solid #b7b7b7", paddingRight: "1rem", marginRight: "1rem", - width: "250px", + width: "213px", }} > @@ -167,11 +167,13 @@ export const Index: NextPage = ({ /> - - - {blueprints.map((bp) => ( - - ))} + + + {blueprints.length ? ( + blueprints.map((bp) => ) + ) : ( +

No results found

+ )}
diff --git a/apps/blueprints/src/pages/user/blueprint-create.tsx b/apps/blueprints/src/pages/user/blueprint-create.tsx index f468049..765312d 100644 --- a/apps/blueprints/src/pages/user/blueprint-create.tsx +++ b/apps/blueprints/src/pages/user/blueprint-create.tsx @@ -7,7 +7,6 @@ import { FormErrorMessage, Input, SimpleGrid, - Button, Box, Text, Textarea, @@ -20,6 +19,7 @@ import { Panel } from "../../components/Panel"; import { validateCreateBlueprintForm } from "../../utils/validate"; import { ImageEditor } from "../../components/ImageEditor"; import { Select } from "../../components/Select"; +import { Button } from "../../components/Button"; import { pageHandler } from "../../utils/page-handler"; const FieldStyle = css` @@ -131,7 +131,7 @@ export const UserBlueprintCreate: NextPage = () => { - {status && {status}} diff --git a/apps/blueprints/src/pages/user/blueprint/[blueprintId].tsx b/apps/blueprints/src/pages/user/blueprint/[blueprintId].tsx index e92bd73..9dc4f17 100644 --- a/apps/blueprints/src/pages/user/blueprint/[blueprintId].tsx +++ b/apps/blueprints/src/pages/user/blueprint/[blueprintId].tsx @@ -9,7 +9,6 @@ import { FormErrorMessage, Input, SimpleGrid, - Button, Box, Text, Textarea, @@ -22,12 +21,13 @@ import { getBlueprintStringByHash, } from "@factorio-sites/database"; import { Blueprint, BlueprintBook, BlueprintPage } from "@factorio-sites/types"; +import { TAGS } from "@factorio-sites/common-utils"; import { pageHandler } from "../../../utils/page-handler"; import { Panel } from "../../../components/Panel"; import { validateCreateBlueprintForm } from "../../../utils/validate"; import { ImageEditor } from "../../../components/ImageEditor"; import { Select } from "../../../components/Select"; -import { TAGS } from "@factorio-sites/common-utils"; +import { Button } from "../../../components/Button"; const FieldStyle = css` margin-bottom: 1rem; @@ -156,7 +156,7 @@ export const UserBlueprint: NextPage = ({ blueprintPage, sel - {status && {status}} diff --git a/apps/blueprints/src/pages/user/blueprints.tsx b/apps/blueprints/src/pages/user/blueprints.tsx index 93e67b1..b2d79a6 100644 --- a/apps/blueprints/src/pages/user/blueprints.tsx +++ b/apps/blueprints/src/pages/user/blueprints.tsx @@ -1,12 +1,13 @@ import React from "react"; import { NextPage } from "next"; import Link from "next/link"; -import { Button, SimpleGrid, Box } from "@chakra-ui/react"; +import { SimpleGrid, Box } from "@chakra-ui/react"; import { getBlueprintPageByUserId } from "@factorio-sites/database"; import { BlueprintPage } from "@factorio-sites/types"; import { pageHandler } from "../../utils/page-handler"; import { BlueprintLink } from "../../components/BlueprintLink"; import { Panel } from "../../components/Panel"; +import { Button } from "../../components/Button"; interface UserBlueprintsProps { blueprints: BlueprintPage[]; } @@ -27,14 +28,18 @@ export const UserBlueprints: NextPage = ({ blueprints }) => > - + - {blueprints.map((bp) => ( - - ))} + {blueprints.length !== 0 ? ( + blueprints.map((bp) => ( + + )) + ) : ( +

You don't have any blueprints yet

+ )}
diff --git a/apps/blueprints/src/pages/user/edit.tsx b/apps/blueprints/src/pages/user/edit.tsx index 896a00e..fb2f4fe 100644 --- a/apps/blueprints/src/pages/user/edit.tsx +++ b/apps/blueprints/src/pages/user/edit.tsx @@ -1,17 +1,11 @@ import React from "react"; import { NextPage } from "next"; import { useRouter } from "next/router"; -import { - FormControl, - FormLabel, - FormErrorMessage, - Input, - SimpleGrid, - Button, -} from "@chakra-ui/react"; +import { FormControl, FormLabel, FormErrorMessage, Input, SimpleGrid } from "@chakra-ui/react"; import { Formik, Field, FieldProps } from "formik"; import { css } from "@emotion/react"; import { Panel } from "../../components/Panel"; +import { Button } from "../../components/Button"; import { validateUserForm } from "../../utils/validate"; import { useAuth } from "../../providers/auth"; import { pageHandler } from "../../utils/page-handler"; @@ -79,8 +73,13 @@ export const UserEdit: NextPage = () => { )} - )} diff --git a/package.json b/package.json index 5570e7b..6e529b9 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@hookstate/core": "3.0.6", "@prisma/client": "2.18.0", "bbcode-to-react": "0.2.9", + "clsx": "1.1.1", "bcrypt": "5.0.1", "cookie": "0.4.1", "document-register-element": "1.14.10", diff --git a/yarn.lock b/yarn.lock index 81086d2..3295223 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6207,6 +6207,11 @@ clone@^2.1.1: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= +clsx@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" + integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"