start frant 050228
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="mx-auto flex min-h-dvh w-full max-w-[768px] flex-col bg-surface shadow-xl shadow-black/5 dark:shadow-black/30"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<button
|
||||
:type="type"
|
||||
class="inline-flex w-full items-center justify-center rounded-xl px-4 py-3 text-sm font-semibold transition disabled:cursor-not-allowed disabled:opacity-50"
|
||||
:class="variantClass"
|
||||
:disabled="disabled || loading"
|
||||
>
|
||||
<slot />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
variant?: 'primary' | 'ghost' | 'danger';
|
||||
type?: 'button' | 'submit';
|
||||
disabled?: boolean;
|
||||
loading?: boolean;
|
||||
}>(),
|
||||
{ variant: 'primary', type: 'button', disabled: false, loading: false },
|
||||
);
|
||||
|
||||
const variantClass = computed(() => {
|
||||
switch (props.variant) {
|
||||
case 'ghost':
|
||||
return 'bg-transparent text-muted hover:bg-surface-3 hover:text-text';
|
||||
case 'danger':
|
||||
return 'bg-red-500/15 text-red-600 dark:text-red-400 hover:bg-red-500/25';
|
||||
default:
|
||||
return 'bg-brand-600 text-white hover:bg-brand-700';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div class="space-y-1.5">
|
||||
<label v-if="label" :for="id" class="block text-sm font-medium text-muted">
|
||||
{{ label }}
|
||||
</label>
|
||||
<input
|
||||
:id="id"
|
||||
class="w-full rounded-xl border border-border bg-surface-2 px-4 py-3 text-text outline-none transition placeholder:text-muted focus:border-brand-500 focus:ring-2 focus:ring-brand-500/30"
|
||||
:class="ltr ? 'text-left' : ''"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ inheritAttrs: false });
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
label?: string;
|
||||
id?: string;
|
||||
ltr?: boolean;
|
||||
}>(),
|
||||
{ ltr: false },
|
||||
);
|
||||
</script>
|
||||
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex h-10 w-10 items-center justify-center rounded-xl border border-border bg-surface-2 text-muted transition hover:text-text"
|
||||
:aria-label="isDark ? 'حالت روشن' : 'حالت تاریک'"
|
||||
@click="toggle"
|
||||
>
|
||||
<span v-if="isDark" aria-hidden="true">☀️</span>
|
||||
<span v-else aria-hidden="true">🌙</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { useTheme } from '@/composables/useTheme';
|
||||
|
||||
const { isDark: mode, toggle } = useTheme();
|
||||
const isDark = computed(() => mode.value === 'dark');
|
||||
</script>
|
||||
Reference in New Issue
Block a user