Add mobile styles to the event card (#190)

closes #160
closes #154

https://csclub.uwaterloo.ca/~a3thakra/csc/adi-mobile-events-card/

Reviewed-on: www/www-new#190
Co-authored-by: Aditya Thakral <a3thakra@csclub.uwaterloo.ca>
Co-committed-by: Aditya Thakral <a3thakra@csclub.uwaterloo.ca>
fix-md-font
Aditya Thakral 1 year ago
parent c31571f745
commit 6b88cf308b
  1. 2
      components/Code.module.css
  2. 78
      components/EventCard.module.css
  3. 52
      components/EventCard.tsx
  4. 2
      components/EventSetting.module.css
  5. 4
      components/Image.module.css
  6. 10
      components/Image.tsx
  7. 1
      components/Link.module.css
  8. 24
      components/playground.tsx
  9. 10
      lib/events.ts
  10. 2
      pages/_app.tsx
  11. 1
      pages/events/[year]/[term]/[event].tsx
  12. 10
      pages/events/[year]/[term]/index.module.css
  13. 1
      pages/events/[year]/[term]/index.tsx

@ -2,5 +2,5 @@
padding: 0 calc(4rem / 16);
background: var(--code-background);
border-radius: calc(5rem / 16);
word-wrap: break-word;
overflow-wrap: break-word;
}

