scroll animation on projects page for filter panel

This commit is contained in:
Mikayla Dobson
2022-06-03 21:00:21 -05:00
parent cfb884d169
commit 028c0843d4
4 changed files with 102 additions and 169 deletions

View File

@@ -24,9 +24,9 @@ function App() {
*/} */}
<main>
<BrowserRouter> <BrowserRouter>
<Navbar /> <Navbar />
<main>
<Routes> <Routes>
<Route path='/' element={<Welcome />} /> <Route path='/' element={<Welcome />} />
<Route path='/about-me' element={<AboutMe />} /> <Route path='/about-me' element={<AboutMe />} />
@@ -35,8 +35,8 @@ function App() {
<Route path='/links' element={<Links />} /> <Route path='/links' element={<Links />} />
<Route path='/creative-works' element={<CreativeWorks />} /> <Route path='/creative-works' element={<CreativeWorks />} />
</Routes> </Routes>
</BrowserRouter>
</main> </main>
</BrowserRouter>
</div> </div>
); );

View File

@@ -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=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'); @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; $pink50: #fce4ec;
$purple100: #e1bee7;
$purple200: #ce93d8; $purple200: #ce93d8;
.App { .App {
text-align: center; text-align: center;
.app-navbar { .app-navbar {
background-color: $purple200; background-color: $purple200;
height: 4.5rem;
display: flex; display: flex;
border-bottom: 1px solid black; border-bottom: 1px solid black;
font-family: 'Open Sans', sans-serif; font-family: 'Open Sans', sans-serif;
position: fixed;
top: 0;
width: 100vw;
z-index: 9;
.navbar-left { .navbar-left {
display: flex; display: flex;
@@ -52,6 +75,10 @@ $purple200: #ce93d8;
padding-left: 1rem; padding-left: 1rem;
} }
} }
main {
position: relative;
top: 4.5rem;
}
} }
.welcome-page { .welcome-page {
@@ -212,30 +239,46 @@ $purple200: #ce93d8;
.projects-page { .projects-page {
.filter-panel { .filter-panel {
display: flex; display: flex;
position: static;
flex-direction: column; flex-direction: column;
background-color: white; background-color: white;
align-items: center; align-items: center;
padding: 2rem; padding: 1rem;
width: 50%; width: 40vw;
border-radius: 12px;
margin-bottom: 2rem;
transition: align-items 1s ease,
position 1s ease
;
.filter-controls { .filter-controls {
display: inline-flex; display: flex;
justify-content: space-between; 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 { .project-cards {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
margin-top: 2rem;
> * { > * {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
background-color: lightblue; background-color: lightblue;
// min-width: 80%;
// max-width: 80%;
width: 80%; width: 80%;
height: auto; height: auto;
margin-bottom: 2rem; margin-bottom: 2rem;

View File

@@ -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 '../App.scss';
import { useState, useEffect, useRef } from 'react';
import { DocumentStyle, ProjectsPage } from '../styles/Style'; const { htmlTheme, dividerStyle } = DocumentStyle;
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
const { htmlTheme, stockGallery } = DocumentStyle;
const { projectsButton } = ProjectsPage;
const defaultFilter = { const defaultFilter = {
language: '', language: '',
searchTerm: '', searchTerm: '',
inProgress: null inProgress: false
} }
export default function Projects() { export default function Projects() {
const [results, setResults] = useState(); const [results, setResults] = useState();
const [filter, setFilter] = useState(); const [filter, setFilter] = useState(defaultFilter);
const [panelStyle, setPanelStyle] = useState('');
const searchInput = useRef(); const searchInput = useRef();
const languageFilter = useRef(); const languageFilter = useRef();
const projectPage = useRef();
useEffect(() => { useEffect(() => {
const galleryArray = [ if (!filter) setResults(projectsArray.map(each => each.jsx));
{
name: "Mikayla's E-Commerce Store",
languages: ["TypeScript", "React", "PERN", "REST_API"],
inProgress: true,
jsx: (
<Card>
<h1>Mikayla's E-Commerce Store</h1>
<p>A fully-featured e-commerce platform</p>
<p>Built in React with TypeScript, Node/Express, and PostgreSQL</p>
<p>Payment processing supported through Stripe</p>
<p>REST API fully documented in Swagger</p>
<p>IN PROGRESS</p>
</Card>
)
},
{
name: "Procedural Drones",
languages: ["JavaScript", "HTML/CSS"],
inProgress: true,
deployed: true,
jsx: (
<Card>
<h1>Procedural Drones</h1>
<p>An experimental space for building out procedural music generation using vanilla JavaScript</p>
<p>Uses Tone.js to interact with the Web Audio API</p>
<p>Features a plain HTML/CSS front end to interact with the program</p>
<div className="links">
<a target="_blank" rel="noreferrer" href="https://github.com/innocuous-symmetry/procedural-drones-01">GitHub Repo</a>
<a target="_blank" rel="noreferrer" href="https://innocuous-symmetry.github.io/procedural-drones-01/">Deployed version</a>
</div>
</Card>
)
},
{
name: "Reddit, but it's all cats",
languages: ["React", "Redux"],
inProgress: false,
deployed: true,
jsx: (
<Card>
<h1>Reddit, but it's all cats</h1>
<p>A read-only Reddit client -- this site fetches data from Reddit and displays a curated feed.</p>
<p>This was built on Reddit's JSON API, using React/Redux and CSS.</p>
<p>And yes, it's all cats.</p>
<div className="links">
<a target="_blank" rel="noreferrer" href="https://github.com/innocuous-symmetry/cat-reddit">GitHub Repo</a>
<a target="_blank" rel="noreferrer" href="https://reddit-but-all-cats.netlify.app/">Deployed version</a>
</div>
</Card>
)
},
{
name: "Personal Timestamp Generator",
languages: ["Python", "SQLite"],
inProgress: false,
jsx: (
<Card>
<h1>Personal Timestamp Generator</h1>
<p>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.
</p>
<p>Command-line interface built on Python with a SQLite Database.</p>
<a href="https://github.com/innocuous-symmetry/timestamp_project" target="_blank" rel="noreferrer">View the repo here!</a>
</Card>
)
},
{
name: "Musical Counterpoint Bot",
languages: ["HTML/CSS", "JavaScript"],
inProgress: true,
jsx: (
<Card>
<h1>Musical Counterpoint Bot</h1>
<p>A web-based program with functionality to evaluate sample solutions of problems in
species-based counterpoint, as detailed by Johann Fux in <em>Gradus ad Parnassum.</em></p>
<p>This project is intended to be used as a practical application of linked lists and
other compound data structures in JavaScript.</p>
<p>In progress. Using vanilla HTML/CSS/JS.</p>
</Card>
)
},
{
name: "Password Game",
languages: ["React", "MongoDB", "MERN", "React", "REST_API", "Socket.io", "Sass", "MaterialUI"],
inProgress: true,
jsx: (
<Card>
<h1>Password Game</h1>
<p>As part of a mentorship program hosted by Metazu Studio</p>
<p>Implemented using MongoDB, React, and Node/Express, styled with Material UI/SCSS.</p>
<p>In progress, building in collaboration with others at Metazu Studio.</p>
</Card>
)
},
{
name: "Splinter",
languages: ["React", "PERN", "Socket.io"],
inProgress: true,
jsx: (
<Card>
<h1>Splinter</h1>
<p>A clone of a popular card-based resource gathering game</p>
<p>Local multiplayer, with plans to build out online multiplayer and solo vs. CPU</p>
<p>In progress. Using React, Node/Express, and PostgreSQL.</p>
</Card>
)
},
{
name: "Carenest",
languages: ["React"],
inProgress: false,
jsx: (
<Card>
<h1>Carenest</h1>
<p>Designed in collaboration with Faith Magras, Elvis Hernandez, and Daytreon Dean
as a submission for #HACKTN in March 2022.</p>
<p>Produced using React. View the repo <a target="_blank" rel="noreferrer" href="https://github.com/Team-Carenest/carenest">here!</a></p>
</Card>
)
},
{
name: "This Site",
languages: ["React", "Sass", "MaterialUI"],
inProgress: true,
jsx: (
<Card>
<h1>And, last but not least, the site you see here!</h1>
<p>This site is built using React, Material UI, and SCSS, and is hosted with Netlify.</p>
<a target="_blank" rel="noreferrer" href="https://github.com/innocuous-symmetry/about-mikayla">View the site repo here!</a>
</Card>
)
}
]
if (!filter) {
setResults(galleryArray.map(each => each.jsx));
}
if (filter) { if (filter) {
let result = galleryArray; let result = projectsArray;
if (filter.searchTerm) { if (filter.searchTerm) {
let termLower = filter.searchTerm.toLowerCase(); let termLower = filter.searchTerm.toLowerCase();
result = result.filter(obj => obj.name.toLowerCase().includes(termLower)); 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); let adjustedLang = ((filter.language === 'PostgreSQL' || filter.language === "Express") ? "PERN" : filter.language);
result = result.filter(obj => obj.languages.includes(adjustedLang)); 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)); setResults(result.map(each => each.jsx));
} }
@@ -194,11 +55,33 @@ export default function Projects() {
languageFilter.current.value = ''; 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 ( return (
<div className="projects-page" style={htmlTheme}> <div className="projects-page" style={htmlTheme}>
<h1>Here are some sample projects from my portfolio!</h1> <h1>Check out these projects from my portfolio!</h1>
<section className="filter-panel"> <section className={`filter-panel ${panelStyle}`}>
<h2>Filter by:</h2> <h2>Filter by:</h2>
<div className="filter-controls"> <div className="filter-controls">
<input <input
@@ -221,12 +104,18 @@ export default function Projects() {
<option value="SQLite">SQLite</option> <option value="SQLite">SQLite</option>
<option value="TypeScript">TypeScript</option> <option value="TypeScript">TypeScript</option>
</select> </select>
<button onClick={() => setFilter({...filter, inProgress: !filter.inProgress})}>Include in-progress</button> <button onClick={() => setFilter({...filter, inProgress: !filter.inProgress})}>
{filter.inProgress ? "Show" : "Hide"} in-progress
</button>
<button onClick={handleReset}>Reset</button> <button onClick={handleReset}>Reset</button>
</div> </div>
</section> </section>
<div className="project-cards">{results}</div> <Divider orientation="horizontal" sx={dividerStyle} />
<div className="project-cards">
{results}
</div>
</div> </div>
) )
} }

View File

@@ -6,7 +6,8 @@ export const DocumentStyle = {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
alignItems: 'center', alignItems: 'center',
height: '100vh', minHeight: '100vh',
height: '100%',
}, },
linkStyle: { linkStyle: {
color: deepPurple[300], color: deepPurple[300],