From 75f82b3bc7107bc9b7afbb3da8a4e3700c9e2b63 Mon Sep 17 00:00:00 2001
From: Chirag Chhatrala <60499540+chiragchhatrala@users.noreply.github.com>
Date: Fri, 3 Jan 2025 20:45:47 +0530
Subject: [PATCH] Refactor form components (#659)

* Add Barcode Input Component and Integrate Quagga for Scanning

- Introduced a new BarcodeInput component for scanning barcodes using the Quagga library.
- Updated package.json and package-lock.json to include Quagga as a dependency.
- Enhanced form themes to accommodate the new BarcodeInput component.
- Added localization support for barcode scanning actions in English.
- Updated blocks_types.json to register the new barcode input type.

These changes improve the application's functionality by allowing users to scan barcodes directly within forms, enhancing user experience and data input efficiency.

* Update Barcode scanner UI

* Barcode decoder as user selection

* improve barcode

* Refactor form components and update Tailwind configuration

- Removed unused box shadow styles from tailwind.config.js.
- Enhanced DateInput, FileInput, MatrixInput, RichTextAreaInput, and VSelect components with improved styling and error handling.
- Updated theme settings in form-themes.js to include new styles for MatrixInput and other form elements.
- Adjusted labels in FieldOptions.vue for clarity.
- Improved overall UI consistency and responsiveness across form components.

---------

Co-authored-by: Julien Nahum <julien@nahum.net>
---
 client/components/forms/DateInput.vue         |   6 +-
 client/components/forms/FileInput.vue         |   1 +
 client/components/forms/MatrixInput.vue       |  19 ++-
 .../forms/RichTextAreaInput.client.vue        |  24 ++-
 .../components/forms/components/VSelect.vue   |  93 +++++------
 .../form-components/FormCustomization.vue     |   2 +-
 .../forms/fields/components/FieldOptions.vue  |   2 +-
 client/lib/forms/themes/form-themes.js        | 146 ++++++++++--------
 client/tailwind.config.js                     |   6 +-
 9 files changed, 175 insertions(+), 124 deletions(-)

diff --git a/client/components/forms/DateInput.vue b/client/components/forms/DateInput.vue
index 912c333c6..52156168e 100644
--- a/client/components/forms/DateInput.vue
+++ b/client/components/forms/DateInput.vue
@@ -59,7 +59,7 @@
         </div>
       </button>
 
-      <template #panel="{ close }">
+      <template #panel>
         <DatePicker
           v-if="props.dateRange"
           v-model.range="modeledValue"
@@ -157,9 +157,11 @@ const inputClasses = computed(() => {
     classes.push('!cursor-not-allowed !bg-gray-200 dark:!bg-gray-800')
   }
   if (input.hasError.value) {
-
     classes.push('!ring-red-500 !ring-2 !border-transparent')
   }
+  if (!props.disabled && !input.hasError.value && pickerOpen.value) {
+    classes.push('ring-2 ring-opacity-100 border-transparent')
+  }
   return classes.join(' ')
 })
 
diff --git a/client/components/forms/FileInput.vue b/client/components/forms/FileInput.vue
index e97d809b5..8615f2215 100644
--- a/client/components/forms/FileInput.vue
+++ b/client/components/forms/FileInput.vue
@@ -23,6 +23,7 @@
       class="flex flex-col w-full items-center justify-center transition-colors duration-40"
       :class="[
         {'!cursor-not-allowed':disabled, 'cursor-pointer':!disabled,
+         '!bg-gray-200 dark:!bg-gray-800': disabled,
          [theme.fileInput.inputHover.light + ' dark:'+theme.fileInput.inputHover.dark]: uploadDragoverEvent,
          ['hover:'+theme.fileInput.inputHover.light +' dark:hover:'+theme.fileInput.inputHover.dark]: !loading},
         theme.fileInput.input,
diff --git a/client/components/forms/MatrixInput.vue b/client/components/forms/MatrixInput.vue
index eea0c2313..bc3368f8c 100644
--- a/client/components/forms/MatrixInput.vue
+++ b/client/components/forms/MatrixInput.vue
@@ -4,9 +4,11 @@
       <slot name="label" />
     </template>
     <div
-      class="border border-gray-300 overflow-x-auto"
+      class="border overflow-x-auto"
       :class="[
         theme.default.borderRadius,
