Modal
The fullscreen Modal can be used for stuff that doesn't really work in an Aside. Note that this component is in development, the design and APIs may change.
The Modal
component must be created with a child component Panel
.
<dialog data-ts="Modal">
<div data-ts="Panel">
<p>Modal content.</p>
</div>
</dialog>
You can create the Modal
wherever you like, just make sure that it's positioned outside of the Main
element when it opens.
<main data-ts="Main">
<p>Main content.</p>
</main>
<dialog data-ts="Modal" data-ts.title="Example Modal">
<div data-ts="Panel">
<p>Modal content.</p>
</div>
</dialog>
Title and layout
The data-ts.title
attribute configures the Modal title. You can also choose to add a Main
element to center the content.
<dialog data-ts="Modal" id="example1">
<div data-ts="Panel">
<main data-ts="Main">
<h1>A Modal Example</h1>
<p>…</p>
<p>
<button onclick="ts.ui.get('#example1').close()" class="ts-primary">
<span>Close the Modal</span>
</button>
</p>
</main>
</div>
</dialog>
Let's see how that looks. To open the Modal, you can either set the data-ts.open
attribute to true
(using jQuery or something like that) or you can use the following API.
ts.ui.get('#example1').open(); // you can pass an element instead of an ID
Adding some buttons
Buttons can be added as part of the content, but some Modals work better when the buttons are presented in a fixed StatusBar, for example when there is a lot of content (and scrolling). These buttons can be added using the API we know from the ToolBar.
ts.ui.get('#example2', modal => {
modal.buttons([{
label: 'Close the Modal',
type: 'ts-primary',
onclick: function() {
modal.close();
}
}]).open();
});
TODO: Enable keyboard focus in the Modal StatusBar.
Here"s a summary of the buttons
collection and button
model.
Adding some tabs
There's two ways to add tabs and one of them is likely to fit your workflow. First, we will add some tabs to the example modal using the API we know from the TabBar.
ts.ui.get('#example1', modal => {
modal.tabs([
{label: 'One'},
{label: 'Two'},
{label: 'Three', onselect: function() {
console.log('Tab three selected!');
}},
]).open();
});
The tabs don"t do anything by default, so what happens at onselect
is completely up to you. If you decice to go with this approach, you should make sure to read the section on busy and done further down the page.
The alternative approach is to declare multiple Panel
elements with a data-ts.label
attribute and this will generate the tabs automatically as seen in this example.
<dialog data-ts="Modal">
<div data-ts="Panel" data-ts.label="Details">
<main data-ts="Main">…</main>
</div>
<div data-ts="Panel" data-ts.label="More Details">
<main data-ts="Main">…</main>
</div>
</dialog>
Note that even if the tabs are automatically generated via Panel
elements, it is still possible to manipulate the tabs programatically.
ts.ui.get('#mymodal', modal => {
var tabs = modal.tabs();
tabs[0].select();
tabs.reverse();
});
Here"s a summary of the tabs
collection and tab
model.
Busy and done
If you are loading the Modal tabs incrementally (so that the content is not hardcoded inside Panels
), you may want to mark the Modal as busy()
and done()
to hide the content while loading. Importantly, if you are using Main
to center the content, this will also instruct the Modal to center the the newly loaded content all over again.
ts.ui.get('#example4', modal => {
function load(page) {
modal.busy();
setTimeout(function throttle() {
$.get(page, function(html) {
modal.html(html).done();
});
}, 200);
}
modal.tabs([
{label: 'Page One', onselect: function() {
load('page1.html');
}},
{label: 'Page Two', onselect: function() {
load('page2.html');
}},
]).open();
});
Note that you can also call modal.reflex()
to center the Main
at any point in time.
Showing a spinner
If you expect the server to respond particularly slowly today, you can also use the equivalent methods spin()
and stop()
to display a spinner while loading.
Tracking the state
You can implement the methods onopen
, onopened
, onclose
and onclosed
to do something whenever the Modal changes state.
ts.ui.get(myelement, modal => {
Object.assign(modal, {
onopen: () => console.log('Will open'),
onopened: () => console.log('Did open'),
onclose: () => console.log('Will close'),
onclosed: () => console.log('Did close')
});
});
If you return false
in methods onopen
and onclose
, the Modal will respect that. You can also setup inline callbacks to be invoked when the Modal changes state.
<dialog data-ts="Modal"
data-ts.onopen="console.log('Will open')"
data-ts.onopened="console.log('Did open')"
data-ts.onclose="console.log('Will close')"
data-ts.onclosed="console.log('Did close')">
<div data-ts="Panel">
<p>Modal content.</p>
</div>
</dialog>
Finally, you can also track the state with some custom DOM events if you like.
function debug(e) {
console.log(e.type, e.target);
}
document.addEventListener('ts-open', debug);
document.addEventListener('ts-opened', debug);
document.addEventListener('ts-close', debug);
document.addEventListener('ts-closed', debug);
The events ts-open
and ts-close
can be blocked with e.preventDefault()
to prevent the Modal from changing state.
Here's finally an overview of the Modal API.