Major changes in tabs and accordion modules (see DEVLOG)

This commit is contained in:
Angelos Chalaris 2016-11-09 23:02:27 +02:00
parent 15f9f47c06
commit e9750940ad
8 changed files with 200 additions and 101 deletions

View file

@ -342,3 +342,18 @@
- Softcoded `tab` module with variables. Optimized.
- Added responsiveness to `tab` module.
- Tested `tab` module thoroughly on both Firefox and Chrome (PC), will test further on phone.
- *DESIGN DECISION* The `accordion` and collapse module will be merged with the `tab` and carousel module. This is a very well-thought out decision, based on the fact that `accordion` components behave like `stacked` `tab` components. This means that users will be forced to use a heavier module for both components (which might not be beneficial if they only wish to use the `accordion` component), however this helps users mnemonically, by allowing more functionality in one technically identical structure. The specifics of this decision are laid out below:
1. The `stacked` class will be used for a `tabs` container, so that an `accordion` component can be easily emulated.
2. Some of the versatility of the `accordion` class will be sacrificed to allow `stacked` `tabs` to include the same functionality. Minor changes can still be made manually.
3. The `tabs` module will use different transformation tricks for `stacked` and normal tabs. Specifically, the responsive stacked tabs on smaller screens will use preset `height`, while `stacked` tabs will use `height: auto;`.
4. All controls for both types of `tab`s will be hidden from screen readers to make the content accessible as-is.
5. The old `accordion` module will be retired and possibly stored in a legacy folder. People that only want that old-school `accordion` module can use it.
6. `stacked` `tabs` will allow both `checkbox` and `radio` `input`s, normal ones will not allow `checkbox`. This is in line with the philosophy of the two components.
7. Carousels can still be built using any of the two styles.
8. `stacked` `tabs` will feature their own color scheme for some things to allow more customization within the module.
9. Both components will use a generic `:hover` effect.
10. The `transform`s applied before to `accordion` will still apply to `stacked` `tabs`.
- Refactored code of `tabs` to work with the above decision, removed obsolete artifacts from the `accordion` module.
- Made a few minor tweaks, decided not to add `accordion`-specific styling, as the current styling is just enough.
- Edited the demo page to include most of the new functionality.
- *TODO* Move `_accordion.scss` to the `legacy` folder etc.

View file

