Как выровнять этот компонент выпадающего меню под указанным c местом на моей панели навигации в реакции? - PullRequest
0 голосов
/ 08 января 2020

Я столкнулся с проблемой при написании простой панели навигации и выпадающего меню в React. Я создал раздел в навигационной панели для учетной записи, которая при наведении на нее приведет к появлению выпадающего меню сразу под ним. Я попытался скопировать код для этого непосредственно с сайта w3, но столкнулся с большим количеством проблем и решил использовать свой собственный подход ...

Я создал функциональный компонент Dropdown, отображаемый моим компонентом Navbar. Видимое / скрытое состояние компонента Dropdown отслеживается в переменной useState с именем hideDropdown.

До этого момента все работало правильно. Моя проблема возникает при попытке настроить этот выпадающий компонент под разделом учетной записи на панели навигации. Независимо от того, что я пытаюсь, я не могу получить его в нужном месте на экране. Даже если я жестко закодирую количество пикселей, что компонент должен быть с левой стороны, изменение размера экрана разрушает это. По умолчанию компонент Dropdown появляется слева. Кроме того, только свойство left влияет на его положение. Право не делает ничего наблюдаемого. Кроме того, проценты, по-видимому, не основаны на ширине страницы, так как для выравнивания раскрывающегося списка полностью справа свойство left должно быть 800%.

https://codepen.io/sjh5888/pen/rNaJgya

Navbar. js

import React, { useState, useContext, useEffect } from "react";
import { Redirect } from "react-router-dom";
import jsonwebtoken from "jsonwebtoken";
import Dropdown from "./Modals/Dropdown";
import "./CSS/navbar.css";
import NewPostModal from "./Modals/NewPostModal";
import { CategoryContext } from "./Context/CategoryContext";

function Navbar(props) {
  const { categories, setCategories, user } = useContext(CategoryContext);
  const [modalOpen, updateModal] = useState(false);
  const [hideDropdown, setHideDropdown] = useState(false); //change to true when done
  const [isLoading, setIsLoading] = useState(true);
  const jwtDecoded = jsonwebtoken.decode(localStorage.getItem("jwt"));

  console.log(
    "is token valid? " +
      (jwtDecoded.exp > (Date.now() - (Date.now() % 1000)) / 1000)
  );
  console.log(jwtDecoded);

  if (jwtDecoded.exp > (Date.now() - (Date.now() % 1000)) / 1000) {
    return (
      <div style={{ zIndex: "1", position: "fixed", display: "flex" }}>
        <ul className="navinator">
          <li className="navElement">
            <a className="anchor" href="/home">
              Home
            </a>
          </li>
          <li className="navElement">
            <a className="anchor" href="/profile">
              Profile
            </a>
          </li>
          <li className="active">
            <a
              className="anchor"
              // href="#"
              onClick={e => updateModal(true)}
            >
              + New Post
            </a>
          </li>
          <li style={{ float: "right" }}>
            <div
              id="profile"
              onMouseOver={e => setHideDropdown(false)}
              onMouseLeave={e => setHideDropdown(true)}
            >
              <div style={{ float: "left", paddingRight: "10px" }}>
                <img
                  src={user.profileImage}
                  alt="error"
                  className="profile-image"
                />
                {/* need profileImage field for user */}
              </div>
              <div style={{ float: "left", paddingRight: "5px" }}>
                {jwtDecoded.sub}
              </div>
              <div style={{ float: "left" }} className="arrow-down"></div>
            </div>
          </li>
        </ul>
        <NewPostModal show={modalOpen} updateModal={updateModal} />
        <div style={{float:"right"}}><Dropdown visible={hideDropdown} setHideDropdown={setHideDropdown}/></div>
      </div>
    );
  } else {
    console.log("redirecting");
    return <Redirect to={{ pathname: "/login", state: { from: "/home" } }} />;
  }
} //class

export default Navbar;

Выпадающий список. js

import React from "react";
import "../CSS/navbar.css";

export default function Dropdown(props) {
  return (
    <div
      hidden={props.visible}
      className="dropdown"
      onMouseOver={e => props.setHideDropdown(false)}
      onMouseLeave={e => props.setHideDropdown(true)}
    >
      <li>
        <a className="anchor" style={{ textAlign: "left" }} href="/profile">
          Profile
        </a>
      </li>
    </div>
  );
}

Navbar . css

