feat(ui): install shadcn Badge; use for accommodation status pills
Add the Badge primitive at src/components/ui/badge with the standard default / secondary / destructive / outline variants. Replace the two hand-rolled status pill patterns in AccommodationView (rooms + cabins) with <Badge>: - Room "Open" pill → variant="default" (filled gold on green) - Room/Cabin "Coming soon" pill → variant="outline" (border + muted) Keeps the small-caps tracking and 10px size via class overrides so the visual rhythm against the room/cabin Card titles is preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4cb0fa14a2
commit
d56664abf9
3 changed files with 52 additions and 11 deletions
17
src/components/ui/badge/Badge.vue
Normal file
17
src/components/ui/badge/Badge.vue
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from "vue"
|
||||||
|
import type { BadgeVariants } from "."
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { badgeVariants } from "."
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
variant?: BadgeVariants["variant"]
|
||||||
|
class?: HTMLAttributes["class"]
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :class="cn(badgeVariants({ variant }), props.class)">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
26
src/components/ui/badge/index.ts
Normal file
26
src/components/ui/badge/index.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import type { VariantProps } from "class-variance-authority"
|
||||||
|
import { cva } from "class-variance-authority"
|
||||||
|
|
||||||
|
export { default as Badge } from "./Badge.vue"
|
||||||
|
|
||||||
|
export const badgeVariants = cva(
|
||||||
|
"inline-flex gap-1 items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default:
|
||||||
|
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
||||||
|
secondary:
|
||||||
|
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||||
|
destructive:
|
||||||
|
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
||||||
|
outline: "text-foreground",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
export type BadgeVariants = VariantProps<typeof badgeVariants>
|
||||||
|
|
@ -3,6 +3,7 @@ import { useI18n } from 'vue-i18n'
|
||||||
import { RouterLink } from 'vue-router'
|
import { RouterLink } from 'vue-router'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Card, CardContent } from '@/components/ui/card'
|
import { Card, CardContent } from '@/components/ui/card'
|
||||||
|
import { Badge } from '@/components/ui/badge'
|
||||||
|
|
||||||
const { t, tm, rt } = useI18n()
|
const { t, tm, rt } = useI18n()
|
||||||
|
|
||||||
|
|
@ -96,20 +97,16 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
|
||||||
<h3 class="font-serif text-xl font-semibold">
|
<h3 class="font-serif text-xl font-semibold">
|
||||||
{{ t(`accommodation.rooms.${room.key}.name`) }}
|
{{ t(`accommodation.rooms.${room.key}.name`) }}
|
||||||
</h3>
|
</h3>
|
||||||
<span
|
<Badge
|
||||||
class="rounded-full px-2 py-0.5 text-[10px] uppercase tracking-wider"
|
:variant="room.open ? 'default' : 'outline'"
|
||||||
:class="
|
class="text-[10px] uppercase tracking-wider"
|
||||||
room.open
|
|
||||||
? 'bg-primary/10 text-primary'
|
|
||||||
: 'border border-border text-muted-foreground'
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
room.open
|
room.open
|
||||||
? t('accommodation.statusOpen')
|
? t('accommodation.statusOpen')
|
||||||
: t('accommodation.statusComingSoon')
|
: t('accommodation.statusComingSoon')
|
||||||
}}
|
}}
|
||||||
</span>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-3 text-sm leading-relaxed text-foreground/85">
|
<p class="mt-3 text-sm leading-relaxed text-foreground/85">
|
||||||
{{ t(`accommodation.rooms.${room.key}.summary`) }}
|
{{ t(`accommodation.rooms.${room.key}.summary`) }}
|
||||||
|
|
@ -142,11 +139,12 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
|
||||||
<h3 class="font-serif text-xl font-semibold">
|
<h3 class="font-serif text-xl font-semibold">
|
||||||
{{ t(`accommodation.cabins.${cabin.key}`) }}
|
{{ t(`accommodation.cabins.${cabin.key}`) }}
|
||||||
</h3>
|
</h3>
|
||||||
<span
|
<Badge
|
||||||
class="rounded-full border border-border px-2 py-0.5 text-[10px] uppercase tracking-wider text-muted-foreground"
|
variant="outline"
|
||||||
|
class="text-[10px] uppercase tracking-wider text-muted-foreground"
|
||||||
>
|
>
|
||||||
{{ t('accommodation.statusComingSoon') }}
|
{{ t('accommodation.statusComingSoon') }}
|
||||||
</span>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue