Skip to content

Commit

Permalink
New .core CSS class for inputs and buttons
Browse files Browse the repository at this point in the history
* Initial .core input/button classes, refs #2415
* Docs for the new .core CSS class, refs #2415
* Applied .core class everywhere that needs it, closes #2415
  • Loading branch information
simonw authored Sep 3, 2024
1 parent 92c4d41 commit 2170269
Show file tree
Hide file tree
Showing 13 changed files with 46 additions and 23 deletions.
33 changes: 23 additions & 10 deletions datasette/static/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,11 @@ label.sort_by_desc {
pre#sql-query {
margin-bottom: 1em;
}
form input[type=text],
form input[type=search] {

.core input[type=text],
input.core[type=text],
.core input[type=search],
input.core[type=search] {
border: 1px solid #ccc;
border-radius: 3px;
width: 60%;
Expand All @@ -540,17 +543,25 @@ form input[type=search] {
}
/* Stop Webkit from styling search boxes in an inconsistent way */
/* https://css-tricks.com/webkit-html5-search-inputs/ comments */
input[type=search] {
.core input[type=search],
input.core[type=search] {
-webkit-appearance: textfield;
}
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-results-button,
input[type="search"]::-webkit-search-results-decoration {
.core input[type="search"]::-webkit-search-decoration,
input.core[type="search"]::-webkit-search-decoration,
.core input[type="search"]::-webkit-search-cancel-button,
input.core[type="search"]::-webkit-search-cancel-button,
.core input[type="search"]::-webkit-search-results-button,
input.core[type="search"]::-webkit-search-results-button,
.core input[type="search"]::-webkit-search-results-decoration,
input.core[type="search"]::-webkit-search-results-decoration {
display: none;
}

form input[type=submit], form button[type=button] {
.core input[type=submit],
.core button[type=button],
input.core[type=submit],
button.core[type=button] {
font-weight: 400;
cursor: pointer;
text-align: center;
Expand All @@ -563,14 +574,16 @@ form input[type=submit], form button[type=button] {
border-radius: .25rem;
}

form input[type=submit] {
.core input[type=submit],
input.core[type=submit] {
color: #fff;
background: linear-gradient(180deg, #007bff 0%, #4E79C7 100%);
border-color: #007bff;
-webkit-appearance: button;
}

form button[type=button] {
.core button[type=button],
button.core[type=button] {
color: #007bff;
background-color: #fff;
border-color: #007bff;
Expand Down
2 changes: 1 addition & 1 deletion datasette/templates/allow_debug.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h1>Debug allow rules</h1>

<p>Use this tool to try out different actor and allow combinations. See <a href="https://docs.datasette.io/en/stable/authentication.html#defining-permissions-with-allow-blocks">Defining permissions with "allow" blocks</a> for documentation.</p>

<form action="{{ urls.path('-/allow-debug') }}" method="get" style="margin-bottom: 1em">
<form class="core" action="{{ urls.path('-/allow-debug') }}" method="get" style="margin-bottom: 1em">
<div class="two-col">
<p><label>Allow block</label></p>
<textarea name="allow">{{ allow_input }}</textarea>
Expand Down
4 changes: 2 additions & 2 deletions datasette/templates/api_explorer.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ <h1>API Explorer{% if private %} 🔒{% endif %}</h1>
</p>
<details open style="border: 2px solid #ccc; border-bottom: none; padding: 0.5em">
<summary style="cursor: pointer;">GET</summary>
<form method="get" id="api-explorer-get" style="margin-top: 0.7em">
<form class="core" method="get" id="api-explorer-get" style="margin-top: 0.7em">
<div>
<label for="path">API path:</label>
<input type="text" id="path" name="path" style="width: 60%">
Expand All @@ -29,7 +29,7 @@ <h1>API Explorer{% if private %} 🔒{% endif %}</h1>
</details>
<details style="border: 2px solid #ccc; padding: 0.5em">
<summary style="cursor: pointer">POST</summary>
<form method="post" id="api-explorer-post" style="margin-top: 0.7em">
<form class="core" method="post" id="api-explorer-post" style="margin-top: 0.7em">
<div>
<label for="path">API path:</label>
<input type="text" id="path" name="path" style="width: 60%">
Expand Down
2 changes: 1 addition & 1 deletion datasette/templates/create_token.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ <h2>Create another token</h2>
{% endfor %}
{% endif %}

<form action="{{ urls.path('-/create-token') }}" method="post">
<form class="core" action="{{ urls.path('-/create-token') }}" method="post">
<div>
<div class="select-wrapper" style="width: unset">
<select name="expire_type">
Expand Down
2 changes: 1 addition & 1 deletion datasette/templates/database.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ <h1>{{ metadata.title or database }}{% if private %} 🔒{% endif %}</h1>
{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}

{% if allow_execute_sql %}
<form class="sql" action="{{ urls.database(database) }}/-/query" method="get">
<form class="sql core" action="{{ urls.database(database) }}/-/query" method="get">
<h3>Custom SQL query</h3>
<p><textarea id="sql-editor" name="sql">{% if tables %}select * from {{ tables[0].name|escape_sqlite }}{% else %}select sqlite_version(){% endif %}</textarea></p>
<p>
Expand Down
2 changes: 1 addition & 1 deletion datasette/templates/logout.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h1>Log out</h1>

<p>You are logged in as <strong>{{ display_actor(actor) }}</strong></p>

<form action="{{ urls.logout() }}" method="post">
<form class="core" action="{{ urls.logout() }}" method="post">
<div>
<input type="hidden" name="csrftoken" value="{{ csrftoken() }}">
<input type="submit" value="Log out">
Expand Down
2 changes: 1 addition & 1 deletion datasette/templates/messages_debug.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h1>Debug messages</h1>

<p>Set a message:</p>

<form action="{{ urls.path('-/messages') }}" method="post">
<form class="core" action="{{ urls.path('-/messages') }}" method="post">
<div>
<input type="text" name="message" style="width: 40%">
<div class="select-wrapper">
Expand Down
2 changes: 1 addition & 1 deletion datasette/templates/permissions_debug.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ <h1>Permission check testing tool</h1>

<p>This tool lets you simulate an actor and a permission check for that actor.</p>

<form action="{{ urls.path('-/permissions') }}" id="debug-post" method="post" style="margin-bottom: 1em">
<form class="core" action="{{ urls.path('-/permissions') }}" id="debug-post" method="post" style="margin-bottom: 1em">
<input type="hidden" name="csrftoken" value="{{ csrftoken() }}">
<div class="two-col">
<p><label>Actor</label></p>
Expand Down
2 changes: 1 addition & 1 deletion datasette/templates/query.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h1 style="padding-left: 10px; border-left: 10px solid #{{ database_color }}">{{

{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}

<form class="sql" action="{{ urls.database(database) }}{% if canned_query %}/{{ canned_query }}{% endif %}" method="{% if canned_query_write %}post{% else %}get{% endif %}">
<form class="sql core" action="{{ urls.database(database) }}{% if canned_query %}/{{ canned_query }}{% endif %}" method="{% if canned_query_write %}post{% else %}get{% endif %}">
<h3>Custom SQL query{% if display_rows %} returning {% if truncated %}more than {% endif %}{{ "{:,}".format(display_rows|length) }} row{% if display_rows|length == 1 %}{% else %}s{% endif %}{% endif %}{% if not query_error %}
<span class="show-hide-sql">(<a href="{{ show_hide_link }}">{{ show_hide_text }}</a>)</span>
{% endif %}</h3>
Expand Down
4 changes: 2 additions & 2 deletions datasette/templates/table.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ <h3>
</h3>
{% endif %}

<form class="filters" action="{{ urls.table(database, table) }}" method="get">
<form class="core" class="filters" action="{{ urls.table(database, table) }}" method="get">
{% if supports_search %}
<div class="search-row"><label for="_search">Search:</label><input id="_search" type="search" name="_search" value="{{ search }}"></div>
{% endif %}
Expand Down Expand Up @@ -152,7 +152,7 @@ <h3>Advanced export</h3>
<a href="{{ append_querystring(renderers['json'], '_shape=object') }}">object</a>
{% endif %}
</p>
<form action="{{ url_csv_path }}" method="get">
<form class="core" action="{{ url_csv_path }}" method="get">
<p>
CSV options:
<label><input type="checkbox" name="_dl"> download file</label>
Expand Down
9 changes: 9 additions & 0 deletions docs/custom_templates.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ database column they are representing, for example:
</tbody>
</table>

.. _customization_css:

Writing custom CSS
~~~~~~~~~~~~~~~~~~

Custom templates need to take Datasette's default CSS into account. The pattern portfolio at ``/-/patterns`` (`example here <https://latest.datasette.io/-/patterns>`__) is a useful reference for understanding the available CSS classes.

The ``core`` class is particularly useful - you can apply this directly to a ``<input>`` or ``<button>`` element to get Datasette's default form styles, or you can apply it to a containing element (such as ``<form>``) to apply those styles to all of the form elements within it.

.. _customization_static_files:

Serving static files
Expand Down
3 changes: 2 additions & 1 deletion docs/writing_plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ And a Python module file, ``datasette_plugin_demos.py``, that implements the plu
"random_integer", 2, random.randint
)
Having built a plugin in this way you can turn it into an installable package using the following command::

python3 setup.py sdist
Expand Down Expand Up @@ -164,6 +163,8 @@ Where ``datasette_plugin_name`` is the name of the plugin package (note that it

`datasette-cluster-map <https://github.com/simonw/datasette-cluster-map>`__ is a useful example of a plugin that includes packaged static assets in this way.

See :ref:`customization_css` for tips on writing CSS that is compatible with Datasette's default CSS, including details of the ``core`` class for applying Datasette's default form element styles.

.. _writing_plugins_custom_templates:

Custom templates
Expand Down
2 changes: 1 addition & 1 deletion tests/test_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ def test_view_query(allow, expected_anon, expected_auth):
def test_execute_sql(config):
schema_re = re.compile("const schema = ({.*?});", re.DOTALL)
with make_app_client(config=config) as client:
form_fragment = '<form class="sql" action="/fixtures/-/query"'
form_fragment = '<form class="sql core" action="/fixtures/-/query"'

# Anonymous users - should not display the form:
anon_html = client.get("/fixtures").text
Expand Down

0 comments on commit 2170269

Please sign in to comment.