+        theme.MatrixInput.cell,
+        theme.MatrixInput.table,
         {
           '!ring-red-500 !ring-2 !border-transparent': hasError,
         },
@@ -19,7 +21,8 @@
             <td
               v-for="column in columns"
               :key="column"
-              class="ltr:border-l rtl:border-r rtl:!border-l-0 border-gray-300 max-w-24 overflow-hidden"
+              class="ltr:border-l rtl:border-r rtl:!border-l-0 max-w-24 overflow-hidden"
+              :class="theme.MatrixInput.cell"
             >
               <div class="p-2 w-full flex items-center justify-center text-sm">
                 {{ column }}
@@ -41,10 +44,14 @@
             <td
               v-for="column in columns"
               :key="row + column"
-              class="ltr:border-l rtl:border-r rtl:!border-l-0 border-gray-300 hover:!bg-gray-100 dark:hover:!bg-gray-800"
-              :class="{
-                '!cursor-not-allowed !bg-gray-200 dark:!bg-gray-800 hover:!bg-gray-200 dark:hover:!bg-gray-800': disabled,
-              }"
+              class="ltr:border-l rtl:border-r rtl:!border-l-0"
+              :class="[
+                theme.MatrixInput.cell,
+                theme.MatrixInput.cellHover,
+                {
+                  '!cursor-not-allowed !bg-gray-200 dark:!bg-gray-800 hover:!bg-gray-200 dark:hover:!bg-gray-800': disabled,
+                },
+              ]"
             >
               <div
                 v-if="compVal"
diff --git a/client/components/forms/RichTextAreaInput.client.vue b/client/components/forms/RichTextAreaInput.client.vue
index c7098659a..c85469d2b 100644
--- a/client/components/forms/RichTextAreaInput.client.vue
+++ b/client/components/forms/RichTextAreaInput.client.vue
@@ -1,5 +1,8 @@
 <template>
-  <InputWrapper v-bind="inputWrapperProps">
+  <InputWrapper
+    v-bind="inputWrapperProps"
+    wrapper-class="not-draggable"
+  >
     <template #label>
       <slot name="label" />
     </template>
@@ -10,19 +13,20 @@
         {
           '!ring-red-500 !ring-2 !border-transparent': hasError,
           '!cursor-not-allowed !bg-gray-200 dark:!bg-gray-800': disabled,
+          'focus-within:ring-2 focus-within:ring-opacity-100 focus-within:border-transparent': !hasError && !disabled
         },
         theme.RichTextAreaInput.input,
         theme.RichTextAreaInput.borderRadius,
         theme.default.fontSize,
       ]"
       :style="{
-        '--font-size': theme.default.fontSize
+        '--font-size': theme.default.fontSize,
+        ...inputStyle
       }"
     >
       <QuillyEditor
         :id="id ? id : name"
         ref="editor"
-        :key="id+placeholder"
         v-model="compVal"
         :options="quillOptions"
         :disabled="disabled"
@@ -37,7 +41,6 @@
     <template #error>
       <slot name="error" />
     </template>
-
     <MentionDropdown
       v-if="enableMentions && mentionState"
       :state="mentionState"
@@ -53,6 +56,7 @@ import InputWrapper from './components/InputWrapper.vue'
 import QuillyEditor from './components/QuillyEditor.vue'
 import MentionDropdown from './components/MentionDropdown.vue'
 import registerMentionExtension from '~/lib/quill/quillMentionExtension.js'
