Improve organizer/event-series calendar UI on mobile

This commit is contained in:
Richard Schreiber
2024-12-04 08:17:52 +01:00
committed by GitHub
parent 8f92eb2d2d
commit 4d94158ff0
4 changed files with 106 additions and 89 deletions

View File

@@ -2,7 +2,7 @@
{% load date_fast %} {% load date_fast %}
{% load calendarhead %} {% load calendarhead %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-calendar"> <table class="table table-calendar" role="grid">
<caption class="sr-only">{% trans "Calendar" %}</caption> <caption class="sr-only">{% trans "Calendar" %}</caption>
<thead> <thead>
<tr> <tr>
@@ -18,7 +18,26 @@
{% if day %} {% if day %}
<td class="day {% if day.events %}has-events{% else %}no-events{% endif %}" <td class="day {% if day.events %}has-events{% else %}no-events{% endif %}"
data-date="{{ day.date|date_fast:"SHORT_DATE_FORMAT" }}"> data-date="{{ day.date|date_fast:"SHORT_DATE_FORMAT" }}">
<p><time datetime="{{ day.date|date_fast:"Y-m-d" }}">{{ day.day }}</time></p> <p>
{% if day.events %}
<a href="#selected-day" class="day-label event hidden-sm hidden-md hidden-lg">
<b aria-hidden="true">{{ day.day }}</b>
<time datetime="{{ day.date|date_fast:"Y-m-d" }}" class="sr-only">
{{ day.date|date_fast:"SHORT_DATE_FORMAT" }}
</time>
<span class="sr-only">
({% blocktrans trimmed count count=day.events|length %}
{{ count }} event
{% plural %}
{{ count }} events
{% endblocktrans %})
</span>
</a>
<time datetime="{{ day.date|date_fast:"Y-m-d" }}" class="hidden-xs">{{ day.day }}</time>
{% else %}
<time datetime="{{ day.date|date_fast:"Y-m-d" }}" class="day-label">{{ day.day }}</time>
{% endif %}
</p>
<ul class="events"> <ul class="events">
{% for event in day.events %} {% for event in day.events %}
<li><a class="event {% if event.continued %}continued{% endif %} {% spaceless %} <li><a class="event {% if event.continued %}continued{% endif %} {% spaceless %}
@@ -111,9 +130,7 @@
{% endfor %} {% endfor %}
</tr> </tr>
{% endfor %} {% endfor %}
<tr class="selected-day hidden">
<td colspan="7"></td>
</tr>
</tbody> </tbody>
</table> </table>
<div id="selected-day" aria-live="polite" class="table-calendar hidden-sm hidden-md hidden-lg"></div>
</div> </div>

View File

@@ -53,7 +53,9 @@ $in-border-radius-small: 2px !default;
--pretix-brand-primary-darken-17: #{darken($in-brand-primary, 17%)}; --pretix-brand-primary-darken-17: #{darken($in-brand-primary, 17%)};
--pretix-brand-primary-darken-20: #{darken($in-brand-primary, 20%)}; --pretix-brand-primary-darken-20: #{darken($in-brand-primary, 20%)};
--pretix-brand-primary-darken-30: #{darken($in-brand-primary, 30%)}; --pretix-brand-primary-darken-30: #{darken($in-brand-primary, 30%)};
--pretix-brand-primary-tint-90: #{tint($in-brand-primary, 90%)};
--pretix-brand-primary-shade-25: #{shade($in-brand-primary, 25%)}; --pretix-brand-primary-shade-25: #{shade($in-brand-primary, 25%)};
--pretix-brand-primary-shade-42: #{shade($in-brand-primary, 42%)};
--pretix-brand-primary-lighten-28-saturate-20: #{saturate(lighten($in-brand-primary, 28%), 20%)}; --pretix-brand-primary-lighten-28-saturate-20: #{saturate(lighten($in-brand-primary, 28%), 20%)};
--pretix-brand-primary-lighten-23-saturate-2: #{saturate(lighten($in-brand-primary, 23%), 2%)}; --pretix-brand-primary-lighten-23-saturate-2: #{saturate(lighten($in-brand-primary, 23%), 2%)};

View File

@@ -459,10 +459,26 @@ $(function () {
.on("change mouseup keyup", update_cart_form); .on("change mouseup keyup", update_cart_form);
$(".table-calendar td.has-events").click(function () { $(".table-calendar td.has-events").click(function () {
var $tr = $(this).closest(".table-calendar").find(".selected-day"); var $grid = $(this).closest("[role='grid']");
$tr.find("td").html($(this).find(".events").clone()); $grid.find("[aria-selected]").attr("aria-selected", false);
$tr.find("td").prepend($("<h3>").text($(this).attr("data-date"))); $(this).attr("aria-selected", true);
$tr.removeClass("hidden"); $("#selected-day")
.html($(this).find(".events").clone())
.prepend($("<h3>").text($(this).attr("data-date")));
}).each(function() {
// check all events classes and set the "winning" class for the availability of the day-label on mobile
var $dayLabel = $('.day-label', this);
if ($('.available.low', this).length == $('.available', this).length) {
$dayLabel.addClass('low');
}
var classes = ['available', 'waitinglist', 'soon', 'reserved', 'soldout', 'continued', 'over'];
for (var c of classes) {
if ($('.'+c, this).length) {
$dayLabel.addClass(c);
// CAREFUL: „return“ as „break“ is not supported before ES2015 and breaks e.g. on iOS 15
return;
}
}
}); });
$(".print-this-page").on("click", function (e) { $(".print-this-page").on("click", function (e) {

View File

@@ -13,93 +13,66 @@
padding: 0; padding: 0;
} }
a.event { a.event {
--status-bg-color: var(--pretix-brand-primary-tint-90);
--status-text-color: var(--pretix-brand-primary-shade-42);
--status-border-color: #{$brand-primary};
position: relative;
display: block; display: block;
background: var(--pretix-brand-primary-lighten-48); background: var(--status-bg-color);
color: $brand-primary; color: var(--status-text-color);
border: 1px solid var(--status-border-color);
border-radius: $border-radius-base; border-radius: $border-radius-base;
border-style: solid; &:before {
border-color: var(--pretix-brand-primary-lighten-30); content: "";
border-width: 1px 1px 1px 12px; position: absolute;
border-left-color: inherit; top: 0;
left: 0;
width: 11px;
height: 100%;
background: var(--status-border-color);
}
padding: 3px 5px; padding: 3px 5px 3px 17px;
margin-bottom: 3px; margin-bottom: 3px;
font-size: 12px; font-size: 12px;
overflow-wrap: anywhere; overflow-wrap: anywhere;
text-decoration: none; text-decoration: none;
&:hover { &:hover {
background: var(--pretix-brand-primary-lighten-50); outline: 1px solid var(--status-border-color);
border-color: $brand-primary; outline-offset: 0;
} }
&:focus { &:focus {
outline-color: inherit; outline: 2px solid var(--status-border-color);
outline-offset: 2px;
} }
&.continued, &.over { &.continued, &.over {
background: lighten(#767676, 54%); --status-bg-color: #{$table-bg-accent};
border-color: lighten(#767676, 44%); --status-text-color: #{$text-muted};
border-left-color: lighten(#767676, 44%); --status-border-color: #{tint($text-muted, 50%)};
color: #767676;
&:hover {
background: lighten(#767676, 54%);
border-color: lighten(#767676, 40%);
}
}
&.soon {
background: var(--pretix-brand-primary-lighten-53);
border-color: var(--pretix-brand-primary-lighten-40);
border-left-color: var(--pretix-brand-primary-lighten-20);
color: var(--pretix-brand-primary-lighten-5);
&:hover {
background: var(--pretix-brand-primary-lighten-55);
border-color: var(--pretix-brand-primary-lighten-20);
}
} }
&.available { &.available {
background: var(--pretix-brand-success-lighten-48); --status-bg-color: #{$alert-success-bg};
border-color: var(--pretix-brand-success-lighten-30); --status-text-color: #{$alert-success-text};
border-left-color: $brand-success; --status-border-color: #{$alert-success-border};
color: var(--pretix-brand-success-darken-12);
&.low { &.low:before {
border-left-color: var(--pretix-brand-warning-lighten-12); background: linear-gradient(to bottom, var(--pretix-brand-warning) 1em, var(--status-border-color) 2.5em);
}
&:hover {
background: var(--pretix-brand-success-lighten-50);
border-color: $brand-success;
&.low {
border-left-color: $brand-warning;
}
} }
} }
&.waitinglist { &.waitinglist {
background: var(--pretix-brand-warning-lighten-41); --status-bg-color: #{$alert-warning-bg};
border-color: var(--pretix-brand-warning-lighten-31); --status-text-color: #{$alert-warning-text};
border-left-color: var(--pretix-brand-warning-lighten-12); --status-border-color: #{$alert-warning-border};
color: #963;
&:hover {
background: var(--pretix-brand-warning-lighten-43);
border-color: $brand-warning;
}
} }
&.reserved, &.soldout, { &.reserved, &.soldout, {
background: var(--pretix-brand-danger-lighten-43); --status-bg-color: #{$alert-danger-bg};
border-color: var(--pretix-brand-danger-lighten-30); --status-text-color: #{$alert-danger-text};
border-left-color: var(--pretix-brand-danger-lighten-30); --status-border-color: #{$alert-danger-border};
color: var(--pretix-brand-danger-darken-5);
&:hover {
background: var(--pretix-brand-danger-lighten-45);
border-color: var(--pretix-brand-danger-lighten-25);
}
} }
&.available > *:first-child, &.available > *:first-child,
@@ -434,8 +407,6 @@ if concurrency is higher than 9, JavaScript (currently in pretixpresale/js/ui/ma
} }
@media (min-width: $screen-md-min) { @media (min-width: $screen-md-min) {
.week-calendar { .week-calendar {
display: flex; display: flex;
@@ -464,24 +435,35 @@ if concurrency is higher than 9, JavaScript (currently in pretixpresale/js/ui/ma
} }
} }
} }
@media (min-width: $screen-sm-min) { @media (max-width: $screen-xs-max) {
.table-calendar, .week-calendar { .table-calendar {
.selected-day { .day, .no-day {
display: none !important; padding: 3px 2px;
}
p {
margin-bottom: 0;
}
.day .events {
display: none;
}
a.day-label, .day-label {
--status-text-color: #{$text-muted};
display: block;
padding: 3px 3px 15px 12px;
font-size: 12px;
font-weight: bold;
color: var(--status-text-color);
margin-bottom: 0;
}
.no-events .day-label {
padding-left: 12px;
}
a.day-label:before {
width: 8px;
} }
} }
} #selected-day:has(*) {
@media (max-width: $screen-xs-max) { padding: $table-cell-padding;
.table-calendar .day .events {
display: none;
}
.table-calendar td.day.has-events {
background: $brand-primary;
cursor: pointer;
color: white;
}
.table-calendar td.day.has-events:hover {
background: var(--pretix-brand-primary-darken-15);
} }
} }
#monthselform .row { #monthselform .row {