From 1887cb45c981fb56df0ed9484f1ced7b3a5e7abd Mon Sep 17 00:00:00 2001 From: mertbagt Date: Sun, 5 Apr 2026 15:17:04 -0400 Subject: [PATCH 01/55] hearing held checks --- components/bill/Status.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/components/bill/Status.tsx b/components/bill/Status.tsx index b672769fd..534f14be5 100644 --- a/components/bill/Status.tsx +++ b/components/bill/Status.tsx @@ -24,6 +24,23 @@ export const Status = ({ bill }: BillProps) => { const handleShowBillHistory = () => setShowBillHistory(true) const handleCloseBillHistory = () => setShowBillHistory(false) const history = last(bill.history) + const today = new Date().toISOString() + const target = "Hearing scheduled for " + + let hearingDateString = "" + if (history?.Date) { + hearingDateString = history.Date + } + + let hearingCheck = false + if (history?.Action.startsWith(target)) { + hearingCheck = true + } + + let dateCheck = false + if (hearingDateString < today) { + dateCheck = true + } if (!history) return null return ( @@ -34,7 +51,7 @@ export const Status = ({ bill }: BillProps) => { className="text-truncate ps-4" onClick={handleShowBillHistory} > - {history.Action} + {hearingCheck && dateCheck ? "Hearing Held" : history.Action} From c7aaa3c12c64c83679a5c835f884ccb62cbc7023 Mon Sep 17 00:00:00 2001 From: mertbagt Date: Sun, 5 Apr 2026 15:19:19 -0400 Subject: [PATCH 02/55] string rename --- components/bill/Status.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/bill/Status.tsx b/components/bill/Status.tsx index 534f14be5..1ccb01bcd 100644 --- a/components/bill/Status.tsx +++ b/components/bill/Status.tsx @@ -27,9 +27,9 @@ export const Status = ({ bill }: BillProps) => { const today = new Date().toISOString() const target = "Hearing scheduled for " - let hearingDateString = "" + let hearingDate = "" if (history?.Date) { - hearingDateString = history.Date + hearingDate = history.Date } let hearingCheck = false @@ -38,7 +38,7 @@ export const Status = ({ bill }: BillProps) => { } let dateCheck = false - if (hearingDateString < today) { + if (hearingDate < today) { dateCheck = true } From 3b62a934d0aab3b046646863ab6a8532f910324a Mon Sep 17 00:00:00 2001 From: mertbagt Date: Wed, 8 Apr 2026 14:45:12 -0400 Subject: [PATCH 03/55] translation added --- components/bill/Status.tsx | 2 +- public/locales/en/common.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/bill/Status.tsx b/components/bill/Status.tsx index 1ccb01bcd..94b8fa0e1 100644 --- a/components/bill/Status.tsx +++ b/components/bill/Status.tsx @@ -51,7 +51,7 @@ export const Status = ({ bill }: BillProps) => { className="text-truncate ps-4" onClick={handleShowBillHistory} > - {hearingCheck && dateCheck ? "Hearing Held" : history.Action} + {hearingCheck && dateCheck ? t("bill.hearing_held") : history.Action} diff --git a/public/locales/en/common.json b/public/locales/en/common.json index a0a3d5fe2..8ad0918c4 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -23,8 +23,9 @@ "disclosure_date": "Disclosure Date", "download_pdf": "Download PDF", "example_name": "Example Name", + "hearing_held": "Hearing Held", "hearing_scheduled_for": "Hearing Scheduled for {{date, datetime(year: 'numeric'; month: 'long'; day: 'numeric'; hour: 'numeric'; minute: 'numeric')}}", - "hearing_video_and_transcript" : "Hearing Video + Transcript", + "hearing_video_and_transcript" : "Hearing Video + Transcript", "history": "History", "icon": { "commerce": "Commerce", From fae4baa57cc2330f85b4c602fffdcf3f00ccfcf3 Mon Sep 17 00:00:00 2001 From: mertbagt Date: Wed, 8 Apr 2026 14:49:58 -0400 Subject: [PATCH 04/55] handle - hearing rescheduled --- components/bill/Status.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/components/bill/Status.tsx b/components/bill/Status.tsx index 94b8fa0e1..89a92ce16 100644 --- a/components/bill/Status.tsx +++ b/components/bill/Status.tsx @@ -25,7 +25,8 @@ export const Status = ({ bill }: BillProps) => { const handleCloseBillHistory = () => setShowBillHistory(false) const history = last(bill.history) const today = new Date().toISOString() - const target = "Hearing scheduled for " + const target1 = "Hearing scheduled for " + const target2 = "Hearing rescheduled to " let hearingDate = "" if (history?.Date) { @@ -33,7 +34,10 @@ export const Status = ({ bill }: BillProps) => { } let hearingCheck = false - if (history?.Action.startsWith(target)) { + if ( + history?.Action.startsWith(target1) || + history?.Action.startsWith(target2) + ) { hearingCheck = true } From c7eb865002cca671d49e3616761e3aefb8b9c277 Mon Sep 17 00:00:00 2001 From: mertbagt Date: Wed, 8 Apr 2026 14:53:07 -0400 Subject: [PATCH 05/55] cleanup --- components/bill/Status.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/components/bill/Status.tsx b/components/bill/Status.tsx index 89a92ce16..ff8c823ac 100644 --- a/components/bill/Status.tsx +++ b/components/bill/Status.tsx @@ -28,11 +28,6 @@ export const Status = ({ bill }: BillProps) => { const target1 = "Hearing scheduled for " const target2 = "Hearing rescheduled to " - let hearingDate = "" - if (history?.Date) { - hearingDate = history.Date - } - let hearingCheck = false if ( history?.Action.startsWith(target1) || @@ -41,6 +36,10 @@ export const Status = ({ bill }: BillProps) => { hearingCheck = true } + let hearingDate = "" + if (history?.Date) { + hearingDate = history.Date + } let dateCheck = false if (hearingDate < today) { dateCheck = true From 48936109fd69cd4c68fdd4f05773d10ba9b65928 Mon Sep 17 00:00:00 2001 From: Andre Coullard <119697079+ACoullard@users.noreply.github.com> Date: Tue, 21 Apr 2026 20:48:20 -0400 Subject: [PATCH 06/55] Merge pull request #2103 from ACoullard/AC/fix-loading-state-in-newsfeed Fix Loading State in Newsfeed --- components/Newsfeed/Newsfeed.tsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/components/Newsfeed/Newsfeed.tsx b/components/Newsfeed/Newsfeed.tsx index 4bca6718f..a3fdf8b9c 100644 --- a/components/Newsfeed/Newsfeed.tsx +++ b/components/Newsfeed/Newsfeed.tsx @@ -2,7 +2,7 @@ import ErrorPage from "next/error" import { flags } from "../featureFlags" import { Timestamp } from "firebase/firestore" import { useTranslation } from "next-i18next" -import { useEffect, useState } from "react" +import { useEffect, useMemo, useState } from "react" import { Frequency, useAuth } from "../auth" import { Col, Row, Spinner } from "../bootstrap" import { Profile, useProfile, usePublicProfile } from "../db" @@ -33,19 +33,17 @@ export default function Newsfeed() { useState(true) const [allResults, setAllResults] = useState([]) - const [filteredResults, setFilteredResults] = useState([]) + const [notificationsLoading, setNotificationsLoading] = useState(true) - useEffect(() => { - const results = allResults.filter(result => { - if (isShowingOrgs && result.type == `testimony`) return true - if (isShowingBills && result.type == `bill`) return true - if (isShowingBallotQuestions && result.type == `ballotQuestion`) + const filteredResults = useMemo(() => { + return allResults.filter(result => { + if (isShowingOrgs && result.type === "testimony") return true + if (isShowingBills && result.type === "bill") return true + if (isShowingBallotQuestions && result.type == "ballotQuestion") return true return false }) - - setFilteredResults(results) - }, [isShowingOrgs, isShowingBills, isShowingBallotQuestions, allResults]) + }, [allResults, isShowingOrgs, isShowingBallotQuestions, isShowingBills]) const onOrgFilterChange = (isShowing: boolean) => { setIsShowingOrgs(isShowing) @@ -65,12 +63,14 @@ export default function Newsfeed() { if (uid) { const notifications = await notificationQuery(uid) setAllResults(notifications) - setFilteredResults(notifications) } } catch (error) { console.error("Error fetching notifications: " + error) + } finally { + setNotificationsLoading(false) } } + setNotificationsLoading(true) fetchNotifications() }, [uid]) @@ -223,7 +223,7 @@ export default function Newsfeed() { return ( <> - {result.loading && uid ? ( + {(uid && result.loading) || notificationsLoading ? ( From ad63191ae9134ce3e8f28b577a14657526a51c74 Mon Sep 17 00:00:00 2001 From: violet <158512193+fastfadingviolets@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:00:21 +0200 Subject: [PATCH 07/55] feat: add the firearms veto referendum and associated schema changes (#2109) --- .../2026/24-firearms-referendum.yaml | 35 +++++++++++++++++++ .../ballotquestions/BallotQuestionHeader.tsx | 4 +++ components/ballotquestions/OverviewTab.tsx | 17 +++++++++ functions/src/ballotQuestions/types.ts | 3 +- pages/ballotQuestions/[id].tsx | 3 +- public/locales/en/search.json | 7 ++++ 6 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 ballotQuestions/2026/24-firearms-referendum.yaml diff --git a/ballotQuestions/2026/24-firearms-referendum.yaml b/ballotQuestions/2026/24-firearms-referendum.yaml new file mode 100644 index 000000000..3fe006b41 --- /dev/null +++ b/ballotQuestions/2026/24-firearms-referendum.yaml @@ -0,0 +1,35 @@ +# ballotQuestions/2026/24-firearms-referendum.yaml +# +# Referendum petition (Article 48 §2) to repeal Chapter 135 of the Acts of 2024, +# "An Act Modernizing Firearm Laws." Filed with the Secretary of the +# Commonwealth on Aug. 9, 2024 by ten qualified voters; certified for the +# November 2026 ballot. Underlying bill is H.4885 of the 193rd General Court. +# +# id: descriptive. Unlike initiative petitions (which carry an AG YY-NN +# docket number — e.g. 25-03), referendum petitions in MA are not assigned +# a docket number; the Secretary's transmittal letter to the AG identifies +# the petition only by the chapter it seeks to repeal. +id: "24-firearms-referendum" +billId: "H4885" +title: "Referendum on the 2024 firearms law (Chapter 135)" +court: 193 +electionYear: 2026 +type: referendum +ballotStatus: certified +ballotQuestionNumber: null +relatedBillIds: [] +description: null +atAGlance: null +fullSummary: |- + This referendum asks voters whether to repeal Chapter 135 of the Acts of 2024, + "An Act Modernizing Firearm Laws," an omnibus law passed by the Legislature + and signed by Governor Healey in 2024 that made several changes to the + state's firearm regulations. + + Opponents of the law gathered enough certified signatures to qualify a + referendum petition for the November 2026 ballot. A YES vote keeps the law + in effect. A NO vote repeals it. + + An official summary prepared by the Attorney General will appear in the + state's Information for Voters guide closer to the election. +pdfUrl: "https://malegislature.gov/Laws/SessionLaws/Acts/2024/Chapter135" diff --git a/components/ballotquestions/BallotQuestionHeader.tsx b/components/ballotquestions/BallotQuestionHeader.tsx index bddafedee..915a28eb0 100644 --- a/components/ballotquestions/BallotQuestionHeader.tsx +++ b/components/ballotquestions/BallotQuestionHeader.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from "next-i18next" import Link from "next/link" import { Container, Row, Col } from "react-bootstrap" import { useAuth } from "../auth" @@ -16,6 +17,7 @@ export const BallotQuestionHeader = ({ ballotQuestion: BallotQuestion bill: Bill | null }) => { + const { t } = useTranslation("search") const { notifications } = useFlags() const { user } = useAuth() const statusLabel = getBallotQuestionStatusLabel(ballotQuestion.ballotStatus) @@ -36,6 +38,8 @@ export const BallotQuestionHeader = ({ return "Constitutional Amendment" case "advisory": return "Advisory Question" + case "referendum": + return t("ballot_question_type.referendum") default: return "Ballot Question" } diff --git a/components/ballotquestions/OverviewTab.tsx b/components/ballotquestions/OverviewTab.tsx index 569c478bb..4804dd127 100644 --- a/components/ballotquestions/OverviewTab.tsx +++ b/components/ballotquestions/OverviewTab.tsx @@ -1,3 +1,4 @@ +import { Trans, useTranslation } from "next-i18next" import type { ReactNode } from "react" import { Col, Row } from "react-bootstrap" import { BallotQuestion, Bill } from "../db" @@ -14,6 +15,7 @@ export const OverviewTab = ({ bill: Bill | null hearings: Hearing[] }) => { + const { t } = useTranslation("search") const sortedHearings = [...hearings].sort((a, b) => b.startsAt - a.startsAt) const sectionCopyStyle = { color: "#334155", @@ -47,6 +49,21 @@ export const OverviewTab = ({ + {ballotQuestion.type === "referendum" && ( + +

+ {t("ballot_question_referendum_how_vote_works.title")} +

+

+ , ]} + /> +

+
+ )} + {ballotQuestion.atAGlance && ballotQuestion.atAGlance.length > 0 && (

Key Details

diff --git a/functions/src/ballotQuestions/types.ts b/functions/src/ballotQuestions/types.ts index cca6adeb4..234dc8ff8 100644 --- a/functions/src/ballotQuestions/types.ts +++ b/functions/src/ballotQuestions/types.ts @@ -36,7 +36,8 @@ export const BallotQuestion = withDefaults( L("initiative_constitutional"), L("legislative_referral"), L("constitutional_amendment"), - L("advisory") + L("advisory"), + L("referendum") ), ballotStatus: BallotQuestionStatus, ballotQuestionNumber: Union(Number, Null), diff --git a/pages/ballotQuestions/[id].tsx b/pages/ballotQuestions/[id].tsx index 15394d031..6e12616bb 100644 --- a/pages/ballotQuestions/[id].tsx +++ b/pages/ballotQuestions/[id].tsx @@ -100,7 +100,8 @@ export const getServerSideProps: GetServerSideProps = async ctx => { "common", "footer", "testimony", - "profile" + "profile", + "search" ])) } } diff --git a/public/locales/en/search.json b/public/locales/en/search.json index c9e6bd8a1..4998206d9 100644 --- a/public/locales/en/search.json +++ b/public/locales/en/search.json @@ -28,6 +28,13 @@ "rejected": "Rejected", "accepted": "Accepted" }, + "ballot_question_type": { + "referendum": "Veto Referendum" + }, + "ballot_question_referendum_how_vote_works": { + "title": "How the vote works", + "body": "This is a referendum on a law the Legislature has already enacted. <0>A YES vote keeps this law in effect. <1>A NO vote repeals it." + }, "ballot_question_results_summary": "Showing {{count}} questions", "ballot_question_reset_filters": "Reset filters", "ballot_question_no_summary": "No summary available yet.", From 5f83cdc0c093d8cd61db4c695e495b28c1606060 Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 28 Apr 2026 19:30:17 -0400 Subject: [PATCH 08/55] clarifying comments --- components/bill/Status.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/bill/Status.tsx b/components/bill/Status.tsx index ff8c823ac..2836c890f 100644 --- a/components/bill/Status.tsx +++ b/components/bill/Status.tsx @@ -25,6 +25,9 @@ export const Status = ({ bill }: BillProps) => { const handleCloseBillHistory = () => setShowBillHistory(false) const history = last(bill.history) const today = new Date().toISOString() + + // target1 and target2 are only used internally and never shown to the User + // as such they are not translated at this time const target1 = "Hearing scheduled for " const target2 = "Hearing rescheduled to " From 5a1b168922a7b4b6989d900ed720612f36481112 Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 28 Apr 2026 19:55:42 -0400 Subject: [PATCH 09/55] translation comments --- components/bill/Status.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/bill/Status.tsx b/components/bill/Status.tsx index 2836c890f..42226395f 100644 --- a/components/bill/Status.tsx +++ b/components/bill/Status.tsx @@ -26,8 +26,7 @@ export const Status = ({ bill }: BillProps) => { const history = last(bill.history) const today = new Date().toISOString() - // target1 and target2 are only used internally and never shown to the User - // as such they are not translated at this time + // revisit this when we revisit translations for the backend const target1 = "Hearing scheduled for " const target2 = "Hearing rescheduled to " From 9dd240be100ce87b628f26c3d66d806910f227d5 Mon Sep 17 00:00:00 2001 From: Janice Lichtman Date: Tue, 28 Apr 2026 21:11:21 -0400 Subject: [PATCH 10/55] Phone verification frontend changes (#2106) * Spruced up phone verification modals * Additional tweak to phone verification modal * Updated verify section of profile page to show both email and phone verification * Added verify account section to edit profile page and refactored * used feature flag to show new or legacy verify account section appropriately on profile page * fixed formatting * minor style adjustment --- .prettierignore | 4 +- .../EditProfilePage/EditProfileHeader.tsx | 27 +--- .../EditProfilePage/EditProfilePage.tsx | 26 ++-- components/ProfilePage/ProfilePage.tsx | 24 +++- ...ion.tsx => VerifyAccountSectionLegacy.tsx} | 2 +- .../PhoneVerificationModal.tsx | 80 ++++++++--- components/shared/VerifyAccountSection.tsx | 132 ++++++++++++++++++ components/shared/index.tsx | 9 +- public/images/verifiedUser.png | Bin 1151 -> 0 bytes public/locales/en/auth.json | 35 ++++- public/locales/en/editProfile.json | 20 --- public/locales/en/profile.json | 2 +- .../profile/VerifyAccountSection.stories.tsx | 2 +- 13 files changed, 280 insertions(+), 83 deletions(-) rename components/ProfilePage/{VerifyAccountSection.tsx => VerifyAccountSectionLegacy.tsx} (96%) rename components/{EditProfilePage => shared}/PhoneVerificationModal.tsx (75%) create mode 100644 components/shared/VerifyAccountSection.tsx delete mode 100644 public/images/verifiedUser.png diff --git a/.prettierignore b/.prettierignore index 261629f4d..fcb12873c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -14,4 +14,6 @@ dist coverage storybook-static llm -playwright-report \ No newline at end of file +playwright-report +CLAUDE.md +.cursor/ \ No newline at end of file diff --git a/components/EditProfilePage/EditProfileHeader.tsx b/components/EditProfilePage/EditProfileHeader.tsx index 8f0b1a111..b5c02f5b7 100644 --- a/components/EditProfilePage/EditProfileHeader.tsx +++ b/components/EditProfilePage/EditProfileHeader.tsx @@ -3,25 +3,19 @@ import { Role } from "../auth" import { Col, Row } from "../bootstrap" import { GearIcon, OutlineButton } from "../buttons" import { ProfileEditToggle } from "components/ProfilePage/ProfileButtons" -import { useFlags } from "components/featureFlags" export const EditProfileHeader = ({ formUpdated, onSettingsModalOpen, - onGetVerifiedClick, uid, - role, - phoneVerified + role }: { formUpdated: boolean onSettingsModalOpen: () => void - onGetVerifiedClick?: () => void uid: string role: Role - phoneVerified?: boolean }) => { const { t } = useTranslation("editProfile") - const { phoneVerificationUI } = useFlags() return ( @@ -36,25 +30,6 @@ export const EditProfileHeader = ({ onClick={() => onSettingsModalOpen()} /> - {phoneVerificationUI && - (phoneVerified === true ? ( -
- {t("verifiedUser")} - {t("verifiedUserBadgeAlt")} -
- ) : onGetVerifiedClick ? ( - - ) : null)}
) diff --git a/components/EditProfilePage/EditProfilePage.tsx b/components/EditProfilePage/EditProfilePage.tsx index 2fff9d96a..6f3d4c2d1 100644 --- a/components/EditProfilePage/EditProfilePage.tsx +++ b/components/EditProfilePage/EditProfilePage.tsx @@ -17,8 +17,8 @@ import { import { EditProfileHeader } from "./EditProfileHeader" import { FollowingTab } from "./FollowingTab" import { PersonalInfoTab } from "./PersonalInfoTab" -import PhoneVerificationModal from "./PhoneVerificationModal" import ProfileSettingsModal from "./ProfileSettingsModal" +import { VerifyAccountSection } from "components/shared" import { StyledTabContent, TabNavItem, @@ -88,8 +88,6 @@ export function EditProfileForm({ const [formUpdated, setFormUpdated] = useState(false) const [settingsModal, setSettingsModal] = useState<"show" | null>(null) - const [showPhoneVerificationModal, setShowPhoneVerificationModal] = - useState(false) const [notifications, setNotifications] = useState( notificationFrequency || "Weekly" ) @@ -114,7 +112,8 @@ export function EditProfileForm({ let isOrg = profile.role === "organization" - const isPendingUpgrade = useAuth().claims?.role === "pendingUpgrade" + const { claims, user } = useAuth() + const isPendingUpgrade = claims?.role === "pendingUpgrade" isOrg = isOrg || isPendingUpgrade @@ -167,7 +166,7 @@ export function EditProfileForm({ } ] - const { followOrg } = useFlags() + const { followOrg, phoneVerificationUI } = useFlags() if (followOrg === false) { tabs.splice(2, 1) @@ -181,11 +180,20 @@ export function EditProfileForm({ setShowPhoneVerificationModal(true)} uid={uid} role={profile.role} - phoneVerified={profile.phoneVerified} /> + {phoneVerificationUI && + user && + (!user.emailVerified || !profile.phoneVerified) && ( +
+ +
+ )} setSettingsModal(null)} show={settingsModal === "show"} /> - setShowPhoneVerificationModal(false)} - /> ) } diff --git a/components/ProfilePage/ProfilePage.tsx b/components/ProfilePage/ProfilePage.tsx index 32c492377..10890ce56 100644 --- a/components/ProfilePage/ProfilePage.tsx +++ b/components/ProfilePage/ProfilePage.tsx @@ -14,7 +14,9 @@ import { OrgContactInfo } from "./OrgContactInfo" import { ProfileAboutSection } from "./ProfileAboutSection" import { ProfileHeader } from "./ProfileHeader" import { ProfileLegislators } from "./ProfileLegislators" -import { VerifyAccountSection } from "./VerifyAccountSection" +import { VerifyAccountSection } from "components/shared" +import { VerifyAccountSectionLegacy } from "./VerifyAccountSectionLegacy" +import { useFlags } from "components/featureFlags" export function ProfilePage(profileprops: { id: string @@ -38,6 +40,8 @@ export function ProfilePage(profileprops: { number | undefined >() + const { phoneVerificationUI } = useFlags() + useEffect(() => { const countPublishedTestimony = async () => { const pubTestRef = query( @@ -105,10 +109,24 @@ export function ProfilePage(profileprops: { profile={profile} /> - {isCurrentUser && !user.emailVerified ? ( + {!phoneVerificationUI && isCurrentUser && !user.emailVerified ? ( + + + + + + ) : null} + + {phoneVerificationUI && + isCurrentUser && + (!user.emailVerified || !profile.phoneVerified) ? ( - + ) : null} diff --git a/components/ProfilePage/VerifyAccountSection.tsx b/components/ProfilePage/VerifyAccountSectionLegacy.tsx similarity index 96% rename from components/ProfilePage/VerifyAccountSection.tsx rename to components/ProfilePage/VerifyAccountSectionLegacy.tsx index 87a6dd2a5..1176fb322 100644 --- a/components/ProfilePage/VerifyAccountSection.tsx +++ b/components/ProfilePage/VerifyAccountSectionLegacy.tsx @@ -5,7 +5,7 @@ import { User } from "firebase/auth" import { LoadingButton } from "components/buttons" import { useTranslation } from "next-i18next" -export const VerifyAccountSection = ({ +export const VerifyAccountSectionLegacy = ({ user, className }: { diff --git a/components/EditProfilePage/PhoneVerificationModal.tsx b/components/shared/PhoneVerificationModal.tsx similarity index 75% rename from components/EditProfilePage/PhoneVerificationModal.tsx rename to components/shared/PhoneVerificationModal.tsx index a08c78370..e966d2e3c 100644 --- a/components/EditProfilePage/PhoneVerificationModal.tsx +++ b/components/shared/PhoneVerificationModal.tsx @@ -28,15 +28,16 @@ const AUTH_ERROR_CODE_TO_KEY: Record = { "auth/operation-not-allowed": "phoneVerification.errors.operationNotAllowed" } -export default function PhoneVerificationModal({ +export function PhoneVerificationModal({ show, - onHide -}: Pick) { - const { t } = useTranslation("editProfile") + onHide, + onVerified +}: Pick & { onVerified?: () => void }) { + const { t } = useTranslation("auth") const { user } = useAuth() const completePhoneVerification = useCompletePhoneVerification() - const [step, setStep] = useState<"phone" | "code">("phone") + const [step, setStep] = useState<"phone" | "code" | "success">("phone") const [phone, setPhone] = useState("") const [code, setCode] = useState("") const [error, setError] = useState(null) @@ -137,7 +138,8 @@ export default function PhoneVerificationModal({ if (completePhoneVerification.execute) { await completePhoneVerification.execute() } - onHide?.() + onVerified?.() + setStep("success") } catch (err: unknown) { const code = (err as { code?: string })?.code setError( @@ -165,6 +167,7 @@ export default function PhoneVerificationModal({ onHide={onHide} aria-labelledby="phone-verification-modal" centered + size="lg" > @@ -178,7 +181,6 @@ export default function PhoneVerificationModal({ {error} ) : null} - {step === "phone" ? (
- + {t("phoneVerification.stepOne")}{" "} + {t("phoneVerification.stepOneDescription")} +

+ setPhone(e.target.value)} - className="mb-3" + className="mb-4" + style={{ + border: "none", + borderRadius: 0, + borderBottom: "1px solid", + boxShadow: "none", + background: "transparent", + paddingLeft: 0 + }} />
- {t("phoneVerification.continue")} + {t("phoneVerification.receiveCode")} - ) : ( + ) : step === "code" ? (
{ @@ -213,23 +226,56 @@ export default function PhoneVerificationModal({ handleVerify() }} > - + {t("phoneVerification.stepTwo")}{" "} + {t("phoneVerification.stepTwoDescription")} +

+ setCode(e.target.value)} - className="mb-3" + className="mb-5" + style={{ + border: "none", + borderRadius: 0, + borderBottom: "1px solid", + boxShadow: "none", + background: "transparent", + paddingLeft: 0 + }} /> {t("phoneVerification.verify")} + ) : ( +
+
+ {"\u2713" /* checkmark */} +
+

+ {t("phoneVerification.successMessage")} +

+
)} diff --git a/components/shared/VerifyAccountSection.tsx b/components/shared/VerifyAccountSection.tsx new file mode 100644 index 000000000..fadcabd4d --- /dev/null +++ b/components/shared/VerifyAccountSection.tsx @@ -0,0 +1,132 @@ +import { useState } from "react" +import { useSendEmailVerification } from "components/auth/hooks" +import { TitledSectionCard } from "components/shared" +import { Alert, Card, Col, Row } from "components/bootstrap" +import { User } from "firebase/auth" +import { LoadingButton } from "components/buttons" +import { Trans, useTranslation } from "next-i18next" +import { PhoneVerificationModal } from "components/shared/PhoneVerificationModal" +import { Profile } from "components/db/profile/types" + +export const VerifyAccountSection = ({ + user, + profile, + className +}: { + user: User + profile: Profile + className: string +}) => { + const sendEmailVerification = useSendEmailVerification() + const { t } = useTranslation("auth") + const [showPhoneModal, setShowPhoneModal] = useState(false) + const [localPhoneVerified, setLocalPhoneVerified] = useState( + profile.phoneVerified ?? false + ) + + return ( + +

+ }} + /> +

+ + + +
+

+ {t("verifyAccountSection.emailHeader")} +

+ {user.emailVerified ? ( +

+ {t("verifyAccountSection.successMessage")} +

+ ) : ( + <> +

+ {t("verifyAccountSection.verifyEmail")} +

+

+ {t("verifyAccountSection.verifyEmailSpam")} +

+ {sendEmailVerification.status === "success" ? ( + + {t("verifyAccountSection.checkEmail")} + + ) : null} + {sendEmailVerification.status === "error" ? ( + + {sendEmailVerification.error?.message} + + ) : null} + + )} +
+ {!user.emailVerified && + sendEmailVerification.status !== "success" ? ( +
+ sendEmailVerification.execute(user)} + style={{ + width: "5.5rem", + height: "4rem", + whiteSpace: "normal", + lineHeight: "1.5", + padding: "0.5rem 0.75rem" + }} + > + {t("verifyAccountSection.sendAnotherLink")} + +
+ ) : null} +
+ + + +
+

+ {t("verifyAccountSection.phoneHeader")} +

+

+ {localPhoneVerified + ? t("verifyAccountSection.successMessage") + : t("verifyAccountSection.phoneDescription")} +

+
+ {!localPhoneVerified ? ( +
+ setShowPhoneModal(true)} + style={{ + width: "5.5rem", + height: "4rem", + whiteSpace: "normal", + lineHeight: "1.5", + padding: "0.5rem 0.75rem" + }} + > + {t("verifyAccountSection.verifyPhone")} + +
+ ) : null} +
+ +
+ setShowPhoneModal(false)} + onVerified={() => setLocalPhoneVerified(true)} + /> +
+ ) +} diff --git a/components/shared/index.tsx b/components/shared/index.tsx index 1e7bd4308..7eddf90b6 100644 --- a/components/shared/index.tsx +++ b/components/shared/index.tsx @@ -1,4 +1,11 @@ import { LabeledIcon } from "./LabeledIcon" +import { PhoneVerificationModal } from "./PhoneVerificationModal" import TitledSectionCard from "./TitledSectionCard" +import { VerifyAccountSection } from "./VerifyAccountSection" -export { LabeledIcon, TitledSectionCard } +export { + LabeledIcon, + PhoneVerificationModal, + TitledSectionCard, + VerifyAccountSection +} diff --git a/public/images/verifiedUser.png b/public/images/verifiedUser.png deleted file mode 100644 index 049f65ce00597314c9148e285febea8867002b52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1151 zcmV-_1c3XAP)()Cc+1RyfafuwZ}1FGE?fN9pZd&ZlfND<(Bg}_Ub`4k|1 z0!Sa*02s@P_FEuW);fkg@S(HjZ^C-ZoKFC%vTnXW0A%g|1ynoptO+L}qkGG-H zRG5u<05E7S08xM)g+F}}I*fBtGv_h@vXp90*;fk&&}w-jz*7$Z9#~5Z=Kv;`06>IS z1p~01lnLPB3Y$W>6pMHuXAyV8_JRSlQ6SJZKLUdu0Q8!kej7OYBI{a#FS1N-DIu@4 zQi9|u<|bEAF^5Z4P7_ca+hVe#56gx|a(zQ{4V((Ly<^)vPq&nD_{=c?S2p#shnxEM z9;@5|R7VyLKvQ}f;^DE%f)2Kl`coarbFej}A8Z-&ylRkidGoK}Rj^~g$&Srac_9i= ze=LZb4vMXw0R$VR4ZD8sn@wJ<#tbPc*m#C~fVckGiGlhKED0xO%fh6@6M#@8-4f!{ zSiz@p_b)wIf9`K=INyp5zqR6x*uK0_%3$&2Kq1v92PLo|yw+D(A;E1*2Kjw6tUA#jkMY)+d@s+n4ywkqhYOL@ecquDB)> z0GE7ST$B9NRe*{}`edjvjsFJ_jLNuGS0F0mrXRaB^X~-+CvhW}IN_T4?LVbHs%RX4 zZU8RWi$G2L$F2Z`_=z7vjpJws;ESX8FW3PnVG!ZuA$I^G=}}t%yfn4p z;K*8kt?kKX@5IUfN&I%hU`Y&9e6eyI#iK zF80?6Z_NON`ndQ3ST0e{%PmHLKve$Ac-_wle;NUNb#eD|zO87&qOH6v%#XksIb^(C z78V13PM}!;F#$F0-u)}N&?t{c#X(*k4o0QR`L37NiI++_F~z2o_wHbM#yf;zctQhw R15f|}002ovPDHLkV1hDC1aANU diff --git a/public/locales/en/auth.json b/public/locales/en/auth.json index 0e518bda3..488a70ecc 100644 --- a/public/locales/en/auth.json +++ b/public/locales/en/auth.json @@ -59,5 +59,38 @@ "pleaseConsider": "Please consider logging in first:", "signInToAccess": "Login required to access the content", "almostThere": "Almost there!", - "justLogIn": "You’ll be redirected automatically after logging in." + "justLogIn": "You’ll be redirected automatically after logging in.", + "verifyAccountSection": { + "title": "Verify Account", + "description": "MAPLE requires our users to verify both their email address and phone number to be able to post testimony on our platform. We do this in an effort to reduce the number of bots that are able to publish on MAPLE.", + "emailHeader": "Email address", + "verifyEmail": "Click the link in your email inbox from MAPLE.", + "verifyEmailSpam": "If you don’t see it, be sure to check your spam folder.", + "checkEmail": "Check your email!", + "sendAnotherLink": "Resend link", + "phoneHeader": "Phone number", + "phoneDescription": "Receive a verification code on your phone", + "verifyPhone": "Verify", + "successMessage": "Successfully verified. Thank you!" + }, + "phoneVerificationModalTitle": "Verify Phone", + "phoneVerification": { + "stepOne": "Step one.", + "stepOneDescription": "Enter your phone number below.", + "phonePlaceholder": "Enter your 10-digit phone number", + "receiveCode": "Receive code", + "stepTwo": "Step two.", + "stepTwoDescription": "Enter the code that was sent to your phone.", + "codePlaceholder": "Enter six-digit code", + "verify": "Verify", + "errors": { + "credentialAlreadyInUse": "This phone number is already linked to another account.", + "providerAlreadyLinked": "This account already has a phone number linked.", + "invalidPhoneNumber": "Please enter a valid phone number\n(e.g. 617 555-1234).", + "operationNotAllowed": "Phone verification is not enabled. Please try again later or contact us at info@mapletestimony.org." + }, + "signedInRequired": "You must be signed in to verify your phone.", + "enterVerificationCode": "Please enter the verification code.", + "successMessage": "Success! Your phone number has been verified." + } } \ No newline at end of file diff --git a/public/locales/en/editProfile.json b/public/locales/en/editProfile.json index 31dd5b39d..2bc1b45be 100644 --- a/public/locales/en/editProfile.json +++ b/public/locales/en/editProfile.json @@ -1,25 +1,5 @@ { "header": "Edit Profile", - "getVerified": "Get Verified", - "phoneVerificationModalTitle": "Verify your phone number", - "phoneVerification": { - "phoneLabel": "Phone number (Ex 617 555-1234)", - "phonePlaceholder": "617 555-1234", - "continue": "Continue", - "codeLabel": "Verification code", - "codePlaceholder": "Enter 6-digit code", - "verify": "Verify", - "errors": { - "credentialAlreadyInUse": "This phone number is already linked to another account.", - "providerAlreadyLinked": "This account already has a phone number linked.", - "invalidPhoneNumber": "Please enter a valid phone number\n(e.g. 617 555-1234).", - "operationNotAllowed": "Phone verification is not enabled. Please try again later or contact us at info@mapletestimony.org." - }, - "signedInRequired": "You must be signed in to verify your phone.", - "enterVerificationCode": "Please enter the verification code." - }, - "verifiedUser": "Verified User", - "verifiedUserBadgeAlt": "Verified user badge", "setting": "Settings", "privacySetting": "Privacy Settings", "save": "Save", diff --git a/public/locales/en/profile.json b/public/locales/en/profile.json index 34bfe4ce4..339637c00 100644 --- a/public/locales/en/profile.json +++ b/public/locales/en/profile.json @@ -19,7 +19,7 @@ "privateProfile": "Your profile is currently private. You can change this in \"settings\"", "noLegislatorInfo": "No legislator information given" }, - "verifyAccountSection":{ + "verifyAccountSection":{ "verifyAccount": "We sent a link to your email to verify your account, but you haven't\nclicked it yet. If you don't see it, be sure to check your spam\nfolder.", "checkEmail": "Check your email!", "sendAnotherLink": "Send Another Link" diff --git a/stories_hold/organisms/profile/VerifyAccountSection.stories.tsx b/stories_hold/organisms/profile/VerifyAccountSection.stories.tsx index 1bdeac49e..389950227 100644 --- a/stories_hold/organisms/profile/VerifyAccountSection.stories.tsx +++ b/stories_hold/organisms/profile/VerifyAccountSection.stories.tsx @@ -1,5 +1,5 @@ import { ComponentStory } from "@storybook/react" -import { VerifyAccountSection } from "components/ProfilePage/VerifyAccountSection" +import { VerifyAccountSection } from "components/shared" import { Providers } from "components/providers" import { wrapper } from "components/store" import { User } from "firebase/auth" From 652d0b3fdd7275586bf69cba9c25a39d0da56cd1 Mon Sep 17 00:00:00 2001 From: Kimin Kim <55262612+kiminkim724@users.noreply.github.com> Date: Tue, 28 Apr 2026 21:12:27 -0400 Subject: [PATCH 11/55] Set maxInstances to 1 to prevent concurrent scraping (#2110) --- functions/src/events/scrapeEvents.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/functions/src/events/scrapeEvents.ts b/functions/src/events/scrapeEvents.ts index 4c989f16c..19d1e7b77 100644 --- a/functions/src/events/scrapeEvents.ts +++ b/functions/src/events/scrapeEvents.ts @@ -44,7 +44,8 @@ abstract class EventScraper { return runWith({ timeoutSeconds: this.timeout, secrets: ["ASSEMBLY_API_KEY"], - memory: this.memory + memory: this.memory, + maxInstances: 1 }) .pubsub.schedule(this.schedule) .onRun(() => this.run()) From 6495fdbb614c9de0c04188cc4ddda29bb92556d8 Mon Sep 17 00:00:00 2001 From: Mephistic Date: Wed, 29 Apr 2026 21:53:21 -0400 Subject: [PATCH 12/55] Remove noisy progress logs from audio processor - now that it's worked, we mainly need to know when it starts and when it ends (#2111) --- functions/src/events/scrapeEvents.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/functions/src/events/scrapeEvents.ts b/functions/src/events/scrapeEvents.ts index 19d1e7b77..419bd505b 100644 --- a/functions/src/events/scrapeEvents.ts +++ b/functions/src/events/scrapeEvents.ts @@ -166,15 +166,6 @@ const extractAudioFromVideo = async ( .on("start", commandLine => { console.log(`Spawned FFmpeg with command: ${commandLine}`) }) - .on("progress", progress => { - if ( - progress && - progress.percent && - Math.round(progress.percent) % 10 === 0 - ) { - console.log(`Processing: ${progress.percent}% done`) - } - }) .on("end", () => { console.log("FFmpeg processing finished successfully") resolve() From 08db8c5ea20769f3293fc22a9cdbfeafef298b2f Mon Sep 17 00:00:00 2001 From: Lexa Michaelides <32111123+LexaMichaelides@users.noreply.github.com> Date: Mon, 11 May 2026 01:31:52 -0400 Subject: [PATCH 13/55] Visual refresh and expanded ballot question support (#2114) * Merge pull request #51 from hyphacoop/visual-system-refinement Refine MAPLE visual system and shared surfaces * Apply visual tokens to search pages and shared components * Fix bill search typecheck * Format search and hearing components * Align ballot question browse search controls * Merge pull request #55 from hyphacoop/ballot-questions-2024-fix Ballot question 2024 data * Merge pull request #56 from hyphacoop/fix-sync-script-validation Skip stale-doc validation in ballot question sync * Merge pull request #57 from hyphacoop/fix-bq-search-responsiveness Fix ballot question search responsiveness for medium and mobile * Merge pull request #61 from hyphacoop/fix/ballot-question-count-scope Fix ballot question bill count scope * Merge pull request #60 from hyphacoop/docs/ballot-questions-field-descriptions docs: add ballot question field reference * Merge pull request #58 from hyphacoop/homepage-redesign Homepage refresh and design polish * Merge pull request #59 from hyphacoop/ballot-question-alert-flag Add ballot question alert flag * Merge pull request #63 from hyphacoop/fix/ballot-question-notification-test Fix ballot question notification test statuses * Make ballot question frontend strings translatable * Remove unused homepage assets * Update ballot question i18n tests * Fix referendum title i18n namespace * Reorganize ballot question i18n into dedicated namespace * Migrate remaining components to ballotquestions namespace * Update 24-firearms-referendum.yaml * Add ballotquestions namespace to serverSideTranslations * Fix formatting --------- Co-authored-by: vincent --- .nvmrc | 1 + ballotQuestions/2024/23-12.yaml | 81 ++- ballotQuestions/2024/23-13.yaml | 140 ++-- ballotQuestions/2024/23-25.yaml | 133 ++-- ballotQuestions/2024/23-26.yaml | 22 - ballotQuestions/2024/23-34.yaml | 19 +- ballotQuestions/2024/23-36.yaml | 66 ++ .../2026/24-firearms-referendum.yaml | 12 +- ballotQuestions/2026/25-03.yaml | 10 + ballotQuestions/2026/25-08.yaml | 10 + ballotQuestions/2026/25-10.yaml | 10 + ballotQuestions/2026/25-12.yaml | 10 + ballotQuestions/2026/25-14.yaml | 10 + ballotQuestions/2026/25-15.yaml | 10 + ballotQuestions/2026/25-17.yaml | 10 + ballotQuestions/2026/25-18.yaml | 10 + ballotQuestions/2026/25-21.yaml | 10 + ballotQuestions/2026/25-22.yaml | 10 + ballotQuestions/2026/25-37.yaml | 10 + components/AboutSection/AboutSection.tsx | 65 -- .../AboutSectionInfoCard/AboutInfoCard.tsx | 34 - .../AnnouncementBanner/AnnouncementBanner.tsx | 6 +- .../TranscriptAnnouncement.tsx | 2 +- components/BillStatusCard/BillStatusCard.tsx | 6 +- components/Card/Card.tsx | 13 +- .../StyledEditProfileComponents.tsx | 4 +- components/FollowingCard/FollowingCard.tsx | 4 +- components/Footer/Footer.tsx | 52 +- components/Footer/FooterContainer.tsx | 6 +- .../HearingsScheduled/HearingsScheduled.tsx | 8 +- components/HeroHeader/HeroHeader.js | 108 --- components/HeroHeader/HeroHeader.module.css | 51 -- components/InTheNews/NewsCard.tsx | 6 +- components/Leaf/Leaf.tsx | 40 -- components/Navbar.tsx | 73 +- components/NavbarComponents.tsx | 60 +- .../Newsfeed/StyledNewsfeedComponents.tsx | 12 +- components/NewsfeedCard/NewsfeedCard.test.tsx | 2 +- components/Policies/PolicyPage.module.css | 24 +- .../TestimonyCalloutSection.tsx | 71 -- components/TestimonyCard/MoreButton.tsx | 5 +- components/TestimonyCard/ReportModal.tsx | 2 +- components/TestimonyCard/Tabs.tsx | 10 +- .../TestimonyCard/UserFilterDropdown.tsx | 4 +- components/TestimonyCard/ViewTestimony.tsx | 4 +- .../BallotQuestionAlert.test.tsx | 69 ++ .../ballotquestions/BallotQuestionAlert.tsx | 43 ++ .../BallotQuestionDetails.test.tsx | 115 +++- .../ballotquestions/BallotQuestionDetails.tsx | 180 ++++- .../ballotquestions/BallotQuestionHeader.tsx | 113 ++- .../ballotquestions/BallotQuestionNav.tsx | 69 +- .../BallotQuestionTabButton.tsx | 4 +- .../BallotQuestionTabLinks.test.tsx | 58 +- .../BrowseBallotQuestions.test.tsx | 17 +- .../ballotquestions/BrowseBallotQuestions.tsx | 589 +++++++--------- .../ballotquestions/CampaignFinancialsTab.tsx | 165 +++++ .../ballotquestions/CommitteeHearing.test.tsx | 27 +- .../ballotquestions/CommitteeHearing.tsx | 42 +- components/ballotquestions/DescriptionBox.tsx | 15 +- .../ballotquestions/ForAndAgainstTab.tsx | 171 +++++ components/ballotquestions/OverviewTab.tsx | 118 ++-- components/ballotquestions/SynthesisTab.tsx | 62 ++ components/ballotquestions/TestimoniesTab.tsx | 62 +- .../YourTestimonyPanel.test.tsx | 15 + .../ballotquestions/YourTestimonyPanel.tsx | 29 +- components/ballotquestions/status.ts | 25 +- components/bill/BillTracker.tsx | 2 +- components/bill/SponsorsAndCommittees.tsx | 2 +- components/bill/Summary.tsx | 18 +- components/bill/TestimonyCounts.tsx | 2 +- components/buttons.tsx | 65 +- components/dashboard/ResourcesCard.tsx | 10 +- components/hearing/HearingDetails.tsx | 9 +- components/hearing/HearingSidebar.tsx | 8 +- components/hearing/Transcriptions.tsx | 33 +- components/homepage/DidYouKnowSection.tsx | 49 ++ components/homepage/ExplainerSection.tsx | 31 + components/homepage/FeaturesSection.tsx | 62 ++ components/homepage/HearingsSection.tsx | 113 +++ components/homepage/HeroSection.tsx | 41 ++ components/homepage/Homepage.module.css | 651 ++++++++++++++++++ components/layout.tsx | 4 +- components/publish/SubmitTestimonyForm.tsx | 2 +- components/publish/TestimonyPreview.tsx | 4 +- components/search/ResultCount.tsx | 4 +- components/search/SearchContainer.tsx | 96 ++- components/search/SortBy.tsx | 2 +- components/search/bills/BillHit.tsx | 33 +- components/search/bills/BillSearch.tsx | 55 +- components/search/hearings/HearingHit.tsx | 46 +- components/search/shared/RefinementPanel.tsx | 67 +- components/search/shared/SearchPage.tsx | 50 +- components/search/testimony/TestimonyHit.tsx | 256 ++++--- .../search/testimony/TestimonySearch.tsx | 42 +- components/search/useRefinements.tsx | 71 +- components/shared/CommonComponents.tsx | 25 +- components/shared/TitledSectionCard.tsx | 38 +- components/table/PaginationButtons.tsx | 6 +- .../PolicyActions.test.tsx | 2 +- components/tooltip.tsx | 2 +- docs/ballot-questions-data-model.md | 47 +- docs/ballot-questions-frontend.md | 12 +- docs/updating-ballot-questions.md | 118 ++++ functions/src/ballotQuestions/types.ts | 42 +- .../src/bills/backfillTestimonyCounts.ts | 1 + ...teBallotQuestionNotificationEvents.test.ts | 18 +- functions/src/testimony/deleteTestimony.ts | 5 +- functions/src/testimony/publishTestimony.ts | 2 + pages/ballotQuestions/[id].tsx | 4 +- pages/ballotQuestions/index.tsx | 4 +- pages/index.tsx | 46 +- public/envelope.svg | 27 + public/handpen.svg | 8 + public/homepage/feature-1.svg | 3 + public/homepage/feature-2.svg | 3 + public/homepage/feature-3.svg | 3 + .../feature-preview-ballot-question.png | Bin 0 -> 175462 bytes public/locales/en/ballotquestions.json | 148 ++++ public/locales/en/common.json | 12 +- public/locales/en/homepage.json | 33 +- public/locales/en/search.json | 39 -- public/skyline_blue.svg | 21 + scripts/README.md | 111 +++ scripts/firebase-admin/syncBallotQuestions.ts | 6 +- scripts/test-integration-ci.js | 2 +- .../BallotQuestionAlert.stories.tsx | 26 + .../BallotQuestionDetails.stories.tsx | 262 +++++++ .../BrowseBallotQuestions.stories.tsx | 90 +++ .../dashboard/ResourcesCard.stories.tsx | 13 + .../hearing/HearingSidebar.stories.tsx | 43 ++ .../homepage/HomepageSections.stories.tsx | 76 ++ .../newsfeed/NewsfeedCard.stories.tsx | 60 ++ .../pageElements/PageHeader.stories.tsx | 18 - styles/bootstrap.scss | 289 +++++++- styles/globals.css | 462 +++++++++---- .../ballotQuestions/bq-test-fixture.yaml | 5 +- tests/integration/ballotQuestions.test.ts | 2 + 137 files changed, 5303 insertions(+), 1903 deletions(-) create mode 100644 .nvmrc delete mode 100644 ballotQuestions/2024/23-26.yaml create mode 100644 ballotQuestions/2024/23-36.yaml delete mode 100644 components/AboutSection/AboutSection.tsx delete mode 100644 components/AboutSectionInfoCard/AboutInfoCard.tsx delete mode 100644 components/HeroHeader/HeroHeader.js delete mode 100644 components/HeroHeader/HeroHeader.module.css delete mode 100644 components/Leaf/Leaf.tsx delete mode 100644 components/TestimonyCallout/TestimonyCalloutSection.tsx create mode 100644 components/ballotquestions/BallotQuestionAlert.test.tsx create mode 100644 components/ballotquestions/BallotQuestionAlert.tsx create mode 100644 components/ballotquestions/CampaignFinancialsTab.tsx create mode 100644 components/ballotquestions/ForAndAgainstTab.tsx create mode 100644 components/ballotquestions/SynthesisTab.tsx create mode 100644 components/homepage/DidYouKnowSection.tsx create mode 100644 components/homepage/ExplainerSection.tsx create mode 100644 components/homepage/FeaturesSection.tsx create mode 100644 components/homepage/HearingsSection.tsx create mode 100644 components/homepage/HeroSection.tsx create mode 100644 components/homepage/Homepage.module.css create mode 100644 docs/updating-ballot-questions.md create mode 100644 public/envelope.svg create mode 100644 public/handpen.svg create mode 100644 public/homepage/feature-1.svg create mode 100644 public/homepage/feature-2.svg create mode 100644 public/homepage/feature-3.svg create mode 100644 public/homepage/feature-preview-ballot-question.png create mode 100644 public/locales/en/ballotquestions.json create mode 100644 public/skyline_blue.svg create mode 100644 stories/organisms/ballotquestions/BallotQuestionAlert.stories.tsx create mode 100644 stories/organisms/ballotquestions/BallotQuestionDetails.stories.tsx create mode 100644 stories/organisms/ballotquestions/BrowseBallotQuestions.stories.tsx create mode 100644 stories/organisms/dashboard/ResourcesCard.stories.tsx create mode 100644 stories/organisms/hearing/HearingSidebar.stories.tsx create mode 100644 stories/organisms/homepage/HomepageSections.stories.tsx create mode 100644 stories/organisms/newsfeed/NewsfeedCard.stories.tsx delete mode 100644 stories_hold/organisms/pageElements/PageHeader.stories.tsx diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..209e3ef4b --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20 diff --git a/ballotQuestions/2024/23-12.yaml b/ballotQuestions/2024/23-12.yaml index e7163e81a..1716bb569 100644 --- a/ballotQuestions/2024/23-12.yaml +++ b/ballotQuestions/2024/23-12.yaml @@ -10,22 +10,69 @@ ballotQuestionNumber: 5 relatedBillIds: [] description: null atAGlance: null -fullSummary: |- +voteEffectYes: "A YES VOTE would increase the minimum hourly wage an employer must pay a tipped worker to the full state minimum wage implemented over five years, at which point employers could pool all tips and distribute them to all non-management workers." +voteEffectNo: "A NO VOTE would make no change in the law governing tip pooling or the minimum wage for tipped workers. " +fiscalConsequences: "There are no direct fiscal consequences on the Commonwealth or municipalities because they generally do not employ tipped employees. Nevertheless, this measure will affect proposed state and municipal revenues and expenditures due to impacts on employee and business income and earnings. While those impacts are difficult to project due to the lack of reliable data, increasing the minimum hourly wage of tipped employees will likely increase state income tax collections because employees will earn more in hourly wages from which state income tax is withheld. The impacts on gratuity earnings and gratuity tax reporting are unknown." +inFavor: |- + Vote Yes for FAIRNESS. It’s fair for Workers: Instead of being paid the + current tipped worker wage of just $6.75 an hour, Massachusetts tipped workers + deserve the full minimum wage with tips on top. Workers in 7 other states earn + a full wage plus tips, and they enjoy robust tips and growing restaurants where + menu prices are comparable to Massachusetts. This law would create greater + financial stability and predictability, acknowledging workers’ skills and + professionalism. It’s fair for Employers: Many Massachusetts small businesses + are already paying the full minimum wage plus tips. Big restaurant + corporations should do the same. This would reduce employee turnover and + improve service quality. It’s fair for Consumers: Big restaurant corporations + are not paying their fair share and are forcing consumers to cover their + employees’ wages through tips. Tips should be a reward for good service, not a + subsidy for low wages paid by large corporations. Estefania Galvis One Fair + Wage 11 Converse Ave Malden, MA 02148 813-898-9136 www.yeson5ma.com +supportCommittee: "One Fair Wage Plus Tips MA Committee 95513" +opposeCommittee: "Committee to Protect Tips 95521" +against: |- + This question is funded by a radical group from California. Tipped employees + have made it abundantly clear the way they earn money does not need to be + changed. State and Federal law guarantee them the $15 hourly minimum wage + with many earning over $40/hr and 90% reporting at least $20/hr. A recent + survey also showed that 88% oppose ‘tip pools’ where tips are shared with + non-service employees and 90% believe that if tipped wages are eliminated, + they will earn less. Other attempts to implement this have seen catastrophic + results. In Washington, D.C., nearly 10% of tipped employees have lost or + left their jobs. This follows increases in menu prices, the implementation of + 20% ‘service fees’ and a wave of closures. This would reduce overall wages + for servers, increase costs for restaurants and skyrocket the cost of eating + out. It will be disastrous with many neighborhood restaurants being forced to + close. Doug Bacon Former Server and Bartender, Current Restaurant Owner + Committee to Protect Tips 160 E Main St # 2 Westborough, MA 01581 + www.ProtectTips.org +campaignFinancials: + support: + - cashRaised: 889526.25 + spent: 889526.25 + inKind: 1036954.37 + oppose: + - cashRaised: 2518234.24 + spent: 2518234.24 + inKind: 658123.44 +fullSummary: >- This proposed law would gradually increase the minimum hourly wage an - employer must pay a tipped worker, over the course of five years, on the following - schedule: - To 64% of the state minimum wage on January 1, 2025; - To 73% of - the state minimum wage on January 1, 2026; - To 82% of the state minimum wage - on January 1, 2027; - To 91% of the state minimum wage on January 1, 2028; and - - To 100% of the state minimum wage on January 1, 2029. The proposed law - would require employers to continue to pay tipped workers the difference between - the state minimum wage and the total amount a tipped worker receives in hourly - wages plus tips through the end of 2028. The proposed law would also permit - employers to calculate this difference over the entire weekly or bi-weekly payroll - period. The requirement to pay this difference would cease when the required - hourly wage for tipped workers would become 100% of the state minimum wage - on January 1, 2029. Under the proposed law, if an employer pays its workers an - hourly wage that is at least the state minimum wage, the employer would be - permitted to administer a “tip pool” that combines all the tips given by customers to - tipped workers and distributes them among all the workers, including non-tipped - workers. + employer must pay a tipped worker, over the course of five years, on the + following schedule: + • To 64% of the state minimum wage on January 1, 2025; + • To 73% of the state minimum wage on January 1, 2026; + • To 82% of the state minimum wage on January 1, 2027; + • To 91% of the state minimum wage on January 1, 2028; and + • To 100% of the state minimum wage on January 1, 2029. + The proposed law would require employers to continue to pay tipped workers + the difference between the state minimum wage and the total amount a tipped + worker receives in hourly wages plus tips through the end of 2028. The + proposed law would also permit employers to calculate this difference over the + entire weekly or bi-weekly payroll period. The requirement to pay this + difference would cease when the required hourly wage for tipped workers would + become 100% of the state minimum wage on January 1, 2029. Under the + proposed law, if an employer pays its workers an hourly wage that is at least + the state minimum wage, the employer would be permitted to administer a “tip + pool” that combines all the tips given by customers to tipped workers and + distributes them among all the workers, including non-tipped workers. pdfUrl: "https://malegislature.gov/Bills/193/H4254.pdf" diff --git a/ballotQuestions/2024/23-13.yaml b/ballotQuestions/2024/23-13.yaml index e395fabe3..d33a6626c 100644 --- a/ballotQuestions/2024/23-13.yaml +++ b/ballotQuestions/2024/23-13.yaml @@ -10,57 +10,95 @@ ballotQuestionNumber: 4 relatedBillIds: [] description: null atAGlance: null -fullSummary: |- - This proposed law would allow persons aged 21 and older to grow, possess, and - use certain natural psychedelic substances in certain circumstances. The psychedelic - substances allowed would be two substances found in mushrooms (psilocybin and - psilocyn) and three substances found in plants (dimethyltryptamine, mescaline, and - ibogaine). These substances could be purchased at an approved location for use under the - supervision of a licensed facilitator. This proposed law would otherwise prohibit any retail - sale of natural psychedelic substances. This proposed law would also provide for the +voteEffectYes: "A YES VOTE would allow persons over age 21 to use certain natural psychedelic substances under licensed supervision and to grow and possess limited quantities of those substances in their home, and would create a commission to regulate those substances." +voteEffectNo: "A NO VOTE would make no change in the law regarding natural psychedelic substances." +fiscalConsequences: "This measure would establish a 15% state excise tax for the sale of natural psychedelic substances, which would be available for spending from a dedicated fund; however, the revenue generating impact is unknown due to the lack of data for the new market being proposed. This measure would also allow for a local tax option that could generate local sales tax revenue. This measure would also create an oversight commission that would require dedicated resources to execute its duties and responsibilities. The costs of establishing and operating the commission would need to be developed and would be subject to appropriation." +inFavor: |- + Vote YES on 4 to provide safe, regulated access to promising natural + psychedelic medicines for treatment-resistant PTSD, anxiety, and depression. + Psychedelics will be available in approved therapeutic settings under the + supervision of trained and licensed facilitators, NOT sold in stores to take + home. +supportCommittee: "Massachusetts for Mental Health Options 95505" +opposeCommittee: "Coalition for Safe Communities 95522" +against: |- + MEDICAL AND MENTAL HEALTH PROFESSIONALS, VETERANS, AND RECOVERY GROUPS URGE + NO ON QUESTION 4. Research from leading medical institutions including Mass + General Brigham, Dana Farber Cancer Institute, and Johns Hopkins shows that + psychedelic medicines can be effective treatments for depression and anxiety. + In fact, the FDA recently granted psilocybin a “breakthrough therapy” + designation. For many people who are suffering, daily medications and other + standard treatments aren’t working. Over 6,000 veterans die by suicide + annually, and countless more struggle from service-related trauma. Natural + psychedelic medicine can also offer patients with a terminal diagnosis relief + from end-of-life anxiety and help them find peace. That’s why question 4 is + supported by doctors, mental health providers, and veteran advocates. Vote YES + to expand mental health options. Lieutenant Sarko Gergerian, Mental Health + Counselor (MHC) Massachusetts for Mental Health Options 14 Sullivan Street + Boston, MA 02129 781-205-9737 https://maformentalhealth.org +campaignFinancials: + support: + - cashRaised: 7752198.94 + spent: 7752198.94 + inKind: 1246724.32 + oppose: + - cashRaised: 137072.5 + spent: 129158.9 + inKind: 0 +fullSummary: >- + This proposed law would allow persons aged 21 and older to grow, possess, + and use certain natural psychedelic substances in certain circumstances. The + psychedelic substances allowed would be two substances found in mushrooms + (psilocybin and psilocyn) and three substances found in plants + (dimethyltryptamine, mescaline, and ibogaine). These substances could be + purchased at an approved location for use under the supervision of a licensed + facilitator. This proposed law would otherwise prohibit any retail sale of + natural psychedelic substances. This proposed law would also provide for the regulation and taxation of these psychedelic substances. - - This proposed law would license and regulate facilities offering supervised use of - these psychedelic substances and provide for the taxation of proceeds from those facilities’ - sales of psychedelic substances. It would also allow persons aged 21 and older to grow - these psychedelic substances in a 12-foot by 12-foot area at their home and use these - psychedelic substances at their home. This proposed law would authorize persons aged 21 - or older to possess up to one gram of psilocybin, one gram of psilocyn, one gram of - dimethyltryptamine, 18 grams of mescaline, and 30 grams of ibogaine (“personal use - amount”), in addition to whatever they might grow at their home, and to give away up to - the personal use amount to a person aged 21 or over. - - This proposed law would create a Natural Psychedelic Substances Commission of - five members appointed by the Governor, Attorney General, and Treasurer which would - administer the law governing the use and distribution of these psychedelic substances. The - Commission would adopt regulations governing licensing qualifications, security, - recordkeeping, education and training, health and safety requirements, testing, and age - verification. This proposed law would also create a Natural Psychedelic Substances - Advisory Board of 20 members appointed by the Governor, Attorney General, and - Treasurer which would study and make recommendations to the Commission on the - regulation and taxation of these psychedelic substances. - - This proposed law would allow cities and towns to reasonably restrict the time, - place, and manner of the operation of licensed facilities offering psychedelic substances, - but cities and towns could not ban those facilities or their provision of these substances. + This proposed law would license and regulate facilities offering supervised use + of these psychedelic substances and provide for the taxation of proceeds from + those facilities’ sales of psychedelic substances. It would also allow persons + aged 21 and older to grow these psychedelic substances in a 12-foot by + 12-foot area at their home and use these psychedelic substances at their + home. This proposed law would authorize persons aged 21 or older to possess + up to one gram of psilocybin, one gram of psilocyn, one gram of + dimethyltryptamine, 18 grams of mescaline, and 30 grams of ibogaine + (“personal use amount”), in addition to whatever they might grow at their + home, and to give away up to the personal use amount to a person aged 21 or + over. + This proposed law would create a Natural Psychedelic Substances Commission + of five members appointed by the Governor, Attorney General, and Treasurer + which would administer the law governing the use and distribution of these + psychedelic substances. The Commission would adopt regulations governing + licensing qualifications, security, recordkeeping, education and training, + health and safety requirements, testing, and age verification. This proposed + law would also create a Natural Psychedelic Substances Advisory Board of 20 + members appointed by the Governor, Attorney General, and Treasurer which + would study and make recommendations to the Commission on the regulation + and taxation of these psychedelic substances. + This proposed law would allow cities and towns to reasonably restrict the + time, place, and manner of the operation of licensed facilities offering + psychedelic substances, but cities and towns could not ban those facilities or + their provision of these substances. The proceeds of sales of psychedelic substances at licensed facilities would be - subject to the state sales tax and an additional excise tax of 15 percent. In addition, a city or - town could impose a separate tax of up to two percent. Revenue received from the - additional state excise tax, license application fees, and civil penalties for violations of this - proposed law would be deposited in a Natural Psychedelic Substances Regulation Fund - and would be used, subject to appropriation, for administration of this proposed law. - Using the psychedelic substances as permitted by this proposed law could not be a - basis to deny a person medical care or public assistance, impose discipline by a - professional licensing board, or enter adverse orders in child custody cases absent clear - and convincing evidence that the activities created an unreasonable danger to the safety of - a minor child. - - This proposed law would not affect existing laws regarding the operation of motor - vehicles while under the influence, or the ability of employers to enforce workplace - policies restricting the consumption of these psychedelic substances by employees. This - proposed law would allow property owners to prohibit the use, display, growing, - processing, or sale of these psychedelic substances on their premises. State and local governments could continue to restrict the possession and use of these psychedelic - substances in public buildings or at schools. - - This proposed law would take effect on December 15, 2024 + subject to the state sales tax and an additional excise tax of 15 percent. In + addition, a city or town could impose a separate tax of up to two percent. + Revenue received from the additional state excise tax, license application + fees, and civil penalties for violations of this proposed law would be deposited + in a Natural Psychedelic Substances Regulation Fund and would be used, + subject to appropriation, for administration of this proposed law. + Using the psychedelic substances as permitted by this proposed law could not + be a basis to deny a person medical care or public assistance, impose + discipline by a professional licensing board, or enter adverse orders in child + custody cases absent clear and convincing evidence that the activities created + an unreasonable danger to the safety of a minor child. + This proposed law would not affect existing laws regarding the operation of + motor vehicles while under the influence, or the ability of employers to + enforce workplace policies restricting the consumption of these psychedelic + substances by employees. This proposed law would allow property owners to + prohibit the use, display, growing, processing, or sale of these psychedelic + substances on their premises. State and local governments could continue to + restrict the possession and use of these psychedelic substances in public + buildings or at schools. + This proposed law would take effect on December 15, 2024. pdfUrl: "https://malegislature.gov/Bills/193/H4255.pdf" diff --git a/ballotQuestions/2024/23-25.yaml b/ballotQuestions/2024/23-25.yaml index 994a67a51..b97054950 100644 --- a/ballotQuestions/2024/23-25.yaml +++ b/ballotQuestions/2024/23-25.yaml @@ -10,50 +10,91 @@ ballotQuestionNumber: 3 relatedBillIds: [] description: null atAGlance: null -fullSummary: |- - The proposed law would provide Transportation Network Drivers (“Drivers”) with the - right to form unions (“Driver Organizations”) to collectively bargain with Transportation - Network Companies (“Companies”)-which are companies that use a digital network to connect - riders to drivers for pre-arranged transportation-to create negotiated recommendations - concerning wages, benefits and terms and conditions of work. Drivers would not be required to - engage in any union activities. Companies would be allowed to form multi-Company - associations to represent them when negotiating with Driver Organizations. The state would - supervise the labor activities permitted by the proposed law and would have responsibility for - approving or disapproving the negotiated recommendations. The proposed law would define - certain activities by a Company or a Driver Organization to be unfair work practices. The - proposed law would establish a hearing process for the state Employment Relations Board - (“Board”) to follow when a Company or Driver Organization is charged with an unfair work - practice. The proposed law would permit the Board to take action, including awarding - compensation to adversely affected Drivers, if it found that an unfair work practice had been - committed. The proposed law would provide for an appeal of a Board decision to the state - Appeals Court. - - This proposed law also would establish a procedure for determining which Drivers are - Active Drivers, meaning that they completed more than the median number of rides in the - previous six months. The proposed law would establish procedures for the Board to determine - that a Driver Organization has signed authorizations from at least five percent of Active Drivers, - entitling the Driver Organization to a list of Active Drivers; to designate a Driver Organization - as the exclusive bargaining representative for all Drivers based on signed authorizations from at - least twenty-five percent of Active Drivers; to resolve disputes over exclusive bargaining status, - including through elections; and to decertify a Driver Organization from exclusive bargaining - status. A Driver Organization that has been designated the exclusive bargaining representative - would have the exclusive right to represent the Drivers and to receive voluntary membership - dues deductions. Once the Board determined that a Driver Organization was the exclusive - bargaining representative for all Drivers, the Companies would be required to bargain with that - Driver Organization concerning wages, benefits and terms and conditions of work. Once the - Driver Organization and Companies reached agreement on wages, benefits, and the terms and - conditions of work, that agreement would be voted upon by all Drivers who has completed at - least 100 trips the previous quarter. If approved by a majority of votes cast, the recommendations - would be submitted to the state Secretary of Labor for approval and if approved, would be - effective for three years. The proposed law would establish procedures for the mediation and - arbitration if the Driver Organization and Companies failed to reach agreement within a certain - period of time. An arbitrator would consider factors set forth in the proposed law, including - whether the wages of Drivers would be enough so that Drivers would not need to rely upon any - public benefits. The proposed law also sets out procedures for the Secretary of Labor’s review - and approval of recommendations negotiated by a Driver Organization and the Companies and - for judicial review of the Secretary’s decision. The proposed law states that neither its - provisions, an agreement nor a determination by the Secretary would be able to lessen labor - standards established by other laws. If there were any conflict between the proposed law and existing Massachusetts labor relations law, the proposed law would prevail. The Board would - make rules and regulations as appropriate to effectuate the proposed law. The proposed law - states that, if any of its parts were declared invalid, the other parts would stay in effect. +voteEffectYes: "A YES VOTE would provide transportation network drivers the option to form unions to collectively bargain with transportation network companies regarding wages, benefits, and terms and conditions of work." +voteEffectNo: "A NO VOTE would make no change in the law relative to the ability of transportation network drivers to form unions." +fiscalConsequences: "The proposed law has no discernible material fiscal consequences for state and municipal government finances." +inFavor: |- + A YES vote will give Massachusetts rideshare drivers, who work for companies + like Uber and Lyft, the option to join a union while also maintaining driver + flexibility and independence. The option to join a union is guaranteed for + most workers, but rideshare drivers currently don’t have that choice. Vote + YES to allow rideshare drivers the option to choose a union. +supportCommittee: "United for Justice 95509" +opposeCommittee: null +against: |- + DRIVERS AND RIDERS URGE NO ON QUESTION 3. Question 3 would RAISE THE PRICES + FOR ALL RIDERS, funding union pockets, not drivers’ pockets. This law gives + Politicians the right to set rules with NO accountability and creates a new + radical labor category that is inconsistent with federal labor law. Drivers in + Massachusetts ALREADY receive: Base of $32.50 per hour with yearly increases, + Paid Sick Leave, Paid Family Medical Leave, Healthcare Stipend, On-the-Job + Injury Insurance, Anti-Discrimination Protections, Domestic Violence Leave, + Anti-Retaliation Protections, Appeals Process. Question 3 does not really + create bargaining for workers. Drivers will have no control over leadership of + the union and will pay significant dues without real representation. This + proposal is not fair to Drivers and allows just 2 ½ percent of drivers to + force unionization and leaves many Drivers without a voice. Vote No on + Question 3. +campaignFinancials: + support: + - cashRaised: 7287547.9 + spent: 7285148.82 + inKind: 583831.27 + oppose: [] +fullSummary: >- + The proposed law would provide Transportation Network Drivers (“Drivers”) with + the right to form unions (“Driver Organizations”) to collectively bargain with + Transportation Network Companies (“Companies”)-which are companies that use a + digital network to connect riders to drivers for pre-arranged transportation-to + create negotiated recommendations concerning wages, benefits and terms and + conditions of work. Drivers would not be required to engage in any union + activities. Companies would be allowed to form multi-Company associations to + represent them when negotiating with Driver Organizations. The state would + supervise the labor activities permitted by the proposed law and would have + responsibility for approving or disapproving the negotiated recommendations. + The proposed law would define certain activities by a Company or a Driver + Organization to be unfair work practices. The proposed law would establish a + hearing process for the state Employment Relations Board (“Board”) to follow + when a Company or Driver Organization is charged with an unfair work practice. + The proposed law would permit the Board to take action, including awarding + compensation to adversely affected Drivers, if it found that an unfair work + practice had been committed. The proposed law would provide for an appeal of a + Board decision to the state Appeals Court. + This proposed law also would establish a procedure for determining which Drivers + are Active Drivers, meaning that they completed more than the median number of + rides in the previous six months. The proposed law would establish procedures + for the Board to determine that a Driver Organization has signed authorizations + from at least five percent of Active Drivers, entitling the Driver Organization + to a list of Active Drivers; to designate a Driver Organization as the exclusive + bargaining representative for all Drivers based on signed authorizations from at + least twenty-five percent of Active Drivers; to resolve disputes over exclusive + bargaining status, including through elections; and to decertify a Driver + Organization from exclusive bargaining status. A Driver Organization that has + been designated the exclusive bargaining representative would have the exclusive + right to represent the Drivers and to receive voluntary membership dues + deductions. Once the Board determined that a Driver Organization was the + exclusive bargaining representative for all Drivers, the Companies would be + required to bargain with that Driver Organization concerning wages, benefits and + terms and conditions of work. Once the Driver Organization and Companies reached + agreement on wages, benefits, and the terms and conditions of work, that + agreement would be voted upon by all Drivers who has completed at least 100 + trips the previous quarter. If approved by a majority of votes cast, the + recommendations would be submitted to the state Secretary of Labor for approval + and if approved, would be effective for three years. The proposed law would + establish procedures for the mediation and arbitration if the Driver Organization + and Companies failed to reach agreement within a certain period of time. An + arbitrator would consider factors set forth in the proposed law, including + whether the wages of Drivers would be enough so that Drivers would not need to + rely upon any public benefits. The proposed law also sets out procedures for the + Secretary of Labor’s review and approval of recommendations negotiated by a + Driver Organization and the Companies and for judicial review of the + Secretary’s decision. + The proposed law states that neither its provisions, an agreement nor a + determination by the Secretary would be able to lessen labor standards + established by other laws. If there were any conflict between the proposed law + and existing Massachusetts labor relations law, the proposed law would prevail. + The Board would make rules and regulations as appropriate to effectuate the + proposed law. + The proposed law states that, if any of its parts were declared invalid, the + other parts would stay in effect. pdfUrl: "https://malegislature.gov/Bills/193/H4253.pdf" diff --git a/ballotQuestions/2024/23-26.yaml b/ballotQuestions/2024/23-26.yaml deleted file mode 100644 index 2f11b924e..000000000 --- a/ballotQuestions/2024/23-26.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# ballotQuestions/23-26.yaml -id: "23-26" -billId: "H4252" -title: "Elimination of MCAS as High School Graduation Requirement" -court: 193 -electionYear: 2024 -type: initiative_statute -ballotStatus: accepted -ballotQuestionNumber: 2 -relatedBillIds: [] -description: null -atAGlance: null -fullSummary: |- - This proposed law would eliminate the requirement that a student pass the Massachusetts - Comprehensive Assessment System (MCAS) tests (or other statewide or district-wide - assessments) in mathematics, science and technology, and English in order to receive a high - school diploma. Instead, in order for a student to receive a high school diploma, the proposed - law would require the student to complete coursework certified by the student’s district as - demonstrating mastery of the competencies contained in the state academic standards in - mathematics, science and technology, and English, as well as any additional areas determined by - the Board of Elementary and Secondary Education. -pdfUrl: "https://malegislature.gov/Bills/193/H4252.pdf" diff --git a/ballotQuestions/2024/23-34.yaml b/ballotQuestions/2024/23-34.yaml index b44f46fb7..0ab55cd1e 100644 --- a/ballotQuestions/2024/23-34.yaml +++ b/ballotQuestions/2024/23-34.yaml @@ -10,5 +10,22 @@ ballotQuestionNumber: 1 relatedBillIds: [] description: null atAGlance: null -fullSummary: "This proposed law would specify that the State Auditor has the authority to audit the Legislature." +voteEffectYes: "A YES VOTE would specify that the State Auditor has the authority to audit the Legislature. " +voteEffectNo: "A NO VOTE would make no change in the law relative to the State Auditor’s authority." +fiscalConsequences: "The proposed law has no discernible material fiscal consequences for state and municipal government finances." +inFavor: |- + A YES vote expressly authorizes the State Auditor to audit the Legislature. +supportCommittee: "Committee for Transparent Democracy 95510" +opposeCommittee: null +against: |- + A NO vote would make no change in the law relative to the State Auditor’s authority. +campaignFinancials: + support: + - cashRaised: 419213.7 + spent: 419213.7 + inKind: 42248.44 + oppose: [] +fullSummary: >- + This proposed law would specify that the State Auditor has the authority to + audit the Legislature. pdfUrl: "https://malegislature.gov/Bills/193/H4251.pdf" diff --git a/ballotQuestions/2024/23-36.yaml b/ballotQuestions/2024/23-36.yaml new file mode 100644 index 000000000..35c92296c --- /dev/null +++ b/ballotQuestions/2024/23-36.yaml @@ -0,0 +1,66 @@ +# ballotQuestions/23-36.yaml +id: "23-36" +billId: "H4252" +title: "Elimination of MCAS as High School Graduation Requirement" +court: 193 +electionYear: 2024 +type: initiative_statute +ballotStatus: accepted +ballotQuestionNumber: 2 +relatedBillIds: [] +description: null +atAGlance: null +voteEffectYes: "A YES VOTE would eliminate the requirement that students pass the Massachusetts Comprehensive Assessment System (MCAS) in order to graduate high school but still require students to complete coursework that meets state standards." +voteEffectNo: "A NO Vote would make no change in the law relative to the requirement that a student pass the MCAS in order to graduate high school." +fiscalConsequences: "The proposed law has no discernible material fiscal consequences for state and municipal government finances." +inFavor: |- + A Yes on Question 2 gives all students the opportunity to thrive and reach + their full potential. We all agree that high standards help keep our public + schools great, and assessments are needed to ensure that students master the + knowledge and skills to succeed in life after high school. However, the MCAS + is a one-size-fits-all exam that fails to measure other student achievement + measures such as GPA, coursework, and teacher assessments in determining if a + student is allowed to graduate. Replacing the MCAS graduation requirement + with more comprehensive measures will allow teachers to stop teaching to a + test and unburden students from a make-or-break standardized test. Voting Yes + will allow schools and teachers, together with parents and students, to focus + on the most important skills and knowledge to help students succeed in life, + rather than having to focus on only those skills that can be measured on a + standardized test. +supportCommittee: "Committee for High Standards Not High Stakes 95507" +opposeCommittee: "Protect Our Kids' Future: Vote No on 2 95518" +against: |- + Vote NO on Question 2. Question 2 is unfair to kids and will increase + inequality. Some school districts will just adopt lower standards so students + “graduate” even if they haven’t learned the knowledge and skills they need to + succeed. It’s not fair to grant diplomas to kids who aren’t yet ready to + graduate. If students cannot pass basic assessments in math, English, or + science, we adults should do the hard work to get them up to speed. Instead + of supporting kids, Question 2 would abandon them. Question 2 would remove + our only statewide graduation standard. Massachusetts would have less + rigorous high school graduation requirements than Mississippi and Alabama. + Question 2 is a radical and untested proposal and should be rejected. + Significant changes to our education system should be carefully studied, + designed, and implemented by experts to ensure these policies are actually + better for our kids. Vote No on Question 2. +campaignFinancials: + support: + - cashRaised: 950000 + spent: 950000 + inKind: 15604360.49 + oppose: + - cashRaised: 5318307.02 + spent: 5318307.02 + inKind: 93763.81 +fullSummary: >- + This proposed law would eliminate the requirement that a student pass the + Massachusetts Comprehensive Assessment System (MCAS) tests (or other statewide + or district-wide assessments) in mathematics, science and technology, and + English in order to receive a high school diploma. Instead, in order for a + student to receive a high school diploma, the proposed law would require the + student to complete coursework certified by the student’s district as + demonstrating mastery of the competencies contained in the state academic + standards in mathematics, science and technology, and English, as well as any + additional areas determined by the Board of Elementary and Secondary + Education. +pdfUrl: "https://malegislature.gov/Bills/193/H4252.pdf" diff --git a/ballotQuestions/2026/24-firearms-referendum.yaml b/ballotQuestions/2026/24-firearms-referendum.yaml index 3fe006b41..89171896c 100644 --- a/ballotQuestions/2026/24-firearms-referendum.yaml +++ b/ballotQuestions/2026/24-firearms-referendum.yaml @@ -15,11 +15,21 @@ title: "Referendum on the 2024 firearms law (Chapter 135)" court: 193 electionYear: 2026 type: referendum -ballotStatus: certified +ballotStatus: "expectedOnBallot" ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: null +alertTip: null atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "The Civil Rights Coalition (Toby Leary, Chair; Gun Owners' Action League)" +opposeCommittee: "MA Coalition to Prevent Gun Violence (Ruth Zakarin, Exec. Dir. & Committee Chair)" +campaignFinancials: null fullSummary: |- This referendum asks voters whether to repeal Chapter 135 of the Acts of 2024, "An Act Modernizing Firearm Laws," an omnibus law passed by the Legislature diff --git a/ballotQuestions/2026/25-03.yaml b/ballotQuestions/2026/25-03.yaml index ac49665e7..ff8e93233 100644 --- a/ballotQuestions/2026/25-03.yaml +++ b/ballotQuestions/2026/25-03.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: null +alertTip: null atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Legalize Starter Homes (Pioneer Institute / Andrew Mikula)" +opposeCommittee: null +campaignFinancials: null fullSummary: |- This proposed law would allow single-family homes to be built in a residentially zoned area as long as the land on which it is to be constructed is at least 5,000 square feet, has at least diff --git a/ballotQuestions/2026/25-08.yaml b/ballotQuestions/2026/25-08.yaml index cf8f4cba6..794423557 100644 --- a/ballotQuestions/2026/25-08.yaml +++ b/ballotQuestions/2026/25-08.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: null +alertTip: null atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Sec. of State Bill Galvin's office campaign" +opposeCommittee: null +campaignFinancials: null fullSummary: |- This proposed law would permit eligible individuals to register to vote or update their voter registration address on Election Day. diff --git a/ballotQuestions/2026/25-10.yaml b/ballotQuestions/2026/25-10.yaml index 8e6c59998..5af22eea8 100644 --- a/ballotQuestions/2026/25-10.yaml +++ b/ballotQuestions/2026/25-10.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: null +alertTip: null atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Coalition for a Healthy Massachusetts (Wendy Wakeman, Spokesperson; Caroline Cunningham, MassGOP)" +opposeCommittee: "Massachusetts Cannabis Business Association (David O'Brien, CEO) + cannabis industry" +campaignFinancials: null fullSummary: |- The proposed law would change the type and amount of marijuana that may legally be possessed in Massachusetts by repealing the laws that legalize, regulate, and tax the retail sale of diff --git a/ballotQuestions/2026/25-12.yaml b/ballotQuestions/2026/25-12.yaml index 1453443ef..9dbb666ca 100644 --- a/ballotQuestions/2026/25-12.yaml +++ b/ballotQuestions/2026/25-12.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: "Active legal challenge" +alertTip: "Dem. State Committee members Jackson & Roosevelt have filed a lawsuit with the Massachusetts Supreme Judicial Court." atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Coalition for Healthy Democracy (Jesse Littlewood, Campaign Mgr.)" +opposeCommittee: null +campaignFinancials: null fullSummary: |- This proposed law would eliminate political party primaries for state elections and instead establish a system where there would be a single, all-party primary in which all diff --git a/ballotQuestions/2026/25-14.yaml b/ballotQuestions/2026/25-14.yaml index e22a3b2b6..2d24b4018 100644 --- a/ballotQuestions/2026/25-14.yaml +++ b/ballotQuestions/2026/25-14.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: "Advisory opinion requested from Massachusetts Supreme Judicial Court" +alertTip: "MA Senate requested an opinion on whether this question violates Legislature's authority over its own rules" atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Coalition for Healthy Democracy / Auditor Diana DiZoglio" +opposeCommittee: null +campaignFinancials: null fullSummary: |- This proposed law would make most records held by the Legislature and the Office of the Governor public records under the Massachusetts Public Records Law. This proposed law would diff --git a/ballotQuestions/2026/25-15.yaml b/ballotQuestions/2026/25-15.yaml index 4ae8eb31c..f2c5814ed 100644 --- a/ballotQuestions/2026/25-15.yaml +++ b/ballotQuestions/2026/25-15.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: null +alertTip: null atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: null +opposeCommittee: null +campaignFinancials: null fullSummary: |- This proposed law would establish a Nature for All Fund that, subject to appropriation by the Legislature, would receive 50% of state taxes collected from the sale and use of sporting diff --git a/ballotQuestions/2026/25-17.yaml b/ballotQuestions/2026/25-17.yaml index c441e9e3b..9e9f561c4 100644 --- a/ballotQuestions/2026/25-17.yaml +++ b/ballotQuestions/2026/25-17.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: null +alertTip: null atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Massachusetts Opportunity Alliance (w/ Pioneer Institute)" +opposeCommittee: "Protect Massachusetts' Future (SEIU MA State Council)" +campaignFinancials: null fullSummary: |- This proposed law would change the limit on how much revenue the state can collect in a given year. The proposal would limit state revenue in a given year to the net amount of state diff --git a/ballotQuestions/2026/25-18.yaml b/ballotQuestions/2026/25-18.yaml index 7bb26ea8f..8cb3b029b 100644 --- a/ballotQuestions/2026/25-18.yaml +++ b/ballotQuestions/2026/25-18.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: null +alertTip: null atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Massachusetts Opportunity Alliance (w/ MA High Technology Council & Pioneer Institute)" +opposeCommittee: "Protect Massachusetts' Future (SEIU MA State Council)" +campaignFinancials: null fullSummary: |- This proposed law would, over a period of three years, lower the tax rates on (1) personal taxable income consisting of interest and dividends, and (2) personal taxable income other than diff --git a/ballotQuestions/2026/25-21.yaml b/ballotQuestions/2026/25-21.yaml index dcc6ff5c2..6f11f9fb2 100644 --- a/ballotQuestions/2026/25-21.yaml +++ b/ballotQuestions/2026/25-21.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: "Active legal challenge - ruling expected in late July" +alertTip: "Opposition Committee has filed a lawsuit with the Massachusetts Supreme Judicial Court." atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Keep Massachusetts Home (Homes for All MA coalition)" +opposeCommittee: "Housing for Massachusetts (Greater Boston Real Estate Board + MA Realtors + NAIOP MA)" +campaignFinancials: null fullSummary: |- This proposed law would limit the annual rent increase for residential units in Massachusetts to the annual increase in the Consumer Price Index for a 12-month period, or 5%, diff --git a/ballotQuestions/2026/25-22.yaml b/ballotQuestions/2026/25-22.yaml index a69b13e9d..36f8c7d2e 100644 --- a/ballotQuestions/2026/25-22.yaml +++ b/ballotQuestions/2026/25-22.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: null +alertTip: null atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "SEIU Local 888" +opposeCommittee: null +campaignFinancials: null fullSummary: |- This proposed law would specify that employees of the Committee for Public Counsel Services (“CPCS”) are permitted to engage in collective bargaining with their employer. It would diff --git a/ballotQuestions/2026/25-37.yaml b/ballotQuestions/2026/25-37.yaml index 5abb2c8fd..e0ebe44cf 100644 --- a/ballotQuestions/2026/25-37.yaml +++ b/ballotQuestions/2026/25-37.yaml @@ -9,7 +9,17 @@ ballotStatus: expectedOnBallot ballotQuestionNumber: null relatedBillIds: [] description: null +alertFlag: "Advisory opinion requested from Massachusetts Supreme Judicial Court" +alertTip: "MA Senate requested an opinion on whether this question is an unconstitutional mandate on internal legislative procedures" atAGlance: null +voteEffectYes: null +voteEffectNo: null +fiscalConsequences: null +inFavor: null +against: null +supportCommittee: "Coalition to Reform Our Legislature (CROL) (John Lippitt, Chair)" +opposeCommittee: null +campaignFinancials: null fullSummary: |- This proposed law would change the method for calculating stipends paid to certain state legislators on top of their base salaries. diff --git a/components/AboutSection/AboutSection.tsx b/components/AboutSection/AboutSection.tsx deleted file mode 100644 index 07debd0e3..000000000 --- a/components/AboutSection/AboutSection.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import styled from "styled-components" -import AboutInfoCard from "../AboutSectionInfoCard/AboutInfoCard" -import { Col, Container, Row } from "../bootstrap" -import BackgroundLogo from "../LogoPlacements/BackgroundLogo" -import ScrollTrackerContainer from "../ScrollTrackEffect/ScrollTrackerContainer" -import ScrollTrackingItem from "../ScrollTrackEffect/ScrollTrackerItem" -import { useTranslation } from "next-i18next" - -const AngledTopRow = styled(Row)` - padding-top: 10em; - padding-bottom: 8em; - z-index: 1; - clip-path: polygon(0 10%, 100% 0, 100% 100%, 0 100%); -` - -export default function AboutSection() { - const { t } = useTranslation("homepage") - - return ( - - - - - - - - - - -

{t("About_MAPLE")}

- - - - - - - - - - -
-
-
- ) -} diff --git a/components/AboutSectionInfoCard/AboutInfoCard.tsx b/components/AboutSectionInfoCard/AboutInfoCard.tsx deleted file mode 100644 index 3f7b42d9c..000000000 --- a/components/AboutSectionInfoCard/AboutInfoCard.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Card, Col } from "react-bootstrap" -import styled from "styled-components" - -export type AboutInfoCardProps = { - title: string - bodytext: string - options?: {} -} - -const StyledCardHeader = styled(Card.Header)` - transform: translateY(-40%); -` - -const StyledCardBody = styled(Card.Body)` - height: fit-content; -` - -export default function AboutInfoCard({ title, bodytext }: AboutInfoCardProps) { - return ( - - - - {title} - - -

{bodytext}

-
-
- - ) -} diff --git a/components/AnnouncementBanner/AnnouncementBanner.tsx b/components/AnnouncementBanner/AnnouncementBanner.tsx index 6e678c1c2..663bfb032 100644 --- a/components/AnnouncementBanner/AnnouncementBanner.tsx +++ b/components/AnnouncementBanner/AnnouncementBanner.tsx @@ -30,7 +30,11 @@ function AnnouncementBanner({ > diff --git a/components/AnnouncementBanner/TranscriptAnnouncement.tsx b/components/AnnouncementBanner/TranscriptAnnouncement.tsx index 8970bbfb5..b4f12dc73 100644 --- a/components/AnnouncementBanner/TranscriptAnnouncement.tsx +++ b/components/AnnouncementBanner/TranscriptAnnouncement.tsx @@ -11,7 +11,7 @@ function TranscriptAnnouncement() { {t("announcement.headingBody")}
{t("announcement.description")}{" "} - + {t("announcement.link")} diff --git a/components/BillStatusCard/BillStatusCard.tsx b/components/BillStatusCard/BillStatusCard.tsx index 02a31227e..8e3302fb4 100644 --- a/components/BillStatusCard/BillStatusCard.tsx +++ b/components/BillStatusCard/BillStatusCard.tsx @@ -39,10 +39,10 @@ const HandleBranchStyle = (branchStyle: string) => { var returnStyle switch (branchStyle) { case "HOUSE": - returnStyle = { backgroundColor: "#1a3185" } + returnStyle = { backgroundColor: "var(--maple-brand-primary)" } break case "SENATE": - returnStyle = { backgroundColor: "#A92929" } + returnStyle = { backgroundColor: "var(--maple-brand-senate)" } break default: returnStyle = { @@ -102,7 +102,7 @@ const ScrollStyle = styled.div` /* Handle */ ::-webkit-scrollbar-thumb { - background: #d9d9d9; + background: var(--maple-border-default); border-radius: 10px; } ` diff --git a/components/Card/Card.tsx b/components/Card/Card.tsx index 3a68788bc..dd3a165d0 100644 --- a/components/Card/Card.tsx +++ b/components/Card/Card.tsx @@ -1,9 +1,18 @@ import { ReactElement, useState } from "react" import CardBootstrap from "react-bootstrap/Card" +import styled from "styled-components" import { CardListItems, ListItem } from "./CardListItem" import { CardTitle } from "./CardTitle" import { SeeMore } from "./SeeMore" +const SurfaceCard = styled(CardBootstrap)` + background-color: var(--maple-surface-base); + border: 1px solid var(--maple-surface-border); + border-radius: var(--maple-radius-lg); + box-shadow: var(--maple-shadow-sm); + overflow: hidden; +` + interface CardItem { billName: string billNameElement?: ReactElement | undefined @@ -92,13 +101,13 @@ export const Card = (CardProps: CardProps) => { const shown = showAll ? allItems : allItems.slice(0, initialRowCount) return ( - + {headerContent} {} {bodyContent} {allItems.length > initialRowCount && ( )} - + ) } diff --git a/components/EditProfilePage/StyledEditProfileComponents.tsx b/components/EditProfilePage/StyledEditProfileComponents.tsx index 37e17f488..175f6d36a 100644 --- a/components/EditProfilePage/StyledEditProfileComponents.tsx +++ b/components/EditProfilePage/StyledEditProfileComponents.tsx @@ -23,7 +23,7 @@ export const StyledTabNav = styled(Nav).attrs(props => ({ color: var(--bs-dark); .nav-link.active { - color: #c71e32; + color: var(--maple-brand-danger); } .nav-link { @@ -53,7 +53,7 @@ export const TabNavLink = styled(Nav.Link).attrs(props => ({ className: `rounded-top m-0 p-0 ${props.className}` }))` &.active { - color: #c71e32; + color: var(--maple-brand-danger); } ` diff --git a/components/FollowingCard/FollowingCard.tsx b/components/FollowingCard/FollowingCard.tsx index ffa66b89d..e5ca9be47 100644 --- a/components/FollowingCard/FollowingCard.tsx +++ b/components/FollowingCard/FollowingCard.tsx @@ -27,8 +27,8 @@ const Link = styled.a` const Item = styled.div` display: flex; align-items: center; - gap: 16px; - padding: 9px 22px; + gap: var(--maple-space-lg); + padding: var(--maple-space-sm) var(--maple-space-xl); ` export const FollowingCard: FC> = ({ diff --git a/components/Footer/Footer.tsx b/components/Footer/Footer.tsx index 97bc9b9e9..ce5063afa 100644 --- a/components/Footer/Footer.tsx +++ b/components/Footer/Footer.tsx @@ -24,37 +24,37 @@ export type PageFooterProps = { const TextHeader = styled.h6` font-size: 1rem; font-weight: bold; - color: #fff; + color: var(--maple-text-inverse); padding: 0.5rem 1rem 0 0; margin: 0; ` const BrowseHeader = styled(NavLink)` font-size: 1rem; - color: #fff; + color: var(--maple-text-inverse); padding: 0.5rem 1rem 0 0; - margin: 0 0 10px 0; + margin: 0 0 var(--maple-space-sm) 0; @media (max-width: 768px) { - padding-bottom: 0.6rem; - border-bottom: solid 1.5px rgba(255, 255, 255, 0.75); + padding-bottom: var(--maple-space-sm); + border-bottom: solid 1.5px var(--maple-border-inverse-soft); margin: 0; } &:hover { - color: white; + color: var(--maple-text-inverse); text-decoration: underline 1.5px; } ` const StyledInternalLink = styled(NavLink)` - color: rgba(255, 255, 255, 0.55); + color: var(--maple-text-inverse-muted); letter-spacing: -0.63px; - padding-top: 4; - margin: 5px 0; + padding-top: var(--maple-space-xs); + margin: var(--maple-space-xs) 0; &:hover { - color: white; + color: var(--maple-text-inverse); text-decoration: none; } ` @@ -64,13 +64,19 @@ function MapleContainer({ className }: { className?: string }) { return (
-

{t("headers.follow")}

+

+ {t("headers.follow")} +

-
+
{t("legal.disclaimer")} {" - "} diff --git a/components/Footer/FooterContainer.tsx b/components/Footer/FooterContainer.tsx index 77bc21e39..266cc483d 100644 --- a/components/Footer/FooterContainer.tsx +++ b/components/Footer/FooterContainer.tsx @@ -15,17 +15,17 @@ export const FooterContainer = styled(Container)` display: flex; flex-grow: 1; justify-content: space-between; - color: (var(--bs-white)); + color: var(--maple-text-inverse); } .navbar-dark .navbar-nav .nav-link { - color: rgba(255, 255, 255, 0.55); + color: var(--maple-text-inverse-muted); } .navbar-dark .navbar-nav, .navbar-dark .navbar-nav .nav-link.active, .navbar-dark .navbar-nav .nav-link:hover { - color: rgba(255, 255, 255, 1); + color: var(--maple-text-inverse); } .dropdown-toggle::after, diff --git a/components/HearingsScheduled/HearingsScheduled.tsx b/components/HearingsScheduled/HearingsScheduled.tsx index 317f72b60..bb51b18d6 100644 --- a/components/HearingsScheduled/HearingsScheduled.tsx +++ b/components/HearingsScheduled/HearingsScheduled.tsx @@ -43,7 +43,7 @@ Event types handled: sessions, hearings. const EventCardContainer = styled.div` border: 2px var(--bs-blue) solid; width: 20rem; /* width: 269px; */ - margin-bottom: 2em; + margin-bottom: var(--maple-space-2xl); border-radius: 0.5rem; display: block; height: fit-content; @@ -62,8 +62,8 @@ const EventCardContainer = styled.div` const EventCardHeader = styled.div` color: white; background: var(--bs-blue); - padding-top: 0.25em; - padding-left: 1em; + padding-top: var(--maple-space-xs); + padding-left: var(--maple-space-lg); height: 3.21em; /* 51.94px */ border-radius: 0.3125em 0.3125em 0 0; display: grid; @@ -144,7 +144,7 @@ export const EventCard = ({ const EventSection = styled.section` min-width: fit-content; max-width: 43rem; - margin-bottom: 2em; + margin-bottom: var(--maple-space-2xl); ` const HearingImage = styled.img` diff --git a/components/HeroHeader/HeroHeader.js b/components/HeroHeader/HeroHeader.js deleted file mode 100644 index 924cdf917..000000000 --- a/components/HeroHeader/HeroHeader.js +++ /dev/null @@ -1,108 +0,0 @@ -import { AltSignInWithButton } from "components/auth/SignInWithButton" -import { Button, Col, Container, Image, Row } from "../bootstrap" -import { Wrap } from "../links" -import ScrollTrackerContainer from "../ScrollTrackEffect/ScrollTrackerContainer" -import ScrollTrackingItem from "../ScrollTrackEffect/ScrollTrackerItem" -import styles from "./HeroHeader.module.css" -import { useTranslation } from "next-i18next" -import { capitalize } from "lodash" -import { NEWSLETTER_SIGNUP_URL, TRAINING_CALENDAR_URL } from "../common" -import TranscriptAnnouncement from "components/AnnouncementBanner/TranscriptAnnouncement" - -const HeroHeader = ({ authenticated }) => { - const { t } = useTranslation("common") - return ( - - - - - - - - - - - - - - - - -
-
- {t("common:let_your_voice_be_heard")} -
-

{t("short_description")}

-

- {t("newcomer")}{" "} - - {t("calendar")} - {" "} - {t("joinTraining")} -

-

- - {t("newsletter")} - -

-
- {!authenticated && ( -
- -
- )} - -
- -
-
-
-
- - - - - - - ) -} - -export default HeroHeader diff --git a/components/HeroHeader/HeroHeader.module.css b/components/HeroHeader/HeroHeader.module.css deleted file mode 100644 index 1381f5898..000000000 --- a/components/HeroHeader/HeroHeader.module.css +++ /dev/null @@ -1,51 +0,0 @@ -.container { - color: white; - background-color: #1a3185; - overflow: hidden; -} - -.btncontainer { - display: inline-block; - padding: 0.25em; -} - -.title { - font-size: 2.5rem; -} - -.subtitle { - font-size: 1rem; -} - -.skyline { - transform-origin: top; - transform: scale(1.5); -} - -.skylineContainer { - display: grid; - place-content: center; - position: absolute; - bottom: 0; -} - -.cloudsContainer { - display: grid; - align-items: center; - position: absolute; - left: 0; - bottom: 0; -} - -.clouds { - transform-origin: 0 70%; - transform: scale(0.9); - place-content: end; -} - -.statehouse { - transform-origin: bottom; - transform: scale(0.9); - align-self: flex-end; - max-width: 100%; -} diff --git a/components/InTheNews/NewsCard.tsx b/components/InTheNews/NewsCard.tsx index cb545e354..bf9c4da20 100644 --- a/components/InTheNews/NewsCard.tsx +++ b/components/InTheNews/NewsCard.tsx @@ -12,7 +12,7 @@ export const NewsCard = ({ newsItem }: NewsCardProps) => {
@@ -33,7 +33,7 @@ export const NewsCard = ({ newsItem }: NewsCardProps) => { style={{ width: "1px", height: "1em", - backgroundColor: "black", + backgroundColor: "var(--maple-border-default)", alignSelf: "center" }} /> @@ -57,7 +57,7 @@ export const NewsCard = ({ newsItem }: NewsCardProps) => { href={newsItem.url} target="_blank" rel="noopener noreferrer" - style={{ color: "#1587D3", fontWeight: 800 }} + style={{ color: "var(--maple-brand-primary)", fontWeight: 800 }} > {t("readMoreButton")} diff --git a/components/Leaf/Leaf.tsx b/components/Leaf/Leaf.tsx deleted file mode 100644 index fca499c2a..000000000 --- a/components/Leaf/Leaf.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Image } from "react-bootstrap" -import styled from "styled-components" - -const LeafContainer = styled.div` - height: 0; - overflow-y: visible; -` -const LeafImage = styled(Image)` - position: relative; - z-index: 2; - - &.first { - left: 100%; - transform: translate(-62%, -50%) rotate(270deg); - } - &.second { - transform: translate(-30%, -60%); - } - &.third { - left: 100%; - transform: translate(-62%, 53%) rotate(270deg); - } - &.fourth { - transform: translate(30%, -67%); - } -` - -const Leaf = ({ - position -}: { - position: "first" | "second" | "third" | "fourth" -}) => { - return ( - - - - ) -} - -export default Leaf diff --git a/components/Navbar.tsx b/components/Navbar.tsx index b9b470e09..942bc54fa 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -10,6 +10,7 @@ import { flags } from "./featureFlags" import { Avatar, NavbarLinkBallotQuestions, + DESKTOP_NAV_ITEM_CLASS, NavbarLinkAI, NavbarLinkBills, NavbarLinkHearings, @@ -29,6 +30,10 @@ import { NavbarLinkWhyUse } from "./NavbarComponents" +const MobileCollapse = styled(Navbar.Collapse)` + background-color: var(--maple-brand-primary); +` + export const MainNavbar: React.FC> = () => { const isMobile = useMediaQuery("(max-width: 768px)") @@ -36,23 +41,6 @@ export const MainNavbar: React.FC> = () => { } const MobileNav: React.FC> = () => { - const BlackCollapse = styled(() => { - return ( - - {/* while MAPLE is trying to do away with inline styling, * - * both styled-components and bootstrap classes have been * - * ignoring height properties for some reason */} -
- {whichMenu == "site" ? : } -
-
- ) - })` - .bg-black { - background-color: black; - } - ` - const ProfileLinks = () => { return (