mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-09-22 12:02:57 +00:00
basic UI and functionality
This commit is contained in:
@@ -9,6 +9,7 @@ import MetadataEditor from './metadataEditor/metadataEditor.jsx';
|
|||||||
import SettingsEditor from './settingsEditor/settingsEditor.jsx';
|
import SettingsEditor from './settingsEditor/settingsEditor.jsx';
|
||||||
|
|
||||||
const EDITOR_THEME_KEY = 'HB_editor_theme';
|
const EDITOR_THEME_KEY = 'HB_editor_theme';
|
||||||
|
const EDITOR_SETTINGS_KEY = 'HB_edit_settings';
|
||||||
|
|
||||||
import defaultCM5Theme from '@themes/codeMirror/default.js';
|
import defaultCM5Theme from '@themes/codeMirror/default.js';
|
||||||
import darkbrewery from '@themes/codeMirror/darkbrewery.js';
|
import darkbrewery from '@themes/codeMirror/darkbrewery.js';
|
||||||
@@ -73,6 +74,12 @@ const Editor = forwardRef(
|
|||||||
const [currentEditorTheme, setEditorTheme] = useState(editorTheme);
|
const [currentEditorTheme, setEditorTheme] = useState(editorTheme);
|
||||||
const [view, setView] = useState('text'); // 'text', 'style', 'meta', 'snippet'
|
const [view, setView] = useState('text'); // 'text', 'style', 'meta', 'snippet'
|
||||||
const [snippetBarHeight, setSnippetBarHeight] = useState(26);
|
const [snippetBarHeight, setSnippetBarHeight] = useState(26);
|
||||||
|
const [editorSettings, setEditorSettings] = useState({
|
||||||
|
blockShading: false,
|
||||||
|
activeLineShading: true,
|
||||||
|
lineNumbers: true,
|
||||||
|
fontSize: 14
|
||||||
|
})
|
||||||
|
|
||||||
const editor = useRef(null);
|
const editor = useRef(null);
|
||||||
const codeEditor = useRef(null);
|
const codeEditor = useRef(null);
|
||||||
@@ -82,6 +89,7 @@ const Editor = forwardRef(
|
|||||||
const isStyle = ()=>isView('style');
|
const isStyle = ()=>isView('style');
|
||||||
const isMeta = ()=>isView('meta');
|
const isMeta = ()=>isView('meta');
|
||||||
const isSnip = ()=>isView('snippet');
|
const isSnip = ()=>isView('snippet');
|
||||||
|
const isSettings = ()=>isView('settings');
|
||||||
|
|
||||||
const isView = (name)=>view === name;
|
const isView = (name)=>view === name;
|
||||||
|
|
||||||
@@ -92,6 +100,8 @@ const Editor = forwardRef(
|
|||||||
|
|
||||||
const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY);
|
const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY);
|
||||||
if(editorTheme && EditorThemes.includes(editorTheme)) setEditorTheme(editorTheme); else setEditorTheme('default');
|
if(editorTheme && EditorThemes.includes(editorTheme)) setEditorTheme(editorTheme); else setEditorTheme('default');
|
||||||
|
const localEditorSettings = window.localStorage.getItem(EDITOR_SETTINGS_KEY);
|
||||||
|
if (localEditorSettings) setEditorSettings(JSON.parse(localEditorSettings));
|
||||||
const snippetBar = document.querySelector('.editor > .snippetBar');
|
const snippetBar = document.querySelector('.editor > .snippetBar');
|
||||||
if(!snippetBar) return;
|
if(!snippetBar) return;
|
||||||
|
|
||||||
@@ -210,6 +220,11 @@ const Editor = forwardRef(
|
|||||||
window.localStorage.setItem(EDITOR_THEME_KEY, newTheme);
|
window.localStorage.setItem(EDITOR_THEME_KEY, newTheme);
|
||||||
setEditorTheme(newTheme);
|
setEditorTheme(newTheme);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateEditorSettings = (newEditorSettings) => {
|
||||||
|
window.localStorage.setItem(EDITOR_SETTINGS_KEY, JSON.stringify(newEditorSettings));
|
||||||
|
setEditorSettings(newEditorSettings);
|
||||||
|
}
|
||||||
|
|
||||||
const renderEditor = ()=>{
|
const renderEditor = ()=>{
|
||||||
if(isText()) {
|
if(isText()) {
|
||||||
@@ -228,6 +243,7 @@ const Editor = forwardRef(
|
|||||||
editorTheme={currentEditorTheme}
|
editorTheme={currentEditorTheme}
|
||||||
renderer={brew.renderer}
|
renderer={brew.renderer}
|
||||||
style={{ height: `calc(100% - ${snippetBarHeight}px)` }}
|
style={{ height: `calc(100% - ${snippetBarHeight}px)` }}
|
||||||
|
settings={editorSettings}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -246,6 +262,7 @@ const Editor = forwardRef(
|
|||||||
editorTheme={currentEditorTheme}
|
editorTheme={currentEditorTheme}
|
||||||
renderer={brew.renderer}
|
renderer={brew.renderer}
|
||||||
style={{ height: `calc(100% - ${snippetBarHeight}px)` }}
|
style={{ height: `calc(100% - ${snippetBarHeight}px)` }}
|
||||||
|
settings={editorSettings}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -268,6 +285,7 @@ const Editor = forwardRef(
|
|||||||
editorTheme={currentEditorTheme}
|
editorTheme={currentEditorTheme}
|
||||||
renderer={brew.renderer}
|
renderer={brew.renderer}
|
||||||
style={{ height: `calc(100% - 25px)` }}
|
style={{ height: `calc(100% - 25px)` }}
|
||||||
|
settings={editorSettings}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -275,7 +293,7 @@ const Editor = forwardRef(
|
|||||||
if(isMeta()) {
|
if(isMeta()) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CodeEditor key='codeEditor' view={view} style={{ display: 'none' }} />
|
<CodeEditor key='codeEditor' tab='brewMetadata' view={view} style={{ display: 'none' }} settings={editorSettings} />
|
||||||
<MetadataEditor
|
<MetadataEditor
|
||||||
metadata={brew}
|
metadata={brew}
|
||||||
themeBundle={themeBundle}
|
themeBundle={themeBundle}
|
||||||
@@ -286,6 +304,23 @@ const Editor = forwardRef(
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if(isSettings()){
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CodeEditor
|
||||||
|
key='codeEditor'
|
||||||
|
tab='brewSettings' //necessary or the brew object loses its contents, culprit possibly on the tab dependent useEffect in codeEditor.jsx
|
||||||
|
view={view}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
settings={editorSettings}
|
||||||
|
/>
|
||||||
|
<SettingsEditor
|
||||||
|
settings={editorSettings}
|
||||||
|
updateSettings={updateEditorSettings}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const redo = ()=>codeEditor.current?.redo();
|
const redo = ()=>codeEditor.current?.redo();
|
||||||
@@ -305,7 +340,6 @@ const Editor = forwardRef(
|
|||||||
unfoldCode,
|
unfoldCode,
|
||||||
historySize,
|
historySize,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='editor' ref={editor}>
|
<div className='editor' ref={editor}>
|
||||||
<SnippetBar
|
<SnippetBar
|
||||||
|
|||||||
@@ -1,55 +1,111 @@
|
|||||||
import "./metadataEditor.less";
|
import './settingsEditor.less';
|
||||||
import React, { useState } from "react";
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
const SettingsEditor = () => {
|
const SettingsEditor = ({settings, updateSettings = () => {} }) => {
|
||||||
const [settings, setSettings] = useState({
|
const [currentSettings, setCurrentSettings] = useState(settings);
|
||||||
blockShading: false,
|
|
||||||
activeLineShading: true,
|
const validations = {
|
||||||
showLineNumbers: true,
|
fontSize: [
|
||||||
});
|
(value) => {
|
||||||
|
const number = Number(value);
|
||||||
|
|
||||||
|
if (number < 9 || number > 30) {
|
||||||
|
return 'Font size must be between 9 and 30.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
const handleFieldChange = (setting, e) => {
|
const handleFieldChange = (setting, e) => {
|
||||||
setSettings((prevSettings) => ({
|
const value =
|
||||||
...prevSettings,
|
e.target.type === 'checkbox'
|
||||||
[setting]: e.target.checked,
|
? e.target.checked
|
||||||
}));
|
: e.target.value;
|
||||||
|
|
||||||
|
const inputRules = validations[setting] ?? [];
|
||||||
|
|
||||||
|
const validationErrors = inputRules
|
||||||
|
.map((rule) => rule(value))
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
if (validationErrors.length > 0) {
|
||||||
|
e.target.setCustomValidity(validationErrors.join('\n'));
|
||||||
|
e.target.reportValidity();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.target.setCustomValidity('');
|
||||||
|
|
||||||
|
const updatedSettings = {
|
||||||
|
...currentSettings,
|
||||||
|
[setting]: e.target.type === 'number'
|
||||||
|
? Number(value)
|
||||||
|
: value,
|
||||||
|
};
|
||||||
|
|
||||||
|
setCurrentSettings(updatedSettings);
|
||||||
|
updateSettings(updatedSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="settingsEditor">
|
<div className='settingsEditor'>
|
||||||
<h1>Editor Settings</h1>
|
<h1>Editor Settings</h1>
|
||||||
|
|
||||||
<label>
|
<div className='field title'>
|
||||||
Background Shading of blocks in editor
|
<label htmlFor='blockShading'>
|
||||||
|
Background Shading of blocks in editor
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
id='blockShading'
|
||||||
name="blockShading"
|
type='checkbox'
|
||||||
checked={settings.blockShading}
|
name='blockShading'
|
||||||
onChange={(e) => handleFieldChange("blockShading", e)}
|
checked={currentSettings.blockShading}
|
||||||
|
onChange={(e) => handleFieldChange('blockShading', e)}
|
||||||
/>
|
/>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
<label>
|
<div className='field title'>
|
||||||
Shading of active line
|
<label htmlFor='activeLineShading'>
|
||||||
|
Background shading of active line
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
id='activeLineShading'
|
||||||
name="activeLineShading"
|
type='checkbox'
|
||||||
checked={settings.activeLineShading}
|
name='activeLineShading'
|
||||||
onChange={(e) => handleFieldChange("activeLineShading", e)}
|
checked={currentSettings.activeLineShading}
|
||||||
|
onChange={(e) => handleFieldChange('activeLineShading', e)}
|
||||||
/>
|
/>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
<label>
|
<div className='field title'>
|
||||||
Show Line Numbers
|
<label htmlFor='lineNumbers'>Show Line Numbers</label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
id='lineNumbers'
|
||||||
name="showLineNumbers"
|
type='checkbox'
|
||||||
checked={settings.showLineNumbers}
|
name='lineNumbers'
|
||||||
onChange={(e) => handleFieldChange("showLineNumbers", e)}
|
checked={currentSettings.lineNumbers}
|
||||||
|
onChange={(e) => handleFieldChange('lineNumbers', e)}
|
||||||
/>
|
/>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
|
<div className='field title'>
|
||||||
|
<label htmlFor='fontSize'>
|
||||||
|
Editor Font Size (in px)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id='fontSize'
|
||||||
|
type='number'
|
||||||
|
min={9}
|
||||||
|
max={30}
|
||||||
|
name='fontSize'
|
||||||
|
value={currentSettings.fontSize}
|
||||||
|
onChange={(e) => handleFieldChange('fontSize', e)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SettingsEditor;
|
export default SettingsEditor;
|
||||||
@@ -0,0 +1,373 @@
|
|||||||
|
@import '@sharedStyles/core.less';
|
||||||
|
|
||||||
|
|
||||||
|
.settingsEditor {
|
||||||
|
position : absolute;
|
||||||
|
box-sizing : border-box;
|
||||||
|
width : 100%;
|
||||||
|
height : calc(100vh - 54px); // 54px is the height of the navbar + snippet bar. probably a better way to dynamic get this.
|
||||||
|
padding : 25px;
|
||||||
|
overflow-y : auto;
|
||||||
|
font-size : 13px;
|
||||||
|
background-color : #999999;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin : 0 0 40px;
|
||||||
|
font-weight : bold;
|
||||||
|
text-transform : uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin : 20px 0;
|
||||||
|
font-weight : bold;
|
||||||
|
color : #555555;
|
||||||
|
border-bottom : 2px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > div { margin-bottom : 10px; }
|
||||||
|
|
||||||
|
.field-group {
|
||||||
|
display : flex;
|
||||||
|
flex-wrap : wrap;
|
||||||
|
gap : 10px;
|
||||||
|
width : 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-column {
|
||||||
|
display : flex;
|
||||||
|
flex : 5 0 200px;
|
||||||
|
flex-direction : column;
|
||||||
|
gap : 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field {
|
||||||
|
position : relative;
|
||||||
|
display : flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap : wrap;
|
||||||
|
width : 100%;
|
||||||
|
min-width : 200px;
|
||||||
|
border-bottom:1px solid;
|
||||||
|
padding:5px;
|
||||||
|
& > label {
|
||||||
|
width : fit-content;
|
||||||
|
font-size : 0.9em;
|
||||||
|
font-weight : 800;
|
||||||
|
line-height : 1.8em;
|
||||||
|
text-transform : uppercase;
|
||||||
|
}
|
||||||
|
& > .value {
|
||||||
|
flex : 1 1 auto;
|
||||||
|
width : 50px;
|
||||||
|
&[data-tooltip-right] { max-width : 380px; }
|
||||||
|
&:invalid { background : #FFB9B9; }
|
||||||
|
small {
|
||||||
|
display : block;
|
||||||
|
font-size : 0.9em;
|
||||||
|
font-style : italic;
|
||||||
|
line-height : 1.4em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input[type='text'], textarea {
|
||||||
|
border : 1px solid gray;
|
||||||
|
&:focus { outline : 1px solid #444444; }
|
||||||
|
}
|
||||||
|
|
||||||
|
&.description {
|
||||||
|
flex : 1;
|
||||||
|
textarea.value {
|
||||||
|
height : auto;
|
||||||
|
font-family : 'Open Sans', sans-serif;
|
||||||
|
resize : none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.thumbnail, &.themes {
|
||||||
|
label { line-height : 2.0em; }
|
||||||
|
.value {
|
||||||
|
overflow : hidden;
|
||||||
|
text-overflow : ellipsis;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
.colorButton();
|
||||||
|
padding : 0px 5px;
|
||||||
|
color : white;
|
||||||
|
background-color : black;
|
||||||
|
border : 1px solid #999999;
|
||||||
|
&:hover { background-color : #777777; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tags .tagInput-dropdown {
|
||||||
|
z-index : 400;
|
||||||
|
max-width : 200px;
|
||||||
|
}
|
||||||
|
&.language .value {
|
||||||
|
z-index : 300;
|
||||||
|
max-width : 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.themes {
|
||||||
|
.value {
|
||||||
|
overflow : visible;
|
||||||
|
text-overflow : auto;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
padding-right : 5px;
|
||||||
|
padding-left : 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.invitedAuthors .value {
|
||||||
|
z-index : 100;
|
||||||
|
|
||||||
|
.tagInput-dropdown { max-width : 200px; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail-preview {
|
||||||
|
position : relative;
|
||||||
|
flex : 1 1;
|
||||||
|
justify-self : center;
|
||||||
|
width : 80px;
|
||||||
|
height : min-content;
|
||||||
|
max-height : 115px;
|
||||||
|
aspect-ratio : 1 / 1;
|
||||||
|
object-fit : contain;
|
||||||
|
background-color : #AAAAAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.renderers.field .value {
|
||||||
|
label {
|
||||||
|
display : inline-flex;
|
||||||
|
align-items : center;
|
||||||
|
margin-right : 15px;
|
||||||
|
font-size : 0.9em;
|
||||||
|
font-weight : 800;
|
||||||
|
vertical-align : middle;
|
||||||
|
white-space : nowrap;
|
||||||
|
cursor : pointer;
|
||||||
|
user-select : none;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
margin : 3px;
|
||||||
|
vertical-align : middle;
|
||||||
|
cursor : pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.publish.field .value {
|
||||||
|
position : relative;
|
||||||
|
margin-bottom : 15px;
|
||||||
|
button { width : 100%; }
|
||||||
|
button.publish {
|
||||||
|
.colorButton(@blueLight);
|
||||||
|
}
|
||||||
|
button.unpublish {
|
||||||
|
.colorButton(@silver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete.field .value {
|
||||||
|
button {
|
||||||
|
.colorButton(@red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.authors.field {
|
||||||
|
.tag {
|
||||||
|
font-weight:300;
|
||||||
|
transition:background-color 0.2s;
|
||||||
|
|
||||||
|
&.owner {
|
||||||
|
position: relative;
|
||||||
|
background-color:@silverLight;
|
||||||
|
min-width:25px;
|
||||||
|
display:grid;
|
||||||
|
place-items:center;
|
||||||
|
font-weight: 900;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "\f521";
|
||||||
|
font-family: "Font Awesome 6 Free";
|
||||||
|
color:gold;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width:15px;
|
||||||
|
height:15px;
|
||||||
|
rotate:-25deg;
|
||||||
|
translate:-30% -50%;
|
||||||
|
transform: scaleY(0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:has(button) a {
|
||||||
|
padding-right:5px;
|
||||||
|
}
|
||||||
|
&:has(button:hover) {
|
||||||
|
background:#d97d7d;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
color:@red;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color:black;
|
||||||
|
text-decoration:unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.themes.field {
|
||||||
|
& .dropdown-container {
|
||||||
|
position : relative;
|
||||||
|
z-index : 200;
|
||||||
|
background-color : white;
|
||||||
|
}
|
||||||
|
& .dropdown-options { overflow-y : visible; }
|
||||||
|
.disabled {
|
||||||
|
font-style : italic;
|
||||||
|
color : dimgray;
|
||||||
|
background-color : darkgray;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
position : relative;
|
||||||
|
padding : 3px 3px;
|
||||||
|
overflow : visible;
|
||||||
|
background-color : white;
|
||||||
|
border-top : 1px solid rgb(118, 118, 118);
|
||||||
|
.preview {
|
||||||
|
position : absolute;
|
||||||
|
top : 0;
|
||||||
|
right : 0;
|
||||||
|
z-index : 1;
|
||||||
|
display : flex;
|
||||||
|
flex-direction : column;
|
||||||
|
width : 200px;
|
||||||
|
overflow : hidden;
|
||||||
|
color : black;
|
||||||
|
background : #CCCCCC;
|
||||||
|
border-radius : 5px;
|
||||||
|
box-shadow : 0 0 5px black;
|
||||||
|
opacity : 0;
|
||||||
|
transition : opacity 250ms ease;
|
||||||
|
h6 {
|
||||||
|
padding-block : 0.5em;
|
||||||
|
padding-inline : 1em;
|
||||||
|
font-weight : 900;
|
||||||
|
border-bottom : 2px solid hsl(0,0%,40%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.texture-container {
|
||||||
|
position : absolute;
|
||||||
|
top : 0;
|
||||||
|
left : 0;
|
||||||
|
width : 100%;
|
||||||
|
height : 100%;
|
||||||
|
min-height : 100%;
|
||||||
|
overflow : hidden;
|
||||||
|
> img {
|
||||||
|
position : absolute;
|
||||||
|
top : 0;
|
||||||
|
right : 0;
|
||||||
|
width : 50%;
|
||||||
|
min-height : 100%;
|
||||||
|
-webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||||
|
mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color : white;
|
||||||
|
background-color : @blue;
|
||||||
|
filter : unset;
|
||||||
|
}
|
||||||
|
&:hover > .preview { opacity : 1; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.field .list {
|
||||||
|
display : flex;
|
||||||
|
flex : 1 0;
|
||||||
|
flex-wrap : wrap;
|
||||||
|
|
||||||
|
> * { flex : 0 0 auto; }
|
||||||
|
|
||||||
|
#groupedIcon {
|
||||||
|
#backgroundColors;
|
||||||
|
position : relative;
|
||||||
|
top : -0.3em;
|
||||||
|
right : -0.3em;
|
||||||
|
display : inline-block;
|
||||||
|
min-width : 20px;
|
||||||
|
height : ~'calc(100% + 0.6em)';
|
||||||
|
color : white;
|
||||||
|
text-align : center;
|
||||||
|
cursor : pointer;
|
||||||
|
|
||||||
|
i {
|
||||||
|
position : relative;
|
||||||
|
top : 50%;
|
||||||
|
transform : translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) { border-right : 1px solid black; }
|
||||||
|
|
||||||
|
&:last-child { border-radius : 0 0.5em 0.5em 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
padding : 0.35em;
|
||||||
|
margin : 2px;
|
||||||
|
font-size : 0.95em;
|
||||||
|
background-color : #DDDDDD;
|
||||||
|
border-radius : 0.5em;
|
||||||
|
|
||||||
|
.icon { #groupedIcon; }
|
||||||
|
|
||||||
|
button {
|
||||||
|
cursor : pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
height : ~'calc(.9em + 4px + .6em)';
|
||||||
|
|
||||||
|
input { border-radius : 0.5em 0 0 0.5em; }
|
||||||
|
|
||||||
|
input:last-child { border-radius : 0.5em; }
|
||||||
|
|
||||||
|
.value {
|
||||||
|
width : 7.5vw;
|
||||||
|
min-width : 75px;
|
||||||
|
height : 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
height : ~'calc(.9em + 4px + .6em)';
|
||||||
|
|
||||||
|
input { border-radius : 0.5em 0 0 0.5em; }
|
||||||
|
|
||||||
|
input:last-child { border-radius : 0.5em; }
|
||||||
|
|
||||||
|
.value {
|
||||||
|
width : 7.5vw;
|
||||||
|
min-width : 75px;
|
||||||
|
height : 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invalid:focus { background-color : pink; }
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
#groupedIcon;
|
||||||
|
top : -0.54em;
|
||||||
|
right : 1px;
|
||||||
|
height : 97%;
|
||||||
|
|
||||||
|
i { font-size : 1.125em; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -245,7 +245,7 @@ const Snippetbar = createReactClass({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='editors'>
|
<div className='editors'>
|
||||||
{this.props.view !== 'meta' && <><div className='historyTools'>
|
{this.props.view !== 'meta' && this.props.view !== 'settings' && <><div className='historyTools'>
|
||||||
<div className={`editorTool snippetGroup history ${this.state.historyExists ? 'active' : ''}`}
|
<div className={`editorTool snippetGroup history ${this.state.historyExists ? 'active' : ''}`}
|
||||||
onClick={this.toggleHistoryMenu} >
|
onClick={this.toggleHistoryMenu} >
|
||||||
<i className='fas fa-clock-rotate-left' />
|
<i className='fas fa-clock-rotate-left' />
|
||||||
@@ -293,6 +293,10 @@ const Snippetbar = createReactClass({
|
|||||||
onClick={()=>this.props.onViewChange('meta')}>
|
onClick={()=>this.props.onViewChange('meta')}>
|
||||||
<i className='fas fa-info-circle' />
|
<i className='fas fa-info-circle' />
|
||||||
</div>
|
</div>
|
||||||
|
<div className={cx('settings', { selected: this.props.view === 'settings' })}
|
||||||
|
onClick={()=>this.props.onViewChange('settings')}>
|
||||||
|
<i className='fas fa-gear' />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
.editors {
|
.editors {
|
||||||
display : flex;
|
display : flex;
|
||||||
justify-content : flex-end;
|
justify-content : flex-end;
|
||||||
min-width : 250px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
|
min-width : 275px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
|
||||||
font-size: .85rem;
|
font-size: .85rem;
|
||||||
&:only-child {min-width : unset; margin-left : auto;}
|
&:only-child {min-width : unset; margin-left : auto;}
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@container editor (width < 816px) {
|
@container editor (width < 841px) {
|
||||||
.snippetBar {
|
.snippetBar {
|
||||||
.editors {
|
.editors {
|
||||||
flex : 1;
|
flex : 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user