Skip to content

Commit

Permalink
[#40549] Implement Styled Components for UI elements
Browse files Browse the repository at this point in the history
  • Loading branch information
Trzcin authored and mgielda committed Sep 7, 2023
1 parent ccce1d6 commit e50e453
Show file tree
Hide file tree
Showing 11 changed files with 1,818 additions and 504 deletions.
15 changes: 12 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,29 @@
"lint": "eslint ."
},
"dependencies": {
"@babel/core": "^7.12.10",
"@codemirror/commands": "^6.2.4",
"@codemirror/state": "^6.2.1",
"@codemirror/view": "^6.16.0",
"@preact/compat": "^17.1.2",
"codemirror": "^6.0.1",
"dompurify": "^2.3.5",
"htm": "^3.1.1",
"markdown-it": "^12.3.2",
"markdown-it-docutils": "^0.1.3",
"preact": "^10.11.3"
"preact": "^10.11.3",
"styled-components": "^6.0.7",
"stylis": "^4.3.0"
},
"devDependencies": {
"@preact/preset-vite": "^2.4.0",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-styled-components": "^2.1.4",
"eslint": "latest",
"vite": "^3.2.3"
"vite": "^3.2.3",
"vite-plugin-babel-macros": "^1.0.6"
},
"alias": {
"react": "@preact/compat",
"react-dom": "@preact/compat"
}
}
77 changes: 64 additions & 13 deletions src/MystEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,61 @@ import { html } from 'htm/preact';
import markdownitDocutils from 'markdown-it-docutils'
import purify from 'dompurify'
import markdownIt from 'markdown-it'
import styled from 'styled-components/macro';

import ButtonGroup from "./components/ButtonGroup";
import CodeMirror from './components/CodeMirror';
import TemplateManager from './components/TemplateManager';
import { TopbarButton } from './components/Buttons';

const EditorParent = styled.div`
display: flex;
flex-flow: row wrap;
width: 100%;
`;

const Topbar = styled.div`
z-index: 10;
position: sticky;
top: 0;
display: ${props => props.$shown ? 'flex' : 'none'};
width: 100%;
height: 60px;
background-color: var(--gray-900);
border-bottom: 1px solid var(--gray-600);
@media print {
display: none;
}
`;

const TopbarRight = styled.div`
width: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
margin-right: 15px;
`;

const Separator = styled.div`
border-left: 1px solid var(--gray-800);
height: 40px;
margin-right: 10px;
margin-left: 10px;
`;

const MystWrapper = styled.div`
padding: 20px;
display: flex;
flex-flow: row wrap;
width: 100%;
`;

