fix some bugs
This commit is contained in:
@@ -46,7 +46,7 @@ defineProps<{
|
||||
}
|
||||
|
||||
.badge-neutral {
|
||||
background: #f1f5f9;
|
||||
background: var(--color-summary-bg);
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
modelValue?: string | number
|
||||
label?: string
|
||||
type?: string
|
||||
placeholder?: string
|
||||
hint?: string
|
||||
error?: string
|
||||
disabled?: boolean
|
||||
min?: number
|
||||
max?: number
|
||||
step?: number
|
||||
}>()
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
modelValue?: string | number
|
||||
label?: string
|
||||
type?: string
|
||||
placeholder?: string
|
||||
hint?: string
|
||||
error?: string
|
||||
disabled?: boolean
|
||||
min?: number
|
||||
max?: number
|
||||
step?: number
|
||||
maxlength?: number | string
|
||||
inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url'
|
||||
autocomplete?: string
|
||||
dir?: string
|
||||
align?: 'start' | 'center' | 'end'
|
||||
}>(),
|
||||
{
|
||||
align: 'start',
|
||||
},
|
||||
)
|
||||
|
||||
defineEmits<{
|
||||
'update:modelValue': [value: string]
|
||||
blur: [event: FocusEvent]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
@@ -22,7 +33,7 @@ defineEmits<{
|
||||
<label v-if="label" class="form-label">{{ label }}</label>
|
||||
<input
|
||||
class="input"
|
||||
:class="{ 'input-error': error }"
|
||||
:class="[`input--align-${align}`, { 'input-error': error }]"
|
||||
:type="type ?? 'text'"
|
||||
:value="modelValue"
|
||||
:placeholder="placeholder"
|
||||
@@ -30,7 +41,12 @@ defineEmits<{
|
||||
:min="min"
|
||||
:max="max"
|
||||
:step="step"
|
||||
:maxlength="maxlength"
|
||||
:inputmode="inputmode"
|
||||
:autocomplete="autocomplete"
|
||||
:dir="dir"
|
||||
@input="$emit('update:modelValue', ($event.target as HTMLInputElement).value)"
|
||||
@blur="$emit('blur', $event)"
|
||||
/>
|
||||
<p v-if="error" class="input-error-text">{{ error }}</p>
|
||||
<p v-else-if="hint" class="form-hint">{{ hint }}</p>
|
||||
@@ -50,6 +66,19 @@ defineEmits<{
|
||||
transition: border-color 0.15s;
|
||||
}
|
||||
|
||||
.input--align-start {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.input--align-center {
|
||||
text-align: center;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.input--align-end {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
|
||||
@@ -1,20 +1,64 @@
|
||||
<script setup lang="ts">
|
||||
import IconClipboardEmpty from '@/components/icons/IconClipboardEmpty.vue'
|
||||
import { computed } from 'vue'
|
||||
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||
|
||||
defineProps<{
|
||||
message?: string
|
||||
}>()
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
message?: string
|
||||
title?: string
|
||||
/** Context for default icon + copy */
|
||||
variant?: 'default' | 'products' | 'catalogs' | 'orders' | 'cart' | 'checks' | 'search'
|
||||
icon?: string
|
||||
iconSize?: number
|
||||
}>(),
|
||||
{
|
||||
message: undefined,
|
||||
title: undefined,
|
||||
variant: 'default',
|
||||
icon: undefined,
|
||||
iconSize: 72,
|
||||
},
|
||||
)
|
||||
|
||||
const variantIcons: Record<string, string> = {
|
||||
default: 'vuesax-linear:clipboard-close',
|
||||
products: 'vuesax-linear:box-remove',
|
||||
catalogs: 'vuesax-linear:category',
|
||||
orders: 'vuesax-linear:document-text',
|
||||
cart: 'vuesax-linear:bag-cross',
|
||||
checks: 'vuesax-linear:card-receive',
|
||||
search: 'vuesax-linear:search-status',
|
||||
}
|
||||
|
||||
const variantTitles: Record<string, string> = {
|
||||
default: '',
|
||||
products: 'محصولی یافت نشد',
|
||||
catalogs: 'کالیتهای یافت نشد',
|
||||
orders: 'سفارشی یافت نشد',
|
||||
cart: 'سبد خرید خالی است',
|
||||
checks: 'چکی ثبت نشده است',
|
||||
search: 'نتیجهای یافت نشد',
|
||||
}
|
||||
|
||||
const resolvedIcon = computed(
|
||||
() => props.icon ?? variantIcons[props.variant] ?? 'vuesax-linear:clipboard-close',
|
||||
)
|
||||
const resolvedTitle = computed(() => props.title ?? variantTitles[props.variant] ?? '')
|
||||
const resolvedMessage = computed(() => props.message ?? '')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="empty-state">
|
||||
<div class="empty-state__icon">
|
||||
<div class="empty-state__icon" aria-hidden="true">
|
||||
<slot name="icon">
|
||||
<IconClipboardEmpty :size="72" />
|
||||
<BasicIcon :icon="resolvedIcon" :size="iconSize" :stroke-width="1.25" />
|
||||
</slot>
|
||||
</div>
|
||||
<p class="empty-state__message">
|
||||
<slot name="message">{{ message }}</slot>
|
||||
<h2 v-if="resolvedTitle || $slots.title" class="empty-state__title">
|
||||
<slot name="title">{{ resolvedTitle }}</slot>
|
||||
</h2>
|
||||
<p v-if="resolvedMessage || $slots.message" class="empty-state__message">
|
||||
<slot name="message">{{ resolvedMessage }}</slot>
|
||||
</p>
|
||||
<div v-if="$slots.default" class="empty-state__action">
|
||||
<slot />
|
||||
@@ -29,20 +73,36 @@ defineProps<{
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 48px 24px;
|
||||
min-height: 320px;
|
||||
min-height: 280px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-state__icon {
|
||||
margin-bottom: 16px;
|
||||
color: var(--color-text-muted);
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.empty-state__title {
|
||||
margin: 0 0 8px;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-text);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.empty-state__message {
|
||||
margin: 0 0 24px;
|
||||
font-size: 0.9375rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-muted);
|
||||
line-height: 1.5;
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
.empty-state__message:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.empty-state__action {
|
||||
|
||||
@@ -50,10 +50,10 @@ defineEmits<{
|
||||
flex-shrink: 0;
|
||||
height: 36px;
|
||||
padding: 0 18px;
|
||||
border: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 999px;
|
||||
background: #f5f5f5;
|
||||
color: #64748b;
|
||||
background: var(--color-tab-inactive-bg);
|
||||
color: var(--color-tab-inactive-text);
|
||||
font-family: inherit;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
@@ -61,7 +61,8 @@ defineEmits<{
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background 0.15s,
|
||||
color 0.15s;
|
||||
color 0.15s,
|
||||
border-color 0.15s;
|
||||
}
|
||||
|
||||
.filter-tabs--equal .filter-tab {
|
||||
@@ -76,6 +77,7 @@ defineEmits<{
|
||||
|
||||
.filter-tab.active {
|
||||
background: var(--color-primary);
|
||||
border-color: var(--color-primary);
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -85,6 +87,7 @@ defineEmits<{
|
||||
}
|
||||
|
||||
.filter-tab:not(.active):hover {
|
||||
background: #eceff1;
|
||||
border-color: var(--color-border);
|
||||
color: var(--color-text);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -269,7 +269,7 @@ onBeforeUnmount(() => {
|
||||
height: 32px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: #fff;
|
||||
background: var(--color-elevated);
|
||||
color: var(--color-text);
|
||||
cursor: pointer;
|
||||
font-size: 1.125rem;
|
||||
|
||||
@@ -37,7 +37,7 @@ defineEmits<{
|
||||
}
|
||||
|
||||
.search-field__input::placeholder {
|
||||
color: #94a3b8;
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
.search-field__input:focus {
|
||||
|
||||
Reference in New Issue
Block a user