From 028c0843d4d59a1e4d043af403c74327f5ede4bb Mon Sep 17 00:00:00 2001 From: Mikayla Dobson <93477693+innocuous-symmetry@users.noreply.github.com> Date: Fri, 3 Jun 2022 21:00:21 -0500 Subject: [PATCH] scroll animation on projects page for filter panel --- src/App.js | 10 +-- src/App.scss | 57 ++++++++++-- src/pages/Projects.js | 201 ++++++++++-------------------------------- src/styles/Style.js | 3 +- 4 files changed, 102 insertions(+), 169 deletions(-) diff --git a/src/App.js b/src/App.js index 3349830..2686c13 100644 --- a/src/App.js +++ b/src/App.js @@ -24,9 +24,9 @@ function App() { */} -
- - + + +
} /> } /> @@ -35,8 +35,8 @@ function App() { } /> } /> - -
+
+ ); diff --git a/src/App.scss b/src/App.scss index afe2483..8edb413 100644 --- a/src/App.scss +++ b/src/App.scss @@ -1,17 +1,40 @@ +// STYLESHEET FOR ABOUT MIKAYLA SITE +// STRUCTURE OF THIS FILE AS FOLLOWS: + +// font imports +// variable declarations +// main app styles: +// ---- navbar +// welcome page +// technologies page +// about me page +// projects page + +//////////////// +//////////////// +//////////////// +//////////////// +//////////////// + @import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap'); $pink50: #fce4ec; +$purple100: #e1bee7; $purple200: #ce93d8; .App { text-align: center; - .app-navbar { background-color: $purple200; + height: 4.5rem; display: flex; border-bottom: 1px solid black; font-family: 'Open Sans', sans-serif; + position: fixed; + top: 0; + width: 100vw; + z-index: 9; .navbar-left { display: flex; @@ -52,6 +75,10 @@ $purple200: #ce93d8; padding-left: 1rem; } } + main { + position: relative; + top: 4.5rem; + } } .welcome-page { @@ -212,30 +239,46 @@ $purple200: #ce93d8; .projects-page { .filter-panel { display: flex; + position: static; flex-direction: column; background-color: white; align-items: center; - padding: 2rem; - width: 50%; + padding: 1rem; + width: 40vw; + border-radius: 12px; + margin-bottom: 2rem; + transition: align-items 1s ease, + position 1s ease + ; + .filter-controls { - display: inline-flex; + display: flex; justify-content: space-between; - width: 65%; + width: 80%; } + + } + .filter-anim-one { + position: sticky; + left: 2rem; + top: 6rem; + justify-content: flex-start; + } + .filter-anim-two { + } .project-cards { display: flex; flex-direction: column; align-items: center; + margin-top: 2rem; > * { display: flex; flex-direction: column; align-items: center; background-color: lightblue; - // min-width: 80%; - // max-width: 80%; width: 80%; height: auto; margin-bottom: 2rem; diff --git a/src/pages/Projects.js b/src/pages/Projects.js index 20af3c0..216bfcd 100644 --- a/src/pages/Projects.js +++ b/src/pages/Projects.js @@ -1,169 +1,31 @@ +import { useState, useEffect, useRef, useCallback } from 'react'; +import { DocumentStyle } from '../styles/Style'; +import { projectsArray } from '../components/ProjectsArray'; +import { Divider } from '@mui/material'; import '../App.scss'; -import { useState, useEffect, useRef } from 'react'; -import { DocumentStyle, ProjectsPage } from '../styles/Style'; - -import Button from '@mui/material/Button'; -import Card from '@mui/material/Card'; - -const { htmlTheme, stockGallery } = DocumentStyle; -const { projectsButton } = ProjectsPage; +const { htmlTheme, dividerStyle } = DocumentStyle; const defaultFilter = { language: '', searchTerm: '', - inProgress: null + inProgress: false } export default function Projects() { const [results, setResults] = useState(); - const [filter, setFilter] = useState(); + const [filter, setFilter] = useState(defaultFilter); + const [panelStyle, setPanelStyle] = useState(''); const searchInput = useRef(); const languageFilter = useRef(); + const projectPage = useRef(); useEffect(() => { - const galleryArray = [ - { - name: "Mikayla's E-Commerce Store", - languages: ["TypeScript", "React", "PERN", "REST_API"], - inProgress: true, - jsx: ( - -

Mikayla's E-Commerce Store

-

A fully-featured e-commerce platform

-

Built in React with TypeScript, Node/Express, and PostgreSQL

-

Payment processing supported through Stripe

-

REST API fully documented in Swagger

-

IN PROGRESS

