Search code examples
cssreactjsnext.jstailwind-cssshadcnui

How do I position a button that's being mapped and needs to be on the opposite side of the data in tailwind?


I know there has to be a simple answer to this question, but I can't find it for some reason.

So here's the deal, I need to I have some data on the left side of the post card component and a button right next to it. Here's a picture:

post card

So the ellipsis is the button, and I want to position the button on the right side, but if I do 'absolute' then I have all the buttons fixed in that position even if I'm scrolling.

Here's my code for the two components:

import * as React from 'react';

import { Button } from '@/components/ui/button';
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from '@/components/ui/card';

import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Ellipsis } from 'lucide-react';
import { PostDialog } from './PostDialog';

interface Props {
  user_id?: string;
  avatar_url: string;
  first_name: string;
  last_name: string;
  connections?: number;
  timestamp?: Date;
  content?: string;
  liked?: boolean;
  comments?: any;
}

export default async function Post({
  user_id,
  avatar_url,
  first_name,
  last_name,
  connections,
  timestamp,
  content,
}: Props) {
  const date = new Date(timestamp!);

  const formattedDate = date.toLocaleString('en-US', {
    month: 'short',
    day: 'numeric',
    hour12: true,
  });

  const formattedConnects = Intl.NumberFormat('en-US', {
    notation: 'compact',
    maximumFractionDigits: 1,
  }).format(connections!);
  return (
    <Card>
      <CardHeader>
        <CardDescription className="flex w-full flex-row items-center">
          <Avatar className="mr-2">
            <AvatarImage src={avatar_url} />
            <AvatarFallback>NX</AvatarFallback>
          </Avatar>
          {`${first_name} ${last_name} · ${formattedConnects} · ${formattedDate}`}
            <PostDialog /> // This is the ellipsis button
        </CardDescription>
      </CardHeader>
      <CardContent>
        <p>{content}</p>
      </CardContent>
      <CardFooter className="border-t pt-5">
        <p>Card Footer</p>
      </CardFooter>
    </Card>
  );
}

Now here's the button itself:

'use client';

import * as React from 'react';
import { Ellipsis, Moon, Sun } from 'lucide-react';
import { useTheme } from 'next-themes';

import { Button } from '@/components/ui/button';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { deletePost } from '@/lib/actions/post.actions';

export function PostDialog() {
  async function handleDeletePost() {
    // return await deletePost(id);
  }

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="ghost" size="sm">
          <Ellipsis />
          <span className="sr-only">Options</span>
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        <DropdownMenuItem onClick={() => console.log('reported')}>
          <span>Report</span>
        </DropdownMenuItem>
        <DropdownMenuItem className="text-rose-500 focus:text-rose-500">
          <span className="">Delete</span>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

Thank you for taking your time to read this!


Solution

  • You have in the parent element CardDescription class flex

    so, you can just add <div className="flex-1"></div> between them

            <CardDescription className="flex w-full flex-row items-center">
              <Avatar className="mr-2">
                <AvatarImage src={avatar_url} />
                <AvatarFallback>NX</AvatarFallback>
              </Avatar>
              {`${first_name} ${last_name} · ${formattedConnects} · ${formattedDate}`}
    
              <div className="flex-1"></div> // add this
    
                <PostDialog /> // This is the ellipsis button
            </CardDescription>