Simplify rating form:

- Create a snippet to regroup similar code.
- Reduce and document tricky logic of CSS.
- Add i18n strings.
This commit is contained in:
Fabien Basmaison
2021-04-04 15:08:42 +02:00
parent 7b3c85f351
commit 485b0fa0f3
7 changed files with 189 additions and 132 deletions

View File

@ -80,52 +80,34 @@ html {
}
}
/* --- STARS --- */
.rate-stars button.icon {
background: none;
border: none;
padding: 0;
margin: 0;
display: inline;
/** Stars in a review form
*
* Specificity makes hovering taking over checked inputs.
*
* \e9d9: filled star
* \e9d7: empty star;
******************************************************************************/
.form-rate-stars {
width: max-content;
}
.rate-stars:hover .icon::before {
/* All stars are visually filled by default. */
.form-rate-stars .icon::before {
content: '\e9d9';
}
.rate-stars form:hover ~ form .icon::before {
/* Icons directly following inputs that follow the checked input are emptied. */
.form-rate-stars input:checked ~ input + .icon::before {
content: '\e9d7';
}
/** stars in a review form
*
* @todo Simplify the logic for those icons.
*/
.form-rate-stars input + .icon.icon::before {
content: '\e9d9';
}
/* When a label is hovered, repeat the fill-all-then-empty-following pattern. */
.form-rate-stars:hover .icon.icon::before {
content: '\e9d9';
}
.form-rate-stars input:checked + .icon.icon::before {
content: '\e9d9';
}
.form-rate-stars input:checked + * ~ .icon.icon::before {
content: '\e9d7';
}
.form-rate-stars:hover label.icon.icon::before {
content: '\e9d9';
}
.form-rate-stars label.icon:hover::before {
content: '\e9d9';
}
.form-rate-stars label.icon:hover ~ label.icon.icon::before {
.form-rate-stars .icon:hover ~ .icon::before {
content: '\e9d7';
}

View File

@ -27,16 +27,8 @@
{% if type == 'review' %}
<fieldset>
<legend class="is-sr-only">{% trans "Rating" %}</legend>
<div class="field is-grouped stars form-rate-stars">
<label class="is-sr-only" for="no-rating-{{ book.id }}">{% trans "No rating" %}</label>
<input class="is-sr-only" type="radio" name="rating" value="" id="no-rating-{{ book.id }}" checked>
{% for i in '12345'|make_list %}
<input class="is-sr-only" id="book{{book.id}}-star-{{ forloop.counter }}" type="radio" name="rating" value="{{ forloop.counter }}">
<label class="icon icon-star-empty" for="book{{book.id}}-star-{{ forloop.counter }}">
<span class="is-sr-only">{{ forloop.counter }} star{{ forloop.counter | pluralize }}</span>
</label>
{% endfor %}
</div>
{% include 'snippets/form_rate_stars.html' with book=book type=type|default:'summary' %}
</fieldset>
{% endif %}

View File

@ -0,0 +1,54 @@
{% spaceless %}
{% load i18n %}
{% load bookwyrm_tags %}
<div class="
field is-grouped
stars form-rate-stars
{% if classes %}{{classes}}{% endif%}
">
<input
id="{{ type|slugify }}-{{ book.id }}-no-rating"
class="is-sr-only"
type="radio"
name="rating"
value="0"
{% if book|user_rating:user == 0 %}checked{% endif %}
>
<label class="is-sr-only" for="{{ type|slugify }}-{{ book.id }}-no-rating">
{% trans "No rating" %}
</label>
{% for i in '12345'|make_list %}
<input
id="{{ type|slugify }}-book{{ book.id }}-star-{{ forloop.counter }}"
class="is-sr-only"
type="radio"
name="rating"
value="{{ forloop.counter }}"
{% if book|user_rating:user == forloop.counter %}checked{% endif %}
/>
<label
class="
icon
{% if forloop.counter <= book|user_rating:user %}
icon-star-full
{% else %}
icon-star-empty
{% endif %}
"
for="{{ type|slugify }}-book{{ book.id }}-star-{{ forloop.counter }}"
>
<span class="is-sr-only">
{% blocktranslate trimmed count rating=forloop.counter %}
{{ rating }} star
{% plural %}
{{ rating }} stars
{% endblocktranslate %}
</span>
</label>
{% endfor %}
</div>
{% endspaceless %}

View File

@ -8,18 +8,8 @@
<input type="hidden" name="user" value="{{ request.user.id }}">
<input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="privacy" value="public">
<input type="hidden" name="rating" value="{{ forloop.counter }}">
<div class="field is-grouped stars form-rate-stars mb-1 has-text-warning-dark">
<label class="is-sr-only" for="rating-no-rating-{{ book.id }}">{% trans "No rating" %}</label>
<input class="is-sr-only" type="radio" name="rating" value="" id="rating-no-rating-{{ book.id }}" checked>
{% for i in '12345'|make_list %}
<input class="is-sr-only" id="rating-book{{book.id}}-star-{{ forloop.counter }}" type="radio" name="rating" value="{{ forloop.counter }}" {% if book|user_rating:user == forloop.counter %}checked{% endif %}>
<label class="icon icon-star-empty" for="rating-book{{book.id}}-star-{{ forloop.counter }}">
<span class="is-sr-only">{{ forloop.counter }} star{{ forloop.counter | pluralize }}</span>
</label>
{% endfor %}
</div>
{% include 'snippets/form_rate_stars.html' with book=book classes='mb-1 has-text-warning-dark' %}
<div class="field has-addons hidden">
<div class="control">

View File

@ -1,8 +1,27 @@
{% spaceless %}
{% load i18n %}
<p class="stars">
<span class="is-sr-only">{% if rating %}{{ rating|floatformat }} star{{ rating|floatformat | pluralize }}{% else %}{% trans "No rating" %}{% endif %}</span>
{% for i in '12345'|make_list %}
<span class="icon is-small mr-1 icon-star-{% if rating >= forloop.counter %}full{% elif rating|floatformat:0 >= forloop.counter|floatformat:0 %}half{% else %}empty{% endif %}" aria-hidden="true">
<span class="is-sr-only">
{% if rating %}
{% blocktranslate trimmed with rating=rating|floatformat count counter=rating|length %}
{{ rating }} star
{% plural %}
{{ rating }} stars
{% endblocktranslate %}
{% else %}
{% trans "No rating" %}
{% endif %}
</span>
{% for i in '12345'|make_list %}
<span
class="
icon is-small mr-1
icon-star-{% if rating >= forloop.counter %}full{% elif rating|floatformat:0 >= forloop.counter|floatformat:0 %}half{% else %}empty{% endif %}
"
aria-hidden="true"
></span>
{% endfor %}
</p>
{% endspaceless %}