Fixed chapter selection on last chapter

This commit is contained in:
2022-05-21 15:55:10 +03:00
parent 9770de6733
commit 448cb46e9e
13 changed files with 184 additions and 37 deletions

View File

@@ -3,14 +3,16 @@ import type { Component } from 'solid-js';
import Controls from './components/Controls';
import Hero from './components/Hero'
import Projects from './components/Projects/Projects'
import ContactForm from './components/ContactForm'
const App: Component = () => {
return (
<>
<div class='App'>
<Controls/>
<Hero/>
<Projects/>
</>
<ContactForm/>
</div>
);
};

View File

@@ -0,0 +1,24 @@
.ContactForm {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
padding: var(--gap-md);
margin-left: var(--gap-xl);
margin-right: var(--gap-xl);
}
.ContactForm > * {
width: 100%;
max-width: 600px;
box-sizing: border-box;
margin-bottom: var(--gap-sm);
}
@media screen and (max-width: 1080px) {
.ContactForm {
margin: 0;
width: 100%;
box-sizing: border-box;
}
}

View File

@@ -0,0 +1,51 @@
import { useI18n } from "@solid-primitives/i18n";
import { createViewportObserver } from '@solid-primitives/intersection-observer';
import { useStore } from '../store/index';
import type { Store } from '../store/index';
import { scrollHereWhenSelected } from "../utlis/scroll";
import styles from './ContactForm.module.css';
export default () => {
const [t] = useI18n();
const [state, setters] = useStore() as Store;
const [observer] = createViewportObserver({threshold: 0.9});
const chapterName = 'mail';
return (
<form
use:observer={(event) => {
if (event.isIntersecting) {
if (!state.scrolling()) {
setters.setVisibleChapter(chapterName);
} else if (state.visibleChapter() === chapterName) {
setters.setScrolling(false)
}
// Сраный костыль
} else if (state.visibleChapter() === chapterName) {
setters.setVisibleChapter('projects');
}
}}
ref={(element) => scrollHereWhenSelected(element, [state, setters], chapterName)}
class={styles.ContactForm}
action="https://send.pageclip.co/ipMETNW8CCV8ka21myU6D22bvnOAV0Ag"
method="post"
>
<input
type="text"
name="name"
placeholder={t('name')}
></input>
<textarea
name="message"
placeholder="Write something.."
></textarea>
<input
type="submit"
value="Submit"
></input>
</form>
)
}

View File

