diff --git a/src/components/Dropdown.tsx b/src/components/Dropdown.tsx
index ffca3f46e5247bceb00d7f963fc631947aa8ed35..b2056dd5e9142a2a0cb6db167564cdd4c0c0a797 100644
--- a/src/components/Dropdown.tsx
+++ b/src/components/Dropdown.tsx
@@ -25,7 +25,7 @@ const Dropdown = ({
       placeholder=" " // so the label stays outside
       disableAnimation
       disableSelectorIconRotation
-      inputProps={{ classNames: baseInputClassNames, variant: "bordered" }} // use the same props as BaseInput
+      inputProps={{ classNames: baseInputClassNames(false) }} // use the same props as BaseInput
       selectorIcon={<Icon name="dropdown" />}
       isClearable={false} // so the "cross" button does not show
       isReadOnly // so the input is not searchable
diff --git a/src/components/TextInput.tsx b/src/components/TextInput.tsx
index 97166e4cf7c66831a0059accbc903a4b71237694..31d27e15bca737533513954da52528912907a5d6 100644
--- a/src/components/TextInput.tsx
+++ b/src/components/TextInput.tsx
@@ -6,9 +6,10 @@ type TextInputProps = {
   endContent?: ReactNode; // such as units (as text element e.g. <span>)
   isClearable?: boolean;
   value: string;
-  onValueChange: Dispatch<SetStateAction<string>>;
+  onValueChange?: Dispatch<SetStateAction<string>>;
   isInvalid?: boolean;
   errorMessage?: string;
+  isDisabled?: boolean;
 };
 
 const TextInput = ({
@@ -19,6 +20,7 @@ const TextInput = ({
   onValueChange,
   isInvalid = false,
   errorMessage = "",
+  isDisabled = false,
 }: TextInputProps) => {
   return (
     <BaseInput
@@ -30,6 +32,7 @@ const TextInput = ({
       onValueChange={onValueChange}
       isInvalid={isInvalid}
       errorMessage={errorMessage}
+      isDisabled={isDisabled}
     />
   );
 };
diff --git a/src/components/utils/baseComponents.tsx b/src/components/utils/baseComponents.tsx
index a6d62d59ccbe8566eb93514dc02cc8a8e57a5ee9..61d002df2986572b49b2a88aac18b85273b84710 100644
--- a/src/components/utils/baseComponents.tsx
+++ b/src/components/utils/baseComponents.tsx
@@ -1,5 +1,6 @@
 import { Input } from "@nextui-org/react";
 import { Dispatch, ReactNode, SetStateAction } from "react";
+import { InputSlots } from "@nextui-org/theme";
 
 type BaseInputProps = {
   // basic info
@@ -9,24 +10,40 @@ type BaseInputProps = {
   placeholder: string;
   isClearable?: boolean;
   value?: string;
-  onValueChange: Dispatch<SetStateAction<string>>;
+  onValueChange?: Dispatch<SetStateAction<string>>;
   isInvalid: boolean;
   errorMessage: string;
+  // interaction
+  isDisabled: boolean;
 };
 
-// No we cannot do "[&>svg]:" + className because Tailwind does not support dynamic class names
-const clearButtonSvgClass =
-  "[&>svg]:w-[42px] [&>svg]:h-[42px] [&>svg]:mt-[-6px] [&>svg]:ml-[-5px]";
+type baseInputClassNamesObj = { [key in InputSlots]: string };
 
-export const baseInputClassNames = {
-  label: "!text-foreground-body",
-  mainWrapper: "text-grey dark:text-mediumGrey",
-  inputWrapper: "bg-baseWhite dark:bg-mediumGrey rounded-[4px] px-2",
-  input: "!text-foreground-body bg-default",
-  clearButton:
-    clearButtonSvgClass +
-    " " +
-    "bg-mediumGrey text-baseWhite dark:bg-baseWhite dark:text-mediumGrey w-[30px] h-[30px] p-0 !opacity-100",
+export const baseInputClassNames = (isDisabled: boolean) => {
+  // No we cannot do "[&>svg]:" + className because Tailwind does not support dynamic class names
+  const clearButtonSvgClass =
+    "[&>svg]:w-[42px] [&>svg]:h-[42px] [&>svg]:mt-[-6px] [&>svg]:ml-[-5px]";
+
+  const defaultClass = {
+    label: "!text-foreground-body",
+    input: "!text-foreground-body bg-default",
+    inputWrapper: "px-2 rounded-[4px] bg-baseWhite dark:bg-mediumGrey",
+    mainWrapper: "text-grey dark:text-mediumGrey", // this is the border color (use text-*)
+    clearButton:
+      clearButtonSvgClass +
+      " " +
+      "bg-mediumGrey text-baseWhite dark:bg-baseWhite dark:text-mediumGrey w-[30px] h-[30px] p-0 !opacity-100",
+  } as baseInputClassNamesObj;
+
+  const disabledClass = {
+    base: "opacity-100 pointer-events-auto cursor-not-allowed",
+    label: "!text-foreground-body",
+    input: "!text-foreground-body bg-default",
+    inputWrapper: "px-2 rounded-[4px] bg-lightGrey dark:bg-darkModeBlue",
+    mainWrapper: "text-mediumGrey dark:text-darkModeBlue",
+  } as baseInputClassNamesObj;
+
+  return isDisabled ? disabledClass : defaultClass;
 };
 
 export const BaseInput = ({
@@ -38,6 +55,7 @@ export const BaseInput = ({
   onValueChange,
   isInvalid,
   errorMessage,
+  isDisabled,
 }: BaseInputProps) => {
   return (
     <Input
@@ -50,10 +68,11 @@ export const BaseInput = ({
       onValueChange={onValueChange}
       isInvalid={isInvalid}
       errorMessage={errorMessage}
+      isDisabled={isDisabled}
       // appearance
       labelPlacement="outside"
       variant="bordered"
-      classNames={baseInputClassNames}
+      classNames={baseInputClassNames(isDisabled)}
     />
   );
 };
diff --git a/src/index.css b/src/index.css
index 16a15f482165a16507c297960203a5d5fcdc7332..876d6a0c7db242412402ef989b5d1acdb722037e 100644
--- a/src/index.css
+++ b/src/index.css
@@ -2701,6 +2701,11 @@ video {
   color: hsl(var(--nextui-warning) / 0.8);
 }
 
+.text-mediumGrey {
+  --tw-text-opacity: 1;
+  color: rgb(49 49 49 / var(--tw-text-opacity));
+}
+
 .underline {
   text-decoration-line: underline;
 }
@@ -3205,7 +3210,7 @@ video {
 
 .dark,[data-theme="dark"] {
   color-scheme: dark;
-  --nextui-background: 240 100% 7%;
+  --nextui-background: 240 25% 13%;
   --nextui-foreground-50: 240 6% 10%;
   --nextui-foreground-100: 240 4% 16%;
   --nextui-foreground-200: 240 5% 26%;
@@ -4480,6 +4485,11 @@ video {
   opacity: 1;
 }
 
+.focus\:text-baseBlack:focus {
+  --tw-text-opacity: 1;
+  color: rgb(0 0 0 / var(--tw-text-opacity));
+}
+
 .focus\:underline:focus {
   text-decoration-line: underline;
 }
@@ -4509,6 +4519,16 @@ video {
   outline-color: hsl(var(--nextui-focus) / var(--nextui-focus-opacity, 1));
 }
 
+.active\:text-primary:active {
+  --tw-text-opacity: 1;
+  color: hsl(var(--nextui-primary) / var(--nextui-primary-opacity, var(--tw-text-opacity)));
+}
+
+.active\:\!text-primary:active {
+  --tw-text-opacity: 1 !important;
+  color: hsl(var(--nextui-primary) / var(--nextui-primary-opacity, var(--tw-text-opacity))) !important;
+}
+
 .active\:underline:active {
   text-decoration-line: underline;
 }
@@ -5047,6 +5067,11 @@ video {
   color: hsl(var(--nextui-secondary) / var(--nextui-secondary-opacity, var(--tw-text-opacity)));
 }
 
+.data-\[active\=false\]\:text-grey[data-active=false] {
+  --tw-text-opacity: 1;
+  color: rgb(119 119 119 / var(--tw-text-opacity));
+}
+
 .data-\[disabled\=true\]\:opacity-30[data-disabled=true] {
   opacity: 0.3;
 }
@@ -6205,6 +6230,11 @@ video {
   background-color: hsl(var(--nextui-content2) / var(--nextui-content2-opacity, var(--tw-bg-opacity)));
 }
 
+:is(.dark .dark\:bg-darkModeBlue) {
+  --tw-bg-opacity: 1;
+  background-color: rgb(0 0 34 / var(--tw-bg-opacity));
+}
+
 :is(.dark .dark\:bg-default) {
   --tw-bg-opacity: 1;
   background-color: hsl(var(--nextui-default) / var(--nextui-default-opacity, var(--tw-bg-opacity)));
@@ -6235,6 +6265,11 @@ video {
   color: hsl(var(--nextui-warning) / var(--nextui-warning-opacity, var(--tw-text-opacity)));
 }
 
+:is(.dark .dark\:text-darkModeBlue) {
+  --tw-text-opacity: 1;
+  color: rgb(0 0 34 / var(--tw-text-opacity));
+}
+
 :is(.dark .dark\:placeholder\:text-success)::-moz-placeholder {
   --tw-text-opacity: 1;
   color: hsl(var(--nextui-success) / var(--nextui-success-opacity, var(--tw-text-opacity)));
diff --git a/src/stories/TextInput.stories.tsx b/src/stories/TextInput.stories.tsx
index d3ece2232f92fd24bf975dbe1f49f2aee23a4641..d949d8b171b8a1d81052a4136735ed7941901fa8 100644
--- a/src/stories/TextInput.stories.tsx
+++ b/src/stories/TextInput.stories.tsx
@@ -43,3 +43,13 @@ export const IsClearable = () => {
     />
   );
 };
+
+export const Disabled = () => {
+  return (
+    <TextInput
+      label="You can't change this!"
+      isDisabled={true}
+      value="*Evil laughter*"
+    />
+  );
+};
diff --git a/tailwind.config.js b/tailwind.config.js
index dc91dc347c4e40c93cd4fd7a8c23b83b11407ee1..fb61e45644763fe6994166019a011a5d8efff565 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -61,7 +61,7 @@ export default {
         },
         dark: {
           colors: {
-            background: palette.darkModeBlue,
+            background: palette.darkBlue,
             foreground: {
               heading: palette.baseWhite,
               heading2: palette.lightBlue,