const buttons = [
{ label: 'Source', img: "data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 30 30' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M22 14.3344V15.6663L17 18.1331V16.7394L20.525 15L17 13.2562V11.8669L22 14.3344ZM12 16.7394L8.475 15L12 13.2562V11.8669L7 14.3344V15.6663L12 18.1331V16.7394ZM16.4044 10H15.1056L12.5988 20H13.8944L16.4044 10V10Z' fill='%23FFFFFF'/%3E%3C/svg%3E" },
{ label: 'Preview', img: "data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 30 30' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12.7232 13.5185L13.0717 13.6453C13.364 13.7516 13.6059 13.4674 13.5201 13.2249L13.394 12.8684C13.1324 13.0434 12.905 13.264 12.7232 13.5185ZM5.3783 14.1143L6.20344 14.6793L5.36684 15.2271L5 14.6669L5.3783 14.1143ZM23.4976 14.6793C23.4976 14.6793 20.4337 20 14.8613 20C9.68749 20 6.20344 14.6793 6.20344 14.6793C6.20344 14.6793 9.40718 10 14.8613 10C20.4056 10 23.4976 14.6793 23.4976 14.6793ZM23.4976 14.6793C24.3642 15.1783 24.364 15.1787 24.3638 15.179L24.3633 15.1799L24.3621 15.182L24.3588 15.1875L24.3489 15.2044C24.3407 15.2182 24.3295 15.2369 24.3153 15.2603C24.2867 15.3069 24.246 15.3722 24.1933 15.4533C24.0878 15.6154 23.9336 15.8417 23.7316 16.1109C23.3288 16.6477 22.7301 17.3626 21.9419 18.0794C20.3721 19.5072 17.9836 21 14.8613 21C11.9278 21 9.5357 19.4963 7.93308 18.0917C7.12296 17.3817 6.48766 16.6739 6.05421 16.1433C5.83691 15.8773 5.66881 15.6539 5.55335 15.4945C5.49559 15.4147 5.45088 15.3508 5.41968 15.3054C5.40407 15.2827 5.39183 15.2646 5.38301 15.2514L5.37234 15.2355L5.36894 15.2303L5.36773 15.2285L5.36724 15.2277C5.36703 15.2274 5.36684 15.2271 6.20344 14.6793C5.3783 14.1143 5.37853 14.114 5.37878 14.1137L5.37933 14.1129L5.38065 14.1109L5.38421 14.1058L5.39489 14.0905C5.40361 14.0781 5.41551 14.0614 5.43057 14.0406C5.46067 13.9989 5.50343 13.941 5.55862 13.8692C5.66894 13.7255 5.82936 13.5255 6.03813 13.288C6.45474 12.814 7.06911 12.1846 7.86767 11.5546C9.45985 10.2984 11.8369 9 14.8613 9C17.9286 9 20.3014 10.2965 21.8823 11.558C22.6741 12.1898 23.2783 12.8211 23.6867 13.2969C23.8913 13.5353 24.048 13.7361 24.1557 13.8806C24.2095 13.9528 24.2513 14.0111 24.2806 14.0531C24.2954 14.0741 24.307 14.091 24.3155 14.1036L24.326 14.1192L24.3296 14.1244L24.3309 14.1264L24.3314 14.1273C24.3317 14.1276 24.3319 14.128 23.4976 14.6793ZM23.4976 14.6793L24.3319 14.128L24.6724 14.6432L24.3642 15.1783L23.4976 14.6793ZM15.5108 12.959C16.3818 13.2357 17.0123 14.0453 17.0123 15C17.0123 16.1836 16.0445 17.1429 14.8505 17.1429C13.8785 17.1429 13.0565 16.5071 12.7844 15.6322C12.7222 15.4324 12.6888 15.2201 12.6888 15C12.6888 14.8579 12.7032 14.7193 12.7298 14.585C12.8702 14.6361 13.0104 14.6627 13.147 14.6678C13.8935 14.6961 14.535 14.0861 14.541 13.3486C14.5422 13.2 14.5176 13.0462 14.4628 12.8914C14.5882 12.87 14.7179 12.8571 14.8505 12.8571C15.0808 12.8571 15.3027 12.8929 15.5108 12.959ZM11.2476 15C11.2476 16.9729 12.861 18.5714 14.8505 18.5714C16.8408 18.5714 18.4535 16.9729 18.4535 15C18.4535 13.0279 16.8408 11.4286 14.8505 11.4286C12.861 11.4286 11.2476 13.0279 11.2476 15Z' fill='%23FFFFFF'/%3E%3C/svg%3E%0A" },
{ label: 'Both', img: "data:image/svg+xml,%3Csvg width='22' height='17' viewBox='0 0 22 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.66667 0.666667H10.5338V15.5109H2.66667C1.5621 15.5109 0.666667 14.6154 0.666667 13.5109V2.66667C0.666667 1.5621 1.5621 0.666667 2.66667 0.666667Z' stroke='white' stroke-width='1.33333'/%3E%3Cpath d='M10.8001 0.666667H18.6673C19.7718 0.666667 20.6673 1.5621 20.6673 2.66667V13.5109C20.6673 14.6154 19.7718 15.5109 18.6673 15.5109H10.8001V0.666667Z' stroke='white' stroke-width='1.33333'/%3E%3C/svg%3E%0A" }
]

