DesignX
Trading@paxeer/trading/positions-tableimplemented

Positions table

Open positions table with P&L badges.

Install

$pnpm exec designx add @paxeer/trading/positions-table

Preview

Loading preview...

Source code

components/designx/trading/positions-table.tsxtsx
import {
  Badge,
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  Empty,
  EmptyDescription,
  EmptyHeader,
  EmptyTitle,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@paxeer/core";

export interface PositionRow {
  id: string;
  symbol: string;
  qty: number;
  avg: number;
  last: number;
}

export function PositionsTable({
  rows = [
    { id: "eth", symbol: "ETH-USD", qty: 12.4, avg: 2410.2, last: 2480.4 },
    { id: "sol", symbol: "SOL-USD", qty: 80, avg: 142.1, last: 138.6 },
  ],
}: {
  rows?: PositionRow[];
}) {
  return (
    <Card className="gap-0 py-0 overflow-hidden" data-slot="positions-table">
      <CardHeader className="border-b border-outline-variant px-3 py-2">
        <CardTitle className="text-[length:var(--md-sys-typescale-label-large-size)]">
          Positions
        </CardTitle>
      </CardHeader>
      <CardContent className="p-0">
        {rows.length === 0 ? (
          <Empty className="p-6">
            <EmptyHeader>
              <EmptyTitle>No open positions</EmptyTitle>
              <EmptyDescription>Fills will land here after a ticket submits.</EmptyDescription>
            </EmptyHeader>
          </Empty>
        ) : (
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Symbol</TableHead>
                <TableHead>Qty</TableHead>
                <TableHead>Avg</TableHead>
                <TableHead>Last</TableHead>
                <TableHead>P&L</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {rows.map((row) => {
                const pnl = (row.last - row.avg) * row.qty;
                const up = pnl >= 0;
                return (
                  <TableRow key={row.id}>
                    <TableCell className="font-[family-name:var(--md-ref-typeface-mono)]">
                      {row.symbol}
                    </TableCell>
                    <TableCell>{row.qty}</TableCell>
                    <TableCell>{row.avg.toFixed(2)}</TableCell>
                    <TableCell>{row.last.toFixed(2)}</TableCell>
                    <TableCell>
                      <Badge variant={up ? "default" : "destructive"}>
                        {up ? "+" : ""}
                        {pnl.toFixed(2)}
                      </Badge>
                    </TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        )}
      </CardContent>
    </Card>
  );
}