-
- ) - }, - { - name: "Procedural Drones", - languages: ["JavaScript", "HTML/CSS"], - inProgress: true, - deployed: true, - jsx: ( - -

Procedural Drones

-

An experimental space for building out procedural music generation using vanilla JavaScript

-

Uses Tone.js to interact with the Web Audio API

-

Features a plain HTML/CSS front end to interact with the program

-
- GitHub Repo - Deployed version -
-
- ) - }, - { - name: "Reddit, but it's all cats", - languages: ["React", "Redux"], - inProgress: false, - deployed: true, - jsx: ( - -

Reddit, but it's all cats

-

A read-only Reddit client -- this site fetches data from Reddit and displays a curated feed.

-

This was built on Reddit's JSON API, using React/Redux and CSS.

-

And yes, it's all cats.

-
- GitHub Repo - Deployed version -
-
- ) - }, - { - name: "Personal Timestamp Generator", - languages: ["Python", "SQLite"], - inProgress: false, - jsx: ( - -

Personal Timestamp Generator

-

A small-scale timestamp/productivity management tool for individual use and logging of - time, including compartmentalization by task and some aggregate functions based on queries. -

-

Command-line interface built on Python with a SQLite Database.

- View the repo here! -
- ) - }, - { - name: "Musical Counterpoint Bot", - languages: ["HTML/CSS", "JavaScript"], - inProgress: true, - jsx: ( - -

Musical Counterpoint Bot

-

A web-based program with functionality to evaluate sample solutions of problems in - species-based counterpoint, as detailed by Johann Fux in Gradus ad Parnassum.

-

This project is intended to be used as a practical application of linked lists and - other compound data structures in JavaScript.

-

In progress. Using vanilla HTML/CSS/JS.

-
- ) - }, - { - name: "Password Game", - languages: ["React", "MongoDB", "MERN", "React", "REST_API", "Socket.io", "Sass", "MaterialUI"], - inProgress: true, - jsx: ( - -

Password Game

-

As part of a mentorship program hosted by Metazu Studio

-

Implemented using MongoDB, React, and Node/Express, styled with Material UI/SCSS.

-

In progress, building in collaboration with others at Metazu Studio.

-
- ) - }, - { - name: "Splinter", - languages: ["React", "PERN", "Socket.io"], - inProgress: true, - jsx: ( - -

Splinter

-

A clone of a popular card-based resource gathering game

-

Local multiplayer, with plans to build out online multiplayer and solo vs. CPU

-

In progress. Using React, Node/Express, and PostgreSQL.

-
- ) - }, - { - name: "Carenest", - languages: ["React"], - inProgress: false, - jsx: ( - -

Carenest

-

Designed in collaboration with Faith Magras, Elvis Hernandez, and Daytreon Dean - as a submission for #HACKTN in March 2022.

-

Produced using React. View the repo here!

-
- ) - }, - { - name: "This Site", - languages: ["React", "Sass", "MaterialUI"], - inProgress: true, - jsx: ( - -

And, last but not least, the site you see here!

-

This site is built using React, Material UI, and SCSS, and is hosted with Netlify.

- View the site repo here! -
- ) - } - ] - - if (!filter) { - setResults(galleryArray.map(each => each.jsx)); - } + if (!filter) setResults(projectsArray.map(each => each.jsx)); if (filter) { - let result = galleryArray; + let result = projectsArray; if (filter.searchTerm) { let termLower = filter.searchTerm.toLowerCase(); result = result.filter(obj => obj.name.toLowerCase().includes(termLower)); @@ -172,9 +34,8 @@ export default function Projects() { let adjustedLang = ((filter.language === 'PostgreSQL' || filter.language === "Express") ? "PERN" : filter.language); result = result.filter(obj => obj.languages.includes(adjustedLang)); } - if (filter.inProgress) { - result = result.filter(obj => obj.inProgress === filter.inProgress); - } + + if (filter.inProgress) result = result.filter(obj => !obj.inProgress); setResults(result.map(each => each.jsx)); } @@ -194,11 +55,33 @@ export default function Projects() { languageFilter.current.value = ''; } + useEffect(() => { + const handleScroll = (e) => { + let position = window.scrollY; + + if (position > 150) { + setPanelStyle("filter-anim-one"); + } else { + setPanelStyle(""); + } + } + + window.addEventListener('scroll', handleScroll); + + return () => { + window.removeEventListener('scroll', handleScroll); + } + }, []); + + useEffect(() => { + console.log(panelStyle); + }, [panelStyle]); + return (
-

Here are some sample projects from my portfolio!

+

Check out these projects from my portfolio!

-
+

Filter by:

SQLite - +
-
{results}
+ + +
+ {results} +
) } \ No newline at end of file diff --git a/src/styles/Style.js b/src/styles/Style.js index 5cc53e8..d285dc7 100644 --- a/src/styles/Style.js +++ b/src/styles/Style.js @@ -6,7 +6,8 @@ export const DocumentStyle = { display: 'flex', flexDirection: 'column', alignItems: 'center', - height: '100vh', + minHeight: '100vh', + height: '100%', }, linkStyle: { color: deepPurple[300],