Add dark mode with CSS custom property theme system

Define 13 semantic color tokens (surface, text, border, hover) with
light/dark values in themes.css. Register with Tailwind via @theme inline.
Migrate all 335 Vue files from hardcoded gray/white classes to semantic
tokens. Add theme toggle (sun/moon/system) in user avatar dropdown.
Replace @tailwindcss/forms with custom form reset using theme vars.
Add status badge and alert tokens for dark mode. Theme-aware chart
grid/labels, skeleton placeholders, and editor. Inline script in
<head> prevents flash of wrong theme on load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Darko Gjorgjijoski
2026-04-04 02:05:00 +02:00
parent 7fbe3d85a3
commit 88adfe0e50
221 changed files with 1265 additions and 982 deletions

View File

@@ -45,7 +45,7 @@
>
<div
v-if="isShow"
class="absolute right-0 mt-2 bg-white rounded-md shadow-lg"
class="absolute right-0 mt-2 bg-surface rounded-md shadow-lg"
>
<div
class="
@@ -60,9 +60,9 @@
<!-- Administration Mode -->
<div v-if="userStore.currentUser?.is_super_admin">
<div
class="p-2 px-3 rounded-md cursor-pointer hover:bg-gray-100 hover:text-primary-500"
class="p-2 px-3 rounded-md cursor-pointer hover:bg-hover-strong hover:text-primary-500"
:class="{
'bg-gray-100 text-primary-500': companyStore.isAdminMode,
'bg-surface-tertiary text-primary-500': companyStore.isAdminMode,
}"
@click="enterAdminMode"
>
@@ -77,7 +77,7 @@
</div>
</div>
</div>
<div class="border-t border-gray-100 my-1"></div>
<div class="border-t border-line-light my-1"></div>
</div>
<label
@@ -86,7 +86,7 @@
py-2
text-xs
font-semibold
text-gray-400
text-subtle
mb-0.5
block
uppercase
@@ -104,10 +104,10 @@
p-2
px-3
mt-4
text-base text-gray-400
text-base text-subtle
"
>
<BaseIcon name="ExclamationCircleIcon" class="h-5 text-gray-400" />
<BaseIcon name="ExclamationCircleIcon" class="h-5 text-subtle" />
{{ $t('company_switcher.no_results_found') }}
</div>
<div v-else>
@@ -120,10 +120,10 @@
px-3
rounded-md
cursor-pointer
hover:bg-gray-100 hover:text-primary-500
hover:bg-hover-strong hover:text-primary-500
"
:class="{
'bg-gray-100 text-primary-500':
'bg-surface-tertiary text-primary-500':
companyStore.selectedCompany && companyStore.selectedCompany.id === company.id,
}"
@click="changeCompany(company)"
@@ -138,7 +138,7 @@
overflow-hidden
text-base
font-semibold
bg-gray-200
bg-surface-muted
rounded-md
w-9
h-9
@@ -166,12 +166,12 @@
<!-- Pending Invitations -->
<div
v-if="invitationStore.pendingInvitations.length > 0"
class="border-t border-gray-100 p-2"
class="border-t border-line-light p-2"
>
<label
class="
block px-1 pt-1 pb-2 text-xs font-semibold
leading-tight text-gray-400 uppercase
leading-tight text-subtle uppercase
"
>
{{ $t('members.pending_invitations') }}
@@ -186,14 +186,14 @@
class="
flex items-center justify-center mr-3
overflow-hidden text-xs font-semibold
bg-gray-200 rounded-md w-9 h-9 shrink-0 text-gray-400
bg-surface-muted rounded-md w-9 h-9 shrink-0 text-subtle
"
>
{{ initGenerator(invitation.company?.name || '?') }}
</span>
<div class="flex flex-col min-w-0">
<span class="text-sm text-gray-700 truncate">{{ invitation.company?.name }}</span>
<span class="text-xs text-gray-400">{{ invitation.role?.title }}</span>
<span class="text-sm text-body truncate">{{ invitation.company?.name }}</span>
<span class="text-xs text-subtle">{{ invitation.role?.title }}</span>
</div>
</div>
<div class="flex space-x-1 pl-12">
@@ -204,7 +204,7 @@
{{ $t('general.accept') }}
</button>
<button
class="text-xs px-2 py-1 rounded bg-gray-200 text-gray-600 hover:bg-gray-300"
class="text-xs px-2 py-1 rounded bg-surface-muted text-body hover:bg-hover-strong"
@click.stop="declineInvitation(invitation.token)"
>
{{ $t('general.decline') }}
@@ -221,7 +221,7 @@
justify-center
p-4
pl-3
border-t-2 border-gray-100
border-t-2 border-line-light
cursor-pointer
text-primary-400
hover:text-primary-500

View File