+
 const props = defineProps({
   ...inputProps,
   editorOptions: {
@@ -68,7 +72,9 @@ const props = defineProps({
     default: () => []
   }
 })
+
 const emit = defineEmits(['update:modelValue'])
+
 const { compVal, inputStyle, hasError, inputWrapperProps } = useFormInput(props, { emit })
 const editor = ref(null)
 const mentionState = ref(null)
@@ -91,6 +97,7 @@ const quillOptions = computed(() => {
       ]
     }
   }
+
   const mergedOptions = { ...defaultOptions, ...props.editorOptions, modules: { ...defaultOptions.modules, ...props.editorOptions.modules } }
   
   if (props.enableMentions) {
@@ -112,21 +119,26 @@ const quillOptions = computed(() => {
     border-right: 0px !important;
     border-left: 0px !important;
     font-size: var(--font-size);
+
     .ql-editor {
       min-height: 100px !important;
     }
   }
+
   .ql-toolbar {
     border-top: 0px !important;
     border-right: 0px !important;
     border-left: 0px !important;
   }
+
   .ql-header {
     @apply rounded-md;
   }
+
   .ql-editor.ql-blank:before {
     @apply text-gray-400 dark:text-gray-500 not-italic;
   }
+
   .ql-snow .ql-toolbar .ql-picker-item.ql-selected,
   .ql-snow .ql-toolbar .ql-picker-item:hover,
   .ql-snow .ql-toolbar .ql-picker-label.ql-active,
@@ -144,14 +156,16 @@ const quillOptions = computed(() => {
     @apply text-nt-blue;
   }
 }
+
 .ql-mention {
   padding-top: 0px !important;
-  margin-top: -5px !important;
 }
 .ql-mention::after {
   content: '@';
   font-size: 16px;
 }
+
+
 .rich-editor, .mention-input {
   span[mention] {
     @apply inline-flex items-center align-baseline leading-tight text-sm relative bg-blue-100 text-blue-800 border border-blue-200 rounded-md px-1 py-0.5 mx-0.5;
diff --git a/client/components/forms/components/VSelect.vue b/client/components/forms/components/VSelect.vue
index 3e65b6080..dc851723a 100644
--- a/client/components/forms/components/VSelect.vue
+++ b/client/components/forms/components/VSelect.vue
@@ -13,7 +13,7 @@
         { 
           '!ring-red-500 !ring-2 !border-transparent': hasError, 
           '!cursor-not-allowed !bg-gray-200 dark:!bg-gray-800': disabled,
-          'focus-within:ring-2 focus-within:ring-opacity-100 focus-within:border-transparent': !hasError
+          'focus-within:ring-2 focus-within:ring-opacity-100 focus-within:border-transparent': !hasError && !disabled
         },
         inputClass
       ]"
@@ -78,9 +78,13 @@
           </transition>
         </div>
         <div
-          class="absolute inset-y-0 ltr:right-6 rtl:left-6 w-10 pointer-events-none bg-gradient-to-r from-transparent to-white dark:to-notion-dark-light"
+          class="absolute inset-y-0 ltr:right-6 rtl:left-6 w-10 pointer-events-none -z-[1]"
+          :class="[disabled ? 'bg-gradient-to-r from-transparent to-gray-200 dark:to-gray-800' : theme.SelectInput.chevronGradient]"
         />
-        <span class="absolute inset-y-0 ltr:right-0 rtl:left-0 rtl:!right-auto flex items-center ltr:pr-2 rtl:pl-2 rtl:!pr-0 pointer-events-none bg-white">
+        <span
+          class="absolute inset-y-0 ltr:right-0 rtl:left-0 rtl:!right-auto flex items-center ltr:pr-2 rtl:pl-2 rtl:!pr-0 pointer-events-none"
+          :class="[disabled ? 'bg-gray-200 dark:bg-gray-800' : theme.SelectInput.background]"
+        >
           <Icon
             name="heroicons:chevron-up-down-16-solid" 
             class="h-5 w-5 text-gray-500"
@@ -88,7 +92,7 @@
         </span>
       </button>
       <button
-        v-if="clearable && showClearButton && !isEmpty"
+        v-if="clearable && showClearButton && !disabled && !isEmpty"
         class="hover:bg-gray-50 dark:hover:bg-gray-900 ltr:border-l rtl:!border-l-0 rtl:border-r px-2 flex items-center"
         :class="[theme.SelectInput.spacing.vertical]"
         @click.prevent="clear()"
@@ -208,47 +212,47 @@
 
 <script>
 import Collapsible from '~/components/global/transitions/Collapsible.vue'
-import CachedDefaultTheme from "~/lib/forms/themes/CachedDefaultTheme.js"
 import debounce from 'debounce'
 import Fuse from 'fuse.js'
+import CachedDefaultTheme from '~/lib/forms/themes/CachedDefaultTheme.js'
 
 export default {
   name: 'VSelect',
-  components: {Collapsible},
+  components: { Collapsible },
   directives: {},
   props: {
     data: Array,
-    modelValue: {default: null, type: [String, Number, Array, Object]},
-    inputClass: {type: String, default: null},
-    dropdownClass: {type: String, default: 'w-full'},
-    loading: {type: Boolean, default: false},
-    required: {type: Boolean, default: false},
-    multiple: {type: Boolean, default: false},
-    searchable: {type: Boolean, default: false},
-    clearable: {type: Boolean, default: false},
-    hasError: {type: Boolean, default: false},
-    remote: {type: Function, default: null},
-    searchKeys: {type: Array, default: () => ['name']},
-    optionKey: {type: String, default: 'id'},
-    emitKey: {type: String, default: null},
-    color: {type: String, default: '#3B82F6'},
-    placeholder: {type: String, default: null},
+    modelValue: { default: null, type: [String, Number, Array, Object, Boolean] },
+    inputClass: { type: String, default: null },
+    dropdownClass: { type: String, default: 'w-full' },
+    loading: { type: Boolean, default: false },
+    required: { type: Boolean, default: false },
+    multiple: { type: Boolean, default: false },
+    searchable: { type: Boolean, default: false },
+    clearable: { type: Boolean, default: false },
+    hasError: { type: Boolean, default: false },
+    remote: { type: Function, default: null },
+    searchKeys: { type: Array, default: () => ['name'] },
+    optionKey: { type: String, default: 'id' },
+    emitKey: { type: String, default: null },
+    color: { type: String, default: '#3B82F6' },
+    placeholder: { type: String, default: null },
     uppercaseLabels: { type: Boolean, default: true },
     showClearButton: { type: Boolean, default: true },
     theme: {
       type: Object, default: () => {
-        const theme = inject("theme", null)
+        const theme = inject('theme', null)
         if (theme) {
           return theme.value
         }
         return CachedDefaultTheme.getInstance()
       }
     },
-    allowCreation: {type: Boolean, default: false},
-    disabled: {type: Boolean, default: false}
+    allowCreation: { type: Boolean, default: false },
+    disabled: { type: Boolean, default: false }
   },
   emits: ['update:modelValue', 'update-options', 'focus', 'blur'],
-  data() {
+  data () {
     return {
       isOpen: false,
       searchTerm: '',
@@ -257,46 +261,46 @@ export default {
     }
   },
   computed: {
-    optionStyle() {
+    optionStyle () {
       return {
         '--bg-form-color': this.color
       }
     },
-    inputStyle() {
+    inputStyle () {
       return {
         '--tw-ring-color': this.color
       }
     },
-    debouncedRemote() {
+    debouncedRemote () {
       if (this.remote) {
         return debounce(this.remote, 300)
       }
       return null
     },
-    filteredOptions() {
+    filteredOptions () {
       if (!this.data) return []
       if (!this.searchable || this.remote || this.searchTerm === '') {
         return this.data
       }
 
       // Fuse search
-      const fuse = new Fuse(this.data, {
-        keys: this.searchKeys,
-        includeScore: true
-      })
-      return fuse.search(this.searchTerm).filter((res) => res.score < 0.5).map((res) => {
+      const fuzeOptions = {
+        keys: this.searchKeys
+      }
+      const fuse = new Fuse(this.data, fuzeOptions)
+      return fuse.search(this.searchTerm).map((res) => {
         return res.item
       })
     },
-    isSearchable() {
+    isSearchable () {
       return this.searchable || this.remote !== null || this.allowCreation
     },
-    isEmpty() {
+    isEmpty () {
       return this.multiple ? !this.modelValue || this.modelValue.length === 0 : !this.modelValue
     }
   },
   watch: {
-    searchTerm(val) {
+    searchTerm (val) {
       if (!this.debouncedRemote) return
       if ((this.remote && val) || (val === '' && !this.modelValue) || (val === '' && this.isOpen)) {
         return this.debouncedRemote(val)
@@ -304,13 +308,13 @@ export default {
     }
   },
   methods: {
-    onClickAway(event) {
+    onClickAway (event) {
       // Check that event target isn't children of dropdown
       if (this.$refs.select && !this.$refs.select.contains(event.target)) {
         this.isOpen = false
       }
     },
-    isSelected(value) {
+    isSelected (value) {
       if (!this.modelValue) return false
 
       if (this.emitKey && value[this.emitKey]) {
@@ -323,16 +327,18 @@ export default {
       return this.modelValue === value
     },
     onFocus(event) {
+      if (this.disabled) return
       this.isFocused = true
       this.$emit('focus', event)
     },
 
     onBlur(event) {
+      if (this.disabled) return
       this.isFocused = false
       this.$emit('blur', event)
     },
 
-    toggleDropdown() {
+    toggleDropdown () {
       if (this.disabled) {
         this.isOpen = false
       } else {
@@ -347,7 +353,7 @@ export default {
         this.searchTerm = ''
       }
     },
-    select(value) {
+    select (value) {
       if (!this.multiple) {
         // Close after select
         this.toggleDropdown()
@@ -382,10 +388,10 @@ export default {
         }
       }
     },
-    clear() {
+    clear () {
       this.$emit('update:modelValue', this.multiple ? [] : null)
     },
-    createOption(newOption) {
+    createOption (newOption) {
       if (newOption) {
         const newItem = {
           name: newOption,
@@ -400,3 +406,4 @@ export default {
   }
 }
 </script>
+
diff --git a/client/components/open/forms/components/form-components/FormCustomization.vue b/client/components/open/forms/components/form-components/FormCustomization.vue
index e920fdea2..2c141d4ec 100644
--- a/client/components/open/forms/components/form-components/FormCustomization.vue
+++ b/client/components/open/forms/components/form-components/FormCustomization.vue
@@ -11,8 +11,8 @@
       class="mt-4"
       :options="[
         { name: 'Default', value: 'default' },
-        { name: 'Simple', value: 'simple' },
         { name: 'Notion', value: 'notion' },
+        { name: 'Simple (no shadows)', value: 'simple' },
       ]"
       :form="form"
       label="Form Theme"
diff --git a/client/components/open/forms/fields/components/FieldOptions.vue b/client/components/open/forms/fields/components/FieldOptions.vue
index 3197abee1..9d411c73c 100644
--- a/client/components/open/forms/fields/components/FieldOptions.vue
+++ b/client/components/open/forms/fields/components/FieldOptions.vue
@@ -231,7 +231,7 @@
         :form="field"
         class="mt-3"
         name="date_range"
-        label="End date"
+        label="Include end date"
         @update:model-value="onFieldDateRangeChange"
       />
       <toggle-switch-input
diff --git a/client/lib/forms/themes/form-themes.js b/client/lib/forms/themes/form-themes.js
index 62a1f0cf6..16886bd00 100644
--- a/client/lib/forms/themes/form-themes.js
+++ b/client/lib/forms/themes/form-themes.js
@@ -1,7 +1,7 @@
 /**
  Input classes for each supported form themes
  */
-export const themes = {
+ export const themes = {
   default: {
     default: {
       wrapper: {
@@ -9,7 +9,7 @@ export const themes = {
         md: 'relative my-1.5',
         lg: 'relative my-1.5',
       },
-      label: 'text-gray-700 dark:text-gray-300 font-medium',
+      label: 'text-gray-700 dark:text-gray-300 font-semibold',
       input:
         'flex-1 appearance-none border border-gray-300 dark:border-gray-600 w-full bg-white text-gray-700 dark:bg-notion-dark-light dark:text-gray-300 dark:placeholder-gray-500 placeholder-gray-400 shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-opacity-100',
       help: 'text-gray-500',
@@ -66,8 +66,30 @@ export const themes = {
         lg: 'min-h-[28px]'
       }
     },
+     PhoneInput: {
+        countrySelectWidth: {
+          sm: 'w-[100px]',
+          md: 'w-[120px]',
+          lg: 'w-[120px]'
+        },
+        flag: {
+          sm: '!-mt-[14px]',
+          md: '!-mt-[9px] rounded',
+          lg: '!-mt-[9px] rounded'
+        },
+        flagSize: {
+          sm: 'small',
+          md: 'normal',
+          lg: 'normal'
+        },
+        maxHeight: {
+          sm: 'max-h-[20px]',
+          md: 'max-h-[24px]',
+          lg: 'max-h-[28px]'
+        }
+     },
     FlatSelectInput: {
-      option: 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-900 flex items-center space-x-2 border-t first:border-t-0 px-2',
+      option: 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-900 flex items-center gap-x-2 border-t first:border-t-0 px-2',
       unselectedIcon: 'text-gray-300 dark:text-gray-600',
       icon: {
         sm: 'w-4 h-4',
@@ -75,40 +97,18 @@ export const themes = {
         lg: 'w-6 h-6 mx-1'
       }
     },
-    PhoneInput: {
-      countrySelectWidth: {
-        sm: 'w-[100px]',
-        md: 'w-[120px]',
-        lg: 'w-[120px]'
-      },
-      flag: {
-        sm: '!-mt-[14px]',
-        md: '!-mt-[9px] rounded',
-        lg: '!-mt-[9px] rounded'
-      },
-      flagSize: {
-        sm: 'small',
-        md: 'normal',
-        lg: 'normal'
-      },
-      maxHeight: {
-        sm: 'max-h-[20px]',
-        md: 'max-h-[24px]',
-        lg: 'max-h-[28px]'
-      }
-    },
     DateInput: {
       input:
         'flex-1 appearance-none border border-gray-300 dark:border-gray-600 w-full bg-white text-gray-700 dark:bg-notion-dark-light dark:text-gray-300 dark:placeholder-gray-500 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:border-transparent focus:ring-opacity-100'
     },
-    CheckboxInput: {
+    CheckboxInput:{
       size: {
         sm: 'w-4 h-4',
         md: 'w-5 h-5',
         lg: 'w-5 h-5'
       },
     },
-    SwitchInput: {
+    SwitchInput:{
       containerSize: {
         sm: 'h-5 w-10 p-0.5',
         md: 'h-6 w-12 p-1',
@@ -125,7 +125,7 @@ export const themes = {
         lg: 'translate-x-6'
       }
     },
-    RatingInput: {
+    RatingInput:{
       size: {
         sm: 'w-6 h-6',
         md: 'w-8 h-8',
@@ -153,6 +153,11 @@ export const themes = {
         md: 'min-h-40',
         lg: 'min-h-48'
       },
+    },
+    MatrixInput: {
+      table: 'bg-white dark:bg-notion-dark-light shadow-sm',
+      cell: 'border-gray-300 dark:border-gray-600',
+      cellHover: 'hover:bg-gray-50 dark:hover:bg-gray-900'
     }
   },
   simple: {
@@ -219,15 +224,6 @@ export const themes = {
         lg: 'min-h-[28px]'
       }
     },
-    FlatSelectInput: {
-      option: 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-900 flex items-center space-x-2 border-t first:border-t-0 px-2',
-      unselectedIcon: 'text-gray-300 dark:text-gray-600',
-      icon: {
-        sm: 'w-4 h-4',
-        md: 'w-5 h-5',
-        lg: 'w-6 h-6 mx-1'
-      }
-    },
     PhoneInput: {
       countrySelectWidth: {
         sm: 'w-[100px]',
@@ -250,17 +246,26 @@ export const themes = {
         lg: 'max-h-[28px]'
       }
     },
+    FlatSelectInput: {
+      option: 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-900 flex items-center space-x-2 border-t first:border-t-0 px-2',
+      unselectedIcon: 'text-gray-300 dark:text-gray-600',
+      icon: {
+        sm: 'w-4 h-4',
+        md: 'w-5 h-5',
+        lg: 'w-6 h-6 mx-1'
+      }
+    },
     DateInput: {
       input: 'flex-1 appearance-none border border-gray-300 dark:border-gray-600 w-full bg-white text-gray-700 dark:bg-notion-dark-light dark:text-gray-300 placeholder-gray-400 text-base focus:outline-none focus:ring-2 focus:border-transparent focus:ring-opacity-100'
     },
-    CheckboxInput: {
+    CheckboxInput:{
       size: {
         sm: 'w-4 h-4',
         md: 'w-5 h-5',
         lg: 'w-5 h-5'
       },
     },
-    SwitchInput: {
+    SwitchInput:{
       containerSize: {
         sm: 'h-5 w-10',
         md: 'h-6 w-12',
@@ -272,7 +277,7 @@ export const themes = {
         lg: 'h-4 w-4'
       },
     },
-    RatingInput: {
+    RatingInput:{
       size: {
         sm: 'w-6 h-6',
         md: 'w-8 h-8',
@@ -300,6 +305,11 @@ export const themes = {
         md: 'min-h-40',
         lg: 'min-h-48'
       },
+    },
+    MatrixInput: {
+      table: 'bg-white dark:bg-notion-dark-light',
+      cell: 'border-gray-300 dark:border-gray-600',
+      cellHover: 'hover:bg-gray-50 dark:hover:bg-gray-900'
     }
   },
   notion: {
@@ -311,7 +321,7 @@ export const themes = {
       },
       label: 'text-gray-900 dark:text-gray-100 mb-1 block mt-4',
       input:
-        'rounded border-transparent flex-1 appearance-none shadow-inner-notion w-full bg-notion-input-background dark:bg-notion-dark-light text-gray-900 dark:text-gray-100 dark:placeholder-gray-500 placeholder-gray-400 focus:outline-none focus:ring-0 focus:border-transparent focus:shadow-focus-notion',
+        'rounded border border-notion-input-border dark:border-notion-input-borderDark flex-1 appearance-none w-full bg-notion-input-background dark:bg-notion-dark-light text-gray-900 dark:text-gray-100 dark:placeholder-gray-500 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent',
       help: 'text-gray-500',
       spacing: {
         horizontal: {
@@ -337,28 +347,28 @@ export const themes = {
       }
     },
     ScaleInput: {
-      button: 'border-transparent flex-1 appearance-none shadow-inner-notion w-full bg-notion-input-background dark:bg-notion-dark-light text-gray-900 dark:text-gray-100 text-center',
-      unselectedButton: 'bg-notion-input-background dark:bg-notion-dark-light border'
+      button: 'border border-notion-input-border dark:border-notion-input-borderDark flex-1 appearance-none w-full bg-notion-input-background dark:bg-notion-dark-light text-gray-900 dark:text-gray-100 text-center focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent',
+      unselectedButton: 'bg-notion-input-background dark:bg-notion-dark-light'
     },
     SliderInput: {
       stepLabel: 'text-gray-700 dark:text-gray-300 text-center text-xs'
     },
     Button: {
-      body: 'transition ease-in duration-200 text-center font-semibold shadow shadow-inner-notion focus:outline-none focus:ring-2 focus:ring-offset-2 filter hover:brightness-90'
+      body: 'transition ease-in duration-200 text-center font-semibold border border-notion-input-border dark:border-notion-input-borderDark focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent filter hover:brightness-90'
     },
     CodeInput: {
-      input: 'shadow-inner-notion border-transparent focus:border-transparent overflow-hidden'
+      input: 'border border-notion-input-border dark:border-notion-input-borderDark focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent overflow-hidden'
     },
     RichTextAreaInput: {
       input:
-        'flex-1 appearance-none shadow-inner-notion  border-transparent focus:border-transparent w-full text-gray-900 bg-notion-input-background dark:bg-notion-dark-light dark:placeholder-gray-500 placeholder-gray-400 text-base focus:outline-none focus:ring-0 focus:ring-opacity-100 focus:border-transparent focus:ring-0 focus:shadow-focus-notion'
+        'flex-1 appearance-none border border-notion-input-border dark:border-notion-input-borderDark w-full bg-notion-input-background dark:bg-notion-dark-light text-gray-900 dark:text-gray-100 dark:placeholder-gray-500 placeholder-gray-400 text-base focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent'
     },
     SelectInput: {
       input:
-        'relative w-full border-transparent flex-1 appearance-none shadow-inner-notion w-full text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 text-base focus:outline-none focus:ring-0 focus:border-transparent focus:shadow-focus-notion',
+        'relative w-full border border-notion-input-border dark:border-notion-input-borderDark flex-1 appearance-none w-full text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 text-base focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent',
       background: 'bg-notion-input-background dark:bg-notion-dark-light',
       chevronGradient: 'bg-gradient-to-r from-transparent to-notion-input-background dark:to-notion-dark-light',
-      dropdown: 'border border-gray-300 dark:border-gray-600',
+      dropdown: 'border border-notion-input-border dark:border-notion-input-borderDark',
       option: 'rounded',
       minHeight: {
         sm: 'min-h-[20px]',
@@ -366,15 +376,6 @@ export const themes = {
         lg: 'min-h-[28px]'
       }
     },
-    FlatSelectInput: {
-      option: 'cursor-pointer hover:backdrop-brightness-95 flex items-center space-x-2 border-t border-neutral-300 first:border-t-0 px-2',
-      unselectedIcon: 'text-neutral-300 dark:text-neutral-600',
-      icon: {
-        sm: 'w-4 h-4',
-        md: 'w-5 h-5',
-        lg: 'w-6 h-6 mx-1'
-      }
-    },
     PhoneInput: {
       countrySelectWidth: {
         sm: 'w-[100px]',
@@ -397,17 +398,26 @@ export const themes = {
         lg: 'max-h-[28px]'
       }
     },
+    FlatSelectInput: {
+      option: 'cursor-pointer hover:backdrop-brightness-95 flex items-center space-x-2 border-t border-neutral-300 first:border-t-0 px-2',
+      unselectedIcon: 'text-neutral-300 dark:text-neutral-600',
+      icon: {
+        sm: 'w-4 h-4',
+        md: 'w-5 h-5',
+        lg: 'w-6 h-6 mx-1'
+      }
+    },
     DateInput: {
-      input: 'shadow-inner-notion border-transparent focus:border-transparent flex-1 appearance-none w-full bg-notion-input-background dark:bg-notion-dark-light text-gray-900 dark:text-gray-100 placeholder-gray-400 text-base focus:outline-none focus:ring-0 focus:border-transparent focus:shadow-focus-notion p-[1px]'
+      input: 'border border-notion-input-border dark:border-notion-input-borderDark flex-1 appearance-none w-full bg-notion-input-background dark:bg-notion-dark-light text-gray-900 dark:text-gray-100 placeholder-gray-400 text-base focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent'
     },
-    CheckboxInput: {
+    CheckboxInput:{
       size: {
         sm: 'w-4 h-4',
         md: 'w-5 h-5',
         lg: 'w-5 h-5'
       },
     },
-    SwitchInput: {
+    SwitchInput:{
       containerSize: {
         sm: 'h-5 w-10',
         md: 'h-6 w-12',
@@ -418,8 +428,13 @@ export const themes = {
         md: 'h-4 w-4',
         lg: 'h-4 w-4'
       },
+      translatedClass: {
+        sm: 'translate-x-5',
+        md: 'translate-x-6',
+        lg: 'translate-x-6'
+      }
     },
-    RatingInput: {
+    RatingInput:{
       size: {
         sm: 'w-6 h-6',
         md: 'w-8 h-8',
@@ -428,7 +443,7 @@ export const themes = {
     },
     fileInput: {
       input:
-        'p-4 rounded bg-notion-input-background dark:bg-notion-dark',
+        'p-4 rounded border border-dashed border-notion-input-border dark:border-notion-input-borderDark bg-notion-input-background dark:bg-notion-dark-light focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent',
       minHeight: {
         sm: 'min-h-28',
         md: 'min-h-40',
@@ -439,7 +454,7 @@ export const themes = {
         dark: 'bg-notion-dark-light'
       },
       uploadedFile:
-        'border border-gray-300 dark:border-gray-600 bg-white dark:bg-notion-dark-light rounded shadow-sm max-w-[10rem]'
+        'border border-notion-input-border dark:border-notion-input-borderDark bg-white dark:bg-notion-dark-light rounded max-w-[10rem] focus:outline-none focus:ring-2 focus:ring-opacity-40 focus:border-transparent'
     },
     SignatureInput: {
       minHeight: {
@@ -447,6 +462,11 @@ export const themes = {
         md: 'min-h-40',
         lg: 'min-h-48'
       },
+    },
+    MatrixInput: {
+      table: 'bg-notion-input-background dark:bg-notion-dark-light',
+      cell: 'border-notion-input-border dark:border-notion-input-borderDark',
+      cellHover: 'hover:backdrop-brightness-95'
     }
   }
 }
diff --git a/client/tailwind.config.js b/client/tailwind.config.js
index db979c79d..b11869a75 100644
--- a/client/tailwind.config.js
+++ b/client/tailwind.config.js
@@ -56,9 +56,7 @@ module.exports = {
         5.5: "1.4rem",
       },
       boxShadow: {
-        "inner-notion": "#0f0f0f1a 0px 0px 0px 1px inset",
-        "focus-notion":
-          "#2eaadcb3 0px 0px 0px 1px inset, #2eaadc66 0px 0px 0px 2px !important",
+        'custom-shadow':'0px 25px 75px 0px #5353531A'
       },
       colors: {
         gray: colors.slate,
@@ -78,6 +76,8 @@ module.exports = {
           backgroundDark: "#272B2C",
           help: "#37352f99",
           helpDark: "#fff9",
+          border: 'rgba(15, 15, 15, 0.1)',
+          borderDark: 'rgba(255, 255, 255, 0.1)'
         },
         "form-color": "var(--bg-form-color)",
       },