diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..90308884 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "enabledPlugins": { + "frontend-design@claude-plugins-official": true + } +} diff --git a/resources/css/components/pace-loader.css b/resources/css/components/pace-loader.css index 0ec870df..f71274ff 100644 --- a/resources/css/components/pace-loader.css +++ b/resources/css/components/pace-loader.css @@ -11,7 +11,7 @@ } .pace .pace-progress { - background: #3f39ad; + background: var(--color-primary-600); position: fixed; z-index: 2000; top: 0; @@ -26,7 +26,7 @@ right: 0px; width: 100px; height: 100%; - box-shadow: 0 0 10px #5851d8, 0 0 5px #5851d8; + box-shadow: 0 0 10px var(--color-primary-500), 0 0 5px var(--color-primary-500); opacity: 1; transform: rotate(3deg) translate(0px, -4px); } @@ -40,8 +40,8 @@ width: 14px; height: 14px; border: solid 2px transparent; - border-top-color: #5851d8; - border-left-color: #5851d8; + border-top-color: var(--color-primary-500); + border-left-color: var(--color-primary-500); border-radius: 10px; animation: pace-spinner 400ms linear infinite; } diff --git a/resources/css/invoiceshelf.css b/resources/css/invoiceshelf.css index eb8a2b27..2a39ef7a 100644 --- a/resources/css/invoiceshelf.css +++ b/resources/css/invoiceshelf.css @@ -4,7 +4,6 @@ @import "./components/pace-loader.css"; @import "./components/v-tooltips.css"; -@plugin "@tailwindcss/forms"; @plugin "@tailwindcss/typography"; @plugin "tailwind-scrollbar"; @@ -25,6 +24,36 @@ --color-primary-900: var(--color-primary-900); --color-primary-950: var(--color-primary-950); --color-black: #040405; + + /* Semantic theme tokens */ + --color-surface: var(--color-surface); + --color-surface-secondary: var(--color-surface-secondary); + --color-surface-tertiary: var(--color-surface-tertiary); + --color-surface-muted: var(--color-surface-muted); + --color-heading: var(--color-heading); + --color-body: var(--color-body); + --color-muted: var(--color-muted); + --color-subtle: var(--color-subtle); + --color-line-light: var(--color-line-light); + --color-line-default: var(--color-line-default); + --color-line-strong: var(--color-line-strong); + --color-hover: var(--color-hover); + --color-hover-strong: var(--color-hover-strong); + + /* Status badge text */ + --color-status-yellow: var(--color-status-yellow); + --color-status-green: var(--color-status-green); + --color-status-blue: var(--color-status-blue); + --color-status-red: var(--color-status-red); + --color-status-purple: var(--color-status-purple); + + /* Alert colors */ + --color-alert-warning-bg: var(--color-alert-warning-bg); + --color-alert-warning-text: var(--color-alert-warning-text); + --color-alert-error-bg: var(--color-alert-error-bg); + --color-alert-error-text: var(--color-alert-error-text); + --color-alert-success-bg: var(--color-alert-success-bg); + --color-alert-success-text: var(--color-alert-success-text); } @theme { @@ -84,9 +113,101 @@ src: url("$fonts/Poppins-SemiBold.ttf") format("truetype"); } +/* Form base styles (replaces @tailwindcss/forms) */ +@layer base { +[type='text'], +[type='email'], +[type='url'], +[type='password'], +[type='number'], +[type='date'], +[type='datetime-local'], +[type='month'], +[type='search'], +[type='tel'], +[type='time'], +[type='week'], +[multiple], +textarea, +select { + @apply appearance-none bg-surface border border-line-default rounded-lg px-3 py-2 text-sm leading-6 text-heading; +} + +[type='text']:focus, +[type='email']:focus, +[type='url']:focus, +[type='password']:focus, +[type='number']:focus, +[type='date']:focus, +[type='datetime-local']:focus, +[type='month']:focus, +[type='search']:focus, +[type='tel']:focus, +[type='time']:focus, +[type='week']:focus, +[multiple]:focus, +textarea:focus, +select:focus { + @apply outline-2 outline-transparent outline-offset-2 border-primary-500 ring-1 ring-primary-500; +} + +select { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e"); + @apply bg-no-repeat pr-10; + background-position: right 0.5rem center; + background-size: 1.5em 1.5em; +} + +[type='checkbox'], +[type='radio'] { + @apply appearance-none p-0 text-primary-500 bg-surface border border-line-strong inline-block align-middle select-none shrink-0 h-4 w-4; + background-origin: border-box; + print-color-adjust: exact; +} + +[type='checkbox'] { + @apply rounded; +} + +[type='radio'] { + @apply rounded-full; +} + +[type='checkbox']:focus, +[type='radio']:focus { + @apply outline-2 outline-transparent outline-offset-2; + box-shadow: 0 0 0 2px var(--color-surface), 0 0 0 4px var(--color-primary-500); +} + +[type='checkbox']:checked, +[type='radio']:checked { + @apply border-transparent bg-current bg-center bg-no-repeat; + background-size: 100% 100%; +} + +[type='checkbox']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e"); +} + +[type='radio']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e"); +} + +[type='checkbox']:indeterminate { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e"); + @apply border-transparent bg-current bg-center bg-no-repeat; + background-size: 100% 100%; +} + +::placeholder { + @apply text-subtle opacity-100; +} +} /* end @layer base */ + body { min-height: 100vh; min-height: -webkit-fill-available; + color: var(--color-heading); } html { diff --git a/resources/css/themes.css b/resources/css/themes.css index e911544e..9313cab8 100644 --- a/resources/css/themes.css +++ b/resources/css/themes.css @@ -10,4 +10,86 @@ --color-primary-800: rgb(27, 3, 211); --color-primary-900: rgb(25, 5, 173); --color-primary-950: rgb(9, 0, 118); + + /* Surfaces */ + --color-surface: rgb(255, 255, 255); + --color-surface-secondary: rgb(249, 250, 251); + --color-surface-tertiary: rgb(243, 244, 246); + --color-surface-muted: rgb(229, 231, 235); + + /* Text */ + --color-heading: rgb(17, 24, 39); + --color-body: rgb(55, 65, 81); + --color-muted: rgb(107, 114, 128); + --color-subtle: rgb(156, 163, 175); + + /* Borders */ + --color-line-light: rgb(229, 231, 235); + --color-line-default: rgb(209, 213, 219); + --color-line-strong: rgb(185, 193, 204); + + /* Hover */ + --color-hover: rgb(249, 250, 251); + --color-hover-strong: rgb(243, 244, 246); + + /* Status badge text */ + --color-status-yellow: rgb(113, 63, 18); + --color-status-green: rgb(20, 83, 45); + --color-status-blue: rgb(30, 58, 138); + --color-status-red: rgb(127, 29, 29); + --color-status-purple: rgb(107, 33, 168); + + /* Alert backgrounds & text */ + --color-alert-warning-bg: rgb(254, 252, 232); + --color-alert-warning-text: rgb(133, 77, 14); + --color-alert-error-bg: rgb(254, 242, 242); + --color-alert-error-text: rgb(153, 27, 27); + --color-alert-success-bg: rgb(240, 253, 244); + --color-alert-success-text: rgb(22, 101, 52); +} + +[data-theme="dark"] { + /* Surfaces — layered depth: tertiary (body) < secondary < surface (cards) */ + --color-surface: rgb(30, 41, 59); + --color-surface-secondary: rgb(23, 33, 50); + --color-surface-tertiary: rgb(10, 18, 32); + --color-surface-muted: rgb(51, 65, 85); + + /* Text */ + --color-heading: rgb(241, 245, 249); + --color-body: rgb(203, 213, 225); + --color-muted: rgb(148, 163, 184); + --color-subtle: rgb(100, 116, 139); + + /* Borders — brighter for visibility */ + --color-line-light: rgb(51, 65, 85); + --color-line-default: rgb(80, 95, 115); + --color-line-strong: rgb(130, 145, 165); + + /* Hover */ + --color-hover: rgb(40, 52, 72); + --color-hover-strong: rgb(51, 65, 85); + + /* Status badge text */ + --color-status-yellow: rgb(253, 224, 71); + --color-status-green: rgb(134, 239, 172); + --color-status-blue: rgb(147, 197, 253); + --color-status-red: rgb(252, 165, 165); + --color-status-purple: rgb(216, 180, 254); + + /* Alert backgrounds & text */ + --color-alert-warning-bg: rgba(113, 63, 18, 0.2); + --color-alert-warning-text: rgb(253, 224, 71); + --color-alert-error-bg: rgba(127, 29, 29, 0.2); + --color-alert-error-text: rgb(252, 165, 165); + --color-alert-success-bg: rgba(20, 83, 45, 0.2); + --color-alert-success-text: rgb(134, 239, 172); + + /* Primary adjustments for dark mode */ + --color-primary-50: rgba(167, 170, 255, 0.15); + --color-primary-100: rgba(167, 170, 255, 0.25); + --color-primary-400: rgb(167, 170, 255); + --color-primary-500: rgb(140, 140, 255); + --color-primary-600: rgb(167, 170, 255); + --color-primary-700: rgb(190, 192, 255); } diff --git a/resources/scripts/admin/components/CopyInputField.vue b/resources/scripts/admin/components/CopyInputField.vue index 1227b63f..7e9512db 100644 --- a/resources/scripts/admin/components/CopyInputField.vue +++ b/resources/scripts/admin/components/CopyInputField.vue @@ -6,7 +6,7 @@ px-4 py-2 rounded-lg - bg-gray-300/40 + bg-surface-muted/40 whitespace-nowrap flex-col mt-1 @@ -18,7 +18,7 @@ pr-10 text-sm font-medium - text-black + text-heading truncate select-all select-color " diff --git a/resources/scripts/admin/components/SelectNotePopup.vue b/resources/scripts/admin/components/SelectNotePopup.vue index a435e358..0cf7ed39 100644 --- a/resources/scripts/admin/components/SelectNotePopup.vue +++ b/resources/scripts/admin/components/SelectNotePopup.vue @@ -53,13 +53,13 @@ ring-1 ring-black/5 " > -
+
@@ -75,9 +75,9 @@ class=" px-6 py-4 - border-b border-gray-200 border-solid + border-b border-line-default border-solid cursor-pointer - hover:bg-gray-100 hover:cursor-pointer + hover:bg-surface-tertiary hover:cursor-pointer last:border-b-0 " @click="selectNote(index, close)" @@ -89,7 +89,7 @@ text-base font-semibold leading-tight - text-gray-700 + text-body cursor-pointer " > @@ -98,8 +98,8 @@
-
-
-

+

{{ $t('recurring_invoices.send_automatically') }}

{{ $t('recurring_invoices.send_automatically_desc') }} diff --git a/resources/scripts/admin/views/recurring-invoices/partials/Invoices.vue b/resources/scripts/admin/views/recurring-invoices/partials/Invoices.vue index fa997aa3..e56ee1a8 100644 --- a/resources/scripts/admin/views/recurring-invoices/partials/Invoices.vue +++ b/resources/scripts/admin/views/recurring-invoices/partials/Invoices.vue @@ -73,7 +73,7 @@ const invoiceColumns = computed(() => { key: 'invoice_date', label: t('invoices.date'), thClass: 'extra', - tdClass: 'font-medium text-gray-900', + tdClass: 'font-medium text-heading', }, { key: 'invoice_number', label: t('invoices.invoice') }, { key: 'customer.name', label: t('invoices.customer') }, diff --git a/resources/scripts/admin/views/recurring-invoices/partials/RecurringInvoiceViewSidebar.vue b/resources/scripts/admin/views/recurring-invoices/partials/RecurringInvoiceViewSidebar.vue index 638101f9..4eb8e759 100644 --- a/resources/scripts/admin/views/recurring-invoices/partials/RecurringInvoiceViewSidebar.vue +++ b/resources/scripts/admin/views/recurring-invoices/partials/RecurringInvoiceViewSidebar.vue @@ -148,7 +148,7 @@ onSearched = debounce(onSearched, 500) pt-16 pb-[6.4rem] ml-56 - bg-white + bg-surface xl:ml-64 w-88 xl:block @@ -162,7 +162,7 @@ onSearched = debounce(onSearched, 500) px-4 pt-8 pb-2 - border border-gray-200 border-solid + border border-line-default border-solid height-full " > @@ -175,7 +175,7 @@ onSearched = debounce(onSearched, 500) @input="onSearched()" >

@@ -194,7 +194,7 @@ onSearched = debounce(onSearched, 500) pb-2 mb-1 mb-2 text-sm - border-b border-gray-200 border-solid + border-b border-line-default border-solid " > {{ $t('general.sort_by') }} @@ -241,7 +241,7 @@ onSearched = debounce(onSearched, 500) class=" h-full overflow-y-scroll - border-l border-gray-200 border-solid + border-l border-line-default border-solid base-scroll " > @@ -251,9 +251,9 @@ onSearched = debounce(onSearched, 500) :id="'recurring-invoice-' + invoice.id" :to="`/admin/recurring-invoices/${invoice.id}/view`" :class="[ - 'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-l-transparent', + 'flex justify-between side-invoice p-4 cursor-pointer hover:bg-hover-strong items-center border-l-4 border-l-transparent', { - 'bg-gray-100 border-l-4 border-l-primary-500 border-solid': + 'bg-surface-tertiary border-l-4 border-l-primary-500 border-solid': hasActiveUrl(invoice.id), }, ]" @@ -269,7 +269,7 @@ onSearched = debounce(onSearched, 500) not-italic font-normal leading-5 - text-black + text-heading capitalize truncate " @@ -283,7 +283,7 @@ onSearched = debounce(onSearched, 500) not-italic font-medium leading-5 - text-gray-600 + text-body " > {{ invoice.invoice_number }} @@ -305,7 +305,7 @@ onSearched = debounce(onSearched, 500) not-italic font-semibold leading-8 - text-right text-gray-900 + text-right text-heading " :amount="invoice.total" :currency="invoice.customer.currency" @@ -317,7 +317,7 @@ onSearched = debounce(onSearched, 500) not-italic font-normal leading-5 - text-right text-gray-600 + text-right text-body est-date " > @@ -331,7 +331,7 @@ onSearched = debounce(onSearched, 500)

{{ $t('invoices.no_matching_invoices') }}

diff --git a/resources/scripts/admin/views/reports/ExpensesReport.vue b/resources/scripts/admin/views/reports/ExpensesReport.vue index 85836669..b6915c32 100644 --- a/resources/scripts/admin/views/reports/ExpensesReport.vue +++ b/resources/scripts/admin/views/reports/ExpensesReport.vue @@ -55,7 +55,7 @@ hidden w-full h-screen - border-gray-100 border-solid + border-line-light border-solid rounded md:flex " diff --git a/resources/scripts/admin/views/reports/ProfitLossReport.vue b/resources/scripts/admin/views/reports/ProfitLossReport.vue index d2ed6df1..91449421 100644 --- a/resources/scripts/admin/views/reports/ProfitLossReport.vue +++ b/resources/scripts/admin/views/reports/ProfitLossReport.vue @@ -55,7 +55,7 @@ hidden w-full h-screen - border-gray-100 border-solid + border-line-light border-solid rounded md:flex " diff --git a/resources/scripts/admin/views/reports/SalesReports.vue b/resources/scripts/admin/views/reports/SalesReports.vue index 4fed5772..3d53543a 100644 --- a/resources/scripts/admin/views/reports/SalesReports.vue +++ b/resources/scripts/admin/views/reports/SalesReports.vue @@ -68,7 +68,7 @@ hidden w-full h-screen - border-gray-100 border-solid + border-line-light border-solid rounded md:flex " diff --git a/resources/scripts/admin/views/reports/TaxReport.vue b/resources/scripts/admin/views/reports/TaxReport.vue index d6f53941..461a547b 100644 --- a/resources/scripts/admin/views/reports/TaxReport.vue +++ b/resources/scripts/admin/views/reports/TaxReport.vue @@ -54,7 +54,7 @@ hidden w-full h-screen - border-gray-100 border-solid + border-line-light border-solid rounded md:flex " diff --git a/resources/scripts/admin/views/settings/BackupSetting.vue b/resources/scripts/admin/views/settings/BackupSetting.vue index 9cc3d56f..625e1932 100644 --- a/resources/scripts/admin/views/settings/BackupSetting.vue +++ b/resources/scripts/admin/views/settings/BackupSetting.vue @@ -47,18 +47,18 @@ - + {{ $t('general.download') }} - + {{ $t('general.delete') }} @@ -95,17 +95,17 @@ const backupColumns = computed(() => { key: 'path', label: t('settings.backup.path'), thClass: 'extra', - tdClass: 'font-medium text-gray-900', + tdClass: 'font-medium text-heading', }, { key: 'created_at', label: t('settings.backup.created_at'), - tdClass: 'font-medium text-gray-900', + tdClass: 'font-medium text-heading', }, { key: 'size', label: t('settings.backup.size'), - tdClass: 'font-medium text-gray-900', + tdClass: 'font-medium text-heading', }, { key: 'actions', diff --git a/resources/scripts/admin/views/settings/CompanyInfoSettings.vue b/resources/scripts/admin/views/settings/CompanyInfoSettings.vue index d712aae9..a5c0d442 100644 --- a/resources/scripts/admin/views/settings/CompanyInfoSettings.vue +++ b/resources/scripts/admin/views/settings/CompanyInfoSettings.vue @@ -110,10 +110,10 @@
-

+

{{ $t('settings.company_info.delete_company') }}

-
+

{{ $t('settings.company_info.delete_company_description') }}

diff --git a/resources/scripts/admin/views/settings/CompanyMailConfigSetting.vue b/resources/scripts/admin/views/settings/CompanyMailConfigSetting.vue index c739478d..4f943bdd 100644 --- a/resources/scripts/admin/views/settings/CompanyMailConfigSetting.vue +++ b/resources/scripts/admin/views/settings/CompanyMailConfigSetting.vue @@ -35,7 +35,7 @@
-
+
{{ $t('settings.mail.using_global_mail_config') }}
diff --git a/resources/scripts/admin/views/settings/CustomFieldsSetting.vue b/resources/scripts/admin/views/settings/CustomFieldsSetting.vue index 016d37f9..39c5705c 100644 --- a/resources/scripts/admin/views/settings/CustomFieldsSetting.vue +++ b/resources/scripts/admin/views/settings/CustomFieldsSetting.vue @@ -27,7 +27,7 @@ >