card
Expandable billing usage card
Expandable billing usage card
Загрузка превью…
src/card/c-card-13.vue
<!--
Расхождение с апстримом: `IconPlaceholder` заменена инлайновым `<svg>`
(lucide-react v0.545.0 "chevron-down") — см. docs/PORTING.md §5.
-->
<script setup lang="ts">
import { ref } from "vue"
import { Button } from "@/components/ui/button"
import { Card, CardAction, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Progress } from "@/components/ui/progress"
import { cn } from "@/lib/utils"
const isOpen = ref(false)
</script>
<template>
<Card class="relative w-full max-w-md gap-6 overflow-visible pb-1">
<CardHeader class="flex items-center justify-between">
<CardTitle>3 days remaining in cycle</CardTitle>
<CardAction>
<Button variant="outline" size="sm">
Billing
</Button>
</CardAction>
</CardHeader>
<CardContent
:class="cn(
'relative space-y-5 overflow-hidden transition-all duration-500 ease-in-out',
isOpen ? 'max-h-[500px]' : 'max-h-48'
)"
>
<!-- Usage Details -->
<div class="bg-muted/60 rounded-lg space-y-3 p-4">
<div class="text-muted-foreground flex justify-between text-xs font-medium">
<span>Included Credit</span>
<span>On-Demand Charges</span>
</div>
<div class="flex justify-between text-lg font-bold">
<span>$18.08 / $20</span>
<span>$0</span>
</div>
<Progress :model-value="90" class="h-2" />
</div>
<!-- Additional Usage Details -->
<div class="flex flex-col gap-4">
<div class="flex justify-between text-sm">
<span class="text-foreground font-medium">Requests</span>
<span class="text-muted-foreground">$210.84</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-foreground font-medium">Active CPU</span>
<span class="text-muted-foreground">$21.95</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-foreground font-medium">Events</span>
<span class="text-muted-foreground">$21.20</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-foreground font-medium">Storage Usage</span>
<span class="text-muted-foreground">$20.45</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-foreground font-medium">Bandwidth</span>
<span class="text-muted-foreground">$0.00</span>
</div>
</div>
<!-- Faded background effect for collapsed state -->
<div
:class="cn(
'from-background pointer-events-none absolute inset-x-0 bottom-0 h-20 rounded-b-lg bg-linear-to-t to-transparent transition-opacity duration-300',
isOpen ? 'opacity-0' : 'opacity-100'
)"
/>
</CardContent>
<!-- Toggle button -->
<div class="absolute -bottom-4 left-1/2 -translate-x-1/2">
<Button
variant="outline"
size="icon-sm"
class="bg-background hover:bg-background rounded-full shadow-sm"
@click="isOpen = !isOpen"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
:class="cn('lucide lucide-chevron-down transition-transform duration-300', isOpen && 'rotate-180')"
><path d="m6 9 6 6 6-6" /></svg>
<span class="sr-only">Toggle card</span>
</Button>
</div>
</Card>
</template>