diff --git a/datasette/hookspecs.py b/datasette/hookspecs.py index dcd502af..7c56f882 100644 --- a/datasette/hookspecs.py +++ b/datasette/hookspecs.py @@ -159,32 +159,32 @@ def jump_items_sql(datasette, actor, request): @hookspec def row_actions(datasette, actor, request, database, table, row): - """Links for the row actions menu""" + """Items for the row actions menu""" @hookspec def table_actions(datasette, actor, database, table, request): - """Links for the table actions menu""" + """Items for the table actions menu""" @hookspec def view_actions(datasette, actor, database, view, request): - """Links for the view actions menu""" + """Items for the view actions menu""" @hookspec def query_actions(datasette, actor, database, query_name, request, sql, params): - """Links for the query and stored query actions menu""" + """Items for the query and stored query actions menu""" @hookspec def database_actions(datasette, actor, database, request): - """Links for the database actions menu""" + """Items for the database actions menu""" @hookspec def homepage_actions(datasette, actor, request): - """Links for the homepage actions menu""" + """Items for the homepage actions menu""" @hookspec diff --git a/datasette/static/app.css b/datasette/static/app.css index c053f484..5fe4502d 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -2061,18 +2061,32 @@ svg.dropdown-menu-icon { .dropdown-menu a:link, .dropdown-menu a:visited, .dropdown-menu a:hover, -.dropdown-menu a:focus -.dropdown-menu a:active { +.dropdown-menu a:focus, +.dropdown-menu a:active, +.dropdown-menu button.action-menu-button { text-decoration: none; display: block; padding: 4px 8px 2px 8px; color: #222; white-space: nowrap; } -.dropdown-menu a:hover { +.dropdown-menu button.action-menu-button { + appearance: none; + background: none; + border: none; + box-sizing: border-box; + cursor: pointer; + font: inherit; + text-align: left; + width: 100%; +} +.dropdown-menu a:hover, +.dropdown-menu button.action-menu-button:hover, +.dropdown-menu button.action-menu-button:focus { background-color: #eee; } .dropdown-menu .dropdown-description { + display: block; margin: 0; color: #666; font-size: 0.8em; diff --git a/datasette/templates/_action_menu.html b/datasette/templates/_action_menu.html index 1ae8c173..86089992 100644 --- a/datasette/templates/_action_menu.html +++ b/datasette/templates/_action_menu.html @@ -15,14 +15,22 @@
-{% endif %} \ No newline at end of file +{% endif %} diff --git a/docs/custom_templates.rst b/docs/custom_templates.rst index aa82a536..8851a841 100644 --- a/docs/custom_templates.rst +++ b/docs/custom_templates.rst @@ -288,6 +288,14 @@ element that wraps the HTML for that row. Datasette uses this attribute to find the element to remove after a delete, or replace after an edit. Any edit or delete controls should be rendered inside that same element. +The ``_action_menu.html`` template renders the action menus used by database, +table, query and row pages. Plugin-provided actions can be link dictionaries +with ``href`` and ``label`` keys, or button dictionaries using ``{"type": +"button", "label": "...", "attrs": {...}}`` for JavaScript-backed interactions. +Both shapes can include an optional ``description`` key. Custom +``_action_menu.html`` templates should preserve support for both link and button +action items. + .. _custom_pages: Custom pages diff --git a/docs/plugin_hooks.rst b/docs/plugin_hooks.rst index 7ae52a68..d2f87e27 100644 --- a/docs/plugin_hooks.rst +++ b/docs/plugin_hooks.rst @@ -1909,7 +1909,80 @@ Action hooks Action hooks can be used to add items to the action menus that appear at the top of different pages within Datasette. Unlike :ref:`menu_links() `, actions which are displayed on every page, actions should only be relevant to the page the user is currently viewing. -Each of these hooks should return return a list of ``{"href": "...", "label": "..."}`` menu items, with optional ``"description": "..."`` keys describing each action in more detail. +Each of these hooks should return a list of menu items, with optional ``"description": "..."`` keys describing each action in more detail. + +The most common action item is a link to another page: + +.. code-block:: python + + { + "href": datasette.urls.path("/-/custom-action"), + "label": "Custom action", + "description": "Run this action on a separate page.", + } + +Plugins can also return button actions for JavaScript-backed interactions: + +.. code-block:: python + + { + "type": "button", + "label": "Open custom dialog", + "description": "Show a dialog without leaving this page.", + "attrs": { + "aria-label": "Open custom dialog", + "data-plugin-action": "open-custom-dialog", + }, + } + +These are rendered as ``