Repository: omegaup/omegaup
Pull request #8097: Added dropdown to update font-size in editor, also added translations
Author: login: Himanshu-Dangwal
Labels: name: GSoC
Created: 2025-03-25T21:19:51Z | Merged: 2025-03-30T03:15:54Z

# Description

This PR adds an **editor toolbar** inside the `editorContainer` in `MonacoEditor.vue`. 

- The toolbar includes an option for users to **change the font size** of their code, allowing them to adjust it according to their preferences.  
- Additionally, since localization is required, I added **translations for "Font Size"** in all three supported languages: **English (en), Spanish (es), and Portuguese (pt)**.

# Changes in UI

<img width="1039" alt="Screenshot 2025-03-25 at 2 18 55 PM" src="https://github.com/user-attachments/assets/59b50798-5acd-4e9f-b53b-d0e00ac04eb6" />

Fixes: #8052 

# Checklist:

- [x] The code follows the [coding guidelines](https://github.com/omegaup/omegaup/wiki/Coding-guidelines) of omegaUp.
- [x] All tests were executed and passed successfully.
- [x] New tests were added for this feature (if applicable).
- [x] If the change is large (> 200 lines), it has been split into multiple PRs.  
  - One for controllers + PHPUnit tests.  
  - Another for UI + Jest or Cypress tests.



Diff:
diff --git a/frontend/templates/en.lang b/frontend/templates/en.lang
index 72fa3fbb657..bc56cbefaec 100644
--- a/frontend/templates/en.lang
+++ b/frontend/templates/en.lang
@@ -702,6 +702,7 @@ feedbackSuccessfullyAdded = "The feedback has been successfully added."
 feedbackSuccessfullyUpdated = "The feedback has been successfully updated."
 feedbackTitle = "Submission feedback"
 firstSumbissionWithIdentity = "Note that you are trying to send a submission with an identity account"
+fontSize = "Font-Size"
 forSelectedItems = "For selected items"
 forbiddenInVirtualContest = "Forbidden in virtual contest"
 frontPageDevelopers = "Developers"
diff --git a/frontend/templates/es.lang b/frontend/templates/es.lang
index 5cc2a9dd119..fb876052fab 100644
--- a/frontend/templates/es.lang
+++ b/frontend/templates/es.lang
@@ -702,6 +702,7 @@ feedbackSuccessfullyAdded = "La retroalimentación se agregó correctamente."
 feedbackSuccessfullyUpdated = "La retroalimentación se actualizó correctamente."
 feedbackTitle = "Retroalimentación sobre el envío"
 firstSumbissionWithIdentity = "Ten en cuenta que estás intentando enviar una solución con una cuenta de identidad"
+fontSize = "Tamaño de fuente"
 forSelectedItems = "Para los items seleccionados"
 forbiddenInVirtualContest = "Prohibido en concurso virtual"
 frontPageDevelopers = "Desarrolladores"
diff --git a/frontend/templates/pseudo.lang b/frontend/templates/pseudo.lang
index 3540b97fed1..b3794559a4c 100644
--- a/frontend/templates/pseudo.lang
+++ b/frontend/templates/pseudo.lang
@@ -702,6 +702,7 @@ feedbackSuccessfullyAdded = "(Th3 f33dback ha5 b33n 5ucc355fu11y add3d.)"
 feedbackSuccessfullyUpdated = "(Th3 f33dback ha5 b33n 5ucc355fu11y upda73d.)"
 feedbackTitle = "(Submi55i0n f33dback)"
 firstSumbissionWithIdentity = "(N073 7ha7 y0u ar3 7rying 70 53nd a 5ubmi55i0n wi7h an id3n7i7y acc0un7)"
+fontSize = "(F0n7-Siz3)"
 forSelectedItems = "(F0r 5313c73d i73m5)"
 forbiddenInVirtualContest = "(F0rbidd3n in vir7ua1 c0n7357)"
 frontPageDevelopers = "(D3v310p3r5)"
diff --git a/frontend/templates/pt.lang b/frontend/templates/pt.lang
index 2d9531a8262..f28bce96429 100644
--- a/frontend/templates/pt.lang
+++ b/frontend/templates/pt.lang
@@ -702,6 +702,7 @@ feedbackSuccessfullyAdded = "O feedback tem sido satisfatóriamente adicionado."
 feedbackSuccessfullyUpdated = "O feedback tem sido satisfatóriamente atualizado."
 feedbackTitle = "Feedback sobre a submissão"
 firstSumbissionWithIdentity = "Tenha em mente que você está tentando enviar uma solução com uma conta de identidade"
+fontSize = "Tamanho da Fonte"
 forSelectedItems = "Para os itens selecionados"
 forbiddenInVirtualContest = "Proibido em concurso virtual"
 frontPageDevelopers = "Desenvolvedores"
diff --git a/frontend/www/js/omegaup/grader/MonacoEditor.vue b/frontend/www/js/omegaup/grader/MonacoEditor.vue
index bf8aca9e70e..e882d22abed 100644
--- a/frontend/www/js/omegaup/grader/MonacoEditor.vue
+++ b/frontend/www/js/omegaup/grader/MonacoEditor.vue
@@ -1,5 +1,19 @@
 <template>
-  <div></div>
+  <div class="h-100 d-flex flex-column">
+    <div class="editor-toolbar d-flex align-items-center p-1 form-inline">
+      <label class="mr-1 mb-0 p-1">{{ T.fontSize }}</label>
+      <select
+        v-model="selectedFontSize"
+        class="custom-select-sm"
+        @change="onFontSizeChange"
+      >
+        <option v-for="size in fontSizes" :key="size" :value="size">
+          {{ size }}px
+        </option>
+      </select>
+    </div>
+    <div ref="editorContainer" class="editor flex-grow-1 w-100 h-100"></div>
+  </div>
 </template>
 
 <script lang="ts">
@@ -8,6 +22,7 @@ import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
 import store from './GraderStore';
 import * as Util from './util';
 import * as monaco from 'monaco-editor';
+import T from '../lang';
 
 @Component
 export default class MonacoEditor extends Vue {
@@ -21,8 +36,10 @@ export default class MonacoEditor extends Vue {
   _model: monaco.editor.ITextModel | null = null;
 
   // default font size and line height
-  readonly baseFontSize: number = 14;
-  readonly baseLineHeight: number = 19;
+  selectedFontSize: number = 12;
+  fontSizes: number[] = [12, 14, 16, 18, 20];
+
+  T = T; //getting translations
 
   get theme(): string {
     return store.getters['theme'];
@@ -80,18 +97,19 @@ export default class MonacoEditor extends Vue {
   mounted(): void {
     window.addEventListener('code-and-language-set', this.onCodeAndLanguageSet);
 
-    this._editor = monaco.editor.create(
-      this.$el as HTMLElement,
-      {
-        autoIndent: 'brackets',
-        formatOnPaste: true,
-        formatOnType: true,
-        language: Util.supportedLanguages[this.language].modelMapping,
-        readOnly: this.readOnly,
-        theme: this.theme,
-        value: this.contents,
-      } as monaco.editor.IStandaloneEditorConstructionOptions,
-    );
+    const container = this.$refs.editorContainer as HTMLElement;
+    if (!container) return;
+
+    this._editor = monaco.editor.create(container, {
+      autoIndent: 'brackets',
+      formatOnPaste: true,
+      formatOnType: true,
+      language: Util.supportedLanguages[this.language].modelMapping,
+      readOnly: this.readOnly,
+      theme: this.theme,
+      value: this.contents,
+      fontSize: this.selectedFontSize,
+    } as monaco.editor.IStandaloneEditorConstructionOptions);
     this._model = this._editor.getModel();
     if (!this._model) return;
 
@@ -116,11 +134,6 @@ export default class MonacoEditor extends Vue {
       // scaling does not work as intended
       // the cursor does not click where it's supposed to
       // this is an alternative solution to zooming in/out
-
-      this._editor.updateOptions({
-        fontSize: this.baseFontSize * window.devicePixelRatio,
-        lineHeight: this.baseLineHeight * window.devicePixelRatio,
-      });
       this._editor.layout();
     }
   }
@@ -129,12 +142,35 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
-<style scoped>
-div {
-  width: 100%;
-  height: 100%;
+<style lang="scss" scoped>
+@import '../../../sass/main.scss';
+
+.editor-toolbar {
+  background: var(--moncao-editor-toolbar-background-color);
+  border-bottom: 1px solid var(--moncao-editor-toolbar-border-bottom-color);
+}
+
+.editor-toolbar label {
+  font-size: 12px;
+  background: var(--moncao-editor-toolbar-label-background-color);
+  color: var(--moncao-editor-toolbar-label-color);
+  border: 1px solid var(--moncao-editor-toolbar-label-border-color);
+}
+
+.editor-toolbar select {
+  font-size: 10px;
+}
+
+.editor {
+  border: 1px solid var(--moncao-editor-toolbar-label-border-color);
 }
 </style>
diff --git a/frontend/www/js/omegaup/lang.en.json b/frontend/www/js/omegaup/lang.en.json
index 0e25e4238f7..62a0e2db6c8 100644
--- a/frontend/www/js/omegaup/lang.en.json
+++ b/frontend/www/js/omegaup/lang.en.json
@@ -703,6 +703,7 @@
 	"feedbackSuccessfullyUpdated": "The feedback has been successfully updated.",
 	"feedbackTitle": "Submission feedback",
 	"firstSumbissionWithIdentity": "Note that you are trying to send a submission with an identity account",
+	"fontSize": "Font-Size",
 	"forSelectedItems": "For selected items",
 	"forbiddenInVirtualContest": "Forbidden in virtual contest",
 	"frontPageDevelopers": "Developers",
diff --git a/frontend/www/js/omegaup/lang.en.ts b/frontend/www/js/omegaup/lang.en.ts
index 800f12bb4bb..4d1e887fe7c 100644
--- a/frontend/www/js/omegaup/lang.en.ts
+++ b/frontend/www/js/omegaup/lang.en.ts
@@ -704,6 +704,7 @@ const translations: { [key: string]: string; } = {
   feedbackSuccessfullyUpdated: "The feedback has been successfully updated.",
   feedbackTitle: "Submission feedback",
   firstSumbissionWithIdentity: "Note that you are trying to send a submission with an identity account",
+  fontSize: "Font-Size",
   forSelectedItems: "For selected items",
   forbiddenInVirtualContest: "Forbidden in virtual contest",
   frontPageDevelopers: "Developers",
diff --git a/frontend/www/js/omegaup/lang.es.json b/frontend/www/js/omegaup/lang.es.json
index 06dcaef538b..fb108930940 100644
--- a/frontend/www/js/omegaup/lang.es.json
+++ b/frontend/www/js/omegaup/lang.es.json
@@ -703,6 +703,7 @@
 	"feedbackSuccessfullyUpdated": "La retroalimentaci\u00f3n se actualiz\u00f3 correctamente.",
 	"feedbackTitle": "Retroalimentaci\u00f3n sobre el env\u00edo",
 	"firstSumbissionWithIdentity": "Ten en cuenta que est\u00e1s intentando enviar una soluci\u00f3n con una cuenta de identidad",
+	"fontSize": "Tama\u00f1o de fuente",
 	"forSelectedItems": "Para los items seleccionados",
 	"forbiddenInVirtualContest": "Prohibido en concurso virtual",
 	"frontPageDevelopers": "Desarrolladores",
diff --git a/frontend/www/js/omegaup/lang.es.ts b/frontend/www/js/omegaup/lang.es.ts
index 7ee76c9c8e4..ab737d383ee 100644
--- a/frontend/www/js/omegaup/lang.es.ts
+++ b/frontend/www/js/omegaup/lang.es.ts
@@ -704,6 +704,7 @@ const translations: { [key: string]: string; } = {
   feedbackSuccessfullyUpdated: "La retroalimentaci\u00f3n se actualiz\u00f3 correctamente.",
   feedbackTitle: "Retroalimentaci\u00f3n sobre el env\u00edo",
   firstSumbissionWithIdentity: "Ten en cuenta que est\u00e1s intentando enviar una soluci\u00f3n con una cuenta de identidad",
+  fontSize: "Tama\u00f1o de fuente",
   forSelectedItems: "Para los items seleccionados",
   forbiddenInVirtualContest: "Prohibido en concurso virtual",
   frontPageDevelopers: "Desarrolladores",
diff --git a/frontend/www/js/omegaup/lang.pseudo.json b/frontend/www/js/omegaup/lang.pseudo.json
index 0a1c59aa809..5ed2e166cc0 100644
--- a/frontend/www/js/omegaup/lang.pseudo.json
+++ b/frontend/www/js/omegaup/lang.pseudo.json
@@ -703,6 +703,7 @@
 	"feedbackSuccessfullyUpdated": "(Th3 f33dback ha5 b33n 5ucc355fu11y upda73d.)",
 	"feedbackTitle": "(Submi55i0n f33dback)",
 	"firstSumbissionWithIdentity": "(N073 7ha7 y0u ar3 7rying 70 53nd a 5ubmi55i0n wi7h an id3n7i7y acc0un7)",
+	"fontSize": "(F0n7-Siz3)",
 	"forSelectedItems": "(F0r 5313c73d i73m5)",
 	"forbiddenInVirtualContest": "(F0rbidd3n in vir7ua1 c0n7357)",
 	"frontPageDevelopers": "(D3v310p3r5)",
diff --git a/frontend/www/js/omegaup/lang.pseudo.ts b/frontend/www/js/omegaup/lang.pseudo.ts
index df33f5a6162..31326fecfa4 100644
--- a/frontend/www/js/omegaup/lang.pseudo.ts
+++ b/frontend/www/js/omegaup/lang.pseudo.ts
@@ -704,6 +704,7 @@ const translations: { [key: string]: string; } = {
   feedbackSuccessfullyUpdated: "(Th3 f33dback ha5 b33n 5ucc355fu11y upda73d.)",
   feedbackTitle: "(Submi55i0n f33dback)",
   firstSumbissionWithIdentity: "(N073 7ha7 y0u ar3 7rying 70 53nd a 5ubmi55i0n wi7h an id3n7i7y acc0un7)",
+  fontSize: "(F0n7-Siz3)",
   forSelectedItems: "(F0r 5313c73d i73m5)",
   forbiddenInVirtualContest: "(F0rbidd3n in vir7ua1 c0n7357)",
   frontPageDevelopers: "(D3v310p3r5)",
diff --git a/frontend/www/js/omegaup/lang.pt.json b/frontend/www/js/omegaup/lang.pt.json
index 11a378201c2..14343b13dc7 100644
--- a/frontend/www/js/omegaup/lang.pt.json
+++ b/frontend/www/js/omegaup/lang.pt.json
@@ -703,6 +703,7 @@
 	"feedbackSuccessfullyUpdated": "O feedback tem sido satisfat\u00f3riamente atualizado.",
 	"feedbackTitle": "Feedback sobre a submiss\u00e3o",
 	"firstSumbissionWithIdentity": "Tenha em mente que voc\u00ea est\u00e1 tentando enviar uma solu\u00e7\u00e3o com uma conta de identidade",
+	"fontSize": "Tamanho da Fonte",
 	"forSelectedItems": "Para os itens selecionados",
 	"forbiddenInVirtualContest": "Proibido em concurso virtual",
 	"frontPageDevelopers": "Desenvolvedores",
diff --git a/frontend/www/js/omegaup/lang.pt.ts b/frontend/www/js/omegaup/lang.pt.ts
index e3220ae19cc..8daad55a6b8 100644
--- a/frontend/www/js/omegaup/lang.pt.ts
+++ b/frontend/www/js/omegaup/lang.pt.ts
@@ -704,6 +704,7 @@ const translations: { [key: string]: string; } = {
   feedbackSuccessfullyUpdated: "O feedback tem sido satisfat\u00f3riamente atualizado.",
   feedbackTitle: "Feedback sobre a submiss\u00e3o",
   firstSumbissionWithIdentity: "Tenha em mente que voc\u00ea est\u00e1 tentando enviar uma solu\u00e7\u00e3o com uma conta de identidade",
+  fontSize: "Tamanho da Fonte",
   forSelectedItems: "Para os itens selecionados",
   forbiddenInVirtualContest: "Proibido em concurso virtual",
   frontPageDevelopers: "Desenvolvedores",
diff --git a/frontend/www/js/omegaup/lang.ts b/frontend/www/js/omegaup/lang.ts
index f7d97f37ae4..32087612846 100644
--- a/frontend/www/js/omegaup/lang.ts
+++ b/frontend/www/js/omegaup/lang.ts
@@ -3,7 +3,7 @@ import * as lang_es from './lang.es';
 import * as lang_pt from './lang.pt';
 import * as lang_pseudo from './lang.pseudo';
 
-const T = (function() {
+const T = (function () {
   const head =
     (document && document.querySelector && document.querySelector('head')) ||
     null;
diff --git a/frontend/www/sass/base/_variables.scss b/frontend/www/sass/base/_variables.scss
index 67c4c0e110e..22a058f824e 100644
--- a/frontend/www/sass/base/_variables.scss
+++ b/frontend/www/sass/base/_variables.scss
@@ -279,4 +279,11 @@
 
   // GENERAL
   --general-in-maintainance-color: #4b4b4b;
+
+  //MONCAO EDITOR
+  --moncao-editor-toolbar-background-color: #f4f4f4;
+  --moncao-editor-toolbar-label-background-color: #e1e1e1;
+  --moncao-editor-toolbar-label-color: #777777;
+  --moncao-editor-toolbar-label-border-color: #cccccc;
+  --moncao-editor-toolbar-border-bottom-color: #ccc;
 }


Reviews:
user: login: pabo99
body: I left you a series of suggestions, most of which are related to styles.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-26T08:04:06Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:03:00Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:03:07Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:03:46Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:04:15Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:04:29Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:05:16Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:05:31Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:16:33Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:39:59Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:41:01Z
user: login: pabo99
body: Excellent!!

You were very close. Just fix the comment I left, and this change looks good to me.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-26T20:25:33Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T20:34:10Z
user: login: Himanshu-Dangwal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T20:54:36Z
user: login: pabo99
body: It LGTM! Thank you, @Himanshu-Dangwal ! 
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-26T22:04:36Z
user: login: heduenas
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-30T03:04:21Z

Review comments:
diff_hunk: @@ -21,8 +32,11 @@ export default class MonacoEditor extends Vue {
   _model: monaco.editor.ITextModel | null = null;
 
   // default font size and line height
-  readonly baseFontSize: number = 14;
-  readonly baseLineHeight: number = 19;
+  selectedFontSize: number = 12;
+  fontSizes: number[] = [12, 14, 16, 18, 20];
+  // readonly baseLineHeight: number = 19;  Changing fontSize automatically resets the line-height
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: Ok, understood! Could you please remove the line if no needed anymore
created_at: 2025-03-26T07:16:14Z
author_association: COLLABORATOR
diff_hunk: @@ -90,6 +104,8 @@ export default class MonacoEditor extends Vue {
         readOnly: this.readOnly,
         theme: this.theme,
         value: this.contents,
+        fontSize: this.selectedFontSize,
+        // lineHeight: this.baseLineHeight => not required anymore
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: This line has to be removed too
created_at: 2025-03-26T07:16:20Z
author_association: COLLABORATOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: How about making the most of Bootstrap 4 since we are already using it?

You could remove all these styles if you replace them with the existing BS4 classes:

```css
class=" h-100 d-flex flex-column"
```

As you can see, the `editor-container` class is no longer needed.
```suggestion
```
created_at: 2025-03-26T07:22:55Z
author_association: COLLABORATOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: Here, we can also take advantage of BS4:

- `display: flex` can be replaced with the `d-flex` class.

- `align-items: center` can be replaced with the `align-items-center` class.

- `padding: 5px` can be replaced with `p-1`.

```suggestion
.editor-toolbar {
  background: #f4f4f4;
  border-bottom: 1px solid #ccc;
}
```
It looks like the remaining two styles are still needed since there is no equivalent class that meets the requirement.
created_at: 2025-03-26T07:31:48Z
author_association: COLLABORATOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
+
+.editor-toolbar label {
+  margin-right: 4px;
+  font-size: 12px;
+  margin-bottom: 0px;
+  background: #e1e1e1;
+  color: #777777;
+  border: 1px solid #cccccc;
+  padding: 3px;
+}
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: For margins and padding, we can use BS4 classes:

- `margin-right: 4px` can be replaced with the `mr-1` class
- `margin-bottom: 0px` can be replaced with the `mb-0` class
- `padding: 3px` can be replaced with the `p-1` class

```suggestion
.editor-toolbar label {
  font-size: 12px;
  background: #e1e1e1;
  color: #777777;
  border: 1px solid #cccccc;
}
```
The remaining styles can stay as they are.
created_at: 2025-03-26T07:38:56Z
author_association: COLLABORATOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
+
+.editor-toolbar label {
+  margin-right: 4px;
+  font-size: 12px;
+  margin-bottom: 0px;
+  background: #e1e1e1;
+  color: #777777;
+  border: 1px solid #cccccc;
+  padding: 3px;
+}
+
+.editor-toolbar select {
+  padding: 3px;
+  font-size: 10px;
+  border: 1px solid #aaa;
+  border-radius: 4px;
+  background: white;
+}
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: Here, you can also take advantage of the classes for dropdowns in forms. The classes you should use for the select element are:
```css
class="custom-select m1"
```
Additionally, you need to add the `form-inline` class to the parent `div` of this element (in this case, `editor-toolbar`).

In your custom class, you only need to keep the font size:
```suggestion
.editor-toolbar select {
  font-size: 10px;
}
```
created_at: 2025-03-26T07:48:34Z
author_association: COLLABORATOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
+
+.editor-toolbar label {
+  margin-right: 4px;
+  font-size: 12px;
+  margin-bottom: 0px;
+  background: #e1e1e1;
+  color: #777777;
+  border: 1px solid #cccccc;
+  padding: 3px;
+}
+
+.editor-toolbar select {
+  padding: 3px;
+  font-size: 10px;
+  border: 1px solid #aaa;
+  border-radius: 4px;
+  background: white;
+}
+
+.editor {
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: All these styles can be replaced with BS4 classes:
- `flex: 1` can be replaced with the class `flex-grow-1`
- `width: 100%` can be replaced with the class  `w-100`
- `height: 100%` can be replaced with the class  `h-100`.

So this custom class can also be removed.
created_at: 2025-03-26T07:53:16Z
author_association: COLLABORATOR
diff_hunk: @@ -1,5 +1,15 @@
 <template>
-  <div></div>
+  <div class="editor-container">
+    <div class="editor-toolbar">
+      <label>{{ T.fontSize }}</label>
+      <select v-model="selectedFontSize" @change="onFontSizeChange">
+        <option v-for="size in fontSizes" :key="size" :value="size">
+          {{ size }}px
+        </option>
+      </select>
+    </div>
+    <div ref="editorContainer" class="editor"></div>
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: In the previous PR you closed, you used this `div` in the `monaco-editor` instance within the `mounted` function. Could you use it again? so that this `div` has a purpose.
created_at: 2025-03-26T07:57:08Z
author_association: COLLABORATOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
+
+.editor-toolbar label {
+  margin-right: 4px;
+  font-size: 12px;
+  margin-bottom: 0px;
+  background: #e1e1e1;
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: Can you add this and all color-related styles as variables?

We're doing this so that when we implement dark mode in omegaUp, most of the color styles will be in one place, making the transition less painful.

Here’s an example of how to add colors as variables:
https://github.com/omegaup/omegaup/blob/1e2a2e1f5a35c5a63ef11fbc82dcc7cd8ac08015/frontend/www/js/omegaup/grader/TextEditor.vue#L67-L70


created_at: 2025-03-26T08:03:05Z
author_association: COLLABORATOR
diff_hunk: @@ -21,8 +32,11 @@ export default class MonacoEditor extends Vue {
   _model: monaco.editor.ITextModel | null = null;
 
   // default font size and line height
-  readonly baseFontSize: number = 14;
-  readonly baseLineHeight: number = 19;
+  selectedFontSize: number = 12;
+  fontSizes: number[] = [12, 14, 16, 18, 20];
+  // readonly baseLineHeight: number = 19;  Changing fontSize automatically resets the line-height
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Removed.
created_at: 2025-03-26T18:03:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -90,6 +104,8 @@ export default class MonacoEditor extends Vue {
         readOnly: this.readOnly,
         theme: this.theme,
         value: this.contents,
+        fontSize: this.selectedFontSize,
+        // lineHeight: this.baseLineHeight => not required anymore
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Removed
created_at: 2025-03-26T18:03:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Added the BS4 class, and removed the editor-container.
created_at: 2025-03-26T18:03:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Done, made the required changes.
created_at: 2025-03-26T18:04:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
+
+.editor-toolbar label {
+  margin-right: 4px;
+  font-size: 12px;
+  margin-bottom: 0px;
+  background: #e1e1e1;
+  color: #777777;
+  border: 1px solid #cccccc;
+  padding: 3px;
+}
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Updated these styles.
created_at: 2025-03-26T18:04:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
+
+.editor-toolbar label {
+  margin-right: 4px;
+  font-size: 12px;
+  margin-bottom: 0px;
+  background: #e1e1e1;
+  color: #777777;
+  border: 1px solid #cccccc;
+  padding: 3px;
+}
+
+.editor-toolbar select {
+  padding: 3px;
+  font-size: 10px;
+  border: 1px solid #aaa;
+  border-radius: 4px;
+  background: white;
+}
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Have used class custom-select-sm and also added the class form-inline in the editor-toolbar
created_at: 2025-03-26T18:05:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
+
+.editor-toolbar label {
+  margin-right: 4px;
+  font-size: 12px;
+  margin-bottom: 0px;
+  background: #e1e1e1;
+  color: #777777;
+  border: 1px solid #cccccc;
+  padding: 3px;
+}
+
+.editor-toolbar select {
+  padding: 3px;
+  font-size: 10px;
+  border: 1px solid #aaa;
+  border-radius: 4px;
+  background: white;
+}
+
+.editor {
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Made these changes.
created_at: 2025-03-26T18:05:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,15 @@
 <template>
-  <div></div>
+  <div class="editor-container">
+    <div class="editor-toolbar">
+      <label>{{ T.fontSize }}</label>
+      <select v-model="selectedFontSize" @change="onFontSizeChange">
+        <option v-for="size in fontSizes" :key="size" :value="size">
+          {{ size }}px
+        </option>
+      </select>
+    </div>
+    <div ref="editorContainer" class="editor"></div>
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Done, have also added a border to the editor area, to make it look a bit better. Have added images for comparision.

<img width="1435" alt="Screenshot 2025-03-26 at 11 14 54 AM" src="https://github.com/user-attachments/assets/08a9726e-4a76-4d86-91b1-4ceb6333ecd4" />
<img width="1438" alt="Screenshot 2025-03-26 at 11 15 32 AM" src="https://github.com/user-attachments/assets/08d7baaa-f48c-4f28-8c3c-f565ee456538" />

created_at: 2025-03-26T18:16:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,15 @@
 <template>
-  <div></div>
+  <div class="editor-container">
+    <div class="editor-toolbar">
+      <label>{{ T.fontSize }}</label>
+      <select v-model="selectedFontSize" @change="onFontSizeChange">
+        <option v-for="size in fontSizes" :key="size" :value="size">
+          {{ size }}px
+        </option>
+      </select>
+    </div>
+    <div ref="editorContainer" class="editor"></div>
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Black type border was not looking good, so using the the same tone (greyish)
<img width="1043" alt="Screenshot 2025-03-26 at 11 39 20 AM" src="https://github.com/user-attachments/assets/54849fad-554c-4fe7-86d7-a89ba89ef593" />

created_at: 2025-03-26T18:39:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,11 +140,50 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
 <style scoped>
-div {
+.editor-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.editor-toolbar {
+  display: flex;
+  align-items: center;
+  padding: 5px;
+  background: #f4f4f4;
+  border-bottom: 1px solid #ccc;
+}
+
+.editor-toolbar label {
+  margin-right: 4px;
+  font-size: 12px;
+  margin-bottom: 0px;
+  background: #e1e1e1;
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Done, have added all the colors in _variables.scss file, under MONCAO EDITOR.
<img width="433" alt="Screenshot 2025-03-26 at 11 40 51 AM" src="https://github.com/user-attachments/assets/75e0dfc9-4637-49a7-be25-b36cd1aabeb8" />

created_at: 2025-03-26T18:41:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,12 +142,35 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
-<style scoped>
-div {
-  width: 100%;
-  height: 100%;
+<style lang="scss" scoped>
+@import '../../../sass/main.scss';
+
+.editor-toolbar {
+  background: var(--moncao-editor-toolbar-background-color);
+  border-bottom: 1px solid #ccc;
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: pabo99
body: This color still needs to be added as a variable.
created_at: 2025-03-26T20:23:44Z
author_association: COLLABORATOR
diff_hunk: @@ -129,12 +142,35 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
-<style scoped>
-div {
-  width: 100%;
-  height: 100%;
+<style lang="scss" scoped>
+@import '../../../sass/main.scss';
+
+.editor-toolbar {
+  background: var(--moncao-editor-toolbar-background-color);
+  border-bottom: 1px solid #ccc;
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Okay sure, will update this.
created_at: 2025-03-26T20:34:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,12 +142,35 @@ export default class MonacoEditor extends Vue {
     e.detail.code = this.contents;
     e.detail.language = this.language;
   }
+
+  onFontSizeChange(): void {
+    if (this._editor) {
+      this._editor.updateOptions({ fontSize: this.selectedFontSize });
+    }
+  }
 }
 </script>
 
-<style scoped>
-div {
-  width: 100%;
-  height: 100%;
+<style lang="scss" scoped>
+@import '../../../sass/main.scss';
+
+.editor-toolbar {
+  background: var(--moncao-editor-toolbar-background-color);
+  border-bottom: 1px solid #ccc;
path: frontend/www/js/omegaup/grader/MonacoEditor.vue
user: login: Himanshu-Dangwal
body: Have added the color as a variable.
created_at: 2025-03-26T20:54:35Z
author_association: CONTRIBUTOR

PR comments:
user: login: Himanshu-Dangwal
created_at: 2025-03-26T19:23:52Z
body: @pabo99 , I have made all the suggested changes, can you please review it again whenever you have some time.
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-03-26T20:24:02Z
body: ## [Codecov](https://app.codecov.io/gh/omegaup/omegaup/pull/8097?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omegaup) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 77.83%. Comparing base [(`1e2a2e1`)](https://app.codecov.io/gh/omegaup/omegaup/commit/1e2a2e1f5a35c5a63ef11fbc82dcc7cd8ac08015?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omegaup) to head [(`5f166ad`)](https://app.codecov.io/gh/omegaup/omegaup/commit/5f166ad56cc35d3b2be96362dbd26f12ec6c9366?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omegaup).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff            @@
##               main    #8097   +/-   ##
=========================================
  Coverage     77.83%   77.83%           
  Complexity     5163     5163           
=========================================
  Files           153      153           
  Lines         31714    31714           
=========================================
  Hits          24684    24684           
  Misses         7030     7030           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/omegaup/omegaup/pull/8097?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omegaup).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omegaup).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: Himanshu-Dangwal
created_at: 2025-03-27T04:13:21Z
body: @heduenas Can you please review this PR?
author_association: CONTRIBUTOR