Improve quiz page layouts: WIDM-style answers and responsive centering

- Add green square answer buttons styled after the TV show
- Two-column answer grid for 6+ answers, single column on mobile
- fit-content centering for question pages so block matches question width
- Narrow fixed-width centering for form pages (enter name, select season)
This commit is contained in:
2026-07-01 22:23:47 +02:00
parent e5198507ae
commit 20c97d9cb5
5 changed files with 112 additions and 35 deletions
+66 -1
View File
@@ -17,7 +17,72 @@ body {
background-color: black; background-color: black;
display: grid; display: grid;
align-content: center; align-content: center;
justify-self: center; }
.quiz-form-narrow {
max-width: 320px;
width: 100%;
margin: 0 auto;
}
.quiz-content {
width: fit-content;
max-width: min(760px, 100%);
margin: 0 auto;
}
.quiz-answers-grid {
display: grid;
grid-template-columns: repeat(2, auto);
column-gap: 2rem;
@media (max-width: 767px) {
grid-template-columns: 1fr;
}
}
.answer-btn {
display: flex;
align-items: center;
gap: 0.8rem;
background: transparent;
border: none;
color: white;
font-size: 1.1rem;
padding: 0.4rem 0;
cursor: pointer;
text-align: left;
line-height: 1.3;
&::before {
content: '';
display: block;
flex-shrink: 0;
width: 2rem;
height: 2rem;
background: radial-gradient(ellipse at 35% 30%, #6abf4b, #2d7a1f);
border-radius: 4px;
box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.25), 0 2px 6px rgba(0, 0, 0, 0.6);
}
&:hover,
&:focus {
color: #7ed45a;
outline: none;
&::before {
background: radial-gradient(ellipse at 35% 30%, #86d45f, #3d9c2a);
}
}
}
input.btn-check:checked + label.answer-btn {
color: #7ed45a;
&::before {
background: radial-gradient(ellipse at 35% 30%, #86d45f, #3d9c2a);
box-shadow: 0 0 10px rgba(106, 191, 75, 0.7), inset 0 1px 2px rgba(255, 255, 255, 0.3);
}
} }
.elimination-screen { .elimination-screen {
+3 -1
View File
@@ -1,4 +1,6 @@
{% extends 'quiz/base.html.twig' %} {% extends 'quiz/base.html.twig' %}
{% block body %} {% block body %}
{{ form(form) }} <div class="quiz-form-narrow">
{{ form(form) }}
</div>
{% endblock body %} {% endblock body %}
+36 -29
View File
@@ -1,36 +1,43 @@
{% extends 'quiz/base.html.twig' %} {% extends 'quiz/base.html.twig' %}
{% block body %} {% block body %}
<h4> <div class="quiz-content">
{% if season.settings.showNumbers %} <h4>
({{ question.ordering }}/{{ question.quiz.questions.count }}) {% if season.settings.showNumbers %}
{% endif %}{{ question.question }}<br/> ({{ question.ordering }}/{{ question.quiz.questions.count }})
</h4> {% endif %}{{ question.question }}<br/>
<form method="post"> </h4>
<input type="hidden" name="token" value="{{ csrf_token('question') }}"> <form method="post">
{% if season.settings.confirmAnswers == false %} <input type="hidden" name="token" value="{{ csrf_token('question') }}">
{% for answer in question.answers %} {% set twoCol = question.answers|length >= 6 %}
{% if season.settings.confirmAnswers == false %}
<div class="{{ twoCol ? 'quiz-answers-grid' : '' }}">
{% for answer in question.answers %}
<div class="py-2">
<button class="answer-btn"
type="submit"
name="answer"
value="{{ answer.id }}">{{ answer.text }}</button>
</div>
{% endfor %}
</div>
{% else %}
<div class="{{ twoCol ? 'quiz-answers-grid' : '' }}">
{% for answer in question.answers %}
<div class="py-1">
<input required="required" type="radio" class="btn-check" name="answer"
id="answer-{{ loop.index0 }}" autocomplete="off"
value="{{ answer.id }}">
<label class="answer-btn" for="answer-{{ loop.index0 }}">{{ answer.text }}</label>
</div>
{% endfor %}
</div>
<div class="py-2"> <div class="py-2">
<button class="btn btn-outline-success" <button class="btn btn-success"
type="submit" type="submit"
name="answer" >{{ 'Next'|trans }}</button>
value="{{ answer.id }}">{{ answer.text }}</button>
</div> </div>
{% endfor %}
{% else %}
{% for answer in question.answers %}
<div class="py-1">
<input required="required" type="radio" class="btn-check" name="answer"
id="answer-{{ loop.index0 }}" autocomplete="off"
value="{{ answer.id }}">
<label class="btn btn-outline-secondary" for="answer-{{ loop.index0 }}">{{ answer.text }}</label>
</div>
{% endfor %}
<div class="py-2">
<button class="btn btn-success"
type="submit"
>{{ 'Next'|trans }}</button>
</div>
{% endif %} {% endif %}
</form> </form>
</div>
{% endblock body %} {% endblock body %}
+4 -2
View File
@@ -1,5 +1,7 @@
{% extends 'quiz/base.html.twig' %} {% extends 'quiz/base.html.twig' %}
{% block body %} {% block body %}
{{ form(form) }} <div class="quiz-form-narrow">
<a href="{{ path('tvdt_backoffice_index') }}" class="btn btn-outline-secondary">{{ 'Manage Quiz'|trans }}</a> {{ form(form) }}
<a href="{{ path('tvdt_backoffice_index') }}" class="btn btn-outline-secondary">{{ 'Manage Quiz'|trans }}</a>
</div>
{% endblock body %} {% endblock body %}
+3 -2
View File
@@ -127,6 +127,7 @@ final class QuizSpreadsheetServiceTest extends TestCase
$question = new Question(); $question = new Question();
$question->question = 'Unanswered question'; $question->question = 'Unanswered question';
$question->ordering = 1; $question->ordering = 1;
$quiz->addQuestion($question); $quiz->addQuestion($question);
$path = $this->captureXlsx($this->subject->quizToXlsx($quiz)); $path = $this->captureXlsx($this->subject->quizToXlsx($quiz));
@@ -134,8 +135,8 @@ final class QuizSpreadsheetServiceTest extends TestCase
try { try {
$this->subject->xlsxToQuiz(new Quiz(), new File($path)); $this->subject->xlsxToQuiz(new Quiz(), new File($path));
$this->fail('Expected SpreadsheetDataException to be thrown'); $this->fail('Expected SpreadsheetDataException to be thrown');
} catch (SpreadsheetDataException $e) { } catch (SpreadsheetDataException $spreadsheetDataException) {
$this->assertNotEmpty($e->errors); $this->assertNotEmpty($spreadsheetDataException->errors);
} }
} }