const MystEditor = ({
name = "myst_editor_textarea",
Expand All @@ -31,20 +82,20 @@ const MystEditor = ({
}

return html`
<div class="myst_editor_parent">
<div class="myst_top_bar ${topbar ? 'shown' : 'hidden'}">
<div class="myst_top_bar-right">
<button type="button" onClick=${(event) => printCallback(event)} id="customButton_print">Export as PDF</button>
<${EditorParent}>
<${Topbar} $shown=${topbar}>
<${TopbarRight}>
<${TopbarButton} type="button" onClick=${(event) => printCallback(event)}>Export as PDF<//>
<${TemplateManager} templatelist=${templatelist} templateState=${templateState} setDocumentTemplate=${setDocumentTemplate}/>
<div class="vl"></div>
<${ButtonGroup} buttons=${["Source", "Preview", "Both"]} clickedId=${2} clickCallback=${(event) => setMode(event.target.name)}/>
</div>
</div>
<div class="myst_wrapper">
<${CodeMirror} setText=${setText} name=${name} id=${id} className="myst_content ${mode === "Both" || mode === "Source" ? 'shown' : 'hidden'}" templateState=${templateState} value=${text}/>
<div class="myst_rendered ${mode === "Both" || mode === "Preview" ? 'shown' : 'hidden'}" dangerouslySetInnerHTML=${{__html: renderAndSanitize(text)}}/>
</div>
</div>`
<${Separator} />
<${ButtonGroup} buttons=${buttons} clickedId=${2} clickCallback=${(newMode) => setMode(newMode)}/>
<//>
<//>
<${MystWrapper}>
<${CodeMirror} setText=${setText} name=${name} id=${id} shown=${mode === "Both" || mode === "Source"} templateState=${templateState} value=${text}/>
<div class="myst_rendered ${mode === "Both" || mode === "Preview" ? '' : 'hidden'}" dangerouslySetInnerHTML=${{ __html: renderAndSanitize(text) }}/>
<//>
<//>`
}

export default MystEditor
Expand Down
26 changes: 19 additions & 7 deletions src/components/ButtonGroup.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
import { useState } from 'preact/hooks';
import { html } from 'htm/preact';
import styled from 'styled-components/macro';
import DefaultButton from './Buttons.js';

const GroupButton = styled(DefaultButton)`
color: ${props => props.$active ? 'white' : 'var(--gray-900)'};
border: ${props => props.$active ? '1px solid var(--green-500)' : '1px solid var(--gray-800)'};
background-color: ${props => props.$active ? 'var(--green-500)' : 'var(--gray-800)'};
margin: 5px;
width: 40px;
`;

const ButtonGroup = ({ buttons, initialClickedId = 2, clickCallback }) => {
const [clickedId, setClickedId] = useState(initialClickedId);
const [clickedId, setClickedId] = useState(initialClickedId);

return html`
${buttons.map((buttonLabel, i) => (
html`<button type="button" key=${buttonLabel} name=${buttonLabel} onClick=${(event) => {setClickedId(i); clickCallback(event);}} class=${i === clickedId ? "customButton active" : "customButton"}>
</button>`
))}
`;
return html`
${buttons.map((buttonOptions, i) => (
html`
<${GroupButton} type="button" key=${buttonOptions.label} name=${buttonOptions.label} onClick=${() => { setClickedId(i); clickCallback(buttonOptions.label); }} $active=${i === clickedId}>
<img src=${buttonOptions.img} alt=${buttonOptions.label} />
<//>`
))}
`;
}

console.log("ButtonGroup component loaded")
Expand Down
31 changes: 31 additions & 0 deletions src/components/Buttons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import styled from 'styled-components/macro';

const DefaultButton = styled.button`
cursor: pointer;
color: #fff;
font-family: "Lato", sans-serif;
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
border: 1px solid var(--gray-800);
background-color: var(--gray-800);
height: 40px;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
transition: 0.4s ease;
border-radius: var(--border-radius);
&:not(:disabled):hover {
background-color: var(--green-400);
border: 1px solid var(--green-400);
}
`;

export const TopbarButton = styled(DefaultButton)`
padding: 0px 15px;
margin: 5px;
`;

export default DefaultButton;
30 changes: 27 additions & 3 deletions src/components/CodeMirror.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@ import { basicSetup, EditorView } from "codemirror";
import { keymap } from "@codemirror/view";
import { indentWithTab } from "@codemirror/commands";
import { EditorState } from "@codemirror/state";
import styled from 'styled-components/macro';

const CodeEditor = styled.div`
border-radius: var(--border-radius);
background: var(--gray-200);
font-family: monospace;
font-size: 0.94em;
resize: none;
border: 0;
padding: 20px;
min-height: 500px;
display: ${props => props.$shown ? 'block' : 'none'};
flex: 1;
border: 1px solid var(--gray-400);
box-shadow: inset 0px 0px 4px rgba(0, 0, 0, 0.15);
@media print {
display: none;
}
`;

const HiddenTextArea = styled.textarea`
display: none;
`;

const usePrevious = (value) => {
const ref = useRef();
Expand All @@ -13,7 +37,7 @@ const usePrevious = (value) => {
return ref.current;
};

const CodeMirror = ({ value, setText, id, name, className, templateState }) => {
const CodeMirror = ({ value, setText, id, name, className, shown, templateState }) => {
const editorRef = useRef(null);
const prevTemplateState = usePrevious(templateState);
const prepareTextToSubmit = (doc, comp) => document.getElementById(comp).value = doc;
Expand Down Expand Up @@ -63,8 +87,8 @@ const CodeMirror = ({ value, setText, id, name, className, templateState }) => {
}, [templateState]);

return html`
<div id="editor" class=${className}></div>
<textarea value=${value} name=${name} id=${id} class="hidden"></textarea>
<${CodeEditor} $shown="${shown}" id="editor" class=${className}><//>
<${HiddenTextArea} value=${value} name=${name} id=${id}><//>
`;
};

Expand Down
54 changes: 47 additions & 7 deletions src/components/Modal.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,55 @@
import { html } from 'htm/preact';
import { styled } from 'styled-components/macro';
import DefaultButton from './Buttons';

const Container = styled.section`
z-index: 2;
display: flex;
flex-direction: column;
justify-content: center;
gap: 10px;
width: 450px;
padding: 20px;
right: 50%;
transform: translate(50%, 0);
top: 100%;
position: absolute;
background-color: var(--white);
border: 1px solid var(--gray-600);
border-radius: var(--border-radius);
`;

const Heading = styled.h3`
font-family: 'Lato', sans-serif;
color: var(--gray-900);
`;

const ButtonContainer = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`;

const ModalButton = styled(DefaultButton)`
padding: 0 10px;
margin-top: 0px;
&:hover {
background-color: ${props => props.$negative ? 'var(--red-500)' : 'var(--green-400)'} !important;
border: 1px solid ${props => props.$negative ? 'var(--red-500)' : 'var(--green-400)'} !important;
}
`;

const Modal = ({changeDocumentTemplate, selectedTemplate, closeModal}) => {

return html`
<section class="modal">
<h3 class="modal-text">Are you sure you want to change the current template?</h3>
<div class="flex-container">
<button type="button" class="modal-button" onClick=${ () => changeDocumentTemplate(selectedTemplate)}>✓ Yes</button>
<button type="button" class="modal-close-button" onClick=${closeModal}>x Cancel</button>
</div>
</section>
<${Container}>
<${Heading}>Are you sure you want to change the current template?<//>
<${ButtonContainer}>
<${ModalButton} type="button" onClick=${ () => changeDocumentTemplate(selectedTemplate)}>✓ Yes<//>
<${ModalButton} $negative type="button" onClick=${closeModal}>x Cancel<//>
<//>
<//>
`
}

Expand Down
Loading

0 comments on commit e50e453

Please sign in to comment.