diff --git a/package.json b/package.json index 04bac2a..d074738 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "react-scripts": "3.4.1", "react-use": "^15.3.2", "recoil": "^0.0.10", + "svg2png-converter": "^1.0.0", "tinycolor2": "^1.4.1" }, "scripts": { diff --git a/src/components/App/App.css b/src/components/App/App.css index b80c244..2bb4400 100644 --- a/src/components/App/App.css +++ b/src/components/App/App.css @@ -28,6 +28,7 @@ pre { background-color: white; border-radius: 6px; border: 1px solid #e1d4d7; + white-space: pre-wrap; } input { diff --git a/src/components/IconGrid/IconGrid.css b/src/components/IconGrid/IconGrid.css index 4a85880..26c51aa 100644 --- a/src/components/IconGrid/IconGrid.css +++ b/src/components/IconGrid/IconGrid.css @@ -48,11 +48,9 @@ display: flex; width: 100%; height: 0px; - margin: 0px; + margin: 0 4px; border-radius: 16px; background-color: rgba(163, 159, 171, 0.1); - overflow-y: hidden; - overflow-x: auto; } @media screen and (max-width: 1023px) { @@ -90,8 +88,8 @@ } .snippet pre { - /* white-space: nowrap; */ - /* overflow: hidden; */ + display: flex; + align-items: center; text-overflow: ellipsis; color: black; user-select: all; @@ -111,12 +109,15 @@ } } +.snippet span { + flex: 1; +} + .snippet button { background-color: transparent; margin: 0; padding: 0; height: 24px; - float: right; cursor: pointer; } @@ -126,6 +127,7 @@ .button-row { display: flex; + flex-wrap: wrap; } .button-row button { diff --git a/src/components/IconGrid/InfoPanel.tsx b/src/components/IconGrid/InfoPanel.tsx index c56de80..7fb4e4a 100644 --- a/src/components/IconGrid/InfoPanel.tsx +++ b/src/components/IconGrid/InfoPanel.tsx @@ -1,6 +1,7 @@ import React, { useRef } from "react"; import { useRecoilValue, useSetRecoilState } from "recoil"; import { motion } from "framer-motion"; +import { Svg2Png } from "svg2png-converter"; import { saveAs } from "file-saver"; import { Icon, Copy, X, CheckCircle, Download } from "phosphor-react"; @@ -12,21 +13,32 @@ import { } from "../../state/atoms"; import useTransientState from "../../hooks/useTransientState"; -const infoVariants = { +const panelVariants = { open: { opacity: 1, - height: 496, - margin: 4, + height: "100%", + marginTop: 4, + marginBottom: 4, // transition: { stiffness: 600, damping: 32, duration: 0.2 }, }, collapsed: { opacity: 0, height: 0, - margin: 0, + marginTop: 0, + marginBottom: 0, // transition: { stiffness: 600, damping: 32, duration: 0.2 }, }, }; +const contentVariants = { + open: { opacity: 1, transition: { duration: 0.2 } }, + collapsed: { opacity: 0, transition: { duration: 0.1 } }, +}; + +const buttonColor = "#35313D"; +const successColor = "#1FA647"; +const disabledColor = "#B7B7B7"; + interface InfoPanelProps { index: number; spans: number; @@ -44,6 +56,12 @@ const InfoPanel: React.FC = (props) => { const [copied, setCopied] = useTransientState(false, 2000); const ref = useRef(null); + const buttonBarStyle = { color: isDark ? "white" : buttonColor }; + const snippetButtonStyle = + weight === "duotone" + ? { color: disabledColor, "user-select": "none" } + : { color: buttonColor }; + const snippets = { html: weight === "duotone" @@ -69,6 +87,14 @@ const InfoPanel: React.FC = (props) => { data && void navigator.clipboard?.writeText(data); }; + const handleCopySVG = ( + event: React.MouseEvent + ) => { + event.currentTarget.blur(); + setCopied("svg"); + ref.current && void navigator.clipboard?.writeText(ref.current.outerHTML); + }; + const handleDownloadSVG = ( event: React.MouseEvent ) => { @@ -78,12 +104,16 @@ const InfoPanel: React.FC = (props) => { saveAs(blob, `${name}${weight === "regular" ? "" : `-${weight}`}.svg`); }; - const handleCopySVG = ( + const handleDownloadPNG = async ( event: React.MouseEvent ) => { event.currentTarget.blur(); - setCopied("svg"); - ref.current && void navigator.clipboard?.writeText(ref.current.outerHTML); + if (!ref.current?.outerHTML) return; + Svg2Png.save( + ref.current, + `${name}${weight === "regular" ? "" : `-${weight}`}.png`, + { scaleX: 1.334, scaleY: 1.334 } + ); }; return ( @@ -91,31 +121,41 @@ const InfoPanel: React.FC = (props) => { className="info-box" animate="open" exit="collapsed" - variants={infoVariants} + variants={panelVariants} style={{ order: index + (spans - (index % spans)), color: isDark ? "white" : "black", }} > -
-
- -

{name}

-
-
-
+ + +

{name}

+
+
React
-            {snippets.react}
+            {snippets.react}
             
           
@@ -123,71 +163,78 @@ const InfoPanel: React.FC = (props) => {
Vue
-            {snippets.vue}
+            {snippets.vue}
             
           
HTML/CSS -
-            {snippets.html}
+          
+            {snippets.html}
             
           
- + -
-
- setOpen(false)} - onKeyDown={(e) => { - e.key === "Enter" && setOpen(false); - }} - /> +
+ + setOpen(false)} + onKeyDown={(e) => { + e.key === "Enter" && setOpen(false); + }} + /> + ); };