diff --git a/src/components/CodePreview.tsx b/src/components/CodePreview.tsx
index c1481ad6..40eacd18 100644
--- a/src/components/CodePreview.tsx
+++ b/src/components/CodePreview.tsx
@@ -5,9 +5,10 @@ import CopyToClipboard from "./CopyToClipboard";
type Props = {
language: string;
code: string[];
+ height?: string;
};
-const CodePreview = ({ language = "markdown", code }: Props) => {
+const CodePreview = ({ language = "markdown", code, height }: Props) => {
const codeString = code.join("\n");
return (
@@ -17,7 +18,7 @@ const CodePreview = ({ language = "markdown", code }: Props) => {
language={language}
style={oneDark}
wrapLines={true}
- customStyle={{ margin: "0", maxHeight: "20rem" }}
+ customStyle={{ margin: "0", maxHeight: height ? height : "20rem" }}
>
{codeString}
diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx
index 7d5f3fd4..98e81352 100644
--- a/src/components/Icons.tsx
+++ b/src/components/Icons.tsx
@@ -168,3 +168,28 @@ export const LeftAngleArrowIcon = ({ fillColor = ACCENT_ICON_COLOR }) => (
);
+
+export const ToolsIcon = ({ fillColor = DEFAULT_ICON_COLOR }) => (
+
+);
diff --git a/src/components/devtools/DevTools.tsx b/src/components/devtools/DevTools.tsx
new file mode 100644
index 00000000..50ea213d
--- /dev/null
+++ b/src/components/devtools/DevTools.tsx
@@ -0,0 +1,109 @@
+import { useEffect, useState } from 'react';
+import useEscapeKey from '../../hooks/useEscapeKey';
+import { createPortal } from 'react-dom';
+import { DevToolsField } from './DevToolsField';
+import CodePreview from '../CodePreview';
+
+export interface DevToolsProps {
+ closeModal: () => void,
+}
+
+export const DevTools = ({ closeModal }: DevToolsProps) => {
+ const modalRoot = document.getElementById("modal-root");
+ if (!modalRoot) return null;
+ useEscapeKey(closeModal);
+
+ const [ title, setTitle ] = useState('');
+ const [ description, setDescription ] = useState('');
+ const [ tags, setTags ] = useState('');
+ const [ author, setAuthor ] = useState('');
+ const [ code, setCode ] = useState('');
+
+ const [ generated, setGenerated ] = useState('');
+
+ const generateSnippet = () => {
+ const codeArray = code.split(/\r?\n/gm);
+
+ const tagsArray = tags
+ .split(',')
+ .map((tag) => tag.trim())
+ .filter((tag) => tag);
+
+ return {
+ title: title.trim(),
+ description: description.trim(),
+ tags: tagsArray,
+ author: author.trim(),
+ code: codeArray,
+ };
+ };
+
+ useEffect(() => {
+ setGenerated(JSON.stringify(generateSnippet(), null, 4));
+ }, [
+ title, description, tags, author, code,
+ ]);
+
+ return createPortal(
+
{
+ if(e.target === e.currentTarget) {
+ closeModal()
+ }
+ } }
+ >
+
+
+
+ setTitle(value)}
+ />
+ setAuthor(value)}
+ />
+
+
setDescription(value)}
+ />
+ setTags(value)}
+ />
+
+
+
+
+
+
+
Your generated snippet:
+
+
+
+
,
+ modalRoot
+ );
+}
diff --git a/src/components/devtools/DevToolsField.tsx b/src/components/devtools/DevToolsField.tsx
new file mode 100644
index 00000000..11df58fb
--- /dev/null
+++ b/src/components/devtools/DevToolsField.tsx
@@ -0,0 +1,27 @@
+
+export interface DevToolsFieldProps {
+ name: string,
+ key: string,
+ value: string,
+ placeholder?: string,
+ setValue: (value: string) => void,
+}
+
+export const DevToolsField = ({
+ name, key, value, placeholder, setValue
+}: DevToolsFieldProps) => {
+ return (
+
+
+ setValue(e.target.value)}
+ />
+
+ )
+};
\ No newline at end of file
diff --git a/src/components/devtools/DevtoolsButton.tsx b/src/components/devtools/DevtoolsButton.tsx
new file mode 100644
index 00000000..72c07185
--- /dev/null
+++ b/src/components/devtools/DevtoolsButton.tsx
@@ -0,0 +1,18 @@
+import { useState } from "react";
+import { ToolsIcon } from "../Icons";
+import { DevTools } from "./DevTools";
+
+export const DevtoolsButton = () => {
+ const [devToolsOpenned, setDevToolsOpenned] = useState(false);
+ return (
+ <>
+
+ {devToolsOpenned ? (
+ setDevToolsOpenned(false)} />
+ ) : null}
+ >
+ );
+};
diff --git a/src/layouts/Footer.tsx b/src/layouts/Footer.tsx
index 64a8470e..2fe5822a 100644
--- a/src/layouts/Footer.tsx
+++ b/src/layouts/Footer.tsx
@@ -1,4 +1,9 @@
+import { useState } from 'react';
+import { DevTools } from '../components/devtools/DevTools';
+
const Footer = () => {
+ const [ devToolsOpenned, setDevToolsOpenned ] = useState(false);
+
return (
<>
@@ -37,6 +42,21 @@ const Footer = () => {
Add your own snippet
+
+
+ {
+ devToolsOpenned ? (
+ setDevToolsOpenned(false)}
+ />
+ ) : null
+ }
+
{
return (
@@ -11,14 +12,18 @@ const Header = () => {
);
diff --git a/src/styles/main.css b/src/styles/main.css
index 576e5a66..9d609fb8 100644
--- a/src/styles/main.css
+++ b/src/styles/main.css
@@ -644,6 +644,21 @@ body:has(.modal-overlay) {
}
}
+.styled-button {
+ background: none;
+ border: none;
+ outline: none;
+ padding: 0;
+
+ color: var(--text-primary);
+ text-decoration: none;
+ font-weight: 600;
+
+ &:is(:hover, :focus-visible) {
+ color: var(--clr-accent);
+ }
+}
+
.footer__nav:first-child {
grid-area: nav1;
width: 100%;
@@ -657,3 +672,112 @@ body:has(.modal-overlay) {
grid-area: content;
max-width: 60ch;
}
+
+/*------------------------------------*\
+ #DEVTOOLS
+\*------------------------------------*/
+
+.devtools-container {
+ display: flex;
+ flex-direction: row;
+ background-color: var(--bg-primary);
+ gap: 1em;
+ max-height: 95vh;
+ max-width: 95vw;
+ overflow-y: auto;
+}
+
+.devtools-form-container {
+ width: 50%;
+ display: flex;
+ flex-direction: column;
+ background-color: var(--bg-primary);
+ gap: 1em;
+}
+
+.devtools-sub-container{
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ gap: 1em;
+}
+
+.devtools-field {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 0.1em;
+}
+
+.devtools-label {
+ color: var(--text-primary);
+ text-decoration: none;
+ font-size: var(--fs-500);
+ font-weight: 600;
+ margin-bottom: 0.1em;
+}
+
+.devtools-input {
+ border: none;
+ outline: none;
+ background: none;
+ padding: 0.5em;
+ border-radius: 0.5em;
+ border: 1px solid var(--clr-neutral-500);
+ flex-grow: 1;
+}
+
+.devtools-textarea {
+ resize: none;
+ background: none;
+ outline: none;
+ font-family: var(--ff-mono);
+ color: var(--text-secondary);
+ height: 25vh;
+ border: 1px solid var(--clr-neutral-500);
+ border-radius: 0.5em;
+ padding: 0.5em;
+ resize: vertical;
+}
+
+.devtools-generated-container {
+ width: 50%;
+}
+
+.devtools-generated-title {
+ color: var(--text-primary);
+ margin-bottom: 0.2em;
+ text-decoration: none;
+ font-size: var(--fs-600);
+ font-weight: 600;
+}
+
+.devtools-generated {
+ max-width: 100%;
+ max-height: 20vh;
+ background-color: var(--bg-secondary);
+ border-radius: 0.5em;
+ overflow-y: auto;
+
+ margin: 0.5em;
+ padding: 0.5em;
+
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+
+@media screen and (max-width: 1024px) {
+ .devtools-container {
+ flex-direction: column;
+ }
+ .devtools-sub-container {
+ flex-direction: column;
+ }
+ .devtools-form-container {
+ width: 100%;
+ }
+ .devtools-generated-container {
+ width: 100%;
+ }
+}
\ No newline at end of file
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy