MDL-85077 theme_boost: Fix responsive tables after BS5 upgrade

- Replace class 'no-overflow' with 'table-responsive' for responsive tables.
- Fix dropdown positioning inside responsive tables.
- Fix visually-hidden elements inside tables generating incorrect page scrolling.
This commit is contained in:
Mikel Martín 2025-04-08 12:30:48 +02:00
parent e3b05240c1
commit ad14d58dc5
12 changed files with 297 additions and 299 deletions

View File

@ -561,7 +561,7 @@ class html_writer {
}
}
if (empty($table->attributes['class'])) {
$table->attributes['class'] = 'generaltable';
$table->attributes['class'] = 'generaltable table';
}
if (!empty($table->tablealign)) {
$table->attributes['class'] .= ' boxalign' . $table->tablealign;

View File

@ -1866,7 +1866,7 @@ class flexible_table {
// Start of main data table.
if ($this->responsive) {
echo html_writer::start_tag('div', ['class' => 'no-overflow']);
echo html_writer::start_tag('div', ['class' => 'table-responsive']);
}
echo html_writer::start_tag('table', $this->attributes) . $this->render_caption();
}

View File

@ -315,7 +315,7 @@ final class html_writer_test extends \basic_testcase {
$output = html_writer::table($table);
$expected = <<<EOF
<table class="generaltable" id="Jeffrey" data-name="Colin">
<table class="generaltable table" id="Jeffrey" data-name="Colin">
<caption>A table of meaningless data.</caption><tbody><tr class="lastrow" id="Bob" data-name="Fred">
<td class="cell c0 lastcol" id="Jeremy" data-name="John" style=""></td>
</tr>
@ -344,7 +344,7 @@ EOF;
$output = html_writer::table($table);
$expected = <<<EOF
<table class="generaltable" id="whodat">
<table class="generaltable table" id="whodat">
<caption class="accesshide">Who even knows?</caption><tbody><tr class="">
<td class="cell c0" style="">fred</td>
<td class="cell c1 lastcol" style="">MDK</td>

View File

@ -1934,7 +1934,7 @@ class assign_grading_table extends table_sql implements renderable {
// Start of main data table.
if ($this->responsive) {
echo html_writer::start_tag('div', ['class' => 'no-overflow']);
echo html_writer::start_tag('div', ['class' => 'table-responsive']);
}
echo html_writer::start_tag('table', $this->attributes) . $this->render_caption();
}

View File

@ -147,5 +147,5 @@ foreach ($datas as $data) {
}
echo "<br />";
echo html_writer::tag('div', html_writer::table($table), array('class'=>'no-overflow'));
echo html_writer::tag('div', html_writer::table($table), ['class' => 'table-responsive']);
echo $OUTPUT->footer();

View File

@ -93,271 +93,269 @@
{{{ pagination }}}
{{/discussion_top_pagination}}
{{$discussion_list_output}}
<div class="position-relative">
<div class="no-overflow">
<table class="table discussion-list generaltable">
<caption id="discussion-table-description-{{uniqid}}" class="visually-hidden">
{{#str}} showingcountoftotaldiscussions, mod_forum, {"count": "{{visiblediscussioncount}}", "total":"{{totaldiscussioncount}}"} {{/str}}
</caption>
{{$discussion_list_header}}
<thead>
<tr>
<th scope="col">
<span class="accesshide">{{#str}}status{{/str}}</span>
</th>
<th scope="col" class="ps-0">
{{#state.sortorder.isdiscussiondesc}}
<a href="{{{forum.urls.sortdiscussionasc}}}" aria-label="{{#str}}discussionlistsortbydiscussionasc, mod_forum{{/str}}">{{#str}}discussion, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isdiscussiondesc}}
{{#state.sortorder.isdiscussionasc}}
<a href="{{{forum.urls.sortdiscussiondesc}}}" aria-label="{{#str}}discussionlistsortbydiscussiondesc, mod_forum{{/str}}">{{#str}}discussion, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
<div class="table-responsive">
<table class="table discussion-list generaltable">
<caption id="discussion-table-description-{{uniqid}}" class="visually-hidden">
{{#str}} showingcountoftotaldiscussions, mod_forum, {"count": "{{visiblediscussioncount}}", "total":"{{totaldiscussioncount}}"} {{/str}}
</caption>
{{$discussion_list_header}}
<thead>
<tr>
<th scope="col">
<span class="accesshide">{{#str}}status{{/str}}</span>
</th>
<th scope="col" class="ps-0">
{{#state.sortorder.isdiscussiondesc}}
<a href="{{{forum.urls.sortdiscussionasc}}}" aria-label="{{#str}}discussionlistsortbydiscussionasc, mod_forum{{/str}}">{{#str}}discussion, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isdiscussiondesc}}
{{#state.sortorder.isdiscussionasc}}
<a href="{{{forum.urls.sortdiscussiondesc}}}" aria-label="{{#str}}discussionlistsortbydiscussiondesc, mod_forum{{/str}}">{{#str}}discussion, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isdiscussionasc}}
{{^state.sortorder.isdiscussiondesc}}
{{^state.sortorder.isdiscussionasc}}
<a href="{{{forum.urls.sortdiscussiondesc}}}" aria-label="{{#str}}discussionlistsortbydiscussiondesc, mod_forum{{/str}}">{{#str}}discussion, mod_forum{{/str}}</a>
{{/state.sortorder.isdiscussionasc}}
{{^state.sortorder.isdiscussiondesc}}
{{^state.sortorder.isdiscussionasc}}
<a href="{{{forum.urls.sortdiscussiondesc}}}" aria-label="{{#str}}discussionlistsortbydiscussiondesc, mod_forum{{/str}}">{{#str}}discussion, mod_forum{{/str}}</a>
{{/state.sortorder.isdiscussionasc}}
{{/state.sortorder.isdiscussiondesc}}
{{/state.sortorder.isdiscussiondesc}}
</th>
{{#forum.state.groupmode}}
<th scope="col" class="group px-3">
{{#state.sortorder.isgroupdesc}}
<a href="{{{forum.urls.sortgroupasc}}}" aria-label="{{#str}}discussionlistsortbygroupasc, mod_forum{{/str}}">{{#str}}group{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isgroupdesc}}
{{#state.sortorder.isgroupasc}}
<a href="{{{forum.urls.sortgroupdesc}}}" aria-label="{{#str}}discussionlistsortbygroupdesc, mod_forum{{/str}}">{{#str}}group{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isgroupasc}}
{{^state.sortorder.isgroupdesc}}
{{^state.sortorder.isgroupasc}}
<a href="{{{forum.urls.sortgroupdesc}}}" aria-label="{{#str}}discussionlistsortbygroupdesc, mod_forum{{/str}}">{{#str}}group{{/str}}</a>
{{/state.sortorder.isgroupasc}}
{{/state.sortorder.isgroupdesc}}
</th>
{{/forum.state.groupmode}}
<th scope="col" class="author px-3">
{{#state.sortorder.isstarterdesc}}
<a href="{{{forum.urls.sortstarterasc}}}" aria-label="{{#str}}discussionlistsortbystarterasc, mod_forum{{/str}}">{{#str}}startedby, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isstarterdesc}}
{{#state.sortorder.isstarterasc}}
<a href="{{{forum.urls.sortstarterdesc}}}" aria-label="{{#str}}discussionlistsortbystarterdesc, mod_forum{{/str}}">{{#str}}startedby, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isstarterasc}}
{{^state.sortorder.isstarterdesc}}
{{^state.sortorder.isstarterasc}}
<a href="{{{forum.urls.sortstarterdesc}}}" aria-label="{{#str}}discussionlistsortbystarterdesc, mod_forum{{/str}}">{{#str}}startedby, mod_forum{{/str}}</a>
{{/state.sortorder.isstarterasc}}
{{/state.sortorder.isstarterdesc}}
</th>
<th scope="col" class="lastpost px-3">
{{#state.sortorder.islastpostdesc}}
<a href="{{{forum.urls.sortlastpostasc}}}" aria-label="{{#str}}discussionlistsortbylastpostasc, mod_forum{{/str}}">{{#str}}lastpost, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.islastpostdesc}}
{{#state.sortorder.islastpostasc}}
<a href="{{{forum.urls.sortlastpostdesc}}}" aria-label="{{#str}}discussionlistsortbylastpostdesc, mod_forum{{/str}}">{{#str}}lastpost, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.islastpostasc}}
{{^state.sortorder.islastpostdesc}}
{{^state.sortorder.islastpostasc}}
<a href="{{{forum.urls.sortlastpostdesc}}}" aria-label="{{#str}}discussionlistsortbylastpostdesc, mod_forum{{/str}}">{{#str}}lastpost, mod_forum{{/str}}</a>
{{/state.sortorder.islastpostasc}}
{{/state.sortorder.islastpostdesc}}
</th>
{{#forum.capabilities.viewdiscussions}}
<th scope="col" class="text-center px-2">
{{#state.sortorder.isrepliesdesc}}
<a href="{{{forum.urls.sortrepliesasc}}}" aria-label="{{#str}}discussionlistsortbyrepliesasc, mod_forum{{/str}}">{{#str}}replies, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isrepliesdesc}}
{{#state.sortorder.isrepliesasc}}
<a href="{{{forum.urls.sortrepliesdesc}}}" aria-label="{{#str}}discussionlistsortbyrepliesdesc, mod_forum{{/str}}">{{#str}}replies, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isrepliesasc}}
{{^state.sortorder.isrepliesdesc}}
{{^state.sortorder.isrepliesasc}}
<a href="{{{forum.urls.sortrepliesdesc}}}" aria-label="{{#str}}discussionlistsortbyrepliesdesc, mod_forum{{/str}}">{{#str}}replies, mod_forum{{/str}}</a>
{{/state.sortorder.isrepliesasc}}
{{/state.sortorder.isrepliesdesc}}
{{#forum.userstate.tracked}}
<a href="{{{forum.urls.markasread}}}">{{#pix}}t/markasread, core, {{#str}}markallread, mod_forum{{/str}}{{/pix}}</a>
{{/forum.userstate.tracked}}
</th>
{{/forum.capabilities.viewdiscussions}}
{{#forum.capabilities.subscribe}}
<th scope="col" class="text-center px-2">{{#str}} notsubscribed, mod_forum {{/str}}</th>
{{/forum.capabilities.subscribe}}
<th scope="col" class="discussionsubscription">
<span class="accesshide">{{#str}}actions{{/str}}</span>
</th>
</tr>
</thead>
{{/discussion_list_header}}
{{$discussion_list_body}}
<tbody>
{{#summaries}}
{{! The discussion class is only required for behat tests to identify the row. }}
<tr class="discussion{{!
}}{{#discussion.pinned}} pinned{{/discussion.pinned}}{{!
}}{{#discussion.userstate.favourited}} favourited{{/discussion.userstate.favourited}}{{!
}}{{#discussion.userstate.subscribed}} subscribed{{/discussion.userstate.subscribed}}{{!
}}{{#unread}} hasunread{{/unread}}{{!
}}{{#discussion.timed}}{{#istimed}}{{^visible}} dimmed_text{{/visible}}{{/istimed}}{{/discussion.timed}}"
data-region="discussion-list-item"
data-discussionid="{{id}}"
data-forumid="{{forumid}}">
<td class="p-0 text-center align-middle icon-no-margin" style="width: 1px;">
{{#discussion}}
{{> mod_forum/forum_discussion_favourite_toggle}}
{{/discussion}}
</td>
<th scope="row" class="topic p-0 align-middle">
<div class="p-3 ps-0">
<div class="d-flex">
{{#discussion.pinned}}
{{#pix}}i/pinned, mod_forum, {{#str}}discussionpinned, mod_forum{{/str}}{{/pix}}
{{/discussion.pinned}}
<a class="w-100 h-100 d-block" href="{{discussion.urls.view}}" title="{{discussion.name}}" aria-label="{{discussion.name}}">
{{#shortentext}}100, {{{discussion.name}}}{{/shortentext}}
</a>
</div>
<div>
<span class="badge bg-danger text-white rounded" data-region="locked-label" {{^discussion.locked}}hidden{{/discussion.locked}}>
{{#str}}locked, forum{{/str}}
</span>
{{#discussion.timed.istimed}}
<span>
<button class="btn badge bg-primary text-white rounded border-0" data-region="timed-label"
data-bs-toggle="popover" data-bs-container="body" data-bs-placement="right" data-bs-html="true"
data-bs-content="{{#discussion.timed}}{{#discussion.times}}{{> mod_forum/discussion_times}}{{/discussion.times}}{{/discussion.timed}}"
data-bs-trigger="click" aria-label="{{#str}}timeddiscussion, forum{{/str}}" title="{{#str}}timeddiscussion, forum{{/str}}">
{{#str}}timed, forum{{/str}}
</button>
</span>
{{/discussion.timed.istimed}}
</div>
</div>
</th>
{{#forum.state.groupmode}}
<th scope="col" class="group px-3">
{{#state.sortorder.isgroupdesc}}
<a href="{{{forum.urls.sortgroupasc}}}" aria-label="{{#str}}discussionlistsortbygroupasc, mod_forum{{/str}}">{{#str}}group{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isgroupdesc}}
{{#state.sortorder.isgroupasc}}
<a href="{{{forum.urls.sortgroupdesc}}}" aria-label="{{#str}}discussionlistsortbygroupdesc, mod_forum{{/str}}">{{#str}}group{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isgroupasc}}
{{^state.sortorder.isgroupdesc}}
{{^state.sortorder.isgroupasc}}
<a href="{{{forum.urls.sortgroupdesc}}}" aria-label="{{#str}}discussionlistsortbygroupdesc, mod_forum{{/str}}">{{#str}}group{{/str}}</a>
{{/state.sortorder.isgroupasc}}
{{/state.sortorder.isgroupdesc}}
</th>
{{/forum.state.groupmode}}
<th scope="col" class="author px-3">
{{#state.sortorder.isstarterdesc}}
<a href="{{{forum.urls.sortstarterasc}}}" aria-label="{{#str}}discussionlistsortbystarterasc, mod_forum{{/str}}">{{#str}}startedby, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isstarterdesc}}
{{#state.sortorder.isstarterasc}}
<a href="{{{forum.urls.sortstarterdesc}}}" aria-label="{{#str}}discussionlistsortbystarterdesc, mod_forum{{/str}}">{{#str}}startedby, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isstarterasc}}
{{^state.sortorder.isstarterdesc}}
{{^state.sortorder.isstarterasc}}
<a href="{{{forum.urls.sortstarterdesc}}}" aria-label="{{#str}}discussionlistsortbystarterdesc, mod_forum{{/str}}">{{#str}}startedby, mod_forum{{/str}}</a>
{{/state.sortorder.isstarterasc}}
{{/state.sortorder.isstarterdesc}}
</th>
<th scope="col" class="lastpost px-3">
{{#state.sortorder.islastpostdesc}}
<a href="{{{forum.urls.sortlastpostasc}}}" aria-label="{{#str}}discussionlistsortbylastpostasc, mod_forum{{/str}}">{{#str}}lastpost, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.islastpostdesc}}
{{#state.sortorder.islastpostasc}}
<a href="{{{forum.urls.sortlastpostdesc}}}" aria-label="{{#str}}discussionlistsortbylastpostdesc, mod_forum{{/str}}">{{#str}}lastpost, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.islastpostasc}}
{{^state.sortorder.islastpostdesc}}
{{^state.sortorder.islastpostasc}}
<a href="{{{forum.urls.sortlastpostdesc}}}" aria-label="{{#str}}discussionlistsortbylastpostdesc, mod_forum{{/str}}">{{#str}}lastpost, mod_forum{{/str}}</a>
{{/state.sortorder.islastpostasc}}
{{/state.sortorder.islastpostdesc}}
</th>
{{#forum.capabilities.viewdiscussions}}
<th scope="col" class="text-center px-2">
{{#state.sortorder.isrepliesdesc}}
<a href="{{{forum.urls.sortrepliesasc}}}" aria-label="{{#str}}discussionlistsortbyrepliesasc, mod_forum{{/str}}">{{#str}}replies, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/downlong, core, {{#str}}desc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isrepliesdesc}}
{{#state.sortorder.isrepliesasc}}
<a href="{{{forum.urls.sortrepliesdesc}}}" aria-label="{{#str}}discussionlistsortbyrepliesdesc, mod_forum{{/str}}">{{#str}}replies, mod_forum{{/str}}</a> <span class="text-primary">{{#pix}}t/uplong, core, {{#str}}asc, core{{/str}}{{/pix}}</span>
{{/state.sortorder.isrepliesasc}}
{{^state.sortorder.isrepliesdesc}}
{{^state.sortorder.isrepliesasc}}
<a href="{{{forum.urls.sortrepliesdesc}}}" aria-label="{{#str}}discussionlistsortbyrepliesdesc, mod_forum{{/str}}">{{#str}}replies, mod_forum{{/str}}</a>
{{/state.sortorder.isrepliesasc}}
{{/state.sortorder.isrepliesdesc}}
{{#forum.userstate.tracked}}
<a href="{{{forum.urls.markasread}}}">{{#pix}}t/markasread, core, {{#str}}markallread, mod_forum{{/str}}{{/pix}}</a>
{{/forum.userstate.tracked}}
</th>
{{/forum.capabilities.viewdiscussions}}
{{#forum.capabilities.subscribe}}
<th scope="col" class="text-center px-2">{{#str}} notsubscribed, mod_forum {{/str}}</th>
{{/forum.capabilities.subscribe}}
<th scope="col" class="discussionsubscription">
<span class="accesshide">{{#str}}actions{{/str}}</span>
</th>
</tr>
</thead>
{{/discussion_list_header}}
{{$discussion_list_body}}
<tbody>
{{#summaries}}
{{! The discussion class is only required for behat tests to identify the row. }}
<tr class="discussion{{!
}}{{#discussion.pinned}} pinned{{/discussion.pinned}}{{!
}}{{#discussion.userstate.favourited}} favourited{{/discussion.userstate.favourited}}{{!
}}{{#discussion.userstate.subscribed}} subscribed{{/discussion.userstate.subscribed}}{{!
}}{{#unread}} hasunread{{/unread}}{{!
}}{{#discussion.timed}}{{#istimed}}{{^visible}} dimmed_text{{/visible}}{{/istimed}}{{/discussion.timed}}"
data-region="discussion-list-item"
data-discussionid="{{id}}"
data-forumid="{{forumid}}">
<td class="p-0 text-center align-middle icon-no-margin" style="width: 1px;">
{{#discussion}}
{{> mod_forum/forum_discussion_favourite_toggle}}
{{/discussion}}
</td>
<th scope="row" class="topic p-0 align-middle">
<div class="p-3 ps-0">
<div class="d-flex">
{{#discussion.pinned}}
{{#pix}}i/pinned, mod_forum, {{#str}}discussionpinned, mod_forum{{/str}}{{/pix}}
{{/discussion.pinned}}
<a class="w-100 h-100 d-block" href="{{discussion.urls.view}}" title="{{discussion.name}}" aria-label="{{discussion.name}}">
{{#shortentext}}100, {{{discussion.name}}}{{/shortentext}}
<td class="group align-middle fit-content limit-width px-3">
{{#discussion.group}}
<img alt="{{#str}} pictureof, core, {{name}} {{/str}}"
class="border rounded h-auto rounded-circle grouppicture"
src="{{{urls.picture}}}"
title="{{#str}} pictureof, core, {{name}} {{/str}}">
{{#urls.userlist}}
<a href="{{{urls.userlist}}}" aria-label='{{#str}} memberofgroup, group, {{name}}{{/str}}'
title='{{#str}} memberofgroup, group, {{name}}{{/str}}'>
{{#shortentext}}30, {{name}}{{/shortentext}}
</a>
{{/urls.userlist}}
{{^urls.userlist}}
<span>{{name}}</span>
{{/urls.userlist}}
{{/discussion.group}}
</td>
{{/forum.state.groupmode}}
<td class="author align-middle fit-content limit-width px-3">
{{#firstpostauthor}}
<div class="d-flex">
<div class="align-middle p-0">
<img class="rounded-circle userpicture" src="{{urls.profileimage}}"
alt="{{#str}}pictureof, moodle, {{fullname}}{{/str}}"
title="{{#str}}pictureof, moodle, {{fullname}}{{/str}}" >
</div>
<div>
<span class="badge bg-danger text-white rounded" data-region="locked-label" {{^discussion.locked}}hidden{{/discussion.locked}}>
{{#str}}locked, forum{{/str}}
</span>
{{#discussion.timed.istimed}}
<span>
<button class="btn badge bg-primary text-white rounded border-0" data-region="timed-label"
data-bs-toggle="popover" data-bs-container="body" data-bs-placement="right" data-bs-html="true"
data-bs-content="{{#discussion.timed}}{{#discussion.times}}{{> mod_forum/discussion_times}}{{/discussion.times}}{{/discussion.timed}}"
data-bs-trigger="click" aria-label="{{#str}}timeddiscussion, forum{{/str}}" title="{{#str}}timeddiscussion, forum{{/str}}">
{{#str}}timed, forum{{/str}}
</button>
</span>
{{/discussion.timed.istimed}}
<div class="author-info align-middle">
<div class="mb-1 line-height-3 text-truncate">{{fullname}}</div>
<div class="line-height-3">
{{< core/time_element }}
{{$elementid}}created-{{discussion.id}}{{/elementid}}
{{$timestampval}}{{discussion.times.created}}{{/timestampval}}
{{$userdateformatval}}{{#str}}strftimedatemonthabbr, langconfig{{/str}}{{/userdateformatval}}
{{/core/time_element}}
</div>
</div>
</div>
</th>
{{#forum.state.groupmode}}
<td class="group align-middle fit-content limit-width px-3">
{{#discussion.group}}
<img alt="{{#str}} pictureof, core, {{name}} {{/str}}"
class="border rounded h-auto rounded-circle grouppicture"
src="{{{urls.picture}}}"
title="{{#str}} pictureof, core, {{name}} {{/str}}">
{{#urls.userlist}}
<a href="{{{urls.userlist}}}" aria-label='{{#str}} memberofgroup, group, {{name}}{{/str}}'
title='{{#str}} memberofgroup, group, {{name}}{{/str}}'>
{{#shortentext}}30, {{name}}{{/shortentext}}
</a>
{{/urls.userlist}}
{{^urls.userlist}}
<span>{{name}}</span>
{{/urls.userlist}}
{{/discussion.group}}
</td>
{{/forum.state.groupmode}}
<td class="author align-middle fit-content limit-width px-3">
{{#firstpostauthor}}
<div class="d-flex">
<div class="align-middle p-0">
<img class="rounded-circle userpicture" src="{{urls.profileimage}}"
alt="{{#str}}pictureof, moodle, {{fullname}}{{/str}}"
title="{{#str}}pictureof, moodle, {{fullname}}{{/str}}" >
</div>
<div class="author-info align-middle">
<div class="mb-1 line-height-3 text-truncate">{{fullname}}</div>
<div class="line-height-3">
{{< core/time_element }}
{{$elementid}}created-{{discussion.id}}{{/elementid}}
{{$timestampval}}{{discussion.times.created}}{{/timestampval}}
{{$userdateformatval}}{{#str}}strftimedatemonthabbr, langconfig{{/str}}{{/userdateformatval}}
{{/core/time_element}}
</div>
</div>
{{/firstpostauthor}}
</td>
<td class="text-start align-middle fit-content limit-width px-3">
{{! TODO Check q&a, eachuser }}
{{#latestpostauthor}}
<div class="d-flex">
<div class="align-middle p-0">
<img class="rounded-circle userpicture" src="{{urls.profileimage}}"
alt="{{#str}}pictureof, moodle, {{fullname}}{{/str}}"
title="{{#str}}pictureof, moodle, {{fullname}}{{/str}}" >
</div>
{{/firstpostauthor}}
</td>
<td class="text-start align-middle fit-content limit-width px-3">
{{! TODO Check q&a, eachuser }}
{{#latestpostauthor}}
<div class="d-flex">
<div class="align-middle p-0">
<img class="rounded-circle userpicture" src="{{urls.profileimage}}"
alt="{{#str}}pictureof, moodle, {{fullname}}{{/str}}"
title="{{#str}}pictureof, moodle, {{fullname}}{{/str}}" >
</div>
<div class="author-info align-middle">
<div class="mb-1 line-height-3 text-truncate">{{fullname}}</div>
<div class="line-height-3">
{{#latestpostid}}
<a href="{{{discussion.urls.viewlatest}}}" title="{{#userdate}}{{discussion.times.modified}},{{#str}}strftimerecentfull{{/str}}{{/userdate}}">
{{< core/time_element }}
{{$elementid}}modified-{{discussion.id}}{{/elementid}}
{{$timestampval}}{{discussion.times.modified}}{{/timestampval}}
{{$userdateformatval}}{{#str}}strftimedatemonthabbr, langconfig{{/str}}{{/userdateformatval}}
{{/ core/time_element }}
</a>
{{/latestpostid}}
</div>
</div>
</div>
{{/latestpostauthor}}
</td>
{{#forum.capabilities.viewdiscussions}}
<td class="p-0 text-center align-middle fit-content px-2">
<span>{{replies}}</span>
{{#forum.userstate.tracked}}
{{#unread}}
{{! TODO Rewrite as AJAX}}
<span class="lead">
<a href="{{{discussion.urls.viewfirstunread}}}" class="badge bg-primary text-white rounded-pill fw-normal"
title="{{#str}}unreadpostsnumber, mod_forum, {{unread}}{{/str}}" aria-label="{{#str}}unreadpostsnumber, mod_forum, {{unread}}{{/str}}">
{{unread}}
<div class="author-info align-middle">
<div class="mb-1 line-height-3 text-truncate">{{fullname}}</div>
<div class="line-height-3">
{{#latestpostid}}
<a href="{{{discussion.urls.viewlatest}}}" title="{{#userdate}}{{discussion.times.modified}},{{#str}}strftimerecentfull{{/str}}{{/userdate}}">
{{< core/time_element }}
{{$elementid}}modified-{{discussion.id}}{{/elementid}}
{{$timestampval}}{{discussion.times.modified}}{{/timestampval}}
{{$userdateformatval}}{{#str}}strftimedatemonthabbr, langconfig{{/str}}{{/userdateformatval}}
{{/ core/time_element }}
</a>
</span>
{{/unread}}
{{/forum.userstate.tracked}}
</td>
{{/forum.capabilities.viewdiscussions}}
{{#forum.capabilities.subscribe}}
<td class="text-center align-middle fit-content px-2">
{{#discussion}}
<div class="form-check form-switch mb-1">
<input
type="checkbox"
class="form-check-input"
id="subscription-toggle-{{id}}"
data-type="subscription-toggle"
data-action="toggle"
data-discussionid="{{id}}"
data-forumid="{{forumid}}"
{{#userstate.subscribed}}data-targetstate="0" checked{{/userstate.subscribed}}
{{^userstate.subscribed}}data-targetstate="1"{{/userstate.subscribed}}>
<label class="form-check-label" for="subscription-toggle-{{id}}">
<span class="visually-hidden">
{{#userstate.subscribed}}
{{#str}}unsubscribediscussion, forum{{/str}}
{{/userstate.subscribed}}
{{^userstate.subscribed}}
{{#str}}subscribediscussion, forum{{/str}}
{{/userstate.subscribed}}
</span>
</label>
{{/latestpostid}}
</div>
{{/discussion}}
</td>
{{/forum.capabilities.subscribe}}
<td class="p-0 align-middle fit-content" data-container="discussion-summary-actions">
</div>
</div>
{{/latestpostauthor}}
</td>
{{#forum.capabilities.viewdiscussions}}
<td class="p-0 text-center align-middle fit-content px-2">
<span>{{replies}}</span>
{{#forum.userstate.tracked}}
{{#unread}}
{{! TODO Rewrite as AJAX}}
<span class="lead">
<a href="{{{discussion.urls.viewfirstunread}}}" class="badge bg-primary text-white rounded-pill fw-normal"
title="{{#str}}unreadpostsnumber, mod_forum, {{unread}}{{/str}}" aria-label="{{#str}}unreadpostsnumber, mod_forum, {{unread}}{{/str}}">
{{unread}}
</a>
</span>
{{/unread}}
{{/forum.userstate.tracked}}
</td>
{{/forum.capabilities.viewdiscussions}}
{{#forum.capabilities.subscribe}}
<td class="text-center align-middle fit-content px-2">
{{#discussion}}
<div class="d-flex flex-wrap justify-content-end icon-no-margin">
{{#hasanyactions}}
<div data-container='discussion-tools'>
{{> mod_forum/forum_action_menu}}
</div>
{{/hasanyactions}}
<div class="form-check form-switch mb-1">
<input
type="checkbox"
class="form-check-input"
id="subscription-toggle-{{id}}"
data-type="subscription-toggle"
data-action="toggle"
data-discussionid="{{id}}"
data-forumid="{{forumid}}"
{{#userstate.subscribed}}data-targetstate="0" checked{{/userstate.subscribed}}
{{^userstate.subscribed}}data-targetstate="1"{{/userstate.subscribed}}>
<label class="form-check-label" for="subscription-toggle-{{id}}">
<span class="visually-hidden">
{{#userstate.subscribed}}
{{#str}}unsubscribediscussion, forum{{/str}}
{{/userstate.subscribed}}
{{^userstate.subscribed}}
{{#str}}subscribediscussion, forum{{/str}}
{{/userstate.subscribed}}
</span>
</label>
</div>
{{/discussion}}
</td>
</tr>
{{/summaries}}
</tbody>
{{/discussion_list_body}}
</table>
</div>
{{/forum.capabilities.subscribe}}
<td class="p-0 align-middle fit-content" data-container="discussion-summary-actions">
{{#discussion}}
<div class="d-flex flex-wrap justify-content-end icon-no-margin">
{{#hasanyactions}}
<div data-container='discussion-tools'>
{{> mod_forum/forum_action_menu}}
</div>
{{/hasanyactions}}
</div>
{{/discussion}}
</td>
</tr>
{{/summaries}}
</tbody>
{{/discussion_list_body}}
</table>
</div>
{{/discussion_list_output}}
{{$discussion_bottom_pagination}}

View File

@ -715,7 +715,7 @@ class page_wiki_comments extends page_wiki {
$t->data[] = $row3;
}
echo html_writer::tag('div', html_writer::table($t), array('class'=>'no-overflow'));
echo html_writer::tag('div', html_writer::table($t), ['class' => 'table-responsive']);
}
}

View File

@ -317,7 +317,7 @@ abstract class base_report_table extends table_sql implements dynamic, renderabl
$this->set_caption($this->report::get_name(), ['class' => 'visually-hidden']);
echo html_writer::start_tag('div');
echo html_writer::start_tag('div', ['class' => 'table-responsive']);
echo html_writer::start_tag('table', $this->attributes) . $this->render_caption();
}
}

View File

@ -405,22 +405,6 @@ form.popupform div {
overflow: auto;
}
// Position required for table sizing inside a flex container.
.no-overflow > .generaltable {
margin-bottom: 0;
}
.no-overflow,
.table-responsive {
.generaltable {
.visually-hidden,
.accesshide {
position: relative;
display: block;
}
}
}
// Accessibility features
// Accessibility: text 'seen' by screen readers but not visual users.

View File

@ -77,3 +77,19 @@ table {
font-size: 3rem;
}
}
.table-responsive {
// Fix dropdown menu position inside responsive tables.
.dropdown {
position: static !important; /* stylelint-disable-line declaration-no-important */
}
// Fix visually hidden text in responsive tables.
.table {
margin-bottom: 0;
.visually-hidden,
.accesshide {
position: relative !important; /* stylelint-disable-line declaration-no-important */
display: block;
}
}
}

View File

@ -25968,18 +25968,6 @@ form.popupform div {
overflow: auto;
}
.no-overflow > .generaltable {
margin-bottom: 0;
}
.no-overflow .generaltable .visually-hidden,
.no-overflow .generaltable .accesshide,
.table-responsive .generaltable .visually-hidden,
.table-responsive .generaltable .accesshide {
position: relative;
display: block;
}
.accesshide {
width: 1px !important;
height: 1px !important;
@ -37126,6 +37114,18 @@ table .sticky-column {
font-size: 3rem;
}
.table-responsive .dropdown {
position: static !important; /* stylelint-disable-line declaration-no-important */
}
.table-responsive .table {
margin-bottom: 0;
}
.table-responsive .table .visually-hidden,
.table-responsive .table .accesshide {
position: relative !important; /* stylelint-disable-line declaration-no-important */
display: block;
}
/**
* File buttons.scss.
* Contains styles for buttons.

View File

@ -25968,18 +25968,6 @@ form.popupform div {
overflow: auto;
}
.no-overflow > .generaltable {
margin-bottom: 0;
}
.no-overflow .generaltable .visually-hidden,
.no-overflow .generaltable .accesshide,
.table-responsive .generaltable .visually-hidden,
.table-responsive .generaltable .accesshide {
position: relative;
display: block;
}
.accesshide {
width: 1px !important;
height: 1px !important;
@ -37126,6 +37114,18 @@ table .sticky-column {
font-size: 3rem;
}
.table-responsive .dropdown {
position: static !important; /* stylelint-disable-line declaration-no-important */
}
.table-responsive .table {
margin-bottom: 0;
}
.table-responsive .table .visually-hidden,
.table-responsive .table .accesshide {
position: relative !important; /* stylelint-disable-line declaration-no-important */
display: block;
}
/**
* File buttons.scss.
* Contains styles for buttons.