table

Leaderboard table with rank, score, and level badges

Leaderboard table with rank, score, and level badges

Загрузка превью…

src/table/c-table-15.vue

<!--
  Расхождение с апстримом: `IconPlaceholder` заменена инлайновым `<svg>`
  (lucide-react v0.545.0 "trending-up", "trending-down") и unsplash-аватары
  заменены локальным 1x1 data-URI (`PIXEL`) — см. docs/PORTING.md §5.
-->
<script setup lang="ts">
import { Badge } from "@/components/reui/badge"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"

const PIXEL = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAUwAOw=="

const leaders = [
  { rank: 1, name: "Sarah Chen", handle: "@sarahchen", avatar: PIXEL, score: 12840, change: "+320", changeUp: true, level: "Diamond", levelVariant: "info" as const },
  { rank: 2, name: "Marcus Johnson", handle: "@marcusj", avatar: PIXEL, score: 11250, change: "+180", changeUp: true, level: "Platinum", levelVariant: "default" as const },
  { rank: 3, name: "Emily Park", handle: "@emilyp", avatar: PIXEL, score: 10890, change: "-45", changeUp: false, level: "Platinum", levelVariant: "default" as const },
  { rank: 4, name: "David Kim", handle: "@davidk", avatar: PIXEL, score: 9420, change: "+520", changeUp: true, level: "Gold", levelVariant: "warning" as const },
  { rank: 5, name: "Sofia Davis", handle: "@sofiad", avatar: PIXEL, score: 8750, change: "+90", changeUp: true, level: "Gold", levelVariant: "warning" as const },
]

function initials(name: string) {
  return name.split(" ").map((n) => n[0]).join("")
}
</script>

<template>
  <div class="mx-auto flex w-full max-w-2xl flex-col">
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead class="w-12 text-center">#</TableHead>
          <TableHead>Player</TableHead>
          <TableHead>Level</TableHead>
          <TableHead class="text-right">Score</TableHead>
          <TableHead class="text-right">Change</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        <TableRow v-for="leader in leaders" :key="leader.rank">
          <TableCell class="text-center text-sm font-bold">{{ leader.rank }}</TableCell>
          <TableCell>
            <div class="flex items-center gap-3">
              <Avatar size="sm">
                <AvatarImage :src="leader.avatar" :alt="leader.name" />
                <AvatarFallback>{{ initials(leader.name) }}</AvatarFallback>
              </Avatar>
              <div class="flex flex-col">
                <span class="text-sm font-medium">{{ leader.name }}</span>
                <span class="text-muted-foreground text-xs">{{ leader.handle }}</span>
              </div>
            </div>
          </TableCell>
          <TableCell>
            <Badge :variant="leader.levelVariant" size="sm">{{ leader.level }}</Badge>
          </TableCell>
          <TableCell class="text-right font-mono text-sm font-medium">{{ leader.score.toLocaleString() }}</TableCell>
          <TableCell class="text-right">
            <span class="inline-flex items-center gap-0.5 text-sm">
              <svg v-if="leader.changeUp" 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="lucide lucide-trending-up text-success size-3.5">
                <path d="M16 7h6v6" />
                <path d="m22 7-8.5 8.5-5-5L2 17" />
              </svg>
              <svg v-else 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="lucide lucide-trending-down text-destructive size-3.5">
                <path d="M16 17h6v-6" />
                <path d="m22 17-8.5-8.5-5 5L2 7" />
              </svg>
              <span :class="leader.changeUp ? 'text-success' : 'text-destructive'">{{ leader.change }}</span>
            </span>
          </TableCell>
        </TableRow>
      </TableBody>
    </Table>
  </div>
</template>

Установка

npx shadcn-vue@latest add https://revueui.rootapi.dev/r/c-table-15.json

Зависимости реестра

Источник: порт из ReUI (Keenthemes, MIT)