# Project DoList: Drop-Down Actions

In this article we will add the drop-down menus for tasks and projects that contain the "Edit" and "Delete" controls. We'll be utilizing AlpineJS to handle the visibility of each menu.

## Task Drop-Down Menu

Let's start by changing the markup for each task item. In the file `app/views/users/projects/_tasks.html.erb` replace the "Edit / Delete" code with the following:

```erb
<div x-data="{ open: false }" class="h-5 flex items-center relative hover:bg-zinc-700 rounded">
  <%= heroicon 'ellipsis-horizontal',
      options: {
        class: 'h-8 w-8 text-slate-100 cursor-pointer',
        '@click' => 'open = true',
        '@click.outside' => 'open = false'
      }
  %>

  <div x-show="open" x-cloak class="absolute top-6 right-0 min-w-[200px] z-10 rounded-xl border border-zinc-600 bg-zinc-800">
    <div class="divide-y divide-zinc-700">
      <div class="px-1.5 py-1.5">
        <%= link_to edit_users_project_task_path(@project, task), class: 'flex gap-2 items-center text-[13px] py-2 px-3 hover:bg-zinc-700 rounded' do %>
          <%= heroicon 'pencil-square', options: { class: 'h-5 w-5 text-slate-100' } %>
          <span>Edit</span>
        <% end %>
      </div>

      <div class="px-1.5 py-1.5">
        <%= link_to users_project_task_path(@project, task), class: 'flex gap-2 items-center text-[13px] py-2 px-3 hover:bg-zinc-700 rounded', data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' } do %>
          <%= heroicon 'trash', options: { class: 'h-5 w-5 text-slate-100' } %>
          <span>Delete</span>
        <% end %>
      </div>
    </div>
  </div>
</div>
```

This bit of code relies on AlpineJS attributes to handle the showing and hiding of the action menu. Some notes:

* The `x-data="{ open: false }"` attribute sets up localized data scoped to the element and its children. This data can be read and changed by the children for different purposes.
    
* The `'@click' => 'open = true'` attribute assigns a click handler to the element that will set the data variable `open` to `true` when clicked.
    
* The `'@click.outside' => 'open = false'` attribute assigns a click handler to any element that is outside of the element (not itself or its children) that will set the data variable `open` to `false` when clicked.
    
* The `x-show="open"` attribute will only show the element when the data variable `open` is `true`.
    
* The `x-cloak` attribute initially hides the element using CSS to prevent the brief flicker of visibility that will occur before the JS is fully loaded on the page.
    

To make the `x-cloak` attribute work correctly we must add code to the file `app/assets/stylesheets/application.css`:

```css
[x-cloak] { display: none !important; }
```

The task drop-down menu should now look like this:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1722512649586/f444a3a7-c78b-4403-a57b-0d55ca206e4a.gif align="center")

## Project Drop-Down Menu

Next let's add the same drop-down functionality to the project list. Let's start by moving the project list from the layout template into its own partial so that we stay organized. Create the file `app/views/layouts/users/_projects.html.erb` and add the following code:

```erb
<% active_list = is_active_link?(users_projects_path, :exact) %>
<% active_list_classes = class_names(
  'bg-[#472525]' => active_list
) %>
<div class="flex justify-between items-center mb-1 rounded-lg <%= active_list_classes %>">
  <%= link_to 'My Projects', users_projects_path, class: 'grow p-2' %>

  <div class="mr-2">
    <%= link_to new_users_project_path, data: { turbo_frame: 'modal' } do %>
      <%= heroicon 'plus', options: { class: 'text-white w-4 h-4' } %>
    <% end %>
  </div>
</div>

<div data-sortable-projects>
  <% projects.each do |project| %>
    <% active_project = is_active_link?(users_project_path(project)) %>
    <% classes = class_names(
        'bg-[#472525] text-red-300' => active_project,
        'hover:bg-zinc-700/25' => !active_project
       )
    %>

    <div x-data="{ open: false }" class="group mb-1 relative flex justify-between items-center rounded-lg <%= classes %>" data-project-id="<%= project.id %>">
      <%= link_to project.name,
          users_project_path(project),
          class: 'block grow p-2'
      %>

      <div class="group-hover:hidden text-[12px] text-zinc-500 mr-3.5">
        <% tasks_count = project.active_tasks.count %>
        <%= tasks_count if tasks_count > 0 %>
      </div>

      <div class="group-hover:flex hidden h-5 items-center relative hover:bg-zinc-700 rounded mr-2 text-white">
        <%= heroicon 'ellipsis-horizontal',
            options: {
              class: 'h-6 w-6 text-zinc-100 cursor-pointer',
              '@click' => 'open = !open; $event.preventDefault();',
              '@click.outside' => 'open = false'
            }
        %>
      </div>

      <div x-show="open" x-cloak class="absolute top-10 right-0 min-w-[200px] z-10 rounded-xl border border-zinc-600 bg-zinc-800 text-zinc-300">
        <div class="divide-y divide-zinc-700">
          <div class="px-1.5 py-1.5">
            <%= link_to edit_users_project_path(project), class: 'flex gap-2 items-center text-[13px] py-2 px-3 hover:bg-zinc-700 rounded', data: { turbo_frame: 'modal' } do %>
              <%= heroicon 'pencil-square', options: { class: 'h-5 w-5 text-slate-100' } %>
              <span>Edit</span>
            <% end %>
          </div>

          <div class="px-1.5 py-1.5">
            <%= link_to users_project_path(project), class: 'flex gap-2 items-center text-[13px] py-2 px-3 hover:bg-zinc-700 rounded', data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' } do %>
              <%= heroicon 'trash', options: { class: 'h-5 w-5 text-slate-100' } %>
              <span>Delete</span>
            <% end %>
          </div>
        </div>
      </div>
    </div>
  <% end %>
</div>
```

This code contains the same functionality as the task drop-down menus: it uses AlpineJS attributes (`x-data`, `x-show`, `@click`) to toggle the visibility of the drop-down menu. This code also contains new styles to correctly match the project list that is found in the Todoist app.

Be sure to render the new partial in the `app/views/layouts/users.html.erb` file like so:

```erb
...
<div class="bg-zinc-800 text-white text-sm p-5 min-w-[300px]">
  <div class="mb-10">
    <div><%= current_user.email %></div>
    <div><%= link_to 'Logout', destroy_user_session_path, data: { turbo_prefetch: false } %></div>
  </div>

  <%= render 'layouts/users/projects', projects: @projects %>
</div>
...
```

After adding the above code the projects list should now look like so:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1722599248419/c0d1cfb5-f0d3-4f9c-8346-8f9674b5dbca.gif align="center")

## Summary

In this article we did the following:

* Moved "Edit" / "Delete" task actions to a drop-down menu
    
* Moved "Edit" / "Delete" project actions to a drop-down menu
    
* Added styles to the project list to match the look and feel of Todoist
