cat dropdown & build

This commit is contained in:
VividTruthKeeper 2023-02-26 01:32:01 +05:00
parent 1cfa997c4c
commit 88ea89cec4
15 changed files with 513 additions and 140 deletions

File diff suppressed because one or more lines are too long

115
dist/assets/index-4f7f6194.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/index.html vendored
View File

@ -6,8 +6,8 @@
<meta name="description" id="meta-description" content="" />
<meta name="keywords" id="meta-keywords" content="" />
<title>Türkmenistan Habarlar Portaly</title>
<script type="module" crossorigin src="/assets/index-06b310f2.js"></script>
<link rel="stylesheet" href="/assets/index-04e47b32.css">
<script type="module" crossorigin src="/assets/index-4f7f6194.js"></script>
<link rel="stylesheet" href="/assets/index-88307ab3.css">
</head>
<body>
<div id="root"></div>

View File

@ -1,4 +1,6 @@
export const linkMotion = {
import { Variants } from "framer-motion";
export const linkMotion: Variants = {
rest: {
fontWeight: "normal",
background: "rgba(241,241, 241, 1)",
@ -18,3 +20,50 @@ export const linkMotion = {
// type: "spring",
// },
};
export const catMotion: Variants = {
rest: {
display: "block",
opacity: 0,
transform: "translateY(-10rem)",
type: "tween",
},
active: {
display: "block",
opacity: 1,
transform: "translateY(0rem)",
type: "tween",
},
menuRest: {
rotate: "0",
type: "spring",
},
menuActive: {
rotate: "90deg",
type: "spring",
},
};
export const dropdownMotion: Variants = {
rest: {
y: "5rem",
opacity: 0,
pointerEvents: "none",
},
active: {
y: "0rem",
opacity: 1,
pointerEvents: "all",
},
linkRest: {
borderBottom: "0.1rem solid rgba(255, 255, 255, 0)",
fontWeight: "normal",
},
linkActive: {
borderBottom: "0.1rem solid rgba(255, 255, 255, 1)",
fontWeight: "bold",
},
};

View File

@ -14,7 +14,7 @@ export const newsScrollParams: IurlParamAdder[] = [
export const categoriesParams: IurlParamAdder[] = [
{
name: "count",
value: 7,
value: 100,
},
{
name: "page",

12
src/assets/icons/menu.svg Normal file
View File

@ -0,0 +1,12 @@
<svg width="24" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_343_1783)">
<path d="M20.05 11.0001H3.95C3.42533 11.0001 3 11.4255 3 11.9501V12.0501C3 12.5748 3.42533 13.0001 3.95 13.0001H20.05C20.5747 13.0001 21 12.5748 21 12.0501V11.9501C21 11.4255 20.5747 11.0001 20.05 11.0001Z" fill="white"/>
<path d="M20.05 16.0001H3.95C3.42533 16.0001 3 16.4255 3 16.9501V17.0501C3 17.5748 3.42533 18.0001 3.95 18.0001H20.05C20.5747 18.0001 21 17.5748 21 17.0501V16.9501C21 16.4255 20.5747 16.0001 20.05 16.0001Z" fill="white"/>
<path d="M20.05 6.00012H3.95C3.42533 6.00012 3 6.42545 3 6.95012V7.05012C3 7.57479 3.42533 8.00012 3.95 8.00012H20.05C20.5747 8.00012 21 7.57479 21 7.05012V6.95012C21 6.42545 20.5747 6.00012 20.05 6.00012Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_343_1783">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 913 B

View File

@ -0,0 +1,52 @@
// Modules
import { Dispatch, SetStateAction } from "react";
import { motion } from "framer-motion";
import { v4 as uuidv4 } from "uuid";
import { Link } from "react-router-dom";
// Types
import { ICategoriesData } from "../../types/data.types";
import { dropdownMotion } from "../../animations/subNav.animations";
interface IProps {
dropdownOpen: boolean;
setDropdownOpen: Dispatch<SetStateAction<boolean>>;
data: ICategoriesData;
onClickLink: (active: number) => void;
activeLink: number;
}
const NavDropdown = ({
dropdownOpen,
setDropdownOpen,
data,
onClickLink,
activeLink,
}: IProps) => {
return (
<motion.div
className="nav-dropdown"
variants={dropdownMotion}
initial={"rest"}
animate={dropdownOpen ? "active" : "rest"}
>
<ul>
{data.data.map((el) => (
<li onClick={() => onClickLink(el.id)} key={uuidv4()}>
<Link to={`/category/${el.id}`}>
<motion.span
variants={dropdownMotion}
initial={"linkRest"}
animate={activeLink === el.id ? "linkActive" : "linkRest"}
>
{el.name}
</motion.span>
</Link>
</li>
))}
</ul>
</motion.div>
);
};
export default NavDropdown;

View File

@ -14,11 +14,12 @@ import { setActiveLink } from "../../actions/setActiveLink.action";
// Api
import { Api } from "../../api/Api";
import { url } from "../../url";
import { categoriesParams } from "../../api/params";
// Components
import Loader from "../global/Loader";
import SubNavLi from "./SubNavLi";
import { categoriesParams } from "../../api/params";
import SubNavLiMain from "./SubNavLiMain";
const SubNav = () => {
const activeLink = useSelector<RootState, RootState["activeLink"]["active"]>(
@ -60,16 +61,21 @@ const SubNav = () => {
<ul className="subnav-inner">
{data ? (
<>
{data.data.map((dataEl) => {
return (
<SubNavLiMain
data={data}
activeLink={activeLink}
onClickLink={onClickLink}
/>
{data.data.map((dataEl, index) =>
index <= 4 ? (
<SubNavLi
key={uuidv4()}
dataEl={dataEl}
activeLink={activeLink}
onClickLink={onClickLink}
/>
);
})}
) : null
)}
</>
) : (
<Loader />

View File

@ -23,8 +23,9 @@ const SubNavLi = ({
}: IProps) => {
return (
<motion.li
initial={linkMotion.rest}
animate={activeLink === dataEl.id ? linkMotion.active : linkMotion.rest}
initial={"rest"}
animate={activeLink === dataEl.id ? "active" : "rest"}
variants={linkMotion}
>
<motion.div>
<Link

View File

@ -0,0 +1,94 @@
// Modules
import { motion } from "framer-motion";
import { useState } from "react";
import { v4 as uuidv4 } from "uuid";
// Animations
import { catMotion, linkMotion } from "../../animations/subNav.animations";
// Types
import { ICategoriesData } from "../../types/data.types";
// Components
import NavDropdown from "./NavDropdown";
interface IProps {
activeLink: number;
data: ICategoriesData;
onClickLink: (active: number) => void;
}
const SubNavLiMain = ({ activeLink, data, onClickLink }: IProps) => {
const [dropdownOpen, setDropdownOpen] = useState<boolean>(false);
return (
<motion.li
className="sub-nav-li-main"
initial={"active"}
variants={linkMotion}
onClick={() => setDropdownOpen(!dropdownOpen)}
>
<motion.div className="inner">
<motion.svg
width="24"
height="20"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
variants={catMotion}
initial={"menuRest"}
animate={dropdownOpen ? "menuActive" : "menuRest"}
>
<g clipPath="url(#clip0_343_1783)">
<path
d="M20.05 11.0001H3.95C3.42533 11.0001 3 11.4255 3 11.9501V12.0501C3 12.5748 3.42533 13.0001 3.95 13.0001H20.05C20.5747 13.0001 21 12.5748 21 12.0501V11.9501C21 11.4255 20.5747 11.0001 20.05 11.0001Z"
fill="white"
/>
<path
d="M20.05 16.0001H3.95C3.42533 16.0001 3 16.4255 3 16.9501V17.0501C3 17.5748 3.42533 18.0001 3.95 18.0001H20.05C20.5747 18.0001 21 17.5748 21 17.0501V16.9501C21 16.4255 20.5747 16.0001 20.05 16.0001Z"
fill="white"
/>
<path
d="M20.05 6.00012H3.95C3.42533 6.00012 3 6.42545 3 6.95012V7.05012C3 7.57479 3.42533 8.00012 3.95 8.00012H20.05C20.5747 8.00012 21 7.57479 21 7.05012V6.95012C21 6.42545 20.5747 6.00012 20.05 6.00012Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0_343_1783">
<rect width="24" height="24" fill="white" />
</clipPath>
</defs>
</motion.svg>
<p className={activeLink === 0 ? "active" : ""}>Категории</p>
<p>|</p>
<p>
<motion.span
variants={catMotion}
initial={"rest"}
animate={activeLink === 0 ? "active" : "rest"}
>
Главная
</motion.span>
{data.data.map((el) => (
<motion.span
key={uuidv4()}
variants={catMotion}
initial={"rest"}
animate={activeLink === el.id ? "active" : "rest"}
>
{el.name}
</motion.span>
))}
</p>
</motion.div>
<NavDropdown
data={data}
dropdownOpen={dropdownOpen}
setDropdownOpen={setDropdownOpen}
onClickLink={onClickLink}
activeLink={activeLink}
/>
</motion.li>
);
};
export default SubNavLiMain;

View File

@ -17,7 +17,11 @@ const ContentItem = ({ type = "small", img, title, id }: IProps) => {
alt={img}
effect="blur"
useIntersectionObserver
style={{ background: `url(${img})` }}
style={{
background: `url(${img})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
}}
/>
<Link to={`/news/${id}`} className="main-content-item-overlay">
<h2>{title}</h2>

View File

@ -121,7 +121,7 @@
}
.language-dropdown {
z-index: 2;
z-index: 4;
position: absolute;
top: calc(100% + 1rem);
left: 0;
@ -154,11 +154,10 @@
.subnav-inner {
padding: 1.6rem 0;
width: 100%;
overflow-x: auto;
display: flex;
display: grid;
grid-template-columns: 34rem repeat(5, 1fr);
align-items: center;
gap: 2.4rem;
justify-content: space-between;
li {
color: $black;
@ -205,13 +204,79 @@
position: relative;
}
.sub-nav-li-main {
cursor: pointer;
position: relative;
max-height: 3.9rem;
padding: 1rem;
.inner {
overflow: hidden;
display: grid;
grid-template-columns: 2.4rem 8rem 1rem 18rem;
gap: 0.8rem;
}
p {
align-self: center;
height: 100%;
pointer-events: none;
position: relative;
border-radius: 0.4rem;
text-transform: capitalize;
display: block;
white-space: nowrap;
font-size: 1.6rem;
color: inherit;
font-family: "Raleway", sans-serif;
-webkit-user-drag: none;
white-space: normal;
text-align: center;
overflow: hidden;
span {
width: 100%;
position: absolute;
font-weight: normal;
white-space: nowrap;
}
}
}
.nav-dropdown {
z-index: 3;
padding: 2.4rem;
background: $main;
position: absolute;
top: 5.6rem;
left: 0;
height: fit-content;
width: max-content;
ul {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.8rem;
}
li {
border-radius: 0;
color: $white;
font-weight: normal;
a {
text-transform: none;
padding: 0.8rem;
text-align: start;
white-space: normal;
}
span {
padding: 0.4rem 0;
display: inline-block;
}
}
}
// Media
@media screen and (max-width: 850px) {
.nav-mid {
h1 {
// text-align: start;
}
}
.nav-right {
display: none;
}
@ -259,3 +324,79 @@
}
}
}
// Media
@media screen and (max-width: 1150px) {
.subnav-inner {
grid-template-columns: 34rem repeat(4, 1fr);
li {
&:nth-child(6) {
display: none;
}
}
}
}
@media screen and (max-width: 900px) {
.subnav-inner {
grid-template-columns: 34rem repeat(3, 1fr);
li {
&:nth-child(5) {
display: none;
}
}
}
}
@media screen and (max-width: 850px) {
.sub-nav-li-main {
padding: 0.8rem;
p,
span {
font-size: 1.4rem;
}
svg {
height: 1.6rem;
}
}
.subnav-inner {
grid-template-columns: 34rem repeat(3, 1fr);
li {
&:nth-child(5) {
display: none;
}
}
}
}
@media screen and (max-width: 700px) {
.subnav-inner {
grid-template-columns: 34rem repeat(2, 1fr);
li {
&:nth-child(4) {
display: none;
}
}
}
}
@media screen and (max-width: 600px) {
.nav-dropdown {
width: 100%;
}
.sub-nav-li-main {
.inner {
grid-template-columns: 2.4rem 8rem 1rem 70%;
}
}
.subnav-inner {
grid-template-columns: 1fr;
li {
&:nth-child(2),
&:nth-child(3) {
display: none;
}
}
}
}

View File

@ -67,7 +67,7 @@
span {
width: 100%;
height: 100%;
object-fit: cover;
object-fit: contain;
}
}

View File

@ -131,6 +131,15 @@
}
}
@media (max-width: 1200px) {
.news-status-left {
p {
&:nth-child(n + 3) {
display: none;
}
}
}
}
@media (max-width: 1024px) {
.news-text {
font-size: 1.6rem;
@ -158,14 +167,19 @@
flex-direction: column;
}
.news-image {
height: 25rem;
height: 35rem;
}
}
@media (max-width: 550px) {
.news-image {
height: 28rem;
}
}
@media (max-width: 400px) {
.news-status-left {
p {
&:nth-child(n + 4) {
&:nth-child(n + 2) {
display: none;
}
}