.navinator {
  z-index: 1;
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: rgb(218, 10, 10);
  position: fixed;
  top: 0;
  width: 100%;
  height: 52px;
}
.navElement {
  float: left;
}
.anchor{
  display: block;
  color: white !important;
  text-align: center;
  padding: 14px 16px; 
  text-decoration: none !important;
  cursor: pointer;
}
.anchor:hover {
  background-color: rgb(255, 23, 15) !important;
}
.active {
  background-color: rgb(28, 13, 110) !important;
  float: right;
  width: 120px;
}
.active .anchor{
  align-items: center;
  justify-content: center;
}
.active .anchor:hover {
  background-color: rgb(32, 11, 156) !important;
}
.profile-image {
  width: 30px;
  height: 30px;
  position: relative;
  overflow: hidden;
  border-radius: 50%;
}
#profile {
  color: white !important;
  text-align: center;
  padding: 14px 16px; 
  text-decoration: none !important;
  /* height: 52px; */
  overflow: auto;
}
#profile:hover {
  background-color: rgb(255, 23, 15) !important;
  cursor: pointer;
}
.arrow-down {
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid white;
  margin-top: 10px;
}
.dropdown{
  top: 52px;
  width: 222px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  display: inline-block;
  background-color: rgb(218, 10, 10);
}
.dropdown li{
  list-style-type: none;
}

Я довольно новичок в веб-разработке и получаю массу удовольствия. Однако, это немного расстраивает, так как я чувствую, что это должно быть довольно простое решение. Любая помощь будет оценена!

1 Ответ

0 голосов
/ 09 января 2020

Я думаю, это то, что вы хотите

У меня были некоторые изменения CSS и JS

CSS

.navinator {
  z-index: 1;
  list-style-type: none;
  margin: 0;
  padding: 0;
  background-color: rgb(218, 10, 10);
  position: fixed;
  top: 0;
  width: 100%;
  height: 47px;
}
.navElement {
  float: left;
}
.anchor{
  display: block;
  color: white !important;
  text-align: center;
  padding: 14px 16px; 
  text-decoration: none !important;
  cursor: pointer;
}
.anchor:hover {
  background-color: rgb(255, 23, 15) !important;
}
.active {
  background-color: rgb(28, 13, 110) !important;
  float: right;
  width: 120px;
}
.active .anchor{
  align-items: center;
  justify-content: center;
}
.active .anchor:hover {
  background-color: rgb(32, 11, 156) !important;
}
.profile-image {
  width: 30px;
  height: 30px;
  position: relative;
  overflow: hidden;
  border-radius: 50%;
}
#profile {
  color: white !important;
  text-align: center;
  padding: 11px 16px; 
  text-decoration: none !important;
  /* height: 52px; */
  overflow: auto;
}
#profile:hover {
  background-color: rgb(255, 23, 15) !important;
  cursor: pointer;
}
.arrow-down {
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid white;
  margin-top: 10px;
}
.dropdown {
  opacity:0;
  visibility: hidden;
    top: 47px;
    width: 222px;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    /* display: inline-block; */
    background-color: rgb(6, 6, 6);
    position: absolute;
}
.drop-item:hover .dropdown{
  opacity:1;
  visibility: visible;
  transition: all .3s;
}

.dropdown li{
  list-style-type: none;
}

JS

const Navbar = () => (
  <div style={{ zIndex: "1", position: "fixed", display: "flex" }}>
        <ul className="navinator">
          <li className="navElement">
            <a className="anchor" href="/home">
              Home
            </a>
          </li>
          <li className="navElement">
            <a className="anchor" href="/profile">
              Profile
            </a>
          </li>
          <li className="active">
            <a
              className="anchor"
              // href="#"

            >
              + New Post
            </a>
          </li>
          <li class="drop-item" style={{ float: "right" }}>
            <div
              id="profile"
              >
              <div style={{ float: "left", paddingRight: "10px" }}>
                <img
                  src=""
                  alt="error"
                  className="profile-image"
                />

              </div>
              <div style={{ float: "left", paddingRight: "5px" }}>
                whatever
              </div>
              <div style={{ float: "left" }} className="arrow-down"></div>
            </div>
            <div style={{float:"right"}} className="dropdown">

     <li>
        <a className="anchor" style={{ textAlign: "left" }} href="/profile">
          Profile
        </a>
      </li>
      <li>
        <a className="anchor" style={{ textAlign: "left" }} href="/profile">
          Profile
        </a>
      </li>

    </div>
          </li>
        </ul>

      </div>
)

ReactDOM.render(<Navbar />, document.getElementById('root'))

То, что я решил, откройте drop-down, когда hover над чем-либо в nav и установите его позицию ниже своего родителя, на котором он завис

...