]> Untitled Git - lemmy-ui.git/commitdiff
Navbar fix 2 (#1038)
authorSleeplessOne1917 <abias1122@gmail.com>
Wed, 24 May 2023 00:42:19 +0000 (00:42 +0000)
committerGitHub <noreply@github.com>
Wed, 24 May 2023 00:42:19 +0000 (20:42 -0400)
* Fix navbar not closing on mobile when it should

* Get rid of unnecessary HTML tags

* Forgot to include this

src/shared/components/app/navbar.tsx

index d92ec259443f144987968190c81e3d56514a030f..25c3a306d48ac8ccd173bbe1acac6c900763066e 100644 (file)
@@ -1,4 +1,4 @@
-import { Component, linkEvent } from "inferno";
+import { Component, createRef, linkEvent } from "inferno";
 import { NavLink } from "inferno-router";
 import {
   CommentResponse,
@@ -39,14 +39,22 @@ interface NavbarProps {
 }
 
 interface NavbarState {
-  expanded: boolean;
   unreadInboxCount: number;
   unreadReportCount: number;
   unreadApplicationCount: number;
-  showDropdown: boolean;
   onSiteBanner?(url: string): any;
 }
 
+function handleCollapseClick(i: Navbar) {
+  if (i.collapseButtonRef.current?.ariaExpanded === "true") {
+    i.collapseButtonRef.current?.click();
+  }
+}
+
+function handleLogOut() {
+  UserService.Instance.logout();
+}
+
 export class Navbar extends Component<NavbarProps, NavbarState> {
   private wsSub: Subscription;
   private userSub: Subscription;
@@ -57,10 +65,9 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
     unreadInboxCount: 0,
     unreadReportCount: 0,
     unreadApplicationCount: 0,
-    expanded: false,
-    showDropdown: false,
   };
   subscription: any;
+  collapseButtonRef = createRef<HTMLButtonElement>();
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -113,85 +120,228 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
     this.unreadApplicationCountSub.unsubscribe();
   }
 
-  render() {
-    return this.navbar();
-  }
-
   // TODO class active corresponding to current page
-  navbar() {
-    let siteView = this.props.siteRes?.site_view;
-    let person = UserService.Instance.myUserInfo?.local_user_view.person;
+  render() {
+    const siteView = this.props.siteRes?.site_view;
+    const person = UserService.Instance.myUserInfo?.local_user_view.person;
     return (
-      <nav className="navbar navbar-expand-md navbar-light shadow-sm p-0 px-3">
-        <div className="container-lg">
-          <NavLink
-            to="/"
-            onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
-            title={siteView?.site.description ?? siteView?.site.name ?? "Lemmy"}
-            className="d-flex align-items-center navbar-brand mr-md-3"
-          >
-            {siteView?.site.icon && showAvatars() && (
-              <PictrsImage src={siteView.site.icon} icon />
+      <nav className="navbar navbar-expand-md navbar-light shadow-sm p-0 px-3 container-lg">
+        <NavLink
+          to="/"
+          title={siteView?.site.description ?? siteView?.site.name}
+          className="d-flex align-items-center navbar-brand mr-md-3"
+          onMouseUp={linkEvent(this, handleCollapseClick)}
+        >
+          {siteView?.site.icon && showAvatars() && (
+            <PictrsImage src={siteView.site.icon} icon />
+          )}
+          {siteView?.site.name}
+        </NavLink>
+        {person && (
+          <ul className="navbar-nav d-flex flex-row ml-auto d-md-none">
+            <li className="nav-item">
+              <NavLink
+                to="/inbox"
+                className="p-1 nav-link border-0"
+                title={i18n.t("unread_messages", {
+                  count: Number(this.state.unreadInboxCount),
+                  formattedCount: numToSI(this.state.unreadInboxCount),
+                })}
+                onMouseUp={linkEvent(this, handleCollapseClick)}
+              >
+                <Icon icon="bell" />
+                {this.state.unreadInboxCount > 0 && (
+                  <span className="mx-1 badge badge-light">
+                    {numToSI(this.state.unreadInboxCount)}
+                  </span>
+                )}
+              </NavLink>
+            </li>
+            {this.moderatesSomething && (
+              <li className="nav-item">
+                <NavLink
+                  to="/reports"
+                  className="p-1 nav-link border-0"
+                  title={i18n.t("unread_reports", {
+                    count: Number(this.state.unreadReportCount),
+                    formattedCount: numToSI(this.state.unreadReportCount),
+                  })}
+                  onMouseUp={linkEvent(this, handleCollapseClick)}
+                >
+                  <Icon icon="shield" />
+                  {this.state.unreadReportCount > 0 && (
+                    <span className="mx-1 badge badge-light">
+                      {numToSI(this.state.unreadReportCount)}
+                    </span>
+                  )}
+                </NavLink>
+              </li>
             )}
-            {siteView?.site.name ?? "Lemmy"}
-          </NavLink>
-          {UserService.Instance.myUserInfo && (
-            <>
-              <ul className="navbar-nav ml-auto">
+            {amAdmin() && (
+              <li className="nav-item">
+                <NavLink
+                  to="/registration_applications"
+                  className="p-1 nav-link border-0"
+                  title={i18n.t("unread_registration_applications", {
+                    count: Number(this.state.unreadApplicationCount),
+                    formattedCount: numToSI(this.state.unreadApplicationCount),
+                  })}
+                  onMouseUp={linkEvent(this, handleCollapseClick)}
+                >
+                  <Icon icon="clipboard" />
+                  {this.state.unreadApplicationCount > 0 && (
+                    <span className="mx-1 badge badge-light">
+                      {numToSI(this.state.unreadApplicationCount)}
+                    </span>
+                  )}
+                </NavLink>
+              </li>
+            )}
+          </ul>
+        )}
+        <button
+          className="navbar-toggler border-0 p-1"
+          type="button"
+          aria-label="menu"
+          data-tippy-content={i18n.t("expand_here")}
+          data-bs-toggle="collapse"
+          data-bs-target="#navbarDropdown"
+          aria-controls="navbarDropdown"
+          aria-expanded="false"
+          ref={this.collapseButtonRef}
+        >
+          <Icon icon="menu" />
+        </button>
+        <div className="collapse navbar-collapse my-2" id="navbarDropdown">
+          <ul className="mr-auto navbar-nav">
+            <li className="nav-item">
+              <NavLink
+                to="/communities"
+                className="nav-link"
+                title={i18n.t("communities")}
+                onMouseUp={linkEvent(this, handleCollapseClick)}
+              >
+                {i18n.t("communities")}
+              </NavLink>
+            </li>
+            <li className="nav-item">
+              {/* TODO make sure this works: https://github.com/infernojs/inferno/issues/1608 */}
+              <NavLink
+                to={{
+                  pathname: "/create_post",
+                  search: "",
+                  hash: "",
+                  key: "",
+                  state: { prevPath: this.currentLocation },
+                }}
+                className="nav-link"
+                title={i18n.t("create_post")}
+                onMouseUp={linkEvent(this, handleCollapseClick)}
+              >
+                {i18n.t("create_post")}
+              </NavLink>
+            </li>
+            {this.props.siteRes && canCreateCommunity(this.props.siteRes) && (
+              <li className="nav-item">
+                <NavLink
+                  to="/create_community"
+                  className="nav-link"
+                  title={i18n.t("create_community")}
+                  onMouseUp={linkEvent(this, handleCollapseClick)}
+                >
+                  {i18n.t("create_community")}
+                </NavLink>
+              </li>
+            )}
+            <li className="nav-item">
+              <a
+                className="nav-link"
+                title={i18n.t("support_lemmy")}
+                href={donateLemmyUrl}
+              >
+                <Icon icon="heart" classes="small" />
+              </a>
+            </li>
+          </ul>
+          <ul className="navbar-nav">
+            {!this.context.router.history.location.pathname.match(
+              /^\/search/
+            ) && (
+              <li className="nav-item">
+                <NavLink
+                  to="/search"
+                  className="nav-link"
+                  title={i18n.t("search")}
+                  onMouseUp={linkEvent(this, handleCollapseClick)}
+                >
+                  <Icon icon="search" />
+                </NavLink>
+              </li>
+            )}
+            {amAdmin() && (
+              <li className="nav-item">
+                <NavLink
+                  to="/admin"
+                  className="nav-link"
+                  title={i18n.t("admin_settings")}
+                  onMouseUp={linkEvent(this, handleCollapseClick)}
+                >
+                  <Icon icon="settings" />
+                </NavLink>
+              </li>
+            )}
+            {person ? (
+              <>
                 <li className="nav-item">
                   <NavLink
+                    className="nav-link"
                     to="/inbox"
-                    className="p-1 navbar-toggler nav-link border-0"
-                    onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
                     title={i18n.t("unread_messages", {
                       count: Number(this.state.unreadInboxCount),
                       formattedCount: numToSI(this.state.unreadInboxCount),
                     })}
+                    onMouseUp={linkEvent(this, handleCollapseClick)}
                   >
                     <Icon icon="bell" />
                     {this.state.unreadInboxCount > 0 && (
-                      <span className="mx-1 badge badge-light">
+                      <span className="ml-1 badge badge-light">
                         {numToSI(this.state.unreadInboxCount)}
                       </span>
                     )}
                   </NavLink>
                 </li>
-              </ul>
-              {this.moderatesSomething && (
-                <ul className="navbar-nav ml-1">
+                {this.moderatesSomething && (
                   <li className="nav-item">
                     <NavLink
+                      className="nav-link"
                       to="/reports"
-                      className="p-1 navbar-toggler nav-link border-0"
-                      onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
                       title={i18n.t("unread_reports", {
                         count: Number(this.state.unreadReportCount),
                         formattedCount: numToSI(this.state.unreadReportCount),
                       })}
+                      onMouseUp={linkEvent(this, handleCollapseClick)}
                     >
                       <Icon icon="shield" />
                       {this.state.unreadReportCount > 0 && (
-                        <span className="mx-1 badge badge-light">
+                        <span className="ml-1 badge badge-light">
                           {numToSI(this.state.unreadReportCount)}
                         </span>
                       )}
                     </NavLink>
                   </li>
-                </ul>
-              )}
-              {amAdmin() && (
-                <ul className="navbar-nav ml-1">
+                )}
+                {amAdmin() && (
                   <li className="nav-item">
                     <NavLink
                       to="/registration_applications"
-                      className="p-1 navbar-toggler nav-link border-0"
-                      onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
+                      className="nav-link"
                       title={i18n.t("unread_registration_applications", {
                         count: Number(this.state.unreadApplicationCount),
                         formattedCount: numToSI(
                           this.state.unreadApplicationCount
                         ),
                       })}
+                      onMouseUp={linkEvent(this, handleCollapseClick)}
                     >
                       <Icon icon="clipboard" />
                       {this.state.unreadApplicationCount > 0 && (
@@ -201,241 +351,70 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                       )}
                     </NavLink>
                   </li>
-                </ul>
-              )}
-            </>
-          )}
-          <button
-            className="navbar-toggler border-0 p-1"
-            type="button"
-            aria-label="menu"
-            onClick={linkEvent(this, this.handleToggleExpandNavbar)}
-            data-tippy-content={i18n.t("expand_here")}
-          >
-            <Icon icon="menu" />
-          </button>
-          <div
-            className={`${!this.state.expanded && "collapse"} navbar-collapse`}
-          >
-            <ul className="navbar-nav my-2 mr-auto">
-              <li className="nav-item">
-                <NavLink
-                  to="/communities"
-                  className="nav-link"
-                  onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
-                  title={i18n.t("communities")}
-                >
-                  {i18n.t("communities")}
-                </NavLink>
-              </li>
-              <li className="nav-item">
-                {/* TODO make sure this works: https://github.com/infernojs/inferno/issues/1608 */}
-                <NavLink
-                  to={{
-                    pathname: "/create_post",
-                    search: "",
-                    hash: "",
-                    key: "",
-                    state: { prevPath: this.currentLocation },
-                  }}
-                  className="nav-link"
-                  onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
-                  title={i18n.t("create_post")}
-                >
-                  {i18n.t("create_post")}
-                </NavLink>
-              </li>
-              {this.props.siteRes && canCreateCommunity(this.props.siteRes) && (
-                <li className="nav-item">
-                  <NavLink
-                    to="/create_community"
-                    className="nav-link"
-                    onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
-                    title={i18n.t("create_community")}
-                  >
-                    {i18n.t("create_community")}
-                  </NavLink>
-                </li>
-              )}
-              <li className="nav-item">
-                <a
-                  className="nav-link"
-                  title={i18n.t("support_lemmy")}
-                  href={donateLemmyUrl}
-                >
-                  <Icon icon="heart" classes="small" />
-                </a>
-              </li>
-            </ul>
-            <ul className="navbar-nav my-2">
-              {amAdmin() && (
-                <li className="nav-item">
-                  <NavLink
-                    to="/admin"
-                    className="nav-link"
-                    onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
-                    title={i18n.t("admin_settings")}
-                  >
-                    <Icon icon="settings" />
-                  </NavLink>
-                </li>
-              )}
-            </ul>
-            {!this.context.router.history.location.pathname.match(
-              /^\/search/
-            ) && (
-              <ul className="navbar-nav">
-                <li className="nav-item">
-                  <NavLink
-                    to="/search"
-                    className="nav-link"
-                    title={i18n.t("search")}
-                  >
-                    <Icon icon="search" />
-                  </NavLink>
-                </li>
-              </ul>
-            )}
-            {UserService.Instance.myUserInfo ? (
-              <>
-                <ul className="navbar-nav my-2">
-                  <li className="nav-item">
-                    <NavLink
-                      className="nav-link"
-                      to="/inbox"
-                      onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
-                      title={i18n.t("unread_messages", {
-                        count: Number(this.state.unreadInboxCount),
-                        formattedCount: numToSI(this.state.unreadInboxCount),
-                      })}
-                    >
-                      <Icon icon="bell" />
-                      {this.state.unreadInboxCount > 0 && (
-                        <span className="ml-1 badge badge-light">
-                          {numToSI(this.state.unreadInboxCount)}
-                        </span>
-                      )}
-                    </NavLink>
-                  </li>
-                </ul>
-                {this.moderatesSomething && (
-                  <ul className="navbar-nav my-2">
-                    <li className="nav-item">
-                      <NavLink
-                        className="nav-link"
-                        to="/reports"
-                        onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
-                        title={i18n.t("unread_reports", {
-                          count: Number(this.state.unreadReportCount),
-                          formattedCount: numToSI(this.state.unreadReportCount),
-                        })}
-                      >
-                        <Icon icon="shield" />
-                        {this.state.unreadReportCount > 0 && (
-                          <span className="ml-1 badge badge-light">
-                            {numToSI(this.state.unreadReportCount)}
-                          </span>
-                        )}
-                      </NavLink>
-                    </li>
-                  </ul>
-                )}
-                {amAdmin() && (
-                  <ul className="navbar-nav my-2">
-                    <li className="nav-item">
-                      <NavLink
-                        to="/registration_applications"
-                        className="nav-link"
-                        onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
-                        title={i18n.t("unread_registration_applications", {
-                          count: Number(this.state.unreadApplicationCount),
-                          formattedCount: numToSI(
-                            this.state.unreadApplicationCount
-                          ),
-                        })}
-                      >
-                        <Icon icon="clipboard" />
-                        {this.state.unreadApplicationCount > 0 && (
-                          <span className="mx-1 badge badge-light">
-                            {numToSI(this.state.unreadApplicationCount)}
-                          </span>
-                        )}
-                      </NavLink>
-                    </li>
-                  </ul>
                 )}
                 {person && (
-                  <ul className="navbar-nav">
-                    <li className="nav-item dropdown">
-                      <button
-                        className="nav-link btn btn-link dropdown-toggle"
-                        onClick={linkEvent(this, this.handleToggleDropdown)}
-                        id="navbarDropdown"
-                        role="button"
-                        aria-expanded="false"
-                      >
-                        <span>
-                          {showAvatars() && person.avatar && (
-                            <PictrsImage src={person.avatar} icon />
-                          )}
-                          {person.display_name ?? person.name}
-                        </span>
-                      </button>
-                      {this.state.showDropdown && (
-                        <div
-                          className="dropdown-content"
-                          onMouseLeave={linkEvent(
-                            this,
-                            this.handleToggleDropdown
-                          )}
-                        >
-                          <li className="nav-item">
-                            <NavLink
-                              to={`/u/${person.name}`}
-                              className="nav-link"
-                              title={i18n.t("profile")}
-                            >
-                              <Icon icon="user" classes="mr-1" />
-                              {i18n.t("profile")}
-                            </NavLink>
-                          </li>
-                          <li className="nav-item">
-                            <NavLink
-                              to="/settings"
-                              className="nav-link"
-                              title={i18n.t("settings")}
-                            >
-                              <Icon icon="settings" classes="mr-1" />
-                              {i18n.t("settings")}
-                            </NavLink>
-                          </li>
-                          <li>
-                            <hr className="dropdown-divider" />
-                          </li>
-                          <li className="nav-item">
-                            <button
-                              className="nav-link btn btn-link"
-                              onClick={linkEvent(this, this.handleLogoutClick)}
-                              title="test"
-                            >
-                              <Icon icon="log-out" classes="mr-1" />
-                              {i18n.t("logout")}
-                            </button>
-                          </li>
-                        </div>
+                  <div className="dropdown">
+                    <button
+                      className="btn dropdown-toggle"
+                      role="button"
+                      aria-expanded="false"
+                      data-bs-toggle="dropdown"
+                    >
+                      {showAvatars() && person.avatar && (
+                        <PictrsImage src={person.avatar} icon />
                       )}
-                    </li>
-                  </ul>
+                      {person.display_name ?? person.name}
+                    </button>
+                    <ul
+                      className="dropdown-menu"
+                      style={{ "min-width": "fit-content" }}
+                    >
+                      <li>
+                        <NavLink
+                          to={`/u/${person.name}`}
+                          className="dropdown-item px-2"
+                          title={i18n.t("profile")}
+                          onMouseUp={linkEvent(this, handleCollapseClick)}
+                        >
+                          <Icon icon="user" classes="mr-1" />
+                          {i18n.t("profile")}
+                        </NavLink>
+                      </li>
+                      <li>
+                        <NavLink
+                          to="/settings"
+                          className="dropdown-item px-2"
+                          title={i18n.t("settings")}
+                          onMouseUp={linkEvent(this, handleCollapseClick)}
+                        >
+                          <Icon icon="settings" classes="mr-1" />
+                          {i18n.t("settings")}
+                        </NavLink>
+                      </li>
+                      <li>
+                        <hr className="dropdown-divider" />
+                      </li>
+                      <li>
+                        <button
+                          className="dropdown-item btn btn-link px-2"
+                          onClick={handleLogOut}
+                        >
+                          <Icon icon="log-out" classes="mr-1" />
+                          {i18n.t("logout")}
+                        </button>
+                      </li>
+                    </ul>
+                  </div>
                 )}
               </>
             ) : (
-              <ul className="navbar-nav my-2">
+              <>
                 <li className="nav-item">
                   <NavLink
                     to="/login"
                     className="nav-link"
-                    onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
                     title={i18n.t("login")}
+                    onMouseUp={linkEvent(this, handleCollapseClick)}
                   >
                     {i18n.t("login")}
                   </NavLink>
@@ -444,15 +423,15 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                   <NavLink
                     to="/signup"
                     className="nav-link"
-                    onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
                     title={i18n.t("sign_up")}
+                    onMouseUp={linkEvent(this, handleCollapseClick)}
                   >
                     {i18n.t("sign_up")}
                   </NavLink>
                 </li>
-              </ul>
+              </>
             )}
-          </div>
+          </ul>
         </div>
       </nav>
     );
@@ -464,23 +443,6 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
     return amAdmin() || moderatesS;
   }
 
-  handleToggleExpandNavbar(i: Navbar) {
-    i.setState({ expanded: !i.state.expanded });
-  }
-
-  handleHideExpandNavbar(i: Navbar) {
-    i.setState({ expanded: false, showDropdown: false });
-  }
-
-  handleLogoutClick(i: Navbar) {
-    i.setState({ showDropdown: false, expanded: false });
-    UserService.Instance.logout();
-  }
-
-  handleToggleDropdown(i: Navbar) {
-    i.setState({ showDropdown: !i.state.showDropdown });
-  }
-
   parseMessage(msg: any) {
     let op = wsUserOp(msg);
     console.log(msg);