@@ -9,7 +9,7 @@
@input="onSearch"
>
<template #left>
<BaseIcon name="MagnifyingGlassIcon" class="text-gray-400" />
<BaseIcon name="MagnifyingGlassIcon" class="text-subtle" />
</template>
<template #right>
<SpinnerIcon v-if="isSearching" class="h-5 text-primary-500" />
@@ -32,7 +32,7 @@
scrollbar-thumb-gray-300
scrollbar-track-gray-100
overflow-y-auto
bg-white
bg-surface
rounded-md
mt-2
shadow-lg
@@ -51,24 +51,24 @@
flex
items-center
justify-center
text-gray-400 text-base
text-subtle text-base
flex-col
mt-4
"
>
<BaseIcon name="ExclamationCircleIcon" class="text-gray-400" />
<BaseIcon name="ExclamationCircleIcon" class="text-subtle" />
{{ $t('global_search.no_results_found') }}
</div>
<div v-else>
<div v-if="usersStore.customerList.length > 0">
<label class="text-sm text-gray-400 mb-0.5 block px-2 uppercase">
<label class="text-sm text-subtle mb-0.5 block px-2 uppercase">
{{ $t('global_search.customers') }}
</label>
<div
v-for="(customer, index) in usersStore.customerList"
:key="index"
class="p-2 hover:bg-gray-100 cursor-pointer rounded-md"
class="p-2 hover:bg-hover-strong cursor-pointer rounded-md"
>
<router-link
:to="{ path: `/admin/customers/${customer.id}/view` }"
@@ -84,7 +84,7 @@
mr-3
text-base
font-semibold
bg-gray-200
bg-surface-muted
rounded-full
text-primary-500
"
@@ -95,11 +95,11 @@
<span class="text-sm">{{ customer.name }}</span>
<span
v-if="customer.contact_name"
class="text-xs text-gray-400"
class="text-xs text-subtle"
>
{{ customer.contact_name }}
</span>
<span v-else class="text-xs text-gray-400">{{
<span v-else class="text-xs text-subtle">{{
customer.email
}}</span>
</div>
@@ -109,14 +109,14 @@
<div v-if="usersStore.userList.length > 0" class="mt-2">
<label
class="text-sm text-gray-400 mb-2 block px-2 mb-0.5 uppercase"
class="text-sm text-subtle mb-2 block px-2 mb-0.5 uppercase"
>
{{ $t('global_search.users') }}
</label>
<div
v-for="(user, index) in usersStore.userList"
:key="index"
class="p-2 hover:bg-gray-100 cursor-pointer rounded-md"
class="p-2 hover:bg-hover-strong cursor-pointer rounded-md"
>
<router-link
:to="{ path: `/admin/members/${user.id}/edit` }"
@@ -132,7 +132,7 @@
mr-3
text-base
font-semibold
bg-gray-200
bg-surface-muted
rounded-full
text-primary-500
"
@@ -141,7 +141,7 @@
</span>
<div class="flex flex-col">
<span class="text-sm">{{ user.name }}</span>
<span class="text-xs text-gray-400">{{ user.email }}</span>
<span class="text-xs text-subtle">{{ user.email }}</span>
</div>
</router-link>
</div>

View File

@@ -1,33 +1,33 @@
<template>
<div class="bg-white shadow overflow-hidden rounded-lg mt-6">
<div class="bg-surface shadow overflow-hidden rounded-lg mt-6">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
<h3 class="text-lg leading-6 font-medium text-heading">
{{ $t('invoices.invoice_information') }}
</h3>
</div>
<div v-if="invoice" class="border-t border-gray-200 px-4 py-5 sm:p-0">
<dl class="sm:divide-y sm:divide-gray-200">
<div v-if="invoice" class="border-t border-line-default px-4 py-5 sm:p-0">
<dl class="sm:divide-y sm:divide-line-default">
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm font-medium text-gray-500">
<dt class="text-sm font-medium text-muted">
{{ $t('general.from') }}
</dt>
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
<dd class="mt-1 text-sm text-heading sm:mt-0 sm:col-span-2">
{{ invoice.company.name }}
</dd>
</div>
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm font-medium text-gray-500">
<dt class="text-sm font-medium text-muted">
{{ $t('general.to') }}
</dt>
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
<dd class="mt-1 text-sm text-heading sm:mt-0 sm:col-span-2">
{{ invoice.customer.name }}
</dd>
</div>
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm font-medium text-gray-500 capitalize">
<dt class="text-sm font-medium text-muted capitalize">
{{ $t('invoices.paid_status').toLowerCase() }}
</dt>
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
<dd class="mt-1 text-sm text-heading sm:mt-0 sm:col-span-2">
<BaseInvoiceStatusBadge
:status="invoice.paid_status"
class="px-3 py-1"
@@ -37,10 +37,10 @@
</dd>
</div>
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm font-medium text-gray-500">
<dt class="text-sm font-medium text-muted">
{{ $t('invoices.total') }}
</dt>
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
<dd class="mt-1 text-sm text-heading sm:mt-0 sm:col-span-2">
<BaseFormatMoney
:currency="invoice.currency"
:amount="invoice.total"
@@ -51,10 +51,10 @@
v-if="invoice.formatted_notes"
class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
>
<dt class="text-sm font-medium text-gray-500">
<dt class="text-sm font-medium text-muted">
{{ $t('invoices.notes') }}
</dt>
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
<dd class="mt-1 text-sm text-heading sm:mt-0 sm:col-span-2">
<span v-html="invoice.formatted_notes"></span>
</dd>
</div>

View File

@@ -61,7 +61,7 @@ I
<div
v-if="!customerLogo"
class="flex items-center justify-center mt-4 text-gray-500 font-normal"
class="flex items-center justify-center mt-4 text-muted font-normal"
>
Powered by
<a href="https://invoiceshelf.com" target="_blank">

View File

@@ -437,9 +437,9 @@ export default {
required: false,
default: () => ({
container:
'p-0 relative mx-auto w-full flex items-center justify-end box-border cursor-pointer border border-gray-200 rounded-md bg-white text-sm leading-snug outline-hidden max-h-10',
'p-0 relative mx-auto w-full flex items-center justify-end box-border cursor-pointer border border-line-default rounded-md bg-surface text-sm leading-snug outline-hidden max-h-10',
containerDisabled:
'cursor-default bg-gray-200/50 !text-gray-400',
'cursor-default bg-surface-muted/50 !text-subtle',
containerOpen: '',
containerOpenTop: '',
containerActive: 'ring-1 ring-primary-400 border-primary-400',
@@ -451,10 +451,10 @@ export default {
multipleLabel:
'flex items-center h-full absolute left-0 top-0 pointer-events-none bg-transparent leading-snug pl-3.5',
search:
'w-full absolute inset-0 outline-hidden appearance-none box-border border-0 text-sm font-sans bg-white rounded-md pl-3.5',
'w-full absolute inset-0 outline-hidden appearance-none box-border border-0 text-sm font-sans bg-surface rounded-md pl-3.5',
tags: 'grow shrink flex flex-wrap mt-1 pl-2',
tag: 'bg-primary-500 text-white text-sm font-semibold py-0.5 pl-2 rounded mr-1 mb-1 flex items-center whitespace-nowrap',
tagDisabled: 'pr-2 !bg-gray-400 text-white',
tagDisabled: 'pr-2 !bg-subtle text-white',
tagRemove:
'flex items-center justify-center p-1 mx-0.5 rounded-xs hover:bg-black/10 group',
tagRemoveIcon:
@@ -464,7 +464,7 @@ export default {
'absolute inset-0 border-0 focus:outline-hidden !shadow-none !focus:shadow-none appearance-none p-0 text-sm font-sans box-border w-full',
tagsSearchCopy: 'invisible whitespace-pre-wrap inline-block h-px',
placeholder:
'flex items-center h-full absolute left-0 top-0 pointer-events-none bg-transparent leading-snug pl-3.5 text-gray-400 text-sm',
'flex items-center h-full absolute left-0 top-0 pointer-events-none bg-transparent leading-snug pl-3.5 text-subtle text-sm',
caret:
'bg-multiselect-caret bg-center bg-no-repeat w-5 h-5 py-px box-content z-5 relative mr-1 opacity-40 shrink-0 grow-0 transition-transform',
caretOpen: 'rotate-180 pointer-events-auto',
@@ -475,7 +475,7 @@ export default {
spinner:
'bg-multiselect-spinner bg-center bg-no-repeat w-4 h-4 z-10 mr-3.5 animate-spin shrink-0 grow-0',
dropdown:
'max-h-60 shadow-lg absolute -left-px -right-px -bottom-1 border border-gray-300 mt-1 overflow-y-auto z-50 bg-white flex flex-col rounded-md',
'max-h-60 shadow-lg absolute -left-px -right-px -bottom-1 border border-line-strong mt-1 overflow-y-auto z-50 bg-surface flex flex-col rounded-md',
dropdownTop:
'-translate-y-full -top-2 bottom-auto flex-col-reverse rounded-md',
dropdownBottom: 'translate-y-full',
@@ -484,25 +484,25 @@ export default {
optionsTop: 'flex-col-reverse',
group: 'p-0 m-0',
groupLabel:
'flex text-sm box-border items-center justify-start text-left py-1 px-3 font-semibold bg-gray-200 cursor-default leading-normal',
'flex text-sm box-border items-center justify-start text-left py-1 px-3 font-semibold bg-surface-muted cursor-default leading-normal',
groupLabelPointable: 'cursor-pointer',
groupLabelPointed: 'bg-gray-300 text-gray-700',
groupLabelPointed: 'bg-surface-muted text-body',
groupLabelSelected: 'bg-primary-600 text-white',
groupLabelDisabled: 'bg-gray-100 text-gray-300 cursor-not-allowed',
groupLabelDisabled: 'bg-surface-tertiary text-subtle cursor-not-allowed',
groupLabelSelectedPointed: 'bg-primary-600 text-white opacity-90',
groupLabelSelectedDisabled:
'text-primary-100 bg-primary-600/50 cursor-not-allowed',
groupOptions: 'p-0 m-0',
option:
'flex items-center justify-start box-border text-left cursor-pointer text-sm leading-snug py-2 px-3',
optionPointed: 'text-gray-800 bg-gray-100',
optionPointed: 'text-heading bg-surface-tertiary',
optionSelected: 'text-white bg-primary-500',
optionDisabled: 'text-gray-300 cursor-not-allowed',
optionDisabled: 'text-subtle cursor-not-allowed',
optionSelectedPointed: 'text-white bg-primary-500 opacity-90',
optionSelectedDisabled:
'text-primary-100 bg-primary-500/50 cursor-not-allowed',
noOptions: 'py-2 px-3 text-gray-600 bg-white',
noResults: 'py-2 px-3 text-gray-600 bg-white',
noOptions: 'py-2 px-3 text-muted bg-surface',
noResults: 'py-2 px-3 text-muted bg-surface',
fakeInput:
'bg-transparent absolute left-0 right-0 -bottom-px w-full h-px border-0 p-0 appearance-none outline-hidden text-transparent',
spacer: 'h-9 py-px box-content',

View File

@@ -5,7 +5,7 @@
py-1
text-sm
font-normal
text-center text-green-800
text-center text-status-green
uppercase
bg-success
"

View File

@@ -1,6 +1,6 @@
<template>
<nav>
<ol class="flex flex-wrap py-4 text-gray-900 rounded list-reset">
<ol class="flex flex-wrap py-4 text-heading rounded list-reset">
<slot />
</ol>
</nav>

View File

@@ -7,7 +7,7 @@
text-sm
font-medium
leading-5
text-gray-900
text-heading
outline-hidden
focus:ring-2 focus:ring-offset-2 focus:ring-primary-400
"

View File

@@ -54,11 +54,11 @@ const props = defineProps({
const sizeClass = computed(() => {
return {
'px-2.5 py-1.5 text-xs leading-4 rounded': props.size === 'xs',
'px-3 py-2 text-sm leading-4 rounded-md': props.size == 'sm',
'px-4 py-2 text-sm leading-5 rounded-md': props.size === 'md',
'px-4 py-2 text-base leading-6 rounded-md': props.size === 'lg',
'px-6 py-3 text-base leading-6 rounded-md': props.size === 'xl',
'px-2.5 py-1.5 text-xs leading-4 rounded-lg': props.size === 'xs',
'px-3 py-2 text-sm leading-4 rounded-lg': props.size == 'sm',
'px-4 py-2 text-sm leading-5 rounded-lg': props.size === 'md',
'px-4 py-2 text-base leading-6 rounded-lg': props.size === 'lg',
'px-6 py-3 text-base leading-6 rounded-lg': props.size === 'xl',
}
})
@@ -87,11 +87,11 @@ const variantClass = computed(() => {
props.variant === 'secondary',
'border-solid border-primary-500 font-normal transition ease-in-out duration-150 text-primary-500 hover:bg-primary-200 shadow-inner focus:ring-primary-500':
props.variant == 'primary-outline',
'border-gray-200 text-gray-700 bg-white hover:bg-gray-50 focus:ring-primary-500 focus:ring-offset-0':
'border-line-default text-body bg-surface hover:bg-hover focus:ring-primary-500 focus:ring-offset-0':
props.variant == 'white',
'border-transparent shadow-xs text-white bg-red-600 hover:bg-red-700 focus:ring-red-500':
props.variant === 'danger',
'border-transparent bg-gray-200 border hover:bg-gray-200/60 focus:ring-gray-500 focus:ring-offset-0':
'border-transparent bg-surface-muted border hover:bg-surface-muted/60 focus:ring-gray-500 focus:ring-offset-0':
props.variant === 'gray',
}
})
@@ -112,8 +112,8 @@ const iconVariantClass = computed(() => {
return {
'text-white': props.variant === 'primary',
'text-primary-700': props.variant === 'secondary',
'text-gray-700': props.variant === 'white',
'text-gray-400': props.variant === 'gray',
'text-body': props.variant === 'white',
'text-subtle': props.variant === 'gray',
}
})

View File

@@ -1,8 +1,8 @@
<template>
<div class="bg-white rounded-xl shadow-sm border border-gray-100">
<div class="bg-surface rounded-xl shadow border border-line-light">
<div
v-if="hasHeaderSlot"
class="px-5 py-4 text-black border-b border-gray-100 border-solid"
class="px-5 py-4 text-heading border-b border-line-light border-solid"
>
<slot name="header" />
</div>
@@ -11,7 +11,7 @@
</div>
<div
v-if="hasFooterSlot"
class="px-5 py-4 border-t border-gray-100 border-solid sm:px-6"
class="px-5 py-4 border-t border-line-light border-solid sm:px-6"
>
<slot name="footer" />
</div>

View File

@@ -15,12 +15,12 @@
v-if="label"
:for="id"
:class="`font-medium ${
disabled ? 'text-gray-400 cursor-not-allowed' : 'text-gray-600'
disabled ? 'text-subtle cursor-not-allowed' : 'text-body'
} cursor-pointer `"
>
{{ label }}
</label>
<p v-if="description" class="text-gray-500">{{ description }}</p>
<p v-if="description" class="text-muted">{{ description }}</p>
</div>
</div>
</template>
@@ -51,7 +51,7 @@ const props = defineProps({
},
checkboxClass: {
type: String,
default: 'w-4 h-4 border-gray-300 rounded cursor-pointer',
default: 'w-4 h-4 border-line-strong rounded cursor-pointer',
},
setInitialValue: {
type: Boolean,
@@ -75,7 +75,7 @@ const checked = computed({
const disabledClass = computed(() => {
if (props.disabled) {
return 'text-gray-300 cursor-not-allowed'
return 'text-subtle cursor-not-allowed'
}
return 'text-primary-600 focus:ring-primary-500'

View File

@@ -55,7 +55,7 @@ const classObject = computed(() => {
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
background: var(--color-surface-muted);
.base-content-placeholders-is-rounded & {
border-radius: 6px;
@@ -72,7 +72,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
@@ -87,7 +87,7 @@ const classObject = computed(() => {
.base-content-placeholders-heading__title {
width: 85%;
margin-bottom: 10px;
background: #ccc;
background: var(--color-surface-muted);
position: relative;
overflow: hidden;
min-height: 15px;
@@ -107,7 +107,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
@@ -117,7 +117,7 @@ const classObject = computed(() => {
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
background: var(--color-surface-muted);
.base-content-placeholders-is-rounded & {
border-radius: 6px;
@@ -134,7 +134,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
@@ -151,7 +151,7 @@ const classObject = computed(() => {
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
background: var(--color-surface-muted);
.base-content-placeholders-is-rounded & {
border-radius: 6px;
@@ -168,7 +168,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
@@ -190,7 +190,7 @@ const classObject = computed(() => {
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
background: var(--color-surface-muted);
.base-content-placeholders-is-animated &::before {
content: '';
@@ -200,7 +200,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}

View File

@@ -27,7 +27,7 @@
<div class="flex p-2">
<ul v-for="(type, index) in fieldList" :key="index" class="list-none">
<li class="mb-1 ml-2 text-xs font-semibold text-gray-500 uppercase">
<li class="mb-1 ml-2 text-xs font-semibold text-muted uppercase">
{{ type.label }}
</li>
@@ -39,7 +39,7 @@
text-sm
font-normal
cursor-pointer
hover:bg-gray-100
hover:bg-hover-strong
rounded
ml-1
py-0.5
@@ -49,7 +49,7 @@
<div class="flex pl-1">
<BaseIcon
name="ChevronDoubleRightIcon"
class="h-3 mt-1 mr-2 text-gray-400"
class="h-3 mt-1 mr-2 text-subtle"
/>
{{ field.label }}

View File

@@ -1,7 +1,7 @@
<template>
<div
v-if="address"
class="text-sm font-bold leading-5 text-black non-italic space-y-1"
class="text-sm font-bold leading-5 text-heading non-italic space-y-1"
>
<p v-if="address?.address_street_1">{{ address?.address_street_1 }},</p>

View File

@@ -16,8 +16,8 @@
class="
flex flex-col
p-4
bg-white
border border-gray-200 border-solid
bg-surface
border border-line-default border-solid
min-h-[170px]
rounded-md
"
@@ -26,7 +26,7 @@
<div class="flex relative justify-between mb-2">
<BaseText
:text="selectedCustomer.name"
class="flex-1 text-base font-medium text-left text-gray-900"
class="flex-1 text-base font-medium text-left text-heading"
/>
<div class="flex">
<a
@@ -43,7 +43,7 @@
"
@click.stop="editCustomer"
>
<BaseIcon name="PencilIcon" class="text-gray-500 h-4 w-4 mr-1" />
<BaseIcon name="PencilIcon" class="text-muted h-4 w-4 mr-1" />
{{ $t('general.edit') }}
</a>
@@ -61,7 +61,7 @@
"
@click="resetSelectedCustomer"
>
<BaseIcon name="XCircleIcon" class="text-gray-500 h-4 w-4 mr-1" />
<BaseIcon name="XCircleIcon" class="text-muted h-4 w-4 mr-1" />
{{ $t('general.deselect') }}
</a>
</div>
@@ -73,7 +73,7 @@
mb-1
text-sm
font-medium
text-left text-gray-400
text-left text-subtle
uppercase
whitespace-nowrap
"
@@ -123,7 +123,7 @@
mb-1
text-sm
font-medium
text-left text-gray-400
text-left text-subtle
uppercase
whitespace-nowrap
"
@@ -187,8 +187,8 @@
px-0
p-0
py-16
bg-white
border border-gray-200 border-solid
bg-surface
border border-line-default border-solid
rounded-md
min-h-[170px]
"
@@ -203,14 +203,14 @@
p-2
mr-5
text-sm text-white
bg-gray-200
bg-surface-muted
rounded-full
font-base
"
/>
<div class="mt-1">
<label class="text-lg font-medium text-gray-900">
<label class="text-lg font-medium text-heading">
{{ $t('customers.new_customer') }}
<span class="text-red-500"> * </span>
</label>
@@ -244,7 +244,7 @@
rounded-md
shadow-lg
ring-1 ring-black/5
bg-white
bg-surface
"
>
<div class="relative">
@@ -263,7 +263,7 @@
flex flex-col
overflow-auto
list
border-t border-gray-200
border-t border-line-default
"
>
<li
@@ -274,10 +274,10 @@
flex
px-6
py-2
border-b border-gray-200 border-solid
border-b border-line-default border-solid
cursor-pointer
hover:cursor-pointer hover:bg-gray-100
focus:outline-hidden focus:bg-gray-100
hover:cursor-pointer hover:bg-hover-strong
focus:outline-hidden focus:bg-surface-tertiary
last:border-b-0
"
@click="selectNewCustomer(customer.id, close)"
@@ -295,7 +295,7 @@
font-semibold
leading-9
text-white
bg-gray-300
bg-surface-muted
rounded-full
avatar
"
@@ -322,7 +322,7 @@
m-0
text-sm
font-medium
text-gray-400
text-subtle
cursor-pointer
"
/>
@@ -330,9 +330,9 @@
</li>
<div
v-if="customerStore.customers.length === 0"
class="flex justify-center p-5 text-gray-400"
class="flex justify-center p-5 text-subtle"
>
<label class="text-base text-gray-500 cursor-pointer">
<label class="text-base text-muted cursor-pointer">
{{ $t('customers.no_customers_found') }}
</label>
</div>
@@ -350,10 +350,10 @@
w-full
px-2
py-3
bg-gray-200
bg-surface-muted
border-none
outline-hidden
focus:bg-gray-300
focus:bg-surface-muted
"
@click="openCustomerModal"
>

View File

@@ -21,7 +21,7 @@
text-sm
not-italic
font-black
text-gray-400
text-subtle
cursor-pointer
"
@click="onClickDp"
@@ -121,7 +121,7 @@ const props = defineProps({
defaultInputClass: {
type: String,
default:
'font-base pl-8 py-2 outline-hidden focus:ring-primary-400 focus:outline-hidden focus:border-primary-400 block w-full sm:text-sm border-gray-200 rounded-md text-black',
'font-base pl-8 py-2 outline-hidden focus:ring-primary-400 focus:outline-hidden focus:border-primary-400 block w-full sm:text-sm border-line-default rounded-md text-heading',
},
time24hr: {
type: Boolean,
@@ -282,7 +282,7 @@ const inputInvalidClass = computed(() => {
const inputDisabledClass = computed(() => {
if (props.disabled) {
return 'border border-solid rounded-md outline-hidden input-field box-border-2 base-date-picker-input placeholder-gray-400 bg-gray-200 text-gray-600 border-gray-200'
return 'border border-solid rounded-md outline-hidden input-field box-border-2 base-date-picker-input placeholder-gray-400 bg-surface-muted text-body border-line-default'
}
return ''

View File

@@ -10,7 +10,7 @@
{{ label }}
</BaseLabel>
<p class="text-sm font-bold leading-5 text-black non-italic">
<p class="text-sm font-bold leading-5 text-heading non-italic">
{{ value }}
<slot />

View File

@@ -30,7 +30,7 @@
leave-to="opacity-0"
>
<DialogOverlay
class="fixed inset-0 transition-opacity bg-gray-500/75"
class="fixed inset-0 transition-opacity bg-surface-secondary0/75"
/>
</TransitionChild>
@@ -59,7 +59,7 @@
text-left
align-bottom
transition-all
bg-white
bg-surface
rounded-lg
shadow-xl
sm:my-8 sm:align-middle sm:w-full sm:p-6
@@ -76,35 +76,35 @@
w-12
h-12
mx-auto
bg-green-100
bg-alert-success-bg
rounded-full
"
:class="{
'bg-green-100': dialogStore.variant === 'primary',
'bg-red-100': dialogStore.variant === 'danger',
'bg-alert-success-bg': dialogStore.variant === 'primary',
'bg-alert-error-bg': dialogStore.variant === 'danger',
}"
>
<BaseIcon
v-if="dialogStore.variant === 'primary'"
name="CheckIcon"
class="w-6 h-6 text-green-600"
class="w-6 h-6 text-alert-success-text"
/>
<BaseIcon
v-else
name="ExclamationIcon"
class="w-6 h-6 text-red-600"
class="w-6 h-6 text-alert-error-text"
aria-hidden="true"
/>
</div>
<div class="mt-3 text-center sm:mt-5">
<DialogTitle
as="h3"
class="text-lg font-medium leading-6 text-gray-900"
class="text-lg font-medium leading-6 text-heading"
>
{{ dialogStore.title }}
</DialogTitle>
<div class="mt-2">
<p class="text-sm text-gray-500">
<p class="text-sm text-muted">
{{ dialogStore.message }}
</p>
</div>

View File

@@ -1,3 +1,3 @@
<template>
<hr class="w-full text-gray-300" />
<hr class="w-full text-subtle" />
</template>

View File

@@ -69,7 +69,7 @@ const props = defineProps({
})
const containerClasses = computed(() => {
const baseClass = `origin-top-right rounded-md shadow-lg bg-white ring-1 ring-black/5 divide-y divide-gray-100 focus:outline-hidden`
const baseClass = `origin-top-right rounded-md shadow-lg bg-surface ring-1 ring-black/5 divide-y divide-line-light focus:outline-hidden`
return `${baseClass} ${props.containerClass}`
})

View File

@@ -3,7 +3,7 @@
<a
href="#"
:class="[
active ? 'bg-gray-100 text-gray-900' : 'text-gray-700',
active ? 'bg-hover-strong text-heading' : 'text-body',
'group flex items-center px-4 py-2 text-sm font-normal whitespace-normal',
]"
>

View File

@@ -7,7 +7,7 @@
<label class="font-medium">{{ title }}</label>
</div>
<div class="mt-2">
<label class="text-gray-500">
<label class="text-muted">
{{ description }}
</label>
</div>

View File

@@ -1,14 +1,14 @@
<template>
<div class="rounded-md bg-red-50 p-4">
<div class="rounded-md bg-alert-error-bg p-4">
<div class="flex">
<div class="shrink-0">
<XCircleIcon class="h-5 w-5 text-red-400" aria-hidden="true" />
<XCircleIcon class="h-5 w-5 text-alert-error-text" aria-hidden="true" />
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-red-800">
<h3 class="text-sm font-medium text-alert-error-text">
{{ errorTitle }}
</h3>
<div class="mt-2 text-sm text-red-700">
<div class="mt-2 text-sm text-alert-error-text">
<ul role="list" class="list-disc pl-5 space-y-1">
<li v-for="(error, key) in errors" :key="key">
{{ error }}

View File

@@ -18,19 +18,19 @@ const props = defineProps({
const badgeColorClasses = computed(() => {
switch (props.status) {
case 'DRAFT':
return 'bg-yellow-300/25 px-2 py-1 text-sm text-yellow-800 uppercase font-normal text-center '
return 'bg-yellow-300/25 px-2 py-1 text-sm text-status-yellow uppercase font-normal text-center '
case 'SENT':
return ' bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center '
return ' bg-yellow-500/25 px-2 py-1 text-sm text-status-yellow uppercase font-normal text-center '
case 'VIEWED':
return 'bg-blue-400/25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
return 'bg-blue-400/25 px-2 py-1 text-sm text-status-blue uppercase font-normal text-center'
case 'EXPIRED':
return 'bg-red-300/25 px-2 py-1 text-sm text-red-800 uppercase font-normal text-center'
return 'bg-red-300/25 px-2 py-1 text-sm text-status-red uppercase font-normal text-center'
case 'ACCEPTED':
return 'bg-green-400/25 px-2 py-1 text-sm text-green-800 uppercase font-normal text-center'
return 'bg-green-400/25 px-2 py-1 text-sm text-status-green uppercase font-normal text-center'
case 'REJECTED':
return 'bg-purple-300/25 px-2 py-1 text-sm text-purple-800 uppercase font-normal text-center'
return 'bg-purple-300/25 px-2 py-1 text-sm text-status-purple uppercase font-normal text-center'
default:
return 'bg-gray-500/25 px-2 py-1 text-sm text-gray-900 uppercase font-normal text-center'
return 'bg-surface-secondary0/25 px-2 py-1 text-sm text-heading uppercase font-normal text-center'
}
})
</script>

View File

@@ -11,15 +11,15 @@
rounded-md
cursor-pointer
avatar-upload
border-gray-300
border-line-strong
transition-all
duration-300
ease-in-out
isolate
hover:border-gray-300
hover:border-line-strong
group
min-h-[100px]
bg-gray-50
bg-surface-secondary
"
:class="avatar ? 'w-32 h-32' : 'w-full'"
>
@@ -48,7 +48,7 @@
<a
href="#"
class="absolute z-30 bg-white rounded-full -bottom-3 -right-3 group"
class="absolute z-30 bg-surface rounded-full -bottom-3 -right-3 group"
@click.prevent.stop="onBrowse"
>
<BaseIcon
@@ -68,9 +68,9 @@
<div v-else-if="!localFiles.length" class="flex flex-col items-center">
<BaseIcon
name="CloudArrowUpIcon"
class="h-6 mb-2 text-xl leading-6 text-gray-400"
class="h-6 mb-2 text-xl leading-6 text-subtle"
/>
<p class="text-xs leading-4 text-center text-gray-400">
<p class="text-xs leading-4 text-center text-subtle">
{{ $t('general.file_upload.drag_a_file') }}
<a
class="
@@ -87,14 +87,14 @@
</a>
{{ $t('general.file_upload.to_choose') }}
</p>
<p class="text-xs leading-4 text-center text-gray-400 mt-2">
<p class="text-xs leading-4 text-center text-subtle mt-2">
{{ recommendedText }}
</p>
</div>
<div
v-else-if="localFiles.length && avatar && !multiple"
class="flex w-full h-full border border-gray-200 rounded justify-center items-center"
class="flex w-full h-full border border-line-default rounded justify-center items-center"
>
<img
v-if="localFiles[0].image"
@@ -110,7 +110,7 @@
flex
justify-center
items-center
text-gray-400
text-subtle
flex-col
space-y-2
px-2
@@ -137,7 +137,7 @@
<p
v-if="localFiles[0].name"
class="
text-gray-600
text-body
font-medium
text-sm
truncate
@@ -160,18 +160,18 @@
justify-center
w-8
h-8
bg-white
border border-gray-200
bg-surface
border border-line-default
rounded-full
shadow-md
-bottom-3
-right-3
group
hover:border-gray-300
hover:border-line-strong
"
@click.prevent.stop="onAvatarRemove(localFiles[0])"
>
<BaseIcon name="XMarkIcon" class="h-4 text-xl leading-6 text-black" />
<BaseIcon name="XMarkIcon" class="h-4 text-xl leading-6 text-heading" />
</a>
</div>
@@ -188,8 +188,8 @@
block
p-2
m-2
bg-white
border border-gray-200
bg-surface
border border-line-default
rounded
hover:border-gray-500
relative
@@ -211,7 +211,7 @@
flex
justify-center
items-center
text-gray-400
text-subtle
flex-col
space-y-2
px-2
@@ -238,7 +238,7 @@
<p
v-if="localFile.name"
class="
text-gray-600
text-body
font-medium
text-sm
truncate
@@ -261,18 +261,18 @@
justify-center
w-8
h-8
bg-white
border border-gray-200
bg-surface
border border-line-default
rounded-full
shadow-md
-bottom-3
-right-3
group
hover:border-gray-300
hover:border-line-strong
"
@click.prevent.stop="onFileRemove(index)"
>
<BaseIcon name="XMarkIcon" class="h-4 text-xl leading-6 text-black" />
<BaseIcon name="XMarkIcon" class="h-4 text-xl leading-6 text-heading" />
</span>
</a>
</div>
@@ -286,8 +286,8 @@
block
p-2
m-2
bg-white
border border-gray-200
bg-surface
border border-line-default
rounded
hover:border-gray-500
relative
@@ -309,7 +309,7 @@
flex
justify-center
items-center
text-gray-400
text-subtle
flex-col
space-y-2
px-2
@@ -336,7 +336,7 @@
<p
v-if="localFile.name"
class="
text-gray-600
text-body
font-medium
text-sm
truncate
@@ -359,18 +359,18 @@
justify-center
w-8
h-8
bg-white
border border-gray-200
bg-surface
border border-line-default
rounded-full
shadow-md
-bottom-3
-right-3
group
hover:border-gray-300
hover:border-line-strong
"
@click.prevent.stop="onFileRemove(index)"
>
<BaseIcon name="XMarkIcon" class="h-4 text-xl leading-6 text-black" />
<BaseIcon name="XMarkIcon" class="h-4 text-xl leading-6 text-heading" />
</span>
</a>
</div>

View File

@@ -7,7 +7,7 @@
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div v-show="show" class="relative z-10 p-4 md:p-8 bg-gray-200 rounded">
<div v-show="show" class="relative z-10 p-4 md:p-8 bg-surface-muted rounded">
<slot name="filter-header" />
<label
@@ -15,9 +15,9 @@
absolute
text-sm
leading-snug
text-gray-900
text-heading
cursor-pointer
hover:text-gray-700
hover:text-body
top-2.5
right-3.5
"

View File

@@ -18,8 +18,8 @@ const props = defineProps({
const typeClass = computed(() => {
return {
'text-gray-900 text-lg font-medium': props.type === 'heading-title',
'text-gray-500 uppercase text-base': props.type === 'section-title',
'text-heading text-lg font-medium': props.type === 'heading-title',
'text-muted uppercase text-base': props.type === 'section-title',
}
})
</script>

View File

@@ -1,8 +1,8 @@
<template>
<div class="rounded-md bg-yellow-50 p-4 relative">
<div class="rounded-md bg-alert-warning-bg p-4 relative">
<BaseIcon
name="XMarkIcon"
class="h-5 w-5 text-yellow-500 absolute right-4 cursor-pointer"
class="h-5 w-5 text-alert-warning-text absolute right-4 cursor-pointer"
@click="$emit('hide')"
/>
<div class="flex flex-col">
@@ -10,15 +10,15 @@
<div class="shrink-0">
<BaseIcon
name="ExclamationIcon"
class="h-5 w-5 text-yellow-400"
class="h-5 w-5 text-alert-warning-text"
aria-hidden="true"
/>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800">
<h3 class="text-sm font-medium text-alert-warning-text">
{{ title }}
</h3>
<div class="mt-2 text-sm text-yellow-700">
<div class="mt-2 text-sm text-alert-warning-text">
<ul role="list" class="list-disc pl-5 space-y-1">
<li v-for="(list, key) in lists" :key="key">
{{ list }}
@@ -34,14 +34,14 @@
:key="i"
type="button"
class="
bg-yellow-50
bg-alert-warning-bg
px-2
py-1.5
rounded-md
text-sm
font-medium
text-yellow-800
hover:bg-yellow-100
text-alert-warning-text
hover:bg-alert-warning-bg
focus:outline-hidden
focus:ring-2
focus:ring-offset-2

View File

@@ -60,10 +60,10 @@
inline-flex
items-center
px-3
text-gray-500
border border-r-0 border-gray-200
text-muted
border border-r-0 border-line-default
rounded-l-md
bg-gray-50
bg-surface-secondary
sm:text-sm
"
>
@@ -82,7 +82,7 @@
pointer-events-none
"
>
<span class="text-gray-500 sm:text-sm">
<span class="text-muted sm:text-sm">
{{ inlineAddon }}
</span>
</div>
@@ -199,15 +199,15 @@ const props = defineProps({
defaultInputClass: {
type: String,
default:
'font-base block w-full sm:text-sm border-gray-200 rounded-md text-black',
'font-base block w-full sm:text-sm border-line-default rounded-md text-heading',
},
iconLeftClass: {
type: String,
default: 'h-5 w-5 text-gray-400',
default: 'h-5 w-5 text-subtle',
},
iconRightClass: {
type: String,
default: 'h-5 w-5 text-gray-400',
default: 'h-5 w-5 text-subtle',
},
modelModifiers: {
default: () => ({}),
@@ -258,7 +258,7 @@ const inputInvalidClass = computed(() => {
const inputDisabledClass = computed(() => {
if (props.disabled) {
return `border-gray-100 bg-gray-100 !text-gray-400 ring-gray-200 focus:ring-gray-200 focus:border-gray-100`
return `border-line-light bg-surface-tertiary !text-subtle ring-surface-muted focus:ring-surface-muted focus:border-line-light`
}
return ''

View File

@@ -12,7 +12,7 @@
not-italic
items-center
font-medium
text-gray-800
text-heading
whitespace-nowrap
justify-between
"
@@ -26,12 +26,12 @@
v-if="tooltip"
v-tooltip="{ content: tooltip }"
name="InformationCircleIcon"
class="h-4 text-gray-400 cursor-pointer hover:text-gray-600"
class="h-4 text-subtle cursor-pointer hover:text-body"
/>
</label>
<div :class="inputContainerClasses">
<slot></slot>
<span v-if="helpText" class="text-gray-500 text-xs mt-1 font-light">
<span v-if="helpText" class="text-muted text-xs mt-1 font-light">
{{ helpText }}
</span>
<span v-if="error" class="block mt-0.5 text-sm text-red-500">

View File

@@ -20,25 +20,25 @@ export default {
const badgeColorClasses = computed(() => {
switch (props.status) {
case 'DRAFT':
return 'bg-yellow-300/25 px-2 py-1 text-sm text-yellow-800 uppercase font-normal text-center'
return 'bg-yellow-300/25 px-2 py-1 text-sm text-status-yellow uppercase font-normal text-center'
case 'SENT':
return ' bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center '
return ' bg-yellow-500/25 px-2 py-1 text-sm text-status-yellow uppercase font-normal text-center '
case 'VIEWED':
return 'bg-blue-400/25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
return 'bg-blue-400/25 px-2 py-1 text-sm text-status-blue uppercase font-normal text-center'
case 'COMPLETED':
return 'bg-green-500/25 px-2 py-1 text-sm text-green-900 uppercase font-normal text-center'
return 'bg-green-500/25 px-2 py-1 text-sm text-status-green uppercase font-normal text-center'
case 'DUE':
return 'bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center'
return 'bg-yellow-500/25 px-2 py-1 text-sm text-status-yellow uppercase font-normal text-center'
case 'OVERDUE':
return 'bg-red-300/50 px-2 py-1 text-sm text-red-900 uppercase font-normal text-center'
return 'bg-red-300/50 px-2 py-1 text-sm text-status-red uppercase font-normal text-center'
case 'UNPAID':
return 'bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center'
return 'bg-yellow-500/25 px-2 py-1 text-sm text-status-yellow uppercase font-normal text-center'
case 'PARTIALLY_PAID':
return 'bg-blue-400/25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
return 'bg-blue-400/25 px-2 py-1 text-sm text-status-blue uppercase font-normal text-center'
case 'PAID':
return 'bg-green-500/25 px-2 py-1 text-sm text-green-900 uppercase font-normal text-center'
return 'bg-green-500/25 px-2 py-1 text-sm text-status-green uppercase font-normal text-center'
default:
return 'bg-gray-500/25 px-2 py-1 text-sm text-gray-900 uppercase font-normal text-center'
return 'bg-surface-secondary0/25 px-2 py-1 text-sm text-heading uppercase font-normal text-center'
}
})
return { badgeColorClasses }

View File

@@ -9,15 +9,15 @@
items-center
h-10
pl-2
bg-gray-200
border border-gray-200 border-solid
bg-surface-muted
border border-line-default border-solid
rounded
"
>
{{ item.name }}
<span
class="absolute text-gray-400 cursor-pointer top-[8px] right-[10px]"
class="absolute text-subtle cursor-pointer top-[8px] right-[10px]"
@click="deselectItem(index)"
>
<BaseIcon name="XCircleIcon" />

View File

@@ -51,7 +51,7 @@
<div
:class="`inline-block
align-middle
bg-white
bg-surface
rounded-lg
text-left
overflow-hidden
@@ -73,8 +73,8 @@
py-4
text-lg
font-medium
text-black
border-b border-gray-200 border-solid
text-heading
border-b border-line-default border-solid
"
>
<slot name="header" />

View File

@@ -39,7 +39,7 @@ const props = defineProps({
inputClass: {
type: String,
default:
'font-base block w-full sm:text-sm border-gray-200 rounded-md text-black',
'font-base block w-full sm:text-sm border-line-default rounded-md text-heading',
},
disabled: {
type: Boolean,

View File

@@ -1,7 +1,7 @@
<template>
<span
:class="[
sucess ? 'bg-green-100 text-green-700 ' : 'bg-red-100 text-red-700',
sucess ? 'bg-green-500/25 text-status-green ' : 'bg-red-500/25 text-status-red',
'px-2 py-1 text-sm font-normal text-center uppercase',
]"
>

View File

@@ -1,7 +1,7 @@
<template>
<div class="flex flex-wrap justify-between">
<div>
<h3 class="text-2xl font-bold text-left text-black">
<h3 class="text-2xl font-bold text-left text-heading">
{{ title }}
</h3>
<slot />

View File

@@ -26,13 +26,13 @@ export default {
case 'PAID':
return 'bg-primary-300/25 text-primary-800 uppercase font-normal text-center'
case 'UNPAID':
return ' bg-yellow-500/25 text-yellow-900 uppercase font-normal text-center '
return ' bg-yellow-500/25 text-status-yellow uppercase font-normal text-center '
case 'PARTIALLY_PAID':
return 'bg-blue-400/25 text-blue-900 uppercase font-normal text-center'
return 'bg-blue-400/25 text-status-blue uppercase font-normal text-center'
case 'OVERDUE':
return 'bg-red-300/50 px-2 py-1 text-sm text-red-900 uppercase font-normal text-center'
return 'bg-red-300/50 px-2 py-1 text-sm text-status-red uppercase font-normal text-center'
default:
return 'bg-gray-500/25 text-gray-900 uppercase font-normal text-center'
return 'bg-surface-secondary0/25 text-heading uppercase font-normal text-center'
}
})
return { badgeColorClasses }

View File

@@ -66,11 +66,11 @@ const props = defineProps({
},
checkedStateClass: {
type: String,
default: 'bg-primary-600',
default: 'bg-primary-500',
},
unCheckedStateClass: {
type: String,
default: 'bg-white ',
default: 'bg-surface ',
},
optionGroupActiveStateClass: {
type: String,
@@ -78,11 +78,11 @@ const props = defineProps({
},
checkedStateLabelClass: {
type: String,
default: 'text-primary-900 ',
default: 'text-primary-500 ',
},
unCheckedStateLabelClass: {
type: String,
default: 'text-gray-900',
default: 'text-heading',
},
optionGroupClass: {
type: String,

View File

@@ -20,13 +20,13 @@ export default {
const badgeColorClasses = computed(() => {
switch (props.status) {
case 'COMPLETED':
return 'bg-green-500/25 px-2 py-1 text-sm text-green-900 uppercase font-normal text-center'
return 'bg-green-500/25 px-2 py-1 text-sm text-status-green uppercase font-normal text-center'
case 'ON_HOLD':
return 'bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center'
return 'bg-yellow-500/25 px-2 py-1 text-sm text-status-yellow uppercase font-normal text-center'
case 'ACTIVE':
return 'bg-blue-400/25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
return 'bg-blue-400/25 px-2 py-1 text-sm text-status-blue uppercase font-normal text-center'
default:
return 'bg-gray-500/25 px-2 py-1 text-sm text-gray-900 uppercase font-normal text-center'
return 'bg-surface-secondary0/25 px-2 py-1 text-sm text-heading uppercase font-normal text-center'
}
})
return { badgeColorClasses }

View File

@@ -8,7 +8,7 @@
px-6
py-2
text-sm
bg-gray-200
bg-surface-muted
cursor-pointer
text-primary-400
"

View File

@@ -12,7 +12,7 @@
>
<ListboxLabel
v-if="label"
class="block text-sm not-italic font-medium text-gray-800 mb-0.5"
class="block text-sm not-italic font-medium text-heading mb-0.5"
>
{{ label }}
</ListboxLabel>
@@ -27,8 +27,8 @@
pl-3
pr-10
text-left
bg-white
border border-gray-200
bg-surface
border border-line-default
rounded-md
shadow-xs
cursor-default
@@ -42,10 +42,10 @@
<span v-if="getValue(selectedValue)" class="block truncate">
{{ getValue(selectedValue) }}
</span>
<span v-else-if="placeholder" class="block text-gray-400 truncate">
<span v-else-if="placeholder" class="block text-subtle truncate">
{{ placeholder }}
</span>
<span v-else class="block text-gray-400 truncate">
<span v-else class="block text-subtle truncate">
Please select an option
</span>
@@ -62,7 +62,7 @@
>
<BaseIcon
name="SelectorIcon"
class="text-gray-400"
class="text-subtle"
aria-hidden="true"
/>
</span>
@@ -82,7 +82,7 @@
mt-1
overflow-auto
text-base
bg-white
bg-surface
rounded-md
shadow-lg
max-h-60
@@ -100,7 +100,7 @@
>
<li
:class="[
active ? 'text-white bg-primary-600' : 'text-gray-900',
active ? 'text-white bg-primary-600' : 'text-heading',
'cursor-default select-none relative py-2 pl-3 pr-9',
]"
>

View File

@@ -11,7 +11,7 @@
mt-2
text-sm
leading-snug
text-left text-gray-500
text-left text-muted
max-w-[680px]
"
>

View File

@@ -7,7 +7,7 @@
<Switch
v-model="enabled"
:class="enabled ? 'bg-primary-500' : 'bg-gray-300'"
:class="enabled ? 'bg-primary-500' : 'bg-surface-muted'"
class="
relative
inline-flex

View File

@@ -5,12 +5,12 @@
<div class="flex flex-col">
<SwitchLabel
as="p"
class="p-0 mb-1 text-sm leading-snug text-black font-medium"
class="p-0 mb-1 text-sm leading-snug text-heading font-medium"
passive
>
{{ title }}
</SwitchLabel>
<SwitchDescription class="text-sm text-gray-500">
<SwitchDescription class="text-sm text-muted">
{{ description }}
</SwitchDescription>
</div>
@@ -18,7 +18,7 @@
:disabled="disabled"
:model-value="modelValue"
:class="[
modelValue ? 'bg-primary-500' : 'bg-gray-200',
modelValue ? 'bg-primary-500' : 'bg-surface-muted',
'ml-4 relative inline-flex shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-primary-500',
]"
@update:modelValue="onUpdate"

View File

@@ -3,7 +3,7 @@
<TabGroup :default-index="defaultIndex" @change="onChange">
<TabList
:class="[
'flex border-b border-gray-200',
'flex border-b border-line-default',
'relative overflow-x-auto overflow-y-hidden',
'lg:pb-0 lg:ml-0',
]"
@@ -18,8 +18,8 @@
:class="[
'px-8 py-2 text-sm leading-5 font-medium flex items-center relative border-b-2 mt-4 focus:outline-hidden whitespace-nowrap',
selected
? ' border-primary-400 text-black font-medium'
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300',
? ' border-primary-400 text-heading font-medium'
: 'border-transparent text-muted hover:text-body hover:border-line-strong',
]"
>
{{ tab.title }}

View File

@@ -45,7 +45,7 @@ const props = defineProps({
defaultInputClass: {
type: String,
default:
'box-border w-full px-3 py-2 text-sm not-italic font-normal leading-snug text-left text-black placeholder-gray-400 bg-white border border-gray-200 border-solid rounded outline-hidden',
'box-border w-full px-3 py-2 text-sm not-italic font-normal leading-snug text-left text-heading placeholder-subtle bg-surface border border-line-default border-solid rounded outline-hidden',
},
autosize: {
type: Boolean,

View File

@@ -21,7 +21,7 @@
text-sm
not-italic
font-black
text-gray-400
text-subtle
cursor-pointer
"
viewBox="0 0 20 20"
@@ -86,7 +86,7 @@ const props = defineProps({
defaultInputClass: {
type: String,
default:
'font-base pl-8 py-2 outline-hidden focus:ring-primary-400 focus:outline-hidden focus:border-primary-400 block w-full sm:text-sm border-gray-300 rounded-md text-black',
'font-base pl-8 py-2 outline-hidden focus:ring-primary-400 focus:outline-hidden focus:border-primary-400 block w-full sm:text-sm border-line-strong rounded-md text-heading',
},
})
@@ -130,7 +130,7 @@ const inputInvalidClass = computed(() => {
const inputDisabledClass = computed(() => {
if (props.disabled) {
return 'border border-solid rounded-md outline-hidden input-field box-border-2 base-date-picker-input placeholder-gray-400 bg-gray-300 text-gray-600 border-gray-300'
return 'border border-solid rounded-md outline-hidden input-field box-border-2 base-date-picker-input placeholder-subtle bg-surface-muted text-body border-line-strong'
}
return ''

View File

@@ -3,7 +3,7 @@
:class="containerClass"
class="
relative
after:bg-gray-200
after:bg-surface-muted
after:absolute
after:transform
after:top-1/2
@@ -62,7 +62,7 @@ export default {
},
nextStepClass: {
type: String,
default: 'border-gray-200 bg-white',
default: 'border-line-default bg-surface',
},
previousStepClass: {
type: String,

View File

@@ -25,16 +25,16 @@ const props = defineProps({
stepContainerClass: {
type: String,
default:
'w-full p-8 mb-8 bg-white border border-gray-200 border-solid rounded',
'w-full p-8 mb-8 bg-surface border border-line-default border-solid rounded',
},
stepTitleClass: {
type: String,
default: 'text-2xl not-italic font-semibold leading-7 text-black',
default: 'text-2xl not-italic font-semibold leading-7 text-heading',
},
stepDescriptionClass: {
type: String,
default:
'w-full mt-2.5 mb-8 text-sm not-italic leading-snug text-gray-500 lg:w-7/12 md:w-7/12 sm:w-7/12',
'w-full mt-2.5 mb-8 text-sm not-italic leading-snug text-muted lg:w-7/12 md:w-7/12 sm:w-7/12',
},
})
</script>

View File

@@ -8,16 +8,16 @@
</BaseContentPlaceholders>
<div
v-else
class="box-border w-full text-sm leading-8 text-left bg-white border border-gray-200 rounded-md min-h-[200px] overflow-hidden"
class="box-border w-full text-sm leading-8 text-left bg-surface border border-line-default rounded-md min-h-[200px] overflow-hidden"
>
<div v-if="editor" class="editor-content">
<div class="flex justify-end p-2 border-b border-gray-200 md:hidden">
<div class="flex justify-end p-2 border-b border-line-default md:hidden">
<BaseDropdown width-class="w-48">
<template #activator>
<div
class="flex items-center justify-center w-6 h-6 ml-2 text-sm text-black bg-white rounded-xs md:h-9 md:w-9"
class="flex items-center justify-center w-6 h-6 ml-2 text-sm text-heading bg-surface rounded-xs md:h-9 md:w-9"
>
<EllipsisVerticalIcon class="w-6 h-6 text-gray-600" />
<EllipsisVerticalIcon class="w-6 h-6 text-body" />
</div>
</template>
<div class="flex flex-wrap space-x-1">
@@ -25,36 +25,36 @@
v-for="button in editorButtons"
type="button"
:key="button.name"
class="p-1 rounded hover:bg-gray-100"
class="p-1 rounded hover:bg-surface-tertiary"
@click="button.action"
>
<component
:is="button.icon"
v-if="button.icon"
class="w-4 h-4 text-gray-700 fill-gray-700"
class="w-4 h-4 text-body fill-current text-body"
/>
<span v-else-if="button.text" class="px-1 text-sm font-medium text-gray-600">
<span v-else-if="button.text" class="px-1 text-sm font-medium text-body">
{{ button.text }}
</span>
</button>
</div>
</BaseDropdown>
</div>
<div class="hidden p-2 border-b border-gray-200 md:flex">
<div class="hidden p-2 border-b border-line-default md:flex">
<div class="flex flex-wrap space-x-1">
<button
v-for="button in editorButtons"
type="button"
:key="button.name"
class="p-1 rounded hover:bg-gray-100"
class="p-1 rounded hover:bg-surface-tertiary"
@click="button.action"
>
<component
:is="button.icon"
v-if="button.icon"
class="w-4 h-4 text-gray-700 fill-gray-700"
class="w-4 h-4 text-body fill-current text-body"
/>
<span v-else-if="button.text" class="px-1 text-sm font-medium text-gray-600">
<span v-else-if="button.text" class="px-1 text-sm font-medium text-body">
{{ button.text }}
</span>
</button>
@@ -209,7 +209,7 @@ export default {
blockquote {
padding-left: 1rem;
border-left: 2px solid rgba(13, 13, 13, 0.1);
border-left: 2px solid var(--color-line-default);
}
code {

View File

@@ -6,9 +6,9 @@
class="
relative
overflow-hidden
bg-white
border border-gray-100
shadow-sm
bg-surface
border border-line-light
shadow
rounded-xl
"
>
@@ -22,7 +22,7 @@
:class="[
getThClass(column),
{
'text-bold text-black': sort.fieldName === column.key,
'text-bold text-heading': sort.fieldName === column.key,
},
]"
@click="changeSorting(column)"
@@ -51,7 +51,7 @@
<tr
v-for="placeRow in placeholderCount"
:key="placeRow"
:class="placeRow % 2 === 0 ? 'bg-white' : 'bg-gray-50'"
:class="placeRow % 2 === 0 ? 'bg-surface' : 'bg-surface-secondary'"
>
<td
v-for="column in columns"
@@ -75,7 +75,7 @@
<tr
v-for="(row, index) in sortedRows"
:key="row.data?.id ?? index"
:class="index % 2 === 0 ? 'bg-white' : 'bg-gray-50'"
:class="index % 2 === 0 ? 'bg-surface' : 'bg-surface-secondary'"
>
<td
v-for="column in columns"
@@ -114,7 +114,7 @@
!loading && !isLoading && sortedRows && sortedRows.length === 0
"
class="
text-center text-gray-500
text-center text-muted
pb-2
flex
h-[160px]
@@ -125,7 +125,7 @@
>
<BaseIcon
name="ExclamationCircleIcon"
class="w-6 h-6 text-gray-400"
class="w-6 h-6 text-subtle"
/>
<span class="block mt-1">{{ $t('general.no_data_found') }}</span>
@@ -163,9 +163,9 @@ const props = defineProps({
sortOrder: { type: String, default: '' },
tableClass: {
type: String,
default: 'min-w-full divide-y divide-gray-200',
default: 'min-w-full divide-y divide-line-default',
},
theadClass: { type: String, default: 'bg-gray-50' },
theadClass: { type: String, default: 'bg-surface-secondary' },
tbodyClass: { type: String, default: '' },
noResultsMessage: {
type: String,
@@ -236,7 +236,7 @@ function getColumn(columnName) {
function getThClass(column) {
let classes =
'whitespace-nowrap px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider'
'whitespace-nowrap px-6 py-3 text-left text-xs font-medium text-muted uppercase tracking-wider'
if (column.defaultThClass) {
classes = column.defaultThClass
@@ -256,7 +256,7 @@ function getThClass(column) {
}
function getTdClass(column) {
let classes = 'px-6 py-4 text-sm text-gray-500 whitespace-nowrap'
let classes = 'px-6 py-4 text-sm text-muted whitespace-nowrap'
if (column.defaultTdClass) {
classes = column.defaultTdClass

View File

@@ -7,8 +7,8 @@
justify-between
px-4
py-3
bg-white
border-t border-gray-200
bg-surface
border-t border-line-default
sm:px-6
"
>
@@ -16,7 +16,7 @@
<a
href="#"
:class="{
'disabled cursor-normal pointer-events-none !bg-gray-100 !text-gray-400':
'disabled cursor-normal pointer-events-none !bg-surface-tertiary !text-subtle':
pagination.currentPage === 1,
}"
class="
@@ -27,11 +27,11 @@
py-2
text-sm
font-medium
text-gray-700
bg-white
border border-gray-200
text-body
bg-surface
border border-line-default
rounded-md
hover:bg-gray-50
hover:bg-hover
"
@click="pageClicked(pagination.currentPage - 1)"
>
@@ -40,7 +40,7 @@
<a
href="#"
:class="{
'disabled cursor-default pointer-events-none !bg-gray-100 !text-gray-400':
'disabled cursor-default pointer-events-none !bg-surface-tertiary !text-subtle':
pagination.currentPage === pagination.totalPages,
}"
class="
@@ -52,11 +52,11 @@
ml-3
text-sm
font-medium
text-gray-700
bg-white
border border-gray-200
text-body
bg-surface
border border-line-default
rounded-md
hover:bg-gray-50
hover:bg-hover
"
@click="pageClicked(pagination.currentPage + 1)"
>
@@ -65,7 +65,7 @@
</div>
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700">
<p class="text-sm text-body">
{{ $t('general.pagination.showing') }}
{{ ' ' }}
<span
@@ -113,7 +113,7 @@
<a
href="#"
:class="{
'disabled cursor-normal pointer-events-none !bg-gray-100 !text-gray-400':
'disabled cursor-normal pointer-events-none !bg-surface-tertiary !text-subtle':
pagination.currentPage === 1,
}"
class="
@@ -124,11 +124,11 @@
py-2
text-sm
font-medium
text-gray-500
bg-white
border border-gray-200
text-muted
bg-surface
border border-line-default
rounded-l-lg
hover:bg-gray-50
hover:bg-hover
"
@click="pageClicked(pagination.currentPage - 1)"
>
@@ -142,7 +142,7 @@
:class="{
'z-10 bg-primary-500 border-primary-500 text-white':
isActive(1),
'bg-white border-gray-200 text-gray-500 hover:bg-gray-50':
'bg-surface border-line-default text-muted hover:bg-hover':
!isActive(1),
}"
class="
@@ -170,9 +170,9 @@
py-2
text-sm
font-medium
text-gray-700
bg-white
border border-gray-200
text-body
bg-surface
border border-line-default
"
>
...
@@ -184,7 +184,7 @@
:class="{
'z-10 bg-primary-500 border-primary-500 text-white':
isActive(page),
'bg-white border-gray-200 text-gray-500 hover:bg-gray-50':
'bg-surface border-line-default text-muted hover:bg-hover':
!isActive(page),
disabled: page === '...',
}"
@@ -214,9 +214,9 @@
py-2
text-sm
font-medium
text-gray-700
bg-white
border border-gray-200
text-body
bg-surface
border border-line-default
"
>
...
@@ -228,7 +228,7 @@
:class="{
'z-10 bg-primary-500 border-primary-500 text-white':
isActive(pagination.totalPages),
'bg-white border-gray-200 text-gray-500 hover:bg-gray-50':
'bg-surface border-line-default text-muted hover:bg-hover':
!isActive(pagination.totalPages),
}"
class="
@@ -255,14 +255,14 @@
py-2
text-sm
font-medium
text-gray-500
bg-white
border border-gray-200
text-muted
bg-surface
border border-line-default
rounded-r-lg
hover:bg-gray-50
hover:bg-hover
"
:class="{
'disabled cursor-default pointer-events-none !bg-gray-100 !text-gray-400':
'disabled cursor-default pointer-events-none !bg-surface-tertiary !text-subtle':
pagination.currentPage === pagination.totalPages,
}"
@click="pageClicked(pagination.currentPage + 1)"

View File

@@ -34,7 +34,7 @@ export default {
})
let containerClass = computed(() => {
if (props.active) return `${defaultClass} text-primary-600 bg-primary-50 font-semibold`
else return `${defaultClass} text-gray-600 hover:bg-gray-50 hover:text-gray-900`
else return `${defaultClass} text-body hover:bg-hover hover:text-heading`
})
return {
hasIconSlot,

View File

@@ -1,6 +1,6 @@
<template>
<div
:class="success || info ? 'bg-white' : 'bg-red-50'"
:class="success || info ? 'bg-surface' : 'bg-alert-error-bg'"
class="
max-w-sm
mb-3
@@ -21,7 +21,7 @@
<div class="shrink-0">
<svg
v-if="success"
class="w-6 h-6 text-green-400"
class="w-6 h-6 text-alert-success-text"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
@@ -35,7 +35,7 @@
</svg>
<svg
v-if="info"
class="w-6 h-6 text-blue-400"
class="w-6 h-6 text-status-blue"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
@@ -48,7 +48,7 @@
</svg>
<svg
v-if="error"
class="w-6 h-6 text-red-400"
class="w-6 h-6 text-alert-error-text"
fill="currentColor"
viewBox="0 0 24 24"
>
@@ -62,7 +62,7 @@
<div class="flex-1 w-0 ml-3 text-left">
<p
:class="`text-sm leading-5 font-medium ${
success || info ? 'text-gray-900' : 'text-red-800'
success || info ? 'text-heading' : 'text-alert-error-text'
}`"
>
{{
@@ -75,7 +75,7 @@
</p>
<p
:class="`mt-1 text-sm leading-5 ${
success || info ? 'text-gray-500' : 'text-red-700'
success || info ? 'text-muted' : 'text-alert-error-text'
}`"
>
{{
@@ -91,8 +91,8 @@
<button
:class="
success || info
? ' text-gray-400 focus:text-gray-500'
: 'text-red-400 focus:text-red-500'
? ' text-subtle focus:text-muted'
: 'text-alert-error-text focus:text-alert-error-text'
"
class="
inline-flex