@@ -57,7 +57,6 @@
transition: width .6s, height .6s, transform .6s;
width: 0;
height: 0;
transform: translate(-50%, 50%);
}
.selected {

View File

@@ -9,31 +9,31 @@ import gridIcon from '../assets/icons/grid.svg'
import mailIcon from '../assets/icons/mail.svg'
export default () => {
const [store, {setVisibleChapter}] = useStore() as Store;
const [state, {setVisibleChapter, setScrolling}] = useStore() as Store;
const [selected, setSelected] = createSignal('home');
const [blobby, setBlobby] = createSignal(['home']);
const chapters = [
{ name: 'home', icon: homeIcon },
{ name: 'projects', icon: gridIcon },
{ name: 'whatever', icon: mailIcon },
{ name: 'mail', icon: mailIcon },
]
const selectChapter = (chapterName: string) => {
if (chapterName !== selected()) {
setSelected(chapterName)
setVisibleChapter(chapterName)
setBlobby(b => [chapterName, ...b])
setSelected(chapterName);
setVisibleChapter(chapterName);
setBlobby(b => [chapterName, ...b]);
setTimeout(() => {
setBlobby(b => [chapterName])
}, 500)
setBlobby(b => [chapterName]);
}, 500);
}
}
createEffect((prev) => {
if (prev !== store.visibleChapter()) {
selectChapter(store.visibleChapter());
if (prev !== state.visibleChapter()) {
selectChapter(state.visibleChapter());
}
return store.visibleChapter();
return state.visibleChapter();
});
return (
@@ -54,6 +54,7 @@ export default () => {
<For each={chapters}>{(chapter) =>
<div
onClick={() => {
setScrolling(true);
selectChapter(chapter.name)
}}
class={styles.control}

View File

@@ -1,4 +1,5 @@
.Hero {
position: relative;
height: 100vh;
display: flex;
flex-direction: column;
@@ -23,6 +24,19 @@
word-break: break-word;
}
.blur {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(50px);
opacity: 1;
transition: opacity 2.5s;
transition-delay: .5s;
}
@keyframes gradient {
0% {
background-position: 0% 50%;

View File

@@ -9,17 +9,22 @@ import styles from './Hero.module.css';
export default () => {
const [t] = useI18n();
const [observer] = createViewportObserver({threshold: 0.9});
const [store, { setVisibleChapter }] = useStore() as Store;
const [observer] = createViewportObserver({threshold: 0.8});
const [state, setters] = useStore() as Store;
const chapterName = 'home'
return (
<header
use:observer={(event) => {
if (event.isIntersecting) {
setVisibleChapter('home');
}}
if (!state.scrolling()) {
setters.setVisibleChapter(chapterName);
} else if (state.visibleChapter() === chapterName) {
setters.setScrolling(false)
}
ref={(element) => scrollHereWhenSelected(element, store, 'home')}
}
}}
ref={(element) => scrollHereWhenSelected(element, [state, setters], chapterName)}
class={styles.Hero}
>
<h1 class={styles.gradientText}>
@@ -30,6 +35,13 @@ export default () => {
</div>
<Links />
<div
class={styles.blur}
ref={(element) => {
setTimeout(() => element.style.opacity = '0')
}}
/>
</header>
)
};

View File

@@ -1,10 +1,19 @@
.Projects {
padding: var(--gap-md);
display: flex;
justify-content: center;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: var(--gap-lg);
margin-left: 130px;
margin-right: 130px;
margin-left: var(--gap-xl);
margin-right: var(--gap-xl);
}
@media screen and (max-width: 1080px) {
.Projects {
margin: 0;
width: 100%;
box-sizing: border-box;
flex-direction: column;
}
}

View File

@@ -10,17 +10,23 @@ import Project from './Project';
import type { Project as ProjectType } from './projectList';
export default () => {
const [store, { setVisibleChapter }] = useStore() as Store;
const [observer] = createViewportObserver({threshold: 0.5});
const [state, setters] = useStore() as Store;
const [observer] = createViewportObserver({threshold: 0.1});
const chapterName = 'projects'
return (
<div
use:observer={(event) => {
if (event.isIntersecting) {
setVisibleChapter('projects');
}}
console.log(chapterName);
if (!state.scrolling()) {
setters.setVisibleChapter(chapterName);
} else if (state.visibleChapter() === chapterName) {
setters.setScrolling(false)
}
ref={(element) => scrollHereWhenSelected(element, store, 'projects')}
}
}}
ref={(element) => scrollHereWhenSelected(element, [state, setters], chapterName)}
class={styles.Projects}
>
<For each={projects}>{(project: ProjectType) =>

View File

@@ -9,6 +9,7 @@
--gap-sm: 18px;
--gap-md: 36px;
--gap-lg: 72px;
--gap-xl: 144px;
--radius-md: 12px;
@@ -19,6 +20,10 @@
--font-md: normal normal 400 18px var(--ff-default);
}
.App {
padding-bottom: var(--gap-xl);
}
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -41,3 +46,12 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
input, textarea {
background: var(--clr-bg-secondary);
border: none;
padding: var(--gap-sm);
border-radius: var(--radius-md);
display: inline-block;
color: var(--clr-text);
}

View File

@@ -7,5 +7,6 @@
"warframe_desc": "A service that monitors prices of items on warframe.market and calculates profitable gaps between them.",
"worktime_desc": "A PWA that I use daily to track my time spent working. Full offline support.",
"studybuddy_desc": "A PWA for splitting into groups or taking topics for an assignment.",
"vkmute_desc": "A Browser extension that allows you to mute people in group chats on VK.com."
"vkmute_desc": "A Browser extension that allows you to mute people in group chats on VK.com.",
"name": "Your name"
}

View File

@@ -2,20 +2,30 @@ import { createSignal, createContext, useContext } from "solid-js";
import type { Accessor, Setter } from 'solid-js';
export type Store = [
{ visibleChapter: Accessor<string> },
{ setVisibleChapter: Setter<string> }
{
visibleChapter: Accessor<string>,
scrolling: Accessor<boolean>,
},
{
setVisibleChapter: Setter<string>,
setScrolling: Setter<boolean>,
}
]
const StoreContext = createContext<Store>();
export function StoreProvider(props: any) {
const [visibleChapter, setVisibleChapter] = createSignal('home');
const [scrolling, setScrolling] = createSignal(false);
const store: Store = [
{
visibleChapter
visibleChapter,
scrolling,
},
{
setVisibleChapter
setVisibleChapter,
setScrolling
}
];

View File

@@ -1,10 +1,14 @@
import { createEffect } from "solid-js";
export const scrollHereWhenSelected = (element: HTMLElement, store, chapter) => {
import type { Store } from '../store/index';
export const scrollHereWhenSelected = (element: HTMLElement, store: Store, chapter: string) => {
const [state, setters] = store;
return createEffect((prev) => {
if (prev !== store.visibleChapter() && store.visibleChapter() === chapter) {
element.scrollIntoView({behavior: "smooth"})
if (prev !== state.visibleChapter() && state.visibleChapter() === chapter && state.scrolling()) {
element.scrollIntoView({behavior: "smooth"});
setters.setScrolling(true);
}
return store.visibleChapter();
return state.visibleChapter();
});
}