mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
New .core CSS class for inputs and buttons
* 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
This commit is contained in:
parent
92c4d41ca6
commit
2170269258
13 changed files with 46 additions and 23 deletions
|
|
@ -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%;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ p.message-warning {
|
|||
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
</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%">
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
</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%">
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
{% 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">
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
{% 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>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<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">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<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">
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ textarea {
|
|||
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
{% 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>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
</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 %}
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
<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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue