mirror of https://github.com/Chocobozzz/PeerTube
Improve navigation sub-menu and tabs effects (#2971)
* Improve nav border and colors on active and non-active * Remove margin-top effect on active nav * Use opacity / bold instead of color change on nav * Remove dropdown items label in sub-menu and add a class active * Position sub-menu to fixed * Autoclose dropdown sub-menu only on outside click * Remove open dropdown on hover in sub-menu * Show reusable h1 for dropdown item in sub-menu * Put reusable sub-menu h1 styles to mixins * Add icons to sub-menu dropdown-item h1 * Make all the sub-menu accessible with focus Co-authored-by: kimsible <kimsible@users.noreply.github.com>pull/2988/head
parent
345b4a22a8
commit
ed5bb51726
|
@ -1,3 +1,8 @@
|
|||
@import '_variables';
|
||||
@import '_mixins';
|
||||
|
||||
my-top-menu-dropdown {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@include sub-menu-h1;
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<h1>
|
||||
<my-global-icon iconName="follower" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Instances following you</ng-container>
|
||||
</h1>
|
||||
|
||||
<p-table
|
||||
[value]="followers" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
|
||||
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<h1>
|
||||
<my-global-icon iconName="following" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Instances you follow</ng-container>
|
||||
</h1>
|
||||
|
||||
<p-table
|
||||
[value]="following" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
|
||||
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<h1>
|
||||
<my-global-icon iconName="videos" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Videos redundancies</ng-container>
|
||||
</h1>
|
||||
|
||||
<div class="admin-sub-header">
|
||||
<div class="select-filter-block">
|
||||
<label for="displayType" i18n>Display</label>
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<h1>
|
||||
<my-global-icon iconName="flag" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Reports</ng-container>
|
||||
</h1>
|
||||
|
||||
<p-table
|
||||
[value]="abuses" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
|
||||
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" [resizableColumns]="true" [lazyLoadOnInit]="false"
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<h1>
|
||||
<my-global-icon iconName="cross" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Video blocks</ng-container>
|
||||
</h1>
|
||||
|
||||
<p-table
|
||||
[value]="blocklist" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
|
||||
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<div class="admin-sub-header">
|
||||
<h1 i18n class="form-sub-title">Plugins/Themes</h1>
|
||||
|
||||
<div class="admin-sub-nav">
|
||||
<a i18n routerLink="list-installed" routerLinkActive="active">Installed</a>
|
||||
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
@import '_variables';
|
||||
@import '_mixins';
|
||||
|
||||
.form-sub-title {
|
||||
flex-grow: 0;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $small-view) {
|
||||
::ng-deep .plugins .plugin .first-row {
|
||||
flex-wrap: wrap;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<div class="admin-sub-header">
|
||||
<h1 i18n class="form-sub-title">System</h1>
|
||||
|
||||
<div class="admin-sub-nav">
|
||||
<a *ngIf="hasJobsRight()" i18n routerLink="jobs" routerLinkActive="active">Jobs</a>
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<h1 class="sr-only" i18n>My channels</h1>
|
||||
<h1>
|
||||
<my-global-icon iconName="channel" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>My channels</ng-container>
|
||||
</h1>
|
||||
|
||||
<div class="video-channels-header">
|
||||
<a class="create-button" routerLink="create">
|
||||
<my-global-icon iconName="add" aria-hidden="true"></my-global-icon>
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<h1 class="sr-only" i18n>History</h1>
|
||||
<h1>
|
||||
<my-global-icon iconName="history" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>My history</ng-container>
|
||||
</h1>
|
||||
|
||||
<div class="top-buttons">
|
||||
<div class="history-switch">
|
||||
<p-inputSwitch [(ngModel)]="videosHistoryEnabled" (ngModelChange)="onVideosHistoryChange()"></p-inputSwitch>
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<h1 class="sr-only" i18n>Ownership changes</h1>
|
||||
<h1>
|
||||
<my-global-icon iconName="download" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>My ownership changes</ng-container>
|
||||
</h1>
|
||||
|
||||
<p-table
|
||||
[value]="videoChangeOwnerships"
|
||||
[lazy]="true"
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<h1 class="sr-only" i18n>Subscriptions</h1>
|
||||
<h1>
|
||||
<my-global-icon iconName="subscriptions" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>My subscriptions</ng-container>
|
||||
</h1>
|
||||
|
||||
<div class="no-results" i18n *ngIf="pagination.totalItems === 0">You don't have any subscriptions yet.</div>
|
||||
|
||||
<div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<h1 class="sr-only" i18n>Imports</h1>
|
||||
<h1>
|
||||
<my-global-icon iconName="cloud-download" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>My imports</ng-container>
|
||||
</h1>
|
||||
|
||||
<p-table
|
||||
[value]="videoImports" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
|
||||
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<div class="video-playlists-header">
|
||||
<h1 i18n>Playlists <span class="badge badge-secondary">{{ pagination.totalItems }}</span></h1>
|
||||
<h1>
|
||||
<my-global-icon iconName="playlists" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>My playlists</ng-container> <span class="badge badge-secondary">{{ pagination.totalItems }}</span>
|
||||
</h1>
|
||||
|
||||
|
||||
<div class="video-playlists-header">
|
||||
<input type="text" placeholder="Search your playlists" i18n-placeholder [(ngModel)]="videoPlaylistsSearch" (ngModelChange)="onVideoPlaylistSearchChanged()" />
|
||||
|
||||
<a class="create-button" routerLink="create">
|
||||
|
|
|
@ -41,10 +41,6 @@
|
|||
input[type=text] {
|
||||
@include peertube-input-text(300px);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $small-view) {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<h1>
|
||||
<my-global-icon iconName="videos" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>My videos</ng-container><span class="badge badge-secondary"> {{ pagination.totalItems }}</span>
|
||||
</h1>
|
||||
|
||||
<div class="videos-header">
|
||||
<h1 i18n>Videos <span class="badge badge-secondary">{{ pagination.totalItems }}</span></h1>
|
||||
|
||||
<input type="text" placeholder="Search your videos" i18n-placeholder [(ngModel)]="videosSearch" (ngModelChange)="onVideosSearchChanged()" />
|
||||
|
||||
<div class="fake-element"></div>
|
||||
</div>
|
||||
|
||||
<my-videos-selection
|
||||
|
|
|
@ -6,12 +6,6 @@
|
|||
justify-content: space-between;
|
||||
margin: 20px 0 50px;
|
||||
|
||||
h1,
|
||||
.fake-element {
|
||||
flex: 1;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
@include peertube-input-text(300px);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@import '_variables';
|
||||
@import '_mixins';
|
||||
|
||||
.row {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
@ -5,4 +8,6 @@
|
|||
& > my-top-menu-dropdown:nth-child(1) {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@include sub-menu-h1;
|
||||
}
|
||||
|
|
|
@ -30,16 +30,25 @@ $nav-link-height: 40px;
|
|||
padding: 0 30px !important;
|
||||
font-size: 15px;
|
||||
|
||||
border: $border-width $border-type transparent;
|
||||
|
||||
span {
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border: $border-width $border-type $border-color;
|
||||
border-bottom: none;
|
||||
border-color: $border-color;
|
||||
border-bottom-color: transparent;
|
||||
background-color: pvar(--submenuColor) !important;
|
||||
|
||||
span {
|
||||
border-bottom: 2px solid pvar(--mainColor);
|
||||
font-weight: $font-bold;
|
||||
border-bottom-color: pvar(--mainColor);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:not(.active) {
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +80,7 @@ $nav-link-height: 40px;
|
|||
|
||||
/* Hide active tab style to not have a moving tab effect */
|
||||
a.nav-link.active {
|
||||
border: none;
|
||||
border-color: transparent;
|
||||
background-color: pvar(--mainBackgroundColor) !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,26 +4,28 @@
|
|||
<a *ngIf="menuEntry.routerLink" [routerLink]="menuEntry.routerLink" routerLinkActive="active" class="title-page title-page-settings">{{ menuEntry.label }}</a>
|
||||
|
||||
<div *ngIf="!menuEntry.routerLink" ngbDropdown class="parent-entry"
|
||||
#dropdown="ngbDropdown" (mouseleave)="closeDropdownIfHovered(dropdown)">
|
||||
#dropdown="ngbDropdown" autoClose="outside">
|
||||
<span
|
||||
*ngIf="isInSmallView"
|
||||
tabindex=0
|
||||
[ngClass]="{ active: !!suffixLabels[menuEntry.label] }"
|
||||
(click)="openModal(id)" role="button" class="title-page title-page-settings">
|
||||
(click)="openModal(id)" (keydown.enter)="openModal(id)"
|
||||
role="button" class="title-page title-page-settings">
|
||||
<ng-container i18n>{{ menuEntry.label }}</ng-container>
|
||||
<ng-container *ngIf="!!suffixLabels[menuEntry.label]"> - {{ suffixLabels[menuEntry.label] }}</ng-container>
|
||||
</span>
|
||||
|
||||
<span
|
||||
*ngIf="!isInSmallView"
|
||||
(mouseenter)="openDropdownOnHover(dropdown)" [ngClass]="{ active: !!suffixLabels[menuEntry.label] }" ngbDropdownAnchor
|
||||
(click)="dropdownAnchorClicked(dropdown)" role="button" class="title-page title-page-settings"
|
||||
tabindex=0
|
||||
[ngClass]="{ active: !!suffixLabels[menuEntry.label] }" ngbDropdownAnchor
|
||||
(click)="dropdownAnchorClicked(dropdown)" (keydown.enter)="dropdownAnchorClicked(dropdown)"
|
||||
role="button" class="title-page title-page-settings"
|
||||
>
|
||||
<ng-container i18n>{{ menuEntry.label }}</ng-container>
|
||||
<ng-container *ngIf="!!suffixLabels[menuEntry.label]"> - {{ suffixLabels[menuEntry.label] }}</ng-container>
|
||||
</span>
|
||||
|
||||
<div ngbDropdownMenu>
|
||||
<a *ngFor="let menuChild of menuEntry.children" class="dropdown-item" [ngClass]="{ icon: hasIcons }" [routerLink]="menuChild.routerLink">
|
||||
<a *ngFor="let menuChild of menuEntry.children" class="dropdown-item" [ngClass]="{ icon: hasIcons, active: suffixLabels[menuEntry.label] === menuChild.label }" [routerLink]="menuChild.routerLink">
|
||||
<my-global-icon *ngIf="menuChild.iconName" [iconName]="menuChild.iconName" aria-hidden="true"></my-global-icon>
|
||||
|
||||
{{ menuChild.label }}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
@import '_variables';
|
||||
@import '_mixins';
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
height: $sub-menu-height;
|
||||
margin-bottom: $sub-menu-margin-bottom;
|
||||
}
|
||||
|
||||
.parent-entry {
|
||||
span[role=button] {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -33,7 +33,6 @@ export class TopMenuDropdownComponent implements OnInit, OnDestroy {
|
|||
isModalOpened = false
|
||||
currentMenuEntryIndex: number
|
||||
|
||||
private openedOnHover = false
|
||||
private routeSub: Subscription
|
||||
|
||||
constructor (
|
||||
|
@ -68,32 +67,10 @@ export class TopMenuDropdownComponent implements OnInit, OnDestroy {
|
|||
if (this.routeSub) this.routeSub.unsubscribe()
|
||||
}
|
||||
|
||||
openDropdownOnHover (dropdown: NgbDropdown) {
|
||||
this.openedOnHover = true
|
||||
dropdown.open()
|
||||
|
||||
// Menu was closed
|
||||
dropdown.openChange
|
||||
.pipe(take(1))
|
||||
.subscribe(() => this.openedOnHover = false)
|
||||
}
|
||||
|
||||
dropdownAnchorClicked (dropdown: NgbDropdown) {
|
||||
if (this.openedOnHover) {
|
||||
this.openedOnHover = false
|
||||
return
|
||||
}
|
||||
|
||||
return dropdown.toggle()
|
||||
}
|
||||
|
||||
closeDropdownIfHovered (dropdown: NgbDropdown) {
|
||||
if (this.openedOnHover === false) return
|
||||
|
||||
dropdown.close()
|
||||
this.openedOnHover = false
|
||||
}
|
||||
|
||||
openModal (index: number) {
|
||||
this.currentMenuEntryIndex = index
|
||||
this.isModalOpened = true
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<h1>
|
||||
<my-global-icon iconName="user" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Muted accounts</ng-container>
|
||||
</h1>
|
||||
|
||||
<p-table
|
||||
[value]="blockedAccounts" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
|
||||
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<h1>
|
||||
<my-global-icon iconName="server" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Muted servers</ng-container>
|
||||
</h1>
|
||||
|
||||
<p-table
|
||||
[value]="blockedServers" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
|
||||
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
|
||||
|
|
|
@ -139,12 +139,13 @@ label {
|
|||
.sub-menu {
|
||||
background-color: pvar(--submenuColor);
|
||||
width: 100%;
|
||||
height: 81px;
|
||||
margin-bottom: $sub-menu-margin-bottom;
|
||||
height: $sub-menu-height;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: $not-expanded-horizontal-margins;
|
||||
padding-right: $not-expanded-horizontal-margins;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
// Override some properties if the main content is expanded (no menu on the left)
|
||||
|
@ -175,6 +176,7 @@ label {
|
|||
}
|
||||
|
||||
.title-page {
|
||||
opacity: 0.6;
|
||||
color: pvar(--mainForegroundColor);
|
||||
font-size: 16px;
|
||||
display: inline-block;
|
||||
|
@ -182,14 +184,15 @@ label {
|
|||
font-weight: $font-semibold;
|
||||
@include disable-default-a-behaviour;
|
||||
|
||||
&.active, &.title-page-single {
|
||||
border-bottom: 2px solid transparent;
|
||||
|
||||
&.title-page-single {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: $font-bold;
|
||||
border-bottom: 2px solid pvar(--mainColor);
|
||||
border-bottom-color: pvar(--mainColor);
|
||||
}
|
||||
|
||||
&.title-page-single {
|
||||
|
@ -200,6 +203,11 @@ label {
|
|||
color: pvar(--mainForegroundColor);
|
||||
}
|
||||
|
||||
&.active, &:hover, &:active, &:focus, &.title-page-single {
|
||||
opacity: 1;
|
||||
outline: 0px hidden !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $mobile-view) {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
@ -209,11 +217,6 @@ label {
|
|||
.title-page-settings {
|
||||
white-space: nowrap;
|
||||
font-size: 115%;
|
||||
font-weight: $font-regular;
|
||||
|
||||
&.active {
|
||||
font-weight: $font-semibold;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-sub-header {
|
||||
|
@ -232,11 +235,15 @@ label {
|
|||
color: pvar(--mainForegroundColor);
|
||||
padding: 5px 15px;
|
||||
border-radius: 0.25rem;
|
||||
font-weight: $font-semibold;
|
||||
opacity: 0.6;
|
||||
|
||||
&.active {
|
||||
font-weight: $font-semibold;
|
||||
background-color: #f0f0f0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
&.active, &:hover, &:active, &:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,9 +161,14 @@ $icon-font-path: '~@neos21/bootstrap3-glyphicons/assets/fonts/';
|
|||
|
||||
.nav.nav-pills {
|
||||
font-size: 16px !important;
|
||||
font-weight: $font-semibold !important;
|
||||
|
||||
.nav-link.active {
|
||||
font-weight: $font-semibold !important;
|
||||
.nav-link {
|
||||
opacity: 0.6 !important;
|
||||
|
||||
&.active, &:hover, &:active, &:focus {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -173,29 +178,23 @@ $icon-font-path: '~@neos21/bootstrap3-glyphicons/assets/fonts/';
|
|||
}
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
|
||||
.nav-link {
|
||||
@include disable-default-a-behaviour;
|
||||
|
||||
color: pvar(--mainForegroundColor) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
&:not(.active) {
|
||||
border-bottom: 3px solid transparent;
|
||||
}
|
||||
@include disable-default-a-behaviour;
|
||||
|
||||
color: pvar(--mainForegroundColor);
|
||||
font-weight: $font-semibold;
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
opacity: 0.6;
|
||||
|
||||
&.active {
|
||||
font-weight: $font-semibold;
|
||||
color: pvar(--mainForegroundColor);
|
||||
background-color: pvar(--mainBackgroundColor) !important;
|
||||
border: none;
|
||||
border-bottom: 2px solid pvar(--mainColor);
|
||||
border-bottom-color: pvar(--mainColor);
|
||||
}
|
||||
&:hover {
|
||||
border-top-color: transparent;
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
|
||||
&.active, &:hover, &:active, &:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -929,3 +929,23 @@
|
|||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin sub-menu-h1 {
|
||||
::ng-deep h1 {
|
||||
font-size: 1.3rem;
|
||||
border-bottom: 2px solid $grey-background-color;
|
||||
padding-bottom: 15px;
|
||||
margin-bottom: $sub-menu-margin-bottom;
|
||||
|
||||
my-global-icon {
|
||||
margin-right: 10px;
|
||||
vertical-align: bottom;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
margin-left: 7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ $menu-width: 240px;
|
|||
$menu-lateral-padding: 26px;
|
||||
|
||||
$sub-menu-color: #F7F7F7;
|
||||
$sub-menu-height: 81px;
|
||||
|
||||
$footer-height: 30px;
|
||||
$footer-margin: 30px;
|
||||
|
|
Loading…
Reference in New Issue