@ -470,21 +470,29 @@
</div>
</div>
</div>
<h2>Content display <small>Present content any way you like</small></h2>
<p><strong>mini.css</strong> gives you some flexible components to show or hide the content you wish. These components are more generic than the ones found in other frameworks and aim to help you present any content the way you like. </p><br>
<h3>Accordion &amp; Collapse</h3>
<p>Use the <code>.accordion</code> class on a <code>&lt;input type=&quot;checkbox&quot;&gt;</code> or <code>&lt;input type=&quot;radio&quot;&gt;</code>, accompanied by a linked <code>&lt;label&gt;</code> and any content afterwards (use something like a <code>&lt;div&gt;</code> if you want to show/hide more than a paragraph of text or an image) to create a collapsible piece of content. Use multiple of these to create an accordion if you like. These components are accessible, although screen readers will read these as normal blocks of content, no distinctions made. Add <code>aria-hidden=&quot;true&quot;</code> to the <code>&lt;label&gt;</code> to make sure there are no confusing elements. Below, you can see a couple of examples:</p>
<input type="checkbox" class="accordion" id="ac1" autocomplete="off"><label for="ac1">Toggle content</label>
<p>This is some content you can hide and show at will using the above label. Isn't that useful?</p>
<input type="checkbox" class="accordion" id="ac2" autocomplete="off"><label for="ac2">Toggle image</label>
<img src="catdemo.jpg">
<br>
<input type="radio" class="accordion" id="acr1" autocomplete="off" name="acr"><label for="acr1">Section 1</label>
<div><h4>Sample</h4> <p>This is the first piece of the accordion. These pieces are mutually exclusive.</p></div>
<input type="radio" class="accordion" id="acr2" autocomplete="off" name="acr"><label for="acr2">Section 2</label>
<div><h4>Demo</h4> <p>This is the second piece of the accordion. Notice how these samples use <code>&lt;div&gt;</code> to display more complex content.</p></div>
<h3>Tabs &amp; Carousels</h3>
<p>Tabbed navigation is a very common element for many websites and single page apps. Carousels provide similar functionality for image portfolios. <strong>mini.css</strong> supports both of these elements using one generic component. Simply create a container with the <code>.tabs</code> class, add a few <code>&lt;label&gt;</code>s inside it, add the complementary <code>&lt;input type=&quot;radio&quot;&gt;</code>s each followed by each tab's content inside a <code>&lt;div&gt;</code> or <code>&lt;section&gt;</code> and you are ready to go. Tabs are accessible, as screen readers will ignore the tab labels and only read the content. Remember to add <code>aria-hidden=&quot;true&quot;</code> to the <code>&lt;label&gt;</code>s. Oh, by the way, tabs are responsive on mobile and will display as a list on smaller displays, so that your users will not have any trouble navigating them. You can see examples of how tabs work below:</p>
<h2>Tabs &amp; accordions<small>Present content any way you like</small></h2>
<p><strong>mini.css</strong> provides you with a very modern tab component, that can easily be used for multiple things, like tabbed navigation, single collapses, accordion collapses and even image carousels. This might sound like a lot to do with one component, but the design behind it allows it to be truly versatile and replace all those components. To use the tab component, simply create a container using a <code>&lt;div&gt;</code> with the <code>.tabs</code> class. Populate it with <code>&lt;input type=&quot;radio&quot;&gt;</code>s, each followed by a linked <code>&lt;label&gt;</code> and another <code>&lt;div&gt;</code> which includes the tab's contents. If you want to create an accordion add the <code>.stacked</code> class to the container. The same thing works for collapses as well. Accordions and collapses can also use <code>&lt;input type=&quot;checkbox&quot;&gt;</code>s instead. Carousels can be created similarly, remember to add images to the inner content <code>&lt;div&gt;</code> and you're good to go. You can see some examples below:</p><br>
<div class="tabs stacked">
<input type="checkbox" id="collapse" autocomplete="off">
<label for="collapse">Single collapse</label>
<div>
<p>This is some content you can hide and show at will using the above label. Isn't that useful?</p>
</div>
</div><br>
<div class="tabs stacked">
<input type="radio" name="accordion" id="a1" autocomplete="off" checked>
<label for="a1">Accordion section 1</label>
<div>
<h3>Section 1 - The amazing versatility of tabs</h3>
<p>Yes, this is still based on tabs. Isn't it wonderful how many things you can accomplish using one simple component?</p>
</div>
<input type="radio" name="accordion" id="a2" autocomplete="off">
<label for="a2">Accordion section 2</label>
<div>
<h3>Section 2 - How accordions work</h3>
<p>Accordions are very similar to collapses. Just add multiple <code>&lt;input type=&quot;radio&quot;&gt;</code>s, along with their content and you are ready to go.</p>
</div>
</div><br>
<div class="tabs">
<input type="radio" name="tabdemo" id="tab1" checked>
<label for="tab1">Tab 1</label>
@ -510,7 +518,24 @@
<h3>Tab 4</h3>
<p>This is the fourth tab's content.</p>
</div>
</div>
</div><br>
<div class="tabs">
<input type="radio" name="carousel" id="car1" checked>
<label for="car1">Image 1</label>
<div>
<img src="catdemo.jpg" style="height: 240px; width: auto;">
</div>
<input type="radio" name="carousel" id="car2">
<label for="car2">Image 2</label>
<div>
<img src="catdemo.jpg" style="height: 480px; width: auto">
</div>
<input type="radio" name="carousel" id="car3">
<label for="car3">Image 3</label>
<div>
<img src="catdemo.jpg" style="height: 720px; width: auto">
</div>
</div><br>
<h2>Spinners<small>Loading with style</small></h2>
<p>Finally, <strong>mini.css</strong> provides you with a couple of spinner variations, <code>.spinner-dot</code> and <code>.spinner-donut</code>. Simply apply these to a <code>&lt;div&gt;</code> and you are ready to go. Both are showcased below:</p>
<p>This is some text with a <code>.spinner-dot</code> spinner. These spinners are designed with normal paragraphs in mind, so some tweaking of the component itself and/or the way it is presented might be requird. Loading looks like this <span class="spinner-dot"></span></p>

