#6828: Fix various mobile UI issues

This commit is contained in:
checktheroads 2021-07-30 00:35:38 -07:00
parent 37c81ecec1
commit 35ecd1494f
14 changed files with 132 additions and 60 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -32,9 +32,7 @@ function handleSearchDropdownClick(event: Event, button: HTMLButtonElement) {
* Initialize Search Bar Elements.
*/
function initSearchBar() {
for (const dropdown of getElements<HTMLUListElement>(
'div.search-container ul.search-obj-selector',
)) {
for (const dropdown of getElements<HTMLUListElement>('.search-obj-selector')) {
for (const button of dropdown.querySelectorAll<HTMLButtonElement>(
'li > button.dropdown-item',
)) {

View File

@ -172,6 +172,34 @@ table td > .progress {
min-width: 6rem;
}
.nav-mobile {
display: none;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 100%;
@include media-breakpoint-down(lg) {
display: flex;
}
.nav-mobile-top {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
}
.search-container {
display: flex;
width: 100%;
@include media-breakpoint-down(lg) {
display: none;
}
}
.card > .table.table-flush {
margin-bottom: 0;
overflow: hidden;
@ -414,6 +442,18 @@ main.login-container {
}
}
.footer {
padding-top: map.get($spacers, 4);
padding-right: 0;
padding-bottom: map.get($spacers, 3);
padding-left: 0;
@include media-breakpoint-down(md) {
// Pad the bottom of the footer on mobile devices to account for mobile browser controls.
margin-bottom: 8rem;
}
}
footer.login-footer {
height: 4rem;
margin-top: auto;
@ -658,6 +698,11 @@ div.content-container {
}
.search-obj-selector {
@include media-breakpoint-down(lg) {
// Limit the height and enable scrolling on mobile devices.
max-height: 75vh;
overflow-y: auto;
}
.dropdown-item,
.dropdown-header {
font-size: $font-size-sm;
@ -833,7 +878,7 @@ div.field-group:not(:first-of-type) {
label.required {
font-weight: $font-weight-bold;
&::after {
&:after {
font-family: 'Material Design Icons';
content: '\f06C4';
font-weight: normal;
@ -853,29 +898,34 @@ div.bulk-buttons {
display: flex;
justify-content: space-between;
margin: $spacer / 2 0;
// Each group of buttons needs to be contained separately for alignment purposes. This way, you
// can put some buttons in a group that aligns left, and other buttons in a group that aligns
// right.
& > div.bulk-button-group {
> div.bulk-button-group {
display: flex;
flex-wrap: wrap;
&:first-of-type:not(:last-of-type) {
// If there are multiple bulk button groups and this is the first, the first button in the
// group should *not* have left spacing applied, so the button group aligns with the rest
// of the page elements.
& > *:first-child {
> *:first-child {
margin-left: 0;
}
}
&:last-of-type:not(:first-of-type) {
// If there are multiple bulk button groups and this is the last, the last button in the
// group should *not* have right spacing applied, so the button group aligns with the rest
// of the page elements.
& > *:last-child {
> *:last-child {
margin-right: 0;
}
}
// However, the rest of the buttons should have spacing applied in all directions.
& > * {
> * {
margin: $spacer / 4;
}
}

View File

@ -80,12 +80,22 @@ $transition-100ms-ease-in-out: all 0.1s ease-in-out;
border-right: 1px solid $border-color;
transition: $transition-100ms-ease-in-out;
// Media fixes for iPhone 5 like resolutions
// Media fixes for mobile resolutions.
@include media-breakpoint-down(lg) {
transform: translateX(-$sidenav-width-closed);
+ .content-container[class] {
margin-left: 0;
}
.profile-button-container[class] {
display: block;
}
}
.profile-button-container {
display: none;
padding: $sidenav-link-spacing-y $sidenav-link-spacing-x;
}
+ .content-container {
@ -322,6 +332,7 @@ $transition-100ms-ease-in-out: all 0.1s ease-in-out;
position: absolute;
opacity: 0;
}
@include media-breakpoint-down(lg) {
transform: translateX(0);
}
@ -331,14 +342,17 @@ $transition-100ms-ease-in-out: all 0.1s ease-in-out;
.sidenav-header {
padding: $spacer * 0.5;
}
.sidenav-brand {
position: absolute;
opacity: 0;
transform: translateX(-150%);
}
.sidenav-brand-icon {
opacity: 1;
}
.navbar-nav > .nav-item {
> .nav-link {
&:after {
@ -354,6 +368,7 @@ $transition-100ms-ease-in-out: all 0.1s ease-in-out;
.nav-link-text {
opacity: 0;
}
@include parent-link() {
&.active {
margin-right: 0;

View File

@ -15,7 +15,7 @@
<meta charset="UTF-8" />
<meta
name="viewport"
content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"
content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width, viewport-fit=cover"
/>
{# Page title #}

View File

@ -19,17 +19,22 @@
<nav class="navbar navbar-light sticky-top flex-md-nowrap ps-6 p-3 search container-fluid">
{# Mobile Navigation #}
<div class="d-md-none w-100 d-flex justify-content-between align-items-center my-3">
<a class="p-2 sidebar-logo d-block d-md-none" href="{% url 'home' %}">
<img src="{% static 'netbox_logo.svg' %}" alt="NetBox logo" width="100%" />
<div class="nav-mobile">
<div class="nav-mobile-top">
<a class="sidebar-logo p-2 d-block" href="{% url 'home' %}">
<img src="{% static 'netbox_logo.svg' %}" alt="NetBox logo" width="75%" />
</a>
<button type="button" aria-label="Toggle Navigation" class="navbar-toggler sidenav-toggle-mobile">
<span class="navbar-toggler-icon"></span>
</button>
</div>
<div class="d-flex my-1 flex-grow-1 justify-content-center">
{% search_options %}
</div>
</div>
{# Desktop Navigation #}
<div class="d-none d-md-flex w-100 row search-container">
<div class="row search-container">
{# Empty spacer column to ensure search is centered. #}
<div class="col-3 d-flex flex-grow-1 ps-0"></div>
@ -95,12 +100,13 @@
{% endif %}
{# Page footer #}
<footer class="footer container-fluid pb-3 pt-4 px-0">
<footer class="footer container-fluid">
<div class="row align-items-center justify-content-between mx-0">
{# Docs & Community Links #}
<div class="col">
<nav class="nav justify-content-start">
<div class="col-sm-12 col-md-auto">
<nav class="nav justify-content-center justify-content-lg-start">
{# Documentation #}
<a type="button" class="nav-link" href="{% static 'docs/' %}" target="_blank">
<i title="Docs" class="mdi mdi-book-open-variant text-primary" data-bs-placement="top" data-bs-toggle="tooltip"></i>
@ -136,7 +142,7 @@
</div>
{# System Info #}
<div class="col text-end small text-muted">
<div class="col-sm-12 col-md-auto text-center text-lg-end small text-muted">
<span class="fw-light d-block d-md-inline">{% annotated_now %} {% now 'T' %}</span>
<span class="ms-md-3 d-block d-md-inline">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</span>
</div>

View File

@ -35,4 +35,7 @@
</div>
</div>
<div class="profile-button-container">
{% include 'inc/profile_button.html' %}
</div>
</nav>

View File

@ -14,7 +14,7 @@
</div>
{% endif %}
</div>
<div class="col col-md-4 d-flex noprint table-controls">
<div class="col col-12 col-lg-4 my-3 my-lg-0 d-flex noprint table-controls">
<div class="input-group input-group-sm">
<input
type="text"

View File

@ -13,7 +13,7 @@
{% for obj_type in results %}
<div class="card">
<h5 class="card-header">{{ obj_type.name|bettertitle }}</h5>
<div class="card-body">
<div class="card-body table-responsive">
{% render_table obj_type.table 'inc/table.html' %}
</div>
<div class="card-footer text-end">

View File

@ -44,6 +44,7 @@
{# Display a disabled link (no permission) #}
<li class="nav-item disabled">
<a href="#" class="nav-link disabled" aria-disabled="true" disabled>
<i class='mdi mdi-lock small'></i>
<span class="sidenav-normal">{{ item.link_text }}</span>
</a>
</li>

View File

@ -7,43 +7,42 @@
class="form-control"
value="{{ request.GET.q }}"
/>
<input name="obj_type" hidden type="text" class="search-obj-type" />
<span class="input-group-text search-obj-selected">All Objects</span>
<button
type="button"
aria-expanded="false"
data-bs-toggle="dropdown"
class="btn btn-outline-secondary dropdown-toggle"
>
<button type="button" aria-expanded="false" data-bs-toggle="dropdown" class="btn btn-outline-secondary dropdown-toggle">
<i class="mdi mdi-filter-variant"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end search-obj-selector">
{% for option in options %} {% if option.items|length == 0 %}
{% for option in options %}
{% if option.items|length == 0 %}
<li>
<button
class="dropdown-item"
type="button"
data-search-value="{{ option.value }}"
>
<button class="dropdown-item" type="button" data-search-value="{{ option.value }}">
{{ option.label }}
</button>
</li>
{% else %}
<li><h6 class="dropdown-header">{{ option.label }}</h6></li>
{% endif %} {% for item in option.items %}
{% endif %}
{% for item in option.items %}
<li>
<button
class="dropdown-item"
type="button"
data-search-value="{{ item.value }}"
>
<button class="dropdown-item" type="button" data-search-value="{{ item.value }}">
{{ item.label }}
</button>
</li>
{% endfor %} {% if forloop.counter != options|length %}
{% endfor %}
{% if forloop.counter != options|length %}
<li><hr class="dropdown-divider" /></li>
{% endif %} {% endfor %}
{% endif %}
{% endfor %}
</ul>
<button class="btn btn-primary" type="submit">
<i class="mdi mdi-magnify"></i>
</button>