Skip to content

Kirby 4.5.0

Panel dropdowns

Our action dropdowns for pages, files and users are all loaded on request. This way, we can load and evaluate permissions individually from the API and then disable items in the dropdowns that should not be accessible.

As part of your Panel area extension, you can also define custom dropdowns easily on the backend and use them in your Panel frontend code with a simple single call.

<k-dropdown>
    <k-button @click="$refs.options.toggle()">Options</k-button>
    <k-dropdown-content :options="$dropdown('pages/projects+project-a')">
</k-dropdown>

The backend code for this is very straightforward as well and is defined as part of our areas

Site area
return [
    'label' => 'Site',
    ...
    'dialogs' => ...
    'views' => ...
    'dropdowns' => [
        'pages/(:any)' => function (string $id) {
            $page = Find::page($id);

            return [
                [
                    'text' => 'Open',
                    'icon' => 'preview',
                    'link' => $page->previewUrl(),
                ],
                ...
                [
                    'text'   => 'Delete',
                    'icon'   => 'trash',
                    'dialog' => 'pages/' . $id . '/delete'
                ]
            ];
        }
    ]
];

Option settings

The dropdown definition returns an array of dropdown options. Each option can define a set of parameters to control how the option is displayed and what happens on click.

Parameter Type Description
click string The name of the event that will be triggered on click
dialog string|array Either a single path to a dialog or dialog settings
disabled bool Enable/disable the item
icon string The name of the option icon
link string An optional url/path to create a link instead of a button
target string A link target (i.e. _blank)
text string The label for the option

Custom dropdowns

Of course, you can create your own dropdowns for your plugins as part of your Panel area extension:

Kirby::plugin('your-plugin/todos', [
    'areas' => [
        'todos' => function ($kirby) {
            return [
                ...
                'dropdowns' => [
                    'todos/(:any)' => function (string $id) {
                        // find the $todo here. (i.e. from a database)
                        return [
                            [
                                'text'   => 'Edit',
                                'dialog' => 'todos/' . $id . '/edit',
                                'icon'   => 'edit'
                            ],
                            [
                                'text'   => 'Duplicate',
                                'dialog' => 'todos/' . $id . '/duplicate',
                                'icon'   => 'copy'
                            ],
                            [
                                'text'   => 'Delete',
                                'dialog' => 'todos/' . $id . '/delete',
                                'icon'   => 'trash'
                            ]
                        ];
                    }
                ]
            ];
        }
    ]
]);

Your dropdown options can then be loaded in your Vue code like this:

<k-dropdown>
    <k-button icon="cog" @click="$refs.options.toggle()">Options</k-button>
    <k-dropdown-content ref="options" :options="$dropdown('todos/the-todo-id')" />
</k-dropdown>

Extending dropdowns

Pages, files and users have dynamic option dropdowns. Those dropdowns show all the available options like changing titles, sorting pages, deleting stuff, etc.

Those dropdowns can be extended or modified to add additional options, remove options or simply change what's normally shown.

<?php

Kirby::plugin('example/dropdown', [
  'areas' => [
    'site' => function ($kirby) {
      return [
        'dropdowns' => [
          'page' => function (string $id) {

            // find the right page for the dropdown
            $page = Find::page($id);

            // load the core dropdown definition
            $dropdown = $page->panel()->dropdown();

            // append a separator
            $dropdown[] = '-';

            // append a new option
            $dropdown[] = [
              'icon'   => 'share',
              'text'   => 'Publish on Netlify',
              'dialog' => 'publish'
            ];

            return $dropdown;
          }
        ]
      ];
    },
  ]
]);
Since 4.3.0

Listen for dropdown event

When you need to react to your added dropdown entry, there is no direct way that you could listen for the event on the Vue dropdown component, since you don't have access to it. Instead, you can pass the click handler in the following way:

$dropdown[] = [
    'icon'  => 'share',
    'text'  => 'Publish on Netlify',
    'click' => [
        'global'  => 'myEvent',
        'payload' => [...]
    ]
];

With this you can listen for your event globally:

this.$events.on("myEvent", (payload) => {...});

Reusing core code

When you plan to extend a dropdown, you might want to fall back to Kirby's core behaviour in some cases. This can be done by loading the core code:

<?php

Kirby::plugin('example/dropdown', [
  'areas' => [
    'site' => function ($kirby) {
      return [
        'dropdowns' => [
          'page' => function (string $id) use ($kirby) {

            // find the right page for the dropdown
            $page = Find::page($id);

            if ($page->id() === 'blog') {
                // return a custom dropdown
            }

            return $kirby->core()->area('site')['dropdowns']['page']['options']($id);
          }
        ]
      ];
    },
  ]
]);

The core models (page, user and file) all have a separate $model->panel()->dropdown() method for their own dropdown. While the code above is the correct way to load core code for any part of an area, you can simplify this for dropdowns by reusing the dropdown method.

<?php

Kirby::plugin('example/dropdown', [
  'areas' => [
    'site' => function ($kirby) {
      return [
        'dropdowns' => [
          'page' => function (string $id) {
            // find the right page for the dropdown
            $page = Find::page($id);

            if ($page->id() === 'blog') {
                // return a custom dropdown
            }

            return $page->panel()->dropdown();
          }
        ]
      ];
    },
  ]
]);

Core dropdowns

Area Dropdown name
site page
site page.file
site site.file
users user
users user.file