View file

@ -824,56 +824,9 @@ progress {
@media only screen and (min-width: 320px) {
.card {
max-width: 320px; } }
[type="checkbox"].accordion, [type="radio"].accordion {
display: none;
visibility: hidden; }
[type="checkbox"].accordion + label, [type="radio"].accordion + label {
display: block;
cursor: pointer;
background: #e0e0e0;
border: 1px solid #9e9e9e;
border-radius: 2px;
padding: 6px 10px 6px;
margin-bottom: 2px; }
[type="checkbox"].accordion + label + *, [type="radio"].accordion + label + * {
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
position: absolute;
clip: rect(0 0 0 0);
-webkit-clip-path: inset(100%);
clip-path: inset(100%);
-webkit-transform: scaleY(0);
transform: scaleY(0);
-webkit-transform-origin: top;
transform-origin: top;
transition: transform 0.3s ease 0s; }
[type="checkbox"].accordion:checked + label, [type="radio"].accordion:checked + label {
margin-bottom: 0;
border-bottom: 1px solid #bdbdbd;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0; }
[type="checkbox"].accordion:checked + label + *, [type="radio"].accordion:checked + label + * {
box-sizing: border-box;
position: relative;
height: auto;
width: 100%;
margin: 0;
clip: auto;
-webkit-clip-path: inset(0%);
clip-path: inset(0%);
-webkit-transform: scaleY(1);
transform: scaleY(1);
border: 1px solid #9e9e9e;
border-top: 0;
border-bottom-right-radius: 2px;
border-bottom-left-radius: 2px;
padding: 6px 10px 8px;
margin-bottom: 2px; }
.tabs {
width: 100%;
opacity: 1;
display: -webkit-box;
-webkit-box-pack: justify;
display: -webkit-flex;
@ -891,17 +844,20 @@ progress {
display: inline-block;
height: 26px;
cursor: pointer;
background: #e0e0e0;
border: 1px solid #9e9e9e;
transition: background 0.3s ease 0s;
background: #b0bec5;
border: 1px solid #78909c;
padding: 4px 6px; }
.tabs > label:first-of-type {
border-top-left-radius: 2px; }
.tabs > label:last-of-type {
border-top-right-radius: 2px; }
.tabs > [type="radio"] {
.tabs > label:hover, .tabs > label:active, .tabs > label:focus {
background: rgba(176, 190, 197, 0.75); }
.tabs > [type="radio"], .tabs.stacked > [type="checkbox"] {
display: none;
visibility: hidden; }
.tabs > [type="radio"] + label + div {
.tabs > [type="radio"] + label + div, .tabs.stacked > [type="checkbox"] + label + div {
-webkit-flex-basis: auto;
flex-basis: auto;
-webkit-order: 2;
@ -917,24 +873,64 @@ progress {
transition: height 0.3s ease 0s;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px; }
.tabs > [type="radio"] + label + div + [type="radio"] + label {
.tabs > [type="radio"] + label + div + [type="radio"] + label, .tabs.stacked > [type="checkbox"] + label + div + [type="radio"] + label {
border-left: 0; }
.tabs > [type="radio"]:checked + label {
background: #bdbdbd; }
.tabs > [type="radio"]:checked + label + div {
.tabs.stacked > [type="checkbox"] + label + div + [type="checkbox"] + label {
border-left: 0; }
.tabs > [type="radio"]:checked + label, .tabs.stacked > [type="checkbox"]:checked + label {
background: #cfd8dc; }
.tabs > [type="radio"]:checked + label:hover, .tabs > [type="radio"]:checked + label:active, .tabs > [type="radio"]:checked + label:focus, .tabs.stacked > [type="checkbox"]:checked + label:hover, .tabs.stacked > [type="checkbox"]:checked + label:active, .tabs.stacked > [type="checkbox"]:checked + label:focus {
background: rgba(207, 216, 220, 0.75); }
.tabs > [type="radio"]:checked + label + div, .tabs.stacked > [type="checkbox"]:checked + label + div {
box-sizing: border-box;
position: relative;
height: 400px;
width: 100%;
overflow: auto;
margin: 0;
border: 1px solid #9e9e9e;
border: 1px solid #78909c;
border-top: 0;
padding: 6px;
clip: auto;
-webkit-clip-path: inset(0%);
clip-path: inset(0%); }
.tabs.stacked {
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
flex-direction: column; }
.tabs.stacked > label {
-webkit-order: initial;
order: initial; }
.tabs.stacked > label:first-of-type {
border-top-right-radius: 2px; }
.tabs.stacked > label:last-of-type {
border-top-right-radius: 0;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px; }
.tabs.stacked > [type="radio"]:checked + label, .tabs.stacked > [type="checkbox"]:checked + label {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0; }
.tabs.stacked > [type="radio"] + label + div, .tabs.stacked > [type="checkbox"] + label + div {
-webkit-order: initial;
order: initial;
-webkit-transform: scaleY(0);
transform: scaleY(0);
-webkit-transform-origin: top;
transform-origin: top;
transition: -webkit-transform 0.3s ease 0s, transform 0.3s ease 0s;
border-radius: 0; }
.tabs.stacked > [type="radio"] + label + div + [type="radio"] + label, .tabs.stacked > [type="radio"] + label + div + [type="checkbox"] + label, .tabs.stacked > [type="checkbox"] + label + div + [type="radio"] + label, .tabs.stacked > [type="checkbox"] + label + div + [type="checkbox"] + label {
border: 1px solid #78909c;
border-top: 0; }
.tabs.stacked > [type="radio"]:checked + label + div, .tabs.stacked > [type="checkbox"]:checked + label + div {
height: auto;
-webkit-transform: scaleY(1);
transform: scaleY(1); }
.tabs.stacked > [type="radio"] + label + div:last-of-type, .tabs.stacked > [type="checkbox"] + label + div:last-of-type {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px; }
@media only screen and (max-width: 800px) {
.tabs {
-webkit-box-orient: vertical;
@ -957,7 +953,7 @@ progress {
order: initial;
border-radius: 0; }
.tabs > [type="radio"] + label + div + [type="radio"] + label {
border: 1px solid #9e9e9e;
border: 1px solid #78909c;
border-top: 0; }
.tabs > [type="radio"] + label + div:last-of-type {
border-bottom-left-radius: 2px;

File diff suppressed because one or more lines are too long

View file

@ -346,34 +346,25 @@ $card-section-padding1-name: 'double-padded'; // Class name for card sect
$card-section-padding1-padding: 12px 16px 12px; // Padding for card section padding style 1
// Notes:
// [1] - The cards module depends heavily on the grid system module.
// Variables for accordions/collapses
$accordion-name: 'accordion'; // Class name for accordions/collapses
$accordion-label-back-color: #e0e0e0; // Background color for accordion label
$accordion-label-fore-color: $fore-color; // Text color for accordion label
$accordion-label-padding: 6px 10px 6px; // Padding for accordion label
$accordion-content-back-color: $back-color; // Background color for accordion content
$accordion-content-fore-color: $fore-color; // Text color for accordion content
$accordion-content-padding: 6px 10px 8px; // Padding for accordion content
$accordion-border-style: 1px solid #9e9e9e; // Border style for accordion
$accordion-border-radius: 2px; // Border radius for accordion
$accordion-margin-bottom: 2px; // Bottom margin for accordion
$accordion-separator-border-style: // Border style for the accordion's separators
1px solid #bdbdbd; // (border between label and content)
// Variables for tabs
// Variables for tabs [1]
$tab-container-name: 'tabs'; // Class name for the tabs' container
$tab-label-back-color: #e0e0e0; // Background color for tabs' labels
$tab-label-back-color: #b0bec5; // Background color for tabs' labels
$tab-label-fore-color: $fore-color; // Text color for tabs' labels
$tab-label-selected-back-color: #bdbdbd; // Background color for open tab's label
$tab-label-selected-back-color: #cfd8dc; // Background color for open tab's label
$tab-label-selected-fore-color: $fore-color; // Text color for open tab's label
$tab-label-hover-opacity: 0.75; // Opacity of the tab's label on hover
$tab-label-padding: 4px 6px; // Padding for tabs' labels
$tab-label-height: 26px; // Height for tabs' labels
$tab-border-style: 1px solid #9e9e9e; // Border style for tabs
$tab-border-style: 1px solid #78909c; // Border style for tabs
$tab-border-radius: 2px; // Border radius for tabs
$tab-panel-back-color: $back-color; // Background color for tabs' panels
$tab-panel-fore-color: $fore-color; // Text color for tabs' panels
$tab-panel-padding: 6px; // Padding for tabs' panels
$tab-panel-height: 400px; // Height for tabs' panels
$tab-stacked-breakpoint: $grid-medium-breakpoint; // Breakpoint for tabs layout (stacked/horizontal)
$tab-stacked-name: 'stacked'; // Class name for stacked tabs
// Notes:
// [1] - The tabs module is somewhat dependent on the grid system module.
// Variables for spinners
$spinner-dot-name: 'spinner-dot'; // Class name for dot spinner
$spinner-dot-font-size: 1em; // Font size for dot spinner

View file

@ -369,7 +369,6 @@ a{
//===================================================
// You can comment out modules you do not want to use.
@import 'mini-shell/card';
@import 'mini-shell/accordion';
@import 'mini-shell/tab';
@import 'mini-shell/spinner';
//===================================================

View file

@ -2,8 +2,10 @@
// Dependency: This module is somewhat dependent on the grid system.
// Tab styling
$tab-container-name: 'tabs' !default; // Class name for the tabs container
$tab-stacked-name: 'stacked' !default; // Class name for stacked tabs container
.#{$tab-container-name} {
width: 100%;
opacity: 1;
// Old syntax
display: -webkit-box;
-webkit-box-pack: justify;
@ -28,6 +30,7 @@ $tab-container-name: 'tabs' !default; // Class name for the tabs contai
display: inline-block;
height: $tab-label-height;
cursor: pointer;
transition: background 0.3s ease 0s;
@if $tab-label-back-color != $back-color {
background: $tab-label-back-color;
}
@ -48,15 +51,18 @@ $tab-container-name: 'tabs' !default; // Class name for the tabs contai
border-top-right-radius: $tab-border-radius;
}
}
// TODO ADD HOVER STYLES HERE AND ON ACCORDION
// Hover styling for tabs' labels
&:hover, &:active, &:focus {
background: rgba($tab-label-back-color, $tab-label-hover-opacity);
}
}
// Tab radio styling
& > [type="radio"] {
& > [type="radio"], &.#{$tab-stacked-name} > [type="checkbox"] {
display: none;
visibility: hidden;
}
// Tab content styling
& > [type="radio"] + label + div {
& > [type="radio"] + label + div, &.#{$tab-stacked-name} > [type="checkbox"] + label + div {
// New syntax
-webkit-flex-basis: auto;
flex-basis: auto;
@ -75,7 +81,7 @@ $tab-container-name: 'tabs' !default; // Class name for the tabs contai
transition: height 0.3s ease 0s;
// Style for tab labels except the first
@if $tab-border-style != 0 {
+ [type="radio"] + label {
& + [type="radio"] + label{
border-left: 0;
}
}
@ -84,17 +90,25 @@ $tab-container-name: 'tabs' !default; // Class name for the tabs contai
border-bottom-right-radius: $tab-border-radius;
}
}
@if $tab-border-style != 0 {
&.stacked > [type="checkbox"] + label + div + [type="checkbox"] + label {
border-left: 0;
}
}
// Tab label styling for open tab
& > [type="radio"]:checked + label {
& > [type="radio"]:checked + label, &.#{$tab-stacked-name} > [type="checkbox"]:checked + label {
@if $tab-label-selected-back-color != $tab-label-back-color {
background: $tab-label-selected-back-color;
&:hover, &:active, &:focus {
background: rgba($tab-label-selected-back-color, $tab-label-hover-opacity);
}
}
@if $tab-label-selected-fore-color != $tab-label-fore-color {
color: $tab-label-selected-fore-color;
}
}
// Tab content styling (open tab)
& > [type="radio"]:checked + label + div {
& > [type="radio"]:checked + label + div, &.#{$tab-stacked-name} > [type="checkbox"]:checked + label + div {
box-sizing: border-box;
position: relative;
height: $tab-panel-height;
@ -120,6 +134,65 @@ $tab-container-name: 'tabs' !default; // Class name for the tabs contai
clip-path: inset(0%);
}
}
// Stacked tabs
.#{$tab-container-name}.#{$tab-stacked-name} {
// Old syntax
-webkit-box-orient: vertical;
// New syntax
-webkit-flex-direction: column;
flex-direction: column;
& > label {
-webkit-order: initial; // Reset order to show stacked tabs properly
order: initial;
@if $tab-border-radius != 0 { // Style first and last tabs' labels' corners as needed
&:first-of-type {
border-top-right-radius: $tab-border-radius;
}
&:last-of-type {
border-top-right-radius: 0;
border-bottom-left-radius: $tab-border-radius;
border-bottom-right-radius: $tab-border-radius;
}
}
}
@if $tab-border-radius != 0 { // Style the last tabs' label corners when it's open as needed
& > [type="radio"]:checked + label, & > [type="checkbox"]:checked + label {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
& > [type="radio"] + label + div, & > [type="checkbox"] + label + div {
-webkit-order: initial; // Reset order to show stacked tabs properly
order: initial;
// Presentation
-webkit-transform: scaleY(0);
transform: scaleY(0);
-webkit-transform-origin: top;
transform-origin: top;
transition: -webkit-transform 0.3s ease 0s,
transform 0.3s ease 0s;
@if $tab-border-radius != 0 {
border-radius: 0;
}
& + [type="radio"] + label, & + [type="checkbox"] + label {
@if $tab-border-style != 0 {
border: $tab-border-style;
border-top: 0;
}
}
}
& > [type="radio"]:checked + label + div, & > [type="checkbox"]:checked + label + div {
height: auto;
-webkit-transform: scaleY(1);
transform: scaleY(1);
}
@if $tab-border-radius != 0 {
& > [type="radio"] + label + div:last-of-type, & > [type="checkbox"] + label + div:last-of-type {
border-bottom-left-radius: $tab-border-radius;
border-bottom-right-radius: $tab-border-radius;
}
}
}
// Responsiveness
@media only screen and (max-width: #{$tab-stacked-breakpoint}) {
.#{$tab-container-name} {