mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-23 10:41:16 +08:00
Image manager: supported a tabbed interface on mobile
Makes interface relatively usable now on mobile sizes. Required updating of tab handling to support tabs being active at only mobile screen sizes, include change on resize, upon support for potentially nested tab usage. Tab component will now search within sensible depths for finding its own tabs and panels to control.
This commit is contained in:
parent
dc6133c4c4
commit
946c9ae804
|
@ -21,15 +21,23 @@ export class Tabs extends Component {
|
|||
|
||||
setup() {
|
||||
this.container = this.$el;
|
||||
this.tabs = Array.from(this.container.querySelectorAll('[role="tab"]'));
|
||||
this.panels = Array.from(this.container.querySelectorAll('[role="tabpanel"]'));
|
||||
this.tabList = this.container.querySelector('[role="tablist"]');
|
||||
this.tabs = Array.from(this.tabList.querySelectorAll('[role="tab"]'));
|
||||
this.panels = Array.from(this.container.querySelectorAll(':scope > [role="tabpanel"], :scope > * > [role="tabpanel"]'));
|
||||
this.activeUnder = this.$opts.activeUnder ? Number(this.$opts.activeUnder) : 10000;
|
||||
this.active = null;
|
||||
|
||||
this.container.addEventListener('click', event => {
|
||||
const button = event.target.closest('[role="tab"]');
|
||||
if (button) {
|
||||
this.show(button.getAttribute('aria-controls'));
|
||||
const tab = event.target.closest('[role="tab"]');
|
||||
if (tab && this.tabs.includes(tab)) {
|
||||
this.show(tab.getAttribute('aria-controls'));
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', this.updateActiveState.bind(this), {
|
||||
passive: true,
|
||||
});
|
||||
this.updateActiveState();
|
||||
}
|
||||
|
||||
show(sectionId) {
|
||||
|
@ -46,4 +54,34 @@ export class Tabs extends Component {
|
|||
this.$emit('change', {showing: sectionId});
|
||||
}
|
||||
|
||||
updateActiveState() {
|
||||
const active = window.innerWidth < this.activeUnder;
|
||||
if (active === this.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (active) {
|
||||
this.activate();
|
||||
} else {
|
||||
this.deactivate();
|
||||
}
|
||||
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.show(this.panels[0].id);
|
||||
this.tabList.toggleAttribute('hidden', false);
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
for (const panel of this.panels) {
|
||||
panel.removeAttribute('hidden');
|
||||
}
|
||||
for (const tab of this.tabs) {
|
||||
tab.setAttribute('aria-selected', 'false');
|
||||
}
|
||||
this.tabList.toggleAttribute('hidden', true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -380,6 +380,12 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
|||
background-color: #FFF;
|
||||
}
|
||||
}
|
||||
|
||||
@include smaller-than($s) {
|
||||
.image-manager-filter-bar .contained-search-box input {
|
||||
width: 180px;
|
||||
}
|
||||
}
|
||||
.image-manager-filters {
|
||||
box-shadow: $bs-med;
|
||||
border-radius: 4px;
|
||||
|
@ -475,6 +481,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
|||
|
||||
.image-manager-sidebar {
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
border-inline-start: 1px solid #DDD;
|
||||
|
@ -500,6 +507,11 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
|||
}
|
||||
}
|
||||
}
|
||||
@include smaller-than($m) {
|
||||
.image-manager-sidebar {
|
||||
border-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.image-manager-content {
|
||||
display: flex;
|
||||
|
|
|
@ -298,6 +298,10 @@ body.flexbox {
|
|||
}
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Border radiuses
|
||||
*/
|
||||
|
|
|
@ -24,9 +24,29 @@
|
|||
<button refs="popup@hide" type="button" class="popup-header-close">@icon('close')</button>
|
||||
</div>
|
||||
|
||||
<div refs="dropzone@drop-target" class="flex-fill image-manager-body">
|
||||
<div class="image-manager-content">
|
||||
<div class="image-manager-filter-bar flex-container-row justify-space-between">
|
||||
<div component="tabs"
|
||||
option:tabs:active-under="880"
|
||||
refs="dropzone@drop-target"
|
||||
class="flex-container-column image-manager-body">
|
||||
<div class="tab-container">
|
||||
<div role="tablist" class="hide-over-m mb-none">
|
||||
<button id="image-manager-list-tab"
|
||||
aria-selected="true"
|
||||
aria-controls="image-manager-list"
|
||||
role="tab">Image List</button>
|
||||
<button id="image-manager-info-tab"
|
||||
aria-selected="true"
|
||||
aria-controls="image-manager-info"
|
||||
role="tab">Image Details</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-container-row flex-fill">
|
||||
<div id="image-manager-list"
|
||||
tabindex="0"
|
||||
role="tabpanel"
|
||||
aria-labelledby="image-manager-list-tab"
|
||||
class="image-manager-content">
|
||||
<div class="image-manager-filter-bar flex-container-row wrap justify-space-between">
|
||||
<div class="primary-background image-manager-filter-bar-bg"></div>
|
||||
<div>
|
||||
<form refs="image-manager@searchForm" class="contained-search-box">
|
||||
|
@ -70,7 +90,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="image-manager-sidebar flex-container-column">
|
||||
<div id="image-manager-info"
|
||||
tabindex="0"
|
||||
role="tabpanel"
|
||||
aria-labelledby="image-manager-info-tab"
|
||||
class="image-manager-sidebar flex-container-column">
|
||||
|
||||
<div refs="image-manager@dropzoneContainer">
|
||||
<div refs="dropzone@status-area"></div>
|
||||
|
@ -84,7 +108,7 @@
|
|||
<div refs="image-manager@formContainer" class="inner flex">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="popup-footer">
|
||||
|
|
Loading…
Reference in New Issue
Block a user