diff --git a/app/assets/css/theme.css b/app/assets/css/theme.css
index a052f6b29..d4a121a7b 100644
--- a/app/assets/css/theme.css
+++ b/app/assets/css/theme.css
@@ -120,8 +120,6 @@
--bg-navtabs-hover-color: var(--grey-16);
--bg-nav-tab-active-color: var(--ui-gray-4);
--bg-table-selected-color: var(--grey-14);
- --bg-codemirror-color: var(--white-color);
- --bg-codemirror-gutters-color: var(--grey-17);
--bg-dropdown-menu-color: var(--white-color);
--bg-log-viewer-color: var(--white-color);
--bg-log-line-selected-color: var(--grey-18);
@@ -136,7 +134,6 @@
--bg-item-highlighted-color: var(--grey-21);
--bg-item-highlighted-null-color: var(--grey-14);
--bg-panel-body-color: var(--white-color);
- --bg-codemirror-selected-color: var(--grey-22);
--bg-tooltip-color: var(--ui-gray-11);
--bg-input-sm-color: var(--white-color);
--bg-app-datatable-thead: var(--grey-23);
@@ -182,11 +179,7 @@
--text-navtabs-color: var(--grey-7);
--text-navtabs-hover-color: var(--grey-6);
--text-nav-tab-active-color: var(--grey-25);
- --text-cm-default-color: var(--blue-1);
- --text-cm-meta-color: var(--black-color);
- --text-cm-string-color: var(--red-3);
- --text-cm-number-color: var(--green-1);
- --text-codemirror-color: var(--black-color);
+
--text-dropdown-menu-color: var(--grey-6);
--text-log-viewer-color: var(--black-color);
--text-json-tree-color: var(--blue-3);
@@ -224,7 +217,6 @@
--border-md-checkbox-color: var(--grey-19);
--border-modal-header-color: var(--grey-45);
--border-navtabs-color: var(--ui-white);
- --border-codemirror-cursor-color: var(--black-color);
--border-pre-color: var(--grey-43);
--border-pagination-span-color: var(--ui-white);
--border-pagination-hover-color: var(--ui-white);
@@ -281,9 +273,6 @@
--bg-card-color: var(--grey-1);
--bg-checkbox-border-color: var(--grey-8);
--bg-code-color: var(--grey-2);
- --bg-codemirror-color: var(--grey-2);
- --bg-codemirror-gutters-color: var(--grey-3);
- --bg-codemirror-selected-color: var(--grey-3);
--bg-dropdown-menu-color: var(--ui-gray-warm-8);
--bg-main-color: var(--grey-2);
--bg-sidebar-color: var(--grey-1);
@@ -361,11 +350,7 @@
--text-navtabs-color: var(--grey-8);
--text-navtabs-hover-color: var(--grey-9);
--text-nav-tab-active-color: var(--white-color);
- --text-cm-default-color: var(--blue-10);
- --text-cm-meta-color: var(--white-color);
- --text-cm-string-color: var(--red-5);
- --text-cm-number-color: var(--green-2);
- --text-codemirror-color: var(--white-color);
+
--text-dropdown-menu-color: var(--white-color);
--text-log-viewer-color: var(--white-color);
--text-json-tree-color: var(--grey-40);
@@ -403,7 +388,6 @@
--border-md-checkbox-color: var(--grey-41);
--border-modal-header-color: var(--grey-1);
--border-navtabs-color: var(--grey-38);
- --border-codemirror-cursor-color: var(--white-color);
--border-pre-color: var(--grey-3);
--border-blocklist: var(--ui-gray-9);
--border-blocklist-item-selected-color: var(--grey-38);
@@ -468,15 +452,12 @@
--bg-switch-box-color: var(--grey-53);
--bg-panel-body-color: var(--black-color);
--bg-dropdown-menu-color: var(--ui-gray-warm-8);
- --bg-codemirror-selected-color: var(--grey-3);
--bg-motd-body-color: var(--black-color);
--bg-blocklist-hover-color: var(--black-color);
--bg-blocklist-item-selected-color: var(--black-color);
--bg-input-group-addon-color: var(--grey-3);
--bg-table-color: var(--black-color);
- --bg-codemirror-gutters-color: var(--ui-gray-warm-11);
- --bg-codemirror-color: var(--black-color);
- --bg-codemirror-selected-color: var(--grey-3);
+
--bg-log-viewer-color: var(--black-color);
--bg-log-line-selected-color: var(--grey-3);
--bg-modal-content-color: var(--black-color);
@@ -536,7 +517,6 @@
--text-tooltip-color: var(--white-color);
--text-blocklist-item-selected-color: var(--blue-9);
--text-input-group-addon-color: var(--white-color);
- --text-codemirror-color: var(--white-color);
--text-dropdown-menu-color: var(--white-color);
--text-log-viewer-color: var(--white-color);
--text-summary-color: var(--white-color);
@@ -582,7 +562,6 @@
--border-pre-next-month: var(--white-color);
--border-daterangepicker-after: var(--black-color);
--border-pre-color: var(--grey-3);
- --border-codemirror-cursor-color: var(--white-color);
--border-modal: 1px solid var(--white-color);
--border-sortbutton: var(--black-color);
--border-bootbox: var(--black-color);
@@ -596,9 +575,7 @@
--text-input-textarea: var(--black-color);
--bg-item-highlighted-null-color: var(--grey-2);
- --text-cm-default-color: var(--blue-9);
- --text-cm-meta-color: var(--white-color);
- --text-cm-string-color: var(--red-7);
+
--text-progress-bar-color: var(--black-color);
--user-menu-icon-color: var(--white-color);
diff --git a/app/assets/css/vendor-override.css b/app/assets/css/vendor-override.css
index 5f83a6583..097b31385 100644
--- a/app/assets/css/vendor-override.css
+++ b/app/assets/css/vendor-override.css
@@ -154,50 +154,6 @@ code {
background-color: var(--bg-table-selected-color);
}
-.CodeMirror-gutters {
- background: var(--bg-codemirror-gutters-color);
- border-right: 0px;
-}
-
-.CodeMirror-linenumber {
- text-align: left;
-}
-
-.CodeMirror pre.CodeMirror-line,
-.CodeMirror pre.CodeMirror-line-like {
- padding: 0 20px;
-}
-
-.CodeMirror {
- background: var(--bg-codemirror-color);
- color: var(--text-codemirror-color);
- border-radius: 8px;
-}
-
-.CodeMirror-selected {
- background: var(--bg-codemirror-selected-color) !important;
-}
-
-.CodeMirror-cursor {
- border-left: 1px solid var(--border-codemirror-cursor-color);
-}
-
-.cm-s-default .cm-atom {
- color: var(--text-cm-default-color);
-}
-
-.cm-s-default .cm-meta {
- color: var(--text-cm-meta-color);
-}
-
-.cm-s-default .cm-string {
- color: var(--text-cm-string-color);
-}
-
-.cm-s-default .cm-number {
- color: var(--text-cm-number-color);
-}
-
.dropdown-menu {
background: var(--bg-dropdown-menu-color);
border-radius: 8px;
diff --git a/app/kubernetes/components/yaml-inspector/yamlInspector.html b/app/kubernetes/components/yaml-inspector/yamlInspector.html
index f424819f0..e33114ace 100644
--- a/app/kubernetes/components/yaml-inspector/yamlInspector.html
+++ b/app/kubernetes/components/yaml-inspector/yamlInspector.html
@@ -6,6 +6,7 @@
placeholder="# Define or paste the content of your manifest here"
read-only="true"
hide-title="true"
+ height="{{ $ctrl.expanded ? '800px' : '500px' }}"
>
diff --git a/app/kubernetes/components/yaml-inspector/yamlInspectorController.js b/app/kubernetes/components/yaml-inspector/yamlInspectorController.js
index dd5986e10..cd2bf00c8 100644
--- a/app/kubernetes/components/yaml-inspector/yamlInspectorController.js
+++ b/app/kubernetes/components/yaml-inspector/yamlInspectorController.js
@@ -33,9 +33,6 @@ class KubernetesYamlInspectorController {
}
toggleYAMLInspectorExpansion() {
- let selector = 'kubernetes-yaml-inspector code-editor > div.CodeMirror';
- let height = this.expanded ? '500px' : '80vh';
- $(selector).css({ height: height });
this.expanded = !this.expanded;
}
diff --git a/app/portainer/components/code-editor/code-editor.html b/app/portainer/components/code-editor/code-editor.html
index 33d43931b..9347d7c8f 100644
--- a/app/portainer/components/code-editor/code-editor.html
+++ b/app/portainer/components/code-editor/code-editor.html
@@ -5,4 +5,5 @@
readonly="$ctrl.readOnly"
on-change="($ctrl.handleChange)"
value="$ctrl.value"
+ height="$ctrl.height || undefined"
>
diff --git a/app/portainer/components/code-editor/code-editor.js b/app/portainer/components/code-editor/code-editor.js
index 788aede3a..a4347a0a6 100644
--- a/app/portainer/components/code-editor/code-editor.js
+++ b/app/portainer/components/code-editor/code-editor.js
@@ -10,5 +10,6 @@ angular.module('portainer.app').component('codeEditor', {
readOnly: '<',
onChange: '<',
value: '<',
+ height: '@',
},
});
diff --git a/app/portainer/components/form-components/web-editor-form/index.js b/app/portainer/components/form-components/web-editor-form/index.js
index b82a7f9ac..5fa476e61 100644
--- a/app/portainer/components/form-components/web-editor-form/index.js
+++ b/app/portainer/components/form-components/web-editor-form/index.js
@@ -12,6 +12,7 @@ export const webEditorForm = {
readOnly: '<',
onChange: '<',
hideTitle: '<',
+ height: '@',
},
transclude: {
diff --git a/app/portainer/components/form-components/web-editor-form/web-editor-form.html b/app/portainer/components/form-components/web-editor-form/web-editor-form.html
index b694a5f77..9dd875abf 100644
--- a/app/portainer/components/form-components/web-editor-form/web-editor-form.html
+++ b/app/portainer/components/form-components/web-editor-form/web-editor-form.html
@@ -47,6 +47,7 @@
yml="$ctrl.yml"
value="$ctrl.value"
on-change="($ctrl.onChange)"
+ height="{{ $ctrl.height }}"
>
diff --git a/app/react/components/CodeEditor.module.css b/app/react/components/CodeEditor.module.css
new file mode 100644
index 000000000..3cb2df907
--- /dev/null
+++ b/app/react/components/CodeEditor.module.css
@@ -0,0 +1,72 @@
+.root {
+ --text-cm-default-color: var(--blue-1);
+ --text-cm-meta-color: var(--black-color);
+ --text-cm-string-color: var(--red-3);
+ --text-cm-number-color: var(--green-1);
+ --text-cm-keyword-color: var(--ui-blue-dark-9);
+ --text-codemirror-color: var(--black-color);
+ --bg-codemirror-color: var(--white-color);
+ --bg-codemirror-gutters-color: var(--grey-17);
+ --bg-codemirror-selected-color: var(--grey-22);
+ --border-codemirror-cursor-color: var(--black-color);
+}
+
+:global([theme='dark']) .root {
+ --text-cm-default-color: var(--blue-10);
+ --text-cm-meta-color: var(--white-color);
+ --text-cm-string-color: var(--red-5);
+ --text-cm-number-color: var(--green-2);
+ --text-cm-keyword-color: var(--ui-purple-6);
+ --text-codemirror-color: var(--white-color);
+ --bg-codemirror-color: var(--grey-2);
+ --bg-codemirror-gutters-color: var(--grey-3);
+ --bg-codemirror-selected-color: var(--grey-3);
+ --border-codemirror-cursor-color: var(--white-color);
+}
+
+:global([theme='highcontrast']) .root {
+ --text-cm-default-color: var(--blue-9);
+ --text-cm-meta-color: var(--white-color);
+ --text-cm-string-color: var(--red-7);
+ --text-cm-number-color: var(--green-2);
+ --text-cm-keyword-color: var(--ui-purple-6);
+ --text-codemirror-color: var(--white-color);
+ --bg-codemirror-color: var(--black-color);
+ --bg-codemirror-gutters-color: var(--ui-gray-warm-11);
+ --bg-codemirror-selected-color: var(--grey-3);
+ --border-codemirror-cursor-color: var(--white-color);
+}
+
+.root :global(.cm-editor .cm-gutters) {
+ border-right: 0px;
+}
+
+.root :global(.cm-editor .cm-gutters .cm-lineNumbers .cm-gutterElement) {
+ text-align: left;
+}
+
+.root :global(.cm-editor),
+.root :global(.cm-editor .cm-scroller) {
+ border-radius: 8px;
+}
+
+/* Search Panel */
+/* Ideally we would use a react component for that, but this is the easy solution for onw */
+
+.root :global(.cm-panels.cm-panels-bottom) {
+ background-color: var(--bg-codemirror-gutters-color);
+ border-top-color: transparent;
+ color: var(--text-codemirror-color);
+}
+
+.root :global(.cm-button) {
+ @apply bg-blue-8;
+ color: var(--text-codemirror-color);
+ background-image: none;
+}
+
+.root :global(.cm-textfield) {
+ border: 1px solid var(--border-form-control-color);
+ background-color: var(--bg-inputbox);
+ color: var(--text-form-control-color);
+}
diff --git a/app/react/components/CodeEditor.tsx b/app/react/components/CodeEditor.tsx
index f0ad8255c..8d77845aa 100644
--- a/app/react/components/CodeEditor.tsx
+++ b/app/react/components/CodeEditor.tsx
@@ -1,7 +1,11 @@
import CodeMirror from '@uiw/react-codemirror';
-import { StreamLanguage } from '@codemirror/language';
+import { StreamLanguage, LanguageSupport } from '@codemirror/language';
import { yaml } from '@codemirror/legacy-modes/mode/yaml';
import { useMemo } from 'react';
+import { createTheme } from '@uiw/codemirror-themes';
+import { tags as highlightTags } from '@lezer/highlight';
+
+import styles from './CodeEditor.module.css';
interface Props {
id: string;
@@ -13,6 +17,30 @@ interface Props {
height?: string;
}
+const theme = createTheme({
+ theme: 'light',
+ settings: {
+ background: 'var(--bg-codemirror-color)',
+ foreground: 'var(--text-codemirror-color)',
+ caret: 'var(--border-codemirror-cursor-color)',
+ selection: 'var(--bg-codemirror-selected-color)',
+ selectionMatch: 'var(--bg-codemirror-selected-color)',
+ gutterBackground: 'var(--bg-codemirror-gutters-color)',
+ },
+ styles: [
+ { tag: highlightTags.atom, color: 'var(--text-cm-default-color)' },
+ { tag: highlightTags.meta, color: 'var(--text-cm-meta-color)' },
+ {
+ tag: [highlightTags.string, highlightTags.special(highlightTags.brace)],
+ color: 'var(--text-cm-string-color)',
+ },
+ { tag: highlightTags.number, color: 'var(--text-cm-number-color)' },
+ { tag: highlightTags.keyword, color: 'var(--text-cm-keyword-color)' },
+ ],
+});
+
+const yamlLanguage = new LanguageSupport(StreamLanguage.define(yaml));
+
export function CodeEditor({
id,
onChange,
@@ -22,13 +50,12 @@ export function CodeEditor({
height = '500px',
yaml: isYaml,
}: Props) {
- const extensions = useMemo(
- () => (isYaml ? [StreamLanguage.define(yaml)] : []),
- [isYaml]
- );
+ const extensions = useMemo(() => (isYaml ? [yamlLanguage] : []), [isYaml]);
return (