diff --git a/components/event-filter/EventFilter.jsx b/components/event-filter/EventFilter.jsx new file mode 100644 index 00000000..b6c8576a --- /dev/null +++ b/components/event-filter/EventFilter.jsx @@ -0,0 +1,23 @@ +import React from 'react'; + +const EventFilter = ({ selectedType, setSelectedType, eventTypes }) => { + const handleChange = (e) => { + setSelectedType(e.target.value); + }; + + return ( + <select + className="events-list__select" + value={selectedType} + onChange={handleChange} + > + {eventTypes.map((type) => ( + <option key={type.value} value={type.value}> + {type.label} + </option> + ))} + </select> + ); +}; + +export default EventFilter; \ No newline at end of file diff --git a/components/event-filter/event-filter.scss b/components/event-filter/event-filter.scss new file mode 100644 index 00000000..f285c02a --- /dev/null +++ b/components/event-filter/event-filter.scss @@ -0,0 +1,38 @@ +.events-list__controls { + display: flex; + justify-content: space-between; + align-items: center; + gap: spacing(2); +} + +.events-list__select { + appearance: none; + -webkit-appearance: none; + background: rgba(255, 255, 255, 0.4); + padding: 12px 10px; + margin-top: 8px; + border-radius: 100px; + border: none; + + color: $white; + text-align: center; + @extend %subtitle-1; + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + background: $white; + color: $purple; + transform: translateY(-1px); + } + + &:focus { + outline: none; + box-shadow: 0 0 0 2px $purple; + } + + option { + background: $purple; + color: $white; + } +} \ No newline at end of file diff --git a/components/event-filter/eventTypes.js b/components/event-filter/eventTypes.js new file mode 100644 index 00000000..bae3ede3 --- /dev/null +++ b/components/event-filter/eventTypes.js @@ -0,0 +1,14 @@ +import literals from '../../content/commons.json'; + +const eventTypes = [ + { value: 'all', label: 'All Events' }, + { value: 'conference', label: literals['event-type:conference'] }, + { value: 'podcast', label: literals['event-type:podcast'] }, + { value: 'stream', label: literals['event-type:stream'] }, + { value: 'talk', label: literals['event-type:talk'] }, + { value: 'meetup', label: literals['event-type:meetup'] }, + { value: 'fundraising', label: literals['event-type:fundraising'] }, + { value: 'misc', label: literals['event-type:misc'] }, +]; + +export default eventTypes; \ No newline at end of file diff --git a/components/events-list/EventsList.jsx b/components/events-list/EventsList.jsx index d62846c7..a53eb4a6 100644 --- a/components/events-list/EventsList.jsx +++ b/components/events-list/EventsList.jsx @@ -1,41 +1,47 @@ -import md from 'markdown-it' -import clsx from 'clsx' +import React, { useState } from 'react'; +import md from 'markdown-it'; +import clsx from 'clsx'; +import Link from 'next/link'; -import Link from 'next/link' +import ButtonLink from '../button-link/ButtonLink'; +import EventFilter from '../event-filter/EventFilter'; +import eventTypes from '../event-filter/eventTypes'; +import { getLiteral } from '../../common/i18n'; +import DateTimeChip from '../date-time-chip/DateTimeChip'; +import EventTypeChip from '../event-type-chip/EventTypeChip'; +import Chip from '../chip/Chip'; -import ButtonLink from '../button-link/ButtonLink' - -import { getLiteral } from '../../common/i18n' -import * as ROUTES from '../../common/routes' - -import DateTimeChip from '../date-time-chip/DateTimeChip' -import EventTypeChip from '../event-type-chip/EventTypeChip' -import PlayLink from '../play-link/PlayLink' -import Chip from '../chip/Chip' const EventsList = ({ events }) => { - const dateLabel = (event) => - `${event.formattedDate.date} to ${event.formattedDate.endDate}` + const [selectedType, setSelectedType] = useState('all'); + const filteredEvents = selectedType === 'all' + ? events + : events.filter((event) => event.type === selectedType); return ( <section className="events-list"> <div className="events-list__header"> <div className="events-list__header-content"> <h1 className="events-list__title">{getLiteral('schedule:title')}</h1> - <p className="events-list__subtitle"> - {getLiteral('schedule:description')} - </p> - <ButtonLink - href="https://github.com/github/maintainermonth/issues/new?template=add-to-calendar.yml" - isExternal={true} - className="events-list__add-button" - > - {getLiteral('schedule:add-event')} - </ButtonLink> + <p className="events-list__subtitle">{getLiteral('schedule:description')}</p> + <div className="events-list__controls"> + <ButtonLink + href="https://github.com/github/maintainermonth/issues/new?template=add-to-calendar.yml" + isExternal={true} + className="events-list__add-button" + > + {getLiteral('schedule:add-event')} + </ButtonLink> + <EventFilter + selectedType={selectedType} + setSelectedType={setSelectedType} + eventTypes={eventTypes} + /> + </div> </div> </div> <div className="events-list__grid"> - {events.map((event, index) => ( + {filteredEvents.map((event, index) => ( <div key={event.slug} className={clsx('events-list__card', { diff --git a/components/events-list/events-list.scss b/components/events-list/events-list.scss index ba6a7d9c..d7284bb1 100644 --- a/components/events-list/events-list.scss +++ b/components/events-list/events-list.scss @@ -9,7 +9,7 @@ } &__header { - display: flex; + // display: flex; align-items: center; justify-content: space-between; margin-bottom: spacing(6); diff --git a/content/events/2025-05-30-effection.md b/content/events/2025-05-30-effection.md index 3cea48b2..3942d47e 100644 --- a/content/events/2025-05-30-effection.md +++ b/content/events/2025-05-30-effection.md @@ -1,20 +1,18 @@ --- title: 'Open Source Friday: Effection' -metaTitle: 'Open Source Friday: Effection' -metaDesc: 'Join Charles Lowell to discuss Effection - Structured Concurrency and Effects for JavaScript.' -date: '05/30' +metaTitle: 'Open Source Friday: Nuxt and AI' +metaDesc: 'Join Daniel Roe to discuss Nuxt, AI, and improving developer experiences with type inference.' +date: '05/23' UTCStartTime: '6:00' UTCEndTime: '7:00' type: 'stream' -language: 'English' location: 'Virtual' +language: 'English' userName: 'GitHub' userLink: 'https://www.twitch.tv/github/schedule' linkUrl: 'https://www.twitch.tv/github/schedule' --- -Join [Charles Lowell](https://github.com/cowboyd) to discuss [Effection](https://github.com/thefrontside/effection) - Structured Concurrency and Effects for JavaScript. - -Effection provides guardrails for managing complex asynchronous operations, helping developers write clean and crisp code. +Join Charles Lowell [@cowboyd](https://github.com/cowboyd) to learn more about [Effection](https://github.com/thefrontside/effection), structured concurrency and effects for JavaScript. [Open Source Fridays](https://www.youtube.com/playlist?list=PL0lo9MOBetEFmtstItnKlhJJVmMghxc0P) stream weekly on GitHub's [Twitch](https://www.twitch.tv/github), [YouTube](https://github.com/youtube), and [LinkedIn](https://www.linkedin.com/company/github). diff --git a/styles/styles.scss b/styles/styles.scss index e1e165d6..23f1a5f7 100644 --- a/styles/styles.scss +++ b/styles/styles.scss @@ -13,6 +13,7 @@ @import '../components/event-detail/event-detail'; @import '../components/event-detail/event-detail-wrapper'; @import '../components/events-list/events-list'; +@import '../components/event-filter/event-filter'; @import '../components/footer/footer'; @import '../components/header/header';