card.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import * as React from 'react';
  2. import { cn } from '@/lib/utils';
  3. function Card({
  4. className,
  5. size = 'default',
  6. ...props
  7. }: React.ComponentProps<'div'> & { size?: 'default' | 'sm' }) {
  8. return (
  9. <div
  10. data-slot="card"
  11. data-size={size}
  12. className={cn(
  13. 'group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl',
  14. className,
  15. )}
  16. {...props}
  17. />
  18. );
  19. }
  20. function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
  21. return (
  22. <div
  23. data-slot="card-header"
  24. className={cn(
  25. 'group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)',
  26. className,
  27. )}
  28. {...props}
  29. />
  30. );
  31. }
  32. function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
  33. return (
  34. <div
  35. data-slot="card-title"
  36. className={cn(
  37. 'font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm',
  38. className,
  39. )}
  40. {...props}
  41. />
  42. );
  43. }
  44. function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
  45. return (
  46. <div
  47. data-slot="card-description"
  48. className={cn('text-sm text-muted-foreground', className)}
  49. {...props}
  50. />
  51. );
  52. }
  53. function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
  54. return (
  55. <div
  56. data-slot="card-action"
  57. className={cn(
  58. 'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
  59. className,
  60. )}
  61. {...props}
  62. />
  63. );
  64. }
  65. function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
  66. return (
  67. <div
  68. data-slot="card-content"
  69. className={cn('px-(--card-spacing)', className)}
  70. {...props}
  71. />
  72. );
  73. }
  74. function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
  75. return (
  76. <div
  77. data-slot="card-footer"
  78. className={cn(
  79. 'flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)',
  80. className,
  81. )}
  82. {...props}
  83. />
  84. );
  85. }
  86. export {
  87. Card,
  88. CardHeader,
  89. CardFooter,
  90. CardTitle,
  91. CardAction,
  92. CardDescription,
  93. CardContent,
  94. };