@ -2,7 +2,7 @@
display: flex;
flex-direction: row;
box-sizing: border-box;
padding: calc(24rem / 16);
padding: calc(20rem / 16) 0;
}
.card aside {
@ -12,16 +12,15 @@
.card aside img {
width: 100%;
margin-bottom: 1rem;
}
.spacer {
margin-top: calc(76rem / 16);
.registerButton {
margin-top: 1rem;
font-weight: bold;
}
.registerButton {
.registerButtonWithPoster {
display: block;
font-weight: bold;
}
.content > h1 {
@ -45,3 +44,70 @@
font-size: 1rem;
margin-bottom: calc(14rem / 16);
}
.mobileLearnMore {
display: none;
}
@media only screen and (max-width: calc(768rem / 16)) {
.card {
flex-direction: column;
}
.card aside {
margin: 0 auto;
max-width: calc(300rem / 16);
}
.card aside img {
box-sizing: border-box;
border: calc(1rem / 16) solid var(--text);
}
.content {
margin-top: 1rem;
}
.content {
text-align: center;
}
.content > h1,
.content > h2 {
font-size: 1rem;
line-height: calc(30 / 16);
}
.content > h2 {
margin-bottom: 0;
}
.mobileShowDescriptionContent {
text-align: unset;
}
.mobileShowDescriptionContent > h1 {
font-size: calc(24rem / 16);
margin-bottom: calc(8rem / 16);
}
.registerButton {
display: block;
}
.mobileLearnMore {
display: unset;
}
.mobileShowDescriptionContent .mobileLearnMore {
display: none;
}
.children {
display: none;
}
.mobileShowDescriptionContent .children {
display: unset;
}
}

@ -3,10 +3,11 @@ import React, { ReactNode } from "react";
import { Button } from "./Button";
import { EventSetting } from "./EventSetting";
import { Image } from "./Image";
import { Link } from "./Link";
import styles from "./EventCard.module.css";
interface EventCardProps {
interface BaseProps {
name: string;
short: string;
date: Date;
@ -17,7 +18,12 @@ interface EventCardProps {
children: ReactNode;
}
type EventCardProps =
| (BaseProps & { showDescription?: false; link: string })
| (BaseProps & { showDescription: true; link?: string });
export function EventCard({
link,
name,
date,
online,
@ -25,13 +31,42 @@ export function EventCard({
poster,
registerLink,
children,
showDescription = false,
}: EventCardProps) {
return (
<article className={styles.card}>
<aside>
{poster && <Image alt={name} src={poster} />}
{!poster && <div className={styles.spacer}></div>}
{registerLink && (
{poster && (
<aside>
<Image alt={name} src={poster} />
{registerLink && (
<Button
isLink={true}
href={registerLink}
size="small"
className={`${styles.registerButton} ${styles.registerButtonWithPoster}`}
>
Register
</Button>
)}
</aside>
)}
<section
className={[
styles.content,
showDescription ? styles.mobileShowDescriptionContent : "",
].join(" ")}
>
<h1>{name}</h1>
<h2>
<EventSetting date={date} online={online} location={location} />
</h2>
{!showDescription && link && (
<Link href={link}>
<span className={styles.mobileLearnMore}>Learn more</span>
</Link>
)}
<div className={styles.children}>{children}</div>
{!poster && registerLink && (
<Button
isLink={true}
href={registerLink}
@ -41,13 +76,6 @@ export function EventCard({
Register
</Button>
)}
</aside>
<section className={styles.content}>
<h1>{name}</h1>
<h2>
<EventSetting date={date} online={online} location={location} />
</h2>
<div>{children}</div>
</section>
</article>
);

@ -2,7 +2,7 @@
.separator {
display: none;
}
.setting {
display: block;
}

@ -0,0 +1,4 @@
.image {
/* So that image doesn't overflow on mobile screens */
max-width: 100%;
}

@ -1,8 +1,14 @@
import React, { ImgHTMLAttributes } from "react";
import styles from "./Image.module.css";
export function Image(props: ImgHTMLAttributes<HTMLImageElement>) {
const classes = props.className
? [props.className, styles.image]
: [styles.image];
if (props.src?.startsWith("http://") || props.src?.startsWith("https://")) {
return <img {...props} />;
return <img {...props} className={classes.join(" ")} />;
}
const { src: relativeSrc = "" } = props;
@ -16,5 +22,5 @@ export function Image(props: ImgHTMLAttributes<HTMLImageElement>) {
absoluteSrc += "/" + relativeSrc;
}
return <img {...props} src={absoluteSrc} />;
return <img {...props} src={absoluteSrc} className={classes.join(" ")} />;
}

@ -3,6 +3,7 @@
transition-duration: 0.3s;
text-decoration: none;
white-space: normal;
overflow-wrap: anywhere;
}
.link:hover {

@ -146,13 +146,23 @@ export function EventDescriptionCardDemo() {
export function EventCardDemo() {
return (
<>
{events.map(({ Content, metadata }) => (
<EventCard
{...metadata}
key={metadata.name + metadata.date.toDateString()}
>
<Content />
</EventCard>
{events.map(({ Content, metadata }, idx) => (
<>
<EventCard
{...metadata}
key={metadata.name + metadata.date.toDateString() + "1"}
showDescription
>
<Content />
</EventCard>
<EventCard
{...metadata}
key={metadata.name + metadata.date.toDateString() + "2"}
link="#"
>
<Content />
</EventCard>
</>
))}
</>
);

@ -27,7 +27,9 @@ export async function getEventTermsByYear(year: string): Promise<string[]> {
}
interface Metadata {
slug: string;
name: string;
poster?: string;
short: string;
date: string;
online: boolean;
@ -52,7 +54,7 @@ export async function getEventBySlug(
return {
content: await serialize(content),
metadata: metadata as Metadata,
metadata: { ...metadata, slug } as Metadata,
};
}
@ -122,12 +124,14 @@ export async function getEventsPageProps({
new Date(a.metadata.date).getTime() - new Date(b.metadata.date).getTime()
);
const currentDate = Date.now();
const pastEvents = events
.filter((event) => new Date(event.metadata.date).getTime() < Date.now())
.filter((event) => new Date(event.metadata.date).getTime() < currentDate)
.reverse();
const futureEvents = events.filter(
(event) => new Date(event.metadata.date).getTime() >= Date.now()
(event) => new Date(event.metadata.date).getTime() >= currentDate
);
const current = getCurrentTerm();

@ -8,6 +8,7 @@ import { Code } from "@/components/Code";
import { DefaultLayout } from "@/components/DefaultLayout";
import { Footer } from "@/components/Footer";
import { HorizontalLine } from "@/components/HorizontalLine";
import { Image } from "@/components/Image";
import { Link } from "@/components/Link";
import { Navbar } from "@/components/Navbar";
import { Pre } from "@/components/Pre";
@ -35,6 +36,7 @@ export default function App({ Component, pageProps }: AppProps): JSX.Element {
button: Button,
pre: Pre,
inlineCode: Code,
img: Image,
}}
>
<div className={styles.appContainer}>

@ -18,6 +18,7 @@ export default function EventInfoPage(props: Props) {
<EventCard
{...props.event.metadata}
date={new Date(props.event.metadata.date)}
showDescription
>
<MDXRemote {...props.event.content} />
</EventCard>

@ -8,12 +8,6 @@
border-bottom: 1px solid var(--primary-heading);
}
@media only screen and (max-width: calc(768rem / 16)) {
.main {
margin-top: calc(60rem / 16);
}
}
.header a {
color: var(--text);
font-size: calc(18rem / 16);
@ -31,3 +25,7 @@
.miniEventCards {
margin-top: calc(30rem / 16);
}
.main > .miniEventCards {
margin-top: 0;
}

@ -73,6 +73,7 @@ export default function Term(props: Props) {
{...metadata}
date={new Date(metadata.date)}
key={metadata.name + metadata.date.toString()}
link={`/events/${props.year}/${props.term}/${metadata.slug}`}
>
<MDXRemote {...content} />
</EventCard>

Loading…
Cancel
Save