UX: horitzontal scroll controls for new user nav (#18583)
This commit is contained in:
parent
a5156d18ff
commit
6b4b279141
|
@ -0,0 +1,106 @@
|
|||
{{!-- template-lint-disable no-down-event-binding --}}
|
||||
|
||||
<div class="user-navigation user-navigation-secondary {{if this.hasScroll "has-scroll"}}">
|
||||
{{#if this.hasScroll}}
|
||||
<a
|
||||
role="button"
|
||||
{{on "mousedown" this.horizScroll}}
|
||||
data-direction="left"
|
||||
class="nav-overflow__scroll-left btn-flat {{if this.hideLeftScroll "transparent"}}"
|
||||
>
|
||||
{{d-icon "chevron-left"}}
|
||||
</a>
|
||||
{{/if}}
|
||||
|
||||
<ul
|
||||
{{did-insert this.scrollToActive}}
|
||||
{{on-resize this.checkScroll}}
|
||||
{{on "scroll" this.watchScroll}}
|
||||
class="nav-pills action-list"
|
||||
>
|
||||
<li class="nav-account">
|
||||
<LinkTo @route="preferences.account">
|
||||
{{d-icon "user"}}
|
||||
<span>{{i18n "user.preferences_nav.account"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li class="nav-security">
|
||||
<LinkTo @route="preferences.security">
|
||||
{{d-icon "lock"}}
|
||||
<span>{{i18n "user.preferences_nav.security"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li class="nav-profile">
|
||||
<LinkTo @route="preferences.profile">
|
||||
{{d-icon "user"}}
|
||||
<span>{{i18n "user.preferences_nav.profile"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li class="nav-emails">
|
||||
<LinkTo @route="preferences.emails">
|
||||
{{d-icon "envelope"}}
|
||||
<span>{{i18n "user.preferences_nav.emails"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li class="nav-notifications">
|
||||
<LinkTo @route="preferences.notifications">
|
||||
{{d-icon "bell"}}
|
||||
<span>{{i18n "user.preferences_nav.notifications"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{#if @model.can_change_tracking_preferences}}
|
||||
<li class="indent nav-categories">
|
||||
<LinkTo @route="preferences.categories">
|
||||
{{d-icon "folder"}}
|
||||
<span>{{i18n "user.preferences_nav.categories"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li class="indent nav-users">
|
||||
<LinkTo @route="preferences.users">
|
||||
{{d-icon "users"}}
|
||||
<span>{{i18n "user.preferences_nav.users"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{#if (and @model.can_change_tracking_preferences @siteSettings.tagging_enabled)}}
|
||||
<li class="indent nav-tags">
|
||||
<LinkTo @route="preferences.tags">
|
||||
{{d-icon "tag"}}
|
||||
<span>{{i18n "user.preferences_nav.tags"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li class="nav-interface">
|
||||
<LinkTo @route="preferences.interface">
|
||||
{{d-icon "desktop"}}
|
||||
<span>{{i18n "user.preferences_nav.interface"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{#if @siteSettings.enable_experimental_sidebar_hamburger}}
|
||||
<li class="indent nav-sidebar">
|
||||
<LinkTo @route="preferences.sidebar">
|
||||
{{d-icon "bars"}}
|
||||
<span>{{i18n "user.preferences_nav.sidebar"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
<PluginOutlet @name="user-preferences-nav-under-interface" @connectorTagName="div" @args={{hash model=@model}} />
|
||||
<li class="nav-apps">
|
||||
<LinkTo @route="preferences.apps">
|
||||
{{d-icon "mobile-alt"}}
|
||||
<span>{{i18n "user.preferences_nav.apps"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<PluginOutlet @name="user-preferences-nav" @connectorTagName="li" @args={{hash model=@model}} />
|
||||
</ul>
|
||||
|
||||
{{#if this.hasScroll}}
|
||||
<a
|
||||
role="button"
|
||||
{{on "mousedown" this.horizScroll}}
|
||||
class="nav-overflow__scroll-right btn-flat {{if this.hideRightScroll "transparent"}}"
|
||||
>
|
||||
{{d-icon "chevron-right"}}
|
||||
</a>
|
||||
{{/if}}
|
||||
</div>
|
|
@ -0,0 +1,80 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { action } from "@ember/object";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
|
||||
export default class UserNavPreferencesNav extends Component {
|
||||
@service site;
|
||||
@tracked hasScroll;
|
||||
@tracked hideRightScroll = false;
|
||||
@tracked hideLeftScroll = true;
|
||||
scrollInterval;
|
||||
|
||||
@bind
|
||||
scrollToActive() {
|
||||
document
|
||||
.querySelector(".user-navigation-secondary a.active")
|
||||
.scrollIntoView({ inline: "center" });
|
||||
}
|
||||
|
||||
@bind
|
||||
checkScroll(element) {
|
||||
if (this.site.mobileView) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.watchScroll(element);
|
||||
return (this.hasScroll =
|
||||
element.target.scrollWidth > element.target.offsetWidth);
|
||||
}
|
||||
|
||||
@bind
|
||||
stopScroll() {
|
||||
clearInterval(this.scrollInterval);
|
||||
}
|
||||
|
||||
@bind
|
||||
watchScroll(element) {
|
||||
if (this.site.mobileView) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
element.target.offsetWidth + element.target.scrollLeft ===
|
||||
element.target.scrollWidth
|
||||
) {
|
||||
this.hideRightScroll = true;
|
||||
clearInterval(this.scrollInterval);
|
||||
} else {
|
||||
this.hideRightScroll = false;
|
||||
}
|
||||
|
||||
if (element.target.scrollLeft === 0) {
|
||||
this.hideLeftScroll = true;
|
||||
clearInterval(this.scrollInterval);
|
||||
} else {
|
||||
this.hideLeftScroll = false;
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
horizScroll(element) {
|
||||
let scrollSpeed = 50;
|
||||
let siblingTarget = element.target.previousElementSibling;
|
||||
|
||||
if (element.target.dataset.direction === "left") {
|
||||
scrollSpeed = scrollSpeed * -1;
|
||||
siblingTarget = element.target.nextElementSibling;
|
||||
}
|
||||
|
||||
this.scrollInterval = setInterval(function () {
|
||||
siblingTarget.scrollLeft += scrollSpeed;
|
||||
}, 50);
|
||||
|
||||
this.scrollTimer;
|
||||
|
||||
element.target.addEventListener("mouseup", this.stopScroll);
|
||||
element.target.addEventListener("mouseleave", this.stopScroll);
|
||||
}
|
||||
}
|
|
@ -1,88 +1,12 @@
|
|||
{{#if this.currentUser.redesigned_user_page_nav_enabled}}
|
||||
<DSection @pageClass="user-preferences" />
|
||||
|
||||
<div class="user-navigation user-navigation-secondary">
|
||||
<ul class="nav-pills action-list">
|
||||
<li class="nav-account">
|
||||
<LinkTo @route="preferences.account">
|
||||
{{d-icon "user"}}
|
||||
<span>{{i18n "user.preferences_nav.account"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li class="nav-security">
|
||||
<LinkTo @route="preferences.security">
|
||||
{{d-icon "lock"}}
|
||||
<span>{{i18n "user.preferences_nav.security"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li class="nav-profile">
|
||||
<LinkTo @route="preferences.profile">
|
||||
{{d-icon "user"}}
|
||||
<span>{{i18n "user.preferences_nav.profile"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li class="nav-emails">
|
||||
<LinkTo @route="preferences.emails">
|
||||
{{d-icon "envelope"}}
|
||||
<span>{{i18n "user.preferences_nav.emails"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
<li class="nav-notifications">
|
||||
<LinkTo @route="preferences.notifications">
|
||||
{{d-icon "bell"}}
|
||||
<span>{{i18n "user.preferences_nav.notifications"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{#if this.model.can_change_tracking_preferences}}
|
||||
<li class="indent nav-categories">
|
||||
<LinkTo @route="preferences.categories">
|
||||
{{d-icon "folder"}}
|
||||
<span>{{i18n "user.preferences_nav.categories"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li class="indent nav-users">
|
||||
<LinkTo @route="preferences.users">
|
||||
{{d-icon "users"}}
|
||||
<span>{{i18n "user.preferences_nav.users"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{#if (and this.model.can_change_tracking_preferences this.siteSettings.tagging_enabled)}}
|
||||
<li class="indent nav-tags">
|
||||
<LinkTo @route="preferences.tags">
|
||||
{{d-icon "tag"}}
|
||||
<span>{{i18n "user.preferences_nav.tags"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li class="nav-interface">
|
||||
<LinkTo @route="preferences.interface">
|
||||
{{d-icon "desktop"}}
|
||||
<span>{{i18n "user.preferences_nav.interface"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
|
||||
{{#if this.siteSettings.enable_experimental_sidebar_hamburger}}
|
||||
<li class="indent nav-sidebar">
|
||||
<LinkTo @route="preferences.sidebar">
|
||||
{{d-icon "bars"}}
|
||||
<span>{{i18n "user.preferences_nav.sidebar"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
<PluginOutlet @name="user-preferences-nav-under-interface" @connectorTagName="div" @args={{hash model=this.model}} />
|
||||
|
||||
<li class="nav-apps">
|
||||
<LinkTo @route="preferences.apps">
|
||||
{{d-icon "mobile-alt"}}
|
||||
<span>{{i18n "user.preferences_nav.apps"}}</span>
|
||||
</LinkTo>
|
||||
</li>
|
||||
|
||||
<PluginOutlet @name="user-preferences-nav" @connectorTagName="li" @args={{hash model=this.model}} />
|
||||
</ul>
|
||||
</div>
|
||||
<UserNav::PreferencesNav
|
||||
@user={{this.model}}
|
||||
@viewingSelf={{this.viewingSelf}}
|
||||
@model={{this.model}}
|
||||
@siteSettings={{this.siteSettings}}
|
||||
/>
|
||||
{{else}}
|
||||
<DSection @pageClass="user-preferences" @class="user-secondary-navigation">
|
||||
<MobileNav @class="preferences-nav" @desktopClass="preferences-list action-list nav-stacked">
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
margin-top: -15px; // temp, can remove margin from sibling element after nav finalized
|
||||
.user-navigation {
|
||||
--user-navigation__border-width: 4px;
|
||||
&.user-navigation-primary {
|
||||
border-bottom: 1px solid var(--primary-low);
|
||||
}
|
||||
.nav-pills {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid var(--primary-low);
|
||||
.d-icon {
|
||||
font-size: var(--font-down-1);
|
||||
}
|
||||
|
@ -80,9 +82,12 @@
|
|||
|
||||
.user-navigation-secondary {
|
||||
--user-navigation__border-width: 2px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
margin: 0.5em 0;
|
||||
gap: 0 0.5em;
|
||||
border-bottom: 1px solid var(--primary-low);
|
||||
|
||||
.select-kit .select-kit-header {
|
||||
height: 100%;
|
||||
|
@ -103,18 +108,84 @@
|
|||
}
|
||||
}
|
||||
|
||||
.nav-overflow__scroll-right,
|
||||
.nav-overflow__scroll-left {
|
||||
--fade-width: 20px;
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
background-color: var(--secondary);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: opacity 0.25s;
|
||||
.d-icon {
|
||||
pointer-events: none;
|
||||
margin-bottom: 0.2em;
|
||||
color: var(--tertiary);
|
||||
}
|
||||
&.transparent {
|
||||
// hiding with opacity so we can transition visibility
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-overflow__scroll-right {
|
||||
right: 0;
|
||||
&:before {
|
||||
content: "";
|
||||
margin-left: -1.5em;
|
||||
height: 100%;
|
||||
width: 1.5em;
|
||||
background: linear-gradient(
|
||||
to left,
|
||||
rgba(var(--secondary-rgb), 1),
|
||||
rgba(var(--secondary-rgb), 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-overflow__scroll-left {
|
||||
left: 0;
|
||||
&:after {
|
||||
content: "";
|
||||
margin-right: -1.5em;
|
||||
height: 100%;
|
||||
width: 1.5em;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
rgba(var(--secondary-rgb), 1),
|
||||
rgba(var(--secondary-rgb), 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-pills {
|
||||
flex: 1 1 auto;
|
||||
font-size: var(--font-down-1);
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
scroll-behavior: smooth;
|
||||
|
||||
// hides scrollbars, but allows mouse scrolling
|
||||
scrollbar-width: none;
|
||||
&::-webkit-scrollbar {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
flex: 1 1 auto;
|
||||
flex: 1 0 auto;
|
||||
|
||||
a {
|
||||
padding: 0.5em 0.5em
|
||||
calc(0.5em + var(--user-navigation__border-width));
|
||||
|
||||
span {
|
||||
text-overflow: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
width: 100%;
|
||||
|
||||
.nav-pills {
|
||||
margin: 0.5em 0;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
|
||||
|
@ -56,10 +55,6 @@
|
|||
#navigation-bar {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.navigation-controls {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.new-user-content-wrapper {
|
||||
|
|
Loading…
Reference in New Issue