Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speakers section fixes #401

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c46dae4
increased spacing after last speaker
lovretomic Aug 25, 2024
b173452
Merge branch 'main' into lovretomic/speakers-section-fix
lovretomic Sep 23, 2024
7391715
Merge branch 'main' into lovretomic/speakers-section-fix
lovretomic Sep 28, 2024
a7cda9c
removed speakers grid
lovretomic Sep 28, 2024
17dd1da
removed everything else
lovretomic Sep 28, 2024
a39f882
added base content
lovretomic Sep 28, 2024
21ac8c1
added base styles
lovretomic Sep 28, 2024
448d23f
added title wrapper base responsivity
lovretomic Sep 28, 2024
087aa2a
added fetching speakers data
lovretomic Sep 28, 2024
12b016a
added new speaker card component
lovretomic Sep 28, 2024
f2413f2
added grid
lovretomic Sep 28, 2024
e2208d5
improved grid layout
lovretomic Sep 28, 2024
72911ec
update layout
lovretomic Nov 6, 2024
847777b
fixed classes collision
lovretomic Nov 11, 2024
ac6ad14
improved desktop grid
lovretomic Nov 11, 2024
9a6ef31
improved grid
lovretomic Nov 11, 2024
3f2686e
improved responsivity
lovretomic Nov 11, 2024
e0cb297
Merge branch 'main' into lovretomic/speakers-section-fix
lovretomic Nov 12, 2024
dfdb0e4
fixed responsive grid styles
lovretomic Nov 12, 2024
f3c6026
improved passing styles from outside
lovretomic Nov 12, 2024
c3ea79a
added text styles
lovretomic Nov 12, 2024
65049a6
fixed margins and paddings
lovretomic Nov 12, 2024
cbcabf7
added motion animations
lovretomic Nov 12, 2024
6f7064e
added new speaker modal component
lovretomic Nov 12, 2024
db55ffd
modal changes
lovretomic Nov 14, 2024
f44bdd8
Merge branch 'main' into lovretomic/speakers-section-fix
lovretomic Nov 17, 2024
caed94f
enabled modal closing
lovretomic Nov 17, 2024
abc423d
disable scroll
lovretomic Nov 17, 2024
e2608fd
imprtoved modal backdrop styles
lovretomic Nov 17, 2024
68af634
improved layout
lovretomic Nov 17, 2024
87bd0f1
added social media buttons conditionals
lovretomic Nov 18, 2024
9516d90
added description styles
lovretomic Nov 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/web/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ body {
src: url('./assets/fonts/PPNeueMontrealMono-Medium.woff2') format('woff2');
font-display: fallback;
}

body:has(dialog[open]) {
overflow: hidden;
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
z-index: 0;
transition: 300ms;
}

&:hover {
overflow: hidden;

Expand Down Expand Up @@ -288,7 +288,7 @@
}

.dottedRuler {
@include mixins.dottedBreak(rgba(255, 255, 255, 0.20));
@include mixins.dottedBreak(rgba(255, 255, 255, 0.2));
margin-top: 10px;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SpeakerWithCompanyDto } from '@ddays-app/types';
import { motion } from 'framer-motion';
import { useState } from 'react';

import SpeakerModal from './SpeakerModal';
import SpeakerModal from '../SpeakerModal';
import c from './SpeakersSection.module.scss';

type SpeakerCardProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.speakerCard {
display: flex;
align-items: flex-start;
flex-direction: column;
color: white;
text-align: center;
font-family: 'Times New Roman', Times, serif;
text-transform: uppercase;

.image {
aspect-ratio: 320/400;
}

.fullName {
color: #fff;
font-family: 'PP Neue Machina';
font-size: 24px;
font-style: normal;
font-weight: 500;
line-height: 32px;
letter-spacing: -0.5px;

margin-top: 24px;
}

.position {
color: #fff;
font-family: 'PP Neue Montreal Mono';
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 16px;
letter-spacing: 1px;
}
}

