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:
Padreug 2026-06-09 17:02:57 +02:00
commit d56664abf9
3 changed files with 52 additions and 11 deletions

View 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>

View 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>

View file

@ -3,6 +3,7 @@ import { useI18n } from 'vue-i18n'
import { RouterLink } from 'vue-router'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
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">
{{ t(`accommodation.rooms.${room.key}.name`) }}
</h3>
<span
class="rounded-full px-2 py-0.5 text-[10px] uppercase tracking-wider"
:class="
room.open
? 'bg-primary/10 text-primary'
: 'border border-border text-muted-foreground'
"
<Badge
:variant="room.open ? 'default' : 'outline'"
class="text-[10px] uppercase tracking-wider"
>
{{
room.open
? t('accommodation.statusOpen')
: t('accommodation.statusComingSoon')
}}
</span>
</Badge>
</div>
<p class="mt-3 text-sm leading-relaxed text-foreground/85">
{{ 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">
{{ t(`accommodation.cabins.${cabin.key}`) }}
</h3>
<span
class="rounded-full border border-border px-2 py-0.5 text-[10px] uppercase tracking-wider text-muted-foreground"
<Badge
variant="outline"
class="text-[10px] uppercase tracking-wider text-muted-foreground"
>
{{ t('accommodation.statusComingSoon') }}
</span>
</Badge>
</div>
</Card>
</li>