@media screen and (max-width: 768px) {
.speakerCard {
.fullName {
font-size: 18px;
line-height: 22px;
margin-top: 8px;
}

.position {
font-size: 14px;
line-height: 16px;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { SpeakerWithCompanyDto } from '@ddays-app/types';
import clsx from 'clsx';
import { motion } from 'framer-motion';
import { useState } from 'react';

import SpeakerModal from '../SpeakerModal';
import c from './SpeakerCard.module.scss';

type SpeakerCardProps = {
speaker: SpeakerWithCompanyDto;
} & React.HTMLAttributes<HTMLDivElement>;

const SpeakerCard = ({
speaker,
className /*, ...handlers*/,
}: SpeakerCardProps) => {
const classes = clsx(c.speakerCard, className);

const [isModalOpen, setIsModalOpen] = useState(false);

const openModal = () => {
setIsModalOpen(true);
};

const closeModal = () => {
setIsModalOpen(false);
};

return (
<>
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
transition={{ ease: 'easeIn', duration: 1 }}
className={classes}
onClick={() => openModal()}
//{...handlers} <-- Zbog ovoga ne radi modion.div
>
<img className={c.image} src={speaker.photo} alt='' />
<p className={c.fullName}>
{speaker.firstName} {speaker.lastName}
</p>
{speaker.title && speaker.company?.name && (
<p className={c.position}>
{speaker.title} @ {speaker.company?.name}
</p>
)}
<SpeakerModal
speaker={speaker}
isOpen={isModalOpen}
close={() => closeModal()}
/>
</motion.div>
</>
);
};

export default SpeakerCard;
3 changes: 3 additions & 0 deletions apps/web/src/components/SpeakersSection/SpeakerCard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import SpeakerCard from './SpeakerCard';

export default SpeakerCard;
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
.backdrop {
position: fixed;
top: 0;
left: 0;

height: 100vh;
width: 100%;

background: rgba(23, 22, 21, 0.8);

display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 32px;

.speakerModal {
background: #181716;
display: flex;
flex-direction: row;
position: relative;
//width: 100%;
box-sizing: border-box;
padding: 64px 56px;

.image {
max-height: 500px;
max-width: 400px;

height: auto;
object-fit: cover;
flex-shrink: 0;
flex-grow: 0;
}

.contentWrapper {
width: 536px;
display: flex;
flex-direction: column;
align-items: flex-start;
text-align: start;
box-sizing: border-box;
padding-left: 80px;

.fullName {
color: #eaeaea;
font-family: 'PP Neue Machina';
font-size: 48px;
line-height: 48px;
letter-spacing: -2px;
margin-bottom: 16px;
width: 100%;
}

.titleAndCompany {
width: 100%;
color: #ff482f;
font-family: 'PP Neue Machina';
font-size: 24px;
line-height: 32px;
letter-spacing: -1px;
text-transform: uppercase;
}

.socialMediaButtons {
display: flex;
gap: 24px;
margin: 32px 0;
}

.description {
color: #fff;
font-family: 'PP Neue Machina';
font-size: 18px;
line-height: 26px;
text-transform: none;
width: 100%;
}

.button {
width: fit-content;
color: #fff;

font-feature-settings:
'ss06' on,
'ss01' on;
font-family: 'PP Neue Montreal Mono', sans-serif;
font-size: 14px;
line-height: 16px;
letter-spacing: 1px;
text-transform: uppercase;
background-color: transparent;
border: none;
cursor: pointer;
text-decoration: none;
position: relative;
transition: 300ms;
padding: 14px 16px;
}

.grainyButton {
&:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 600'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.4' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)'/%3E%3C/svg%3E");
background-size: cover;
opacity: 0;
z-index: 0;
transition: 300ms;
}

&:hover {
overflow: hidden;

.text {
color: white;
z-index: 5;
}

&:before {
opacity: 0.2;
}
}

&:active {
&::before {
opacity: 0.85;
}
}
}
}

.closeButton {
position: absolute;
top: 0;
right: 0;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { SpeakerWithCompanyDto } from '@ddays-app/types';
import { useEffect } from 'react';
import clsx from 'clsx';

import c from './SpeakerModal.module.scss';

type SpeakerModalProps = {
close: () => void;
isOpen: boolean;
speaker: SpeakerWithCompanyDto;
};

const SpeakerModal = ({ close, isOpen, speaker }: SpeakerModalProps) => {
const stopPropagation = (event: React.MouseEvent) => {
event.stopPropagation(); // Prevent clicks inside the modal from bubbling to the parent
};

useEffect(() => {
const disableScroll = (e: Event) => {
e.preventDefault();
e.stopPropagation();
};

const disableKeyboardScroll = (e: KeyboardEvent) => {
if (
['ArrowUp', 'ArrowDown', 'Space', 'PageUp', 'PageDown'].includes(e.code)
) {
e.preventDefault();
}
};

if (isOpen) {
document.addEventListener('wheel', disableScroll, { passive: false });
document.addEventListener('touchmove', disableScroll, { passive: false });
document.addEventListener('keydown', disableKeyboardScroll);
} else {
document.removeEventListener('wheel', disableScroll);
document.removeEventListener('touchmove', disableScroll);
document.removeEventListener('keydown', disableKeyboardScroll);
}

return () => {
document.removeEventListener('wheel', disableScroll);
document.removeEventListener('touchmove', disableScroll);
document.removeEventListener('keydown', disableKeyboardScroll);
};
}, [isOpen]);

if (!isOpen) return null;

const openLink = (href: string | undefined) => {
if (!href) return;
window.open(href, '_blank');
};

return (
<div className={c.backdrop}>
<div className={c.speakerModal} onClick={stopPropagation}>
<img className={c.image} src={speaker.photo} alt='' />
<div className={c.contentWrapper}>
<h2 className={c.fullName}>
{speaker.firstName} {speaker.lastName}
</h2>
<h3 className={c.titleAndCompany}>
{speaker.title} {speaker.title && speaker.company?.name && '@'}{' '}
{speaker.company?.name}
</h3>
<div className={c.socialMediaButtons}>
{speaker.linkedin && (
<button
className={clsx(c.button, c.grainyButton)}
onClick={() => openLink(speaker.linkedin)}>
{`[ `}
LinkedIn
{` ]`}
</button>
)}
{speaker.instagram && (
<button
className={clsx(c.button, c.grainyButton)}
onClick={() => openLink(speaker.instagram)}>
{`[ `}
Instagram
{` ]`}
</button>
)}
</div>
<p className={c.description}>{speaker.description}</p>
</div>
<button className={c.closeButton} onClick={() => close()}>
Zatvori
</button>
</div>
</div>
);
};

export default SpeakerModal;
3 changes: 3 additions & 0 deletions apps/web/src/components/SpeakersSection/SpeakerModal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import SpeakerModal from './SpeakerModal';

export default SpeakerModal;
Loading
Loading