Repository: webkom/lego-webapp
Pull request #5397: Replace mazemap button with accordion
Author: login: eikhr
Labels: name: review-needed
description: Pull requests that need review
name: approved
description: Pull requests that have been approved
Created: 2025-03-04T10:42:08Z | Merged: 2025-03-04T13:10:36Z

# Description

I like the new Pizza accordion and figured a similar thing would fit well for the mazemap embed:)

# Result

- [x] Changes look good on both light and dark theme.
- [x] Changes look good with different viewports (mobile, tablet, etc.).
- [x] Changes look good with slower Internet connections.

<table>
    <tr>
        <td width="25%">Description</td>
        <td>Before</td>
        <td>After</td>
    </tr>
    <tr>
        <td>
            Event Page (closed)
        </td>
        <td>
<img width="425" alt="Screenshot 2025-03-04 at 11 39 20" src="https://github.com/user-attachments/assets/2af17a6d-8d3d-44d6-b2fc-7a3a1c2bb273" />
        </td>
        <td>
<img width="425" alt="Screenshot 2025-03-04 at 11 39 38" src="https://github.com/user-attachments/assets/f1fc221a-91a6-4dba-8bbf-8cd32efc138b" />
        </td>
    </tr>
    <tr>
        <td>
            Event Page (open)
        </td>
        <td>
<img width="425" alt="Screenshot 2025-03-04 at 11 39 53" src="https://github.com/user-attachments/assets/d21c4705-869e-42ed-ae4e-d0c96fdc164d" />
        </td>
        <td>
<img width="425" alt="Screenshot 2025-03-04 at 11 40 11" src="https://github.com/user-attachments/assets/f5cffa41-6d68-4d4e-87a0-e919c9f26db8" />
        </td>
    </tr>
    <tr>
        <td>
            Meeting Page
        </td>
        <td>
<img width="425" alt="Screenshot 2025-03-04 at 11 40 34" src="https://github.com/user-attachments/assets/c2d9d591-ca0d-4fc4-b5e3-8db5c7125640" />
        </td>
        <td>
<img width="425" alt="Screenshot 2025-03-04 at 11 40 50" src="https://github.com/user-attachments/assets/e4148c96-f7a7-43b2-b8c8-489dac10a753" />
        </td>
    </tr>
</table>

# Testing

- [x] I have thoroughly tested my changes.

Mazemap doesn't work in dev, but I'm assuming it will work in production:)

---

Resolves ABA-1315



Diff:
diff --git a/app/components/MazemapEmbed/MazemapAccordion.module.css b/app/components/MazemapEmbed/MazemapAccordion.module.css
new file mode 100644
index 0000000000..6480342f06
--- /dev/null
+++ b/app/components/MazemapEmbed/MazemapAccordion.module.css
@@ -0,0 +1,25 @@
+.mazemapAccordion {
+  background-color: var(--additive-background);
+  border-radius: var(--border-radius-lg);
+}
+
+.mazemapAccordionTrigger {
+  padding: var(--spacing-xs) var(--spacing-md);
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: var(--spacing-sm);
+  height: fit-content;
+  color: var(--lego-font-color);
+  cursor: pointer;
+}
+
+.mazemapImg {
+  width: 30px;
+  margin-left: calc(-1 * var(--spacing-xs));
+}
+
+.mazemapEmbed {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
diff --git a/app/components/MazemapEmbed/MazemapAccordion.tsx b/app/components/MazemapEmbed/MazemapAccordion.tsx
new file mode 100644
index 0000000000..76cc7fd7dd
--- /dev/null
+++ b/app/components/MazemapEmbed/MazemapAccordion.tsx
@@ -0,0 +1,57 @@
+import { Accordion, Flex, Icon } from '@webkom/lego-bricks';
+import { ChevronRight } from 'lucide-react';
+import { useState } from 'react';
+import mazemapLogo from 'app/assets/mazemap.svg';
+import MazemapLink from 'app/components/MazemapEmbed/MazemapLink';
+import { MazemapEmbed } from 'app/components/MazemapEmbed/index';
+import styles from './MazemapAccordion.module.css';
+import type { ComponentProps } from 'react';
+
+type Props = ComponentProps<typeof MazemapEmbed> & {
+  defaultOpen?: boolean;
+};
+
+export const MazemapAccordion = ({ defaultOpen = false, ...props }: Props) => {
+  const [mapIsOpen, setMapIsOpen] = useState(defaultOpen);
+
+  return (
+    <>
+      <Flex column gap="var(--spacing-xs)" className={styles.mazemapAccordion}>
+        <Accordion
+          defaultOpen={defaultOpen}
+          triggerComponent={({ onClick, rotateClassName }) => (
+            <div
+              onClick={() => {
+                onClick();
+                setMapIsOpen(!mapIsOpen);
+              }}
+              className={styles.mazemapAccordionTrigger}
+            >
+              <Flex alignItems="center" gap="var(--spacing-sm)">
+                <img
+                  className={styles.mazemapImg}
+                  alt="MazeMap sin logo"
+                  src={mazemapLogo}
+                />
+                Kart
+              </Flex>
+              <Icon
+                onPress={() => {
+                  onClick();
+                  setMapIsOpen(!mapIsOpen);
+                }}
+                iconNode={<ChevronRight />}
+                className={rotateClassName}
+              />
+            </div>
+          )}
+        >
+          <MazemapEmbed {...props} className={styles.mazemapEmbed} />
+        </Accordion>
+      </Flex>
+      {mapIsOpen && (
+        <MazemapLink mazemapPoi={props.mazemapPoi} linkText={props.linkText} />
+      )}
+    </>
+  );
+};
diff --git a/app/components/MazemapEmbed/MazemapButton.tsx b/app/components/MazemapEmbed/MazemapButton.tsx
deleted file mode 100644
index 75d838e4b5..0000000000
--- a/app/components/MazemapEmbed/MazemapButton.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { Button, Flex } from '@webkom/lego-bricks';
-import { useState } from 'react';
-import mazemapLogo from 'app/assets/mazemap.svg';
-import { MazemapEmbed } from 'app/components/MazemapEmbed/index';
-import styles from 'app/routes/events/components/EventDetail/EventDetail.module.css';
-import type { ComponentProps } from 'react';
-
-type Props = ComponentProps<typeof MazemapEmbed> & {
-  defaultOpen?: boolean;
-};
-
-export const MazemapButton = ({ defaultOpen = false, ...props }: Props) => {
-  const [mapIsOpen, setMapIsOpen] = useState(defaultOpen);
-
-  return (
-    <Flex column gap="var(--spacing-xs)">
-      <Button
-        className={styles.mapButton}
-        onPress={() => setMapIsOpen(!mapIsOpen)}
-      >
-        <img
-          className={styles.mazemapImg}
-          alt="MazeMap sin logo"
-          src={mazemapLogo}
-        />
-        {mapIsOpen ? 'Skjul kart' : 'Vis kart'}
-      </Button>
-      {mapIsOpen && <MazemapEmbed {...props} />}
-    </Flex>
-  );
-};
diff --git a/app/components/MazemapEmbed/index.tsx b/app/components/MazemapEmbed/index.tsx
index 6ea5f8f547..7768e1d2af 100644
--- a/app/components/MazemapEmbed/index.tsx
+++ b/app/components/MazemapEmbed/index.tsx
@@ -1,9 +1,9 @@
 import { Flex } from '@webkom/lego-bricks';
+import cx from 'classnames';
 import { useEffect, useState } from 'react';
 import '@webkom/mazemap/css';
 import { Keyboard } from 'app/utils/constants';
 import styles from './MazemapEmbed.module.css';
-import MazemapLink from './MazemapLink';
 
 type MazeMap = {
   Map: any;
@@ -16,6 +16,7 @@ type MazeMap = {
 type Props = {
   mazemapPoi: number;
   height?: number;
+  className?: string;
   linkText?: string;
 };
 
@@ -174,7 +175,6 @@ export const MazemapEmbed = ({ mazemapPoi, ...props }: Props) => {
             height: props.height || 400,
           }}
         />
-        <MazemapLink mazemapPoi={mazemapPoi} linkText={props.linkText} />
       </>
     );
   }
@@ -188,7 +188,7 @@ export const MazemapEmbed = ({ mazemapPoi, ...props }: Props) => {
           touchAction: 'pan-x pan-y',
         }}
         id="mazemap-embed"
-        className={styles.mazemapEmbed}
+        className={cx(styles.mazemapEmbed, props.className)}
       >
         {(blockScrollZoom || blockTouchMovement) && (
           <span className={styles.blockingText}>
@@ -198,7 +198,6 @@ export const MazemapEmbed = ({ mazemapPoi, ...props }: Props) => {
           </span>
         )}
       </div>
-      <MazemapLink mazemapPoi={mazemapPoi} linkText={props.linkText} />
     </Flex>
   );
 };
diff --git a/app/routes/events/components/EventDetail/EventDetail.module.css b/app/routes/events/components/EventDetail/EventDetail.module.css
index 59e4a9bdad..7c452b9306 100644
--- a/app/routes/events/components/EventDetail/EventDetail.module.css
+++ b/app/routes/events/components/EventDetail/EventDetail.module.css
@@ -47,16 +47,6 @@
   }
 }
 
-.mapButton {
-  gap: var(--spacing-xs);
-  font-size: var(--font-size-sm);
-}
-
-.mazemapImg {
-  width: 30px;
-  margin-left: calc(-1 * var(--spacing-xs));
-}
-
 .registrationMeta {
   margin-top: var(--spacing-sm);
 }
diff --git a/app/routes/events/components/EventDetail/SidebarInfo.tsx b/app/routes/events/components/EventDetail/SidebarInfo.tsx
index 1284d06620..306ade10bb 100644
--- a/app/routes/events/components/EventDetail/SidebarInfo.tsx
+++ b/app/routes/events/components/EventDetail/SidebarInfo.tsx
@@ -7,7 +7,7 @@ import {
   MapPin,
 } from 'lucide-react';
 import { Link } from 'react-router';
-import { MazemapButton } from 'app/components/MazemapEmbed/MazemapButton';
+import { MazemapAccordion } from 'app/components/MazemapEmbed/MazemapAccordion';
 import TextWithIcon from 'app/components/TextWithIcon';
 import { FromToTime } from 'app/components/Time';
 import styles from 'app/routes/events/components/EventDetail/EventDetail.module.css';
@@ -79,7 +79,7 @@ export const SidebarInfo = ({ event }: Props) => {
         className={styles.sidebarInfo}
       />
 
-      {event.mazemapPoi && <MazemapButton mazemapPoi={event.mazemapPoi} />}
+      {event.mazemapPoi && <MazemapAccordion mazemapPoi={event.mazemapPoi} />}
     </Flex>
   );
 };
diff --git a/app/routes/meetings/components/MeetingDetail.tsx b/app/routes/meetings/components/MeetingDetail.tsx
index d430735f61..229ff87fb2 100644
--- a/app/routes/meetings/components/MeetingDetail.tsx
+++ b/app/routes/meetings/components/MeetingDetail.tsx
@@ -29,7 +29,7 @@ import Dropdown from 'app/components/Dropdown';
 import { ProfilePicture } from 'app/components/Image';
 import InfoList from 'app/components/InfoList';
 import LegoReactions from 'app/components/LegoReactions';
-import { MazemapEmbed } from 'app/components/MazemapEmbed';
+import { MazemapAccordion } from 'app/components/MazemapEmbed/MazemapAccordion';
 import Time, { FromToTime } from 'app/components/Time';
 import Tooltip from 'app/components/Tooltip';
 import Attendance from 'app/components/UserAttendance/Attendance';
@@ -272,14 +272,13 @@ const MeetingDetails = () => {
         </ContentMain>
         <ContentSidebar>
           {attendanceButtons(statusMe, meeting.startTime)}
+
           <InfoList items={infoItems} />
 
           <Attendance isMeeting pools={sortInvitations()} />
-
           {meeting.mazemapPoi && (
-            <MazemapEmbed mazemapPoi={meeting.mazemapPoi} />
+            <MazemapAccordion mazemapPoi={meeting.mazemapPoi} />
           )}
-
           {icalToken && (
             <AddToCalendar icalToken={icalToken} meeting={meeting} />
           )}


Reviews:
user: login: itsisak
body: Looks great!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T10:54:16Z
user: login: ivarnakken
body: Looks very good! I like
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-04T11:06:30Z
user: login: ch0rizo
body: Very good, very nice
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T12:17:18Z
user: login: itsisak
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T12:39:14Z
user: login: eikhr
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-04T12:41:15Z

Review comments:
diff_hunk: @@ -0,0 +1,67 @@
+import { Accordion, Flex, Icon } from '@webkom/lego-bricks';
+import { ChevronRight } from 'lucide-react';
+import { useState } from 'react';
+import mazemapLogo from 'app/assets/mazemap.svg';
+import { FlexRow } from 'app/components/FlexBox';
+import MazemapLink from 'app/components/MazemapEmbed/MazemapLink';
+import { MazemapEmbed } from 'app/components/MazemapEmbed/index';
+import styles from './MazemapAccordion.module.css';
+import type { ComponentProps } from 'react';
+
+type Props = ComponentProps<typeof MazemapEmbed> & {
+  defaultOpen?: boolean;
+};
+
+export const MazemapAccordion = ({ defaultOpen = false, ...props }: Props) => {
+  const [mapIsOpen, setMapIsOpen] = useState(defaultOpen);
+
+  return (
+    <>
+      <Flex column gap="var(--spacing-xs)" className={styles.mazemapAccordion}>
+        <Accordion
+          defaultOpen={defaultOpen}
+          triggerComponent={({ onClick, rotateClassName }) => (
+            <div
+              onClick={() => {
+                onClick();
+                setMapIsOpen(!mapIsOpen);
+              }}
+              className={styles.mazemapAccordionTrigger}
+            >
+              <FlexRow alignItems="center">
+                <img
+                  className={styles.mazemapImg}
+                  alt="MazeMap sin logo"
+                  src={mazemapLogo}
+                />
+                Kart
+              </FlexRow>
+              <Icon
+                onPress={() => {
+                  onClick();
+                  setMapIsOpen(!mapIsOpen);
+                }}
+                iconNode={<ChevronRight />}
+                className={rotateClassName}
+              />
+            </div>
+          )}
+        >
+          {mapIsOpen ? (
+            <MazemapEmbed
+              {...props}
+              height={400}
+              link={false}
+              className={styles.mazemapEmbed}
+            />
+          ) : (
+            <div style={{ height: 400 }} />
+          )}
path: app/components/MazemapEmbed/MazemapAccordion.tsx
user: login: itsisak
body: This is will not be needed, see #5387 

Will merge that very soon. 
created_at: 2025-03-04T10:53:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,67 @@
+import { Accordion, Flex, Icon } from '@webkom/lego-bricks';
+import { ChevronRight } from 'lucide-react';
+import { useState } from 'react';
+import mazemapLogo from 'app/assets/mazemap.svg';
+import { FlexRow } from 'app/components/FlexBox';
+import MazemapLink from 'app/components/MazemapEmbed/MazemapLink';
+import { MazemapEmbed } from 'app/components/MazemapEmbed/index';
+import styles from './MazemapAccordion.module.css';
+import type { ComponentProps } from 'react';
+
+type Props = ComponentProps<typeof MazemapEmbed> & {
+  defaultOpen?: boolean;
+};
+
+export const MazemapAccordion = ({ defaultOpen = false, ...props }: Props) => {
+  const [mapIsOpen, setMapIsOpen] = useState(defaultOpen);
+
+  return (
+    <>
+      <Flex column gap="var(--spacing-xs)" className={styles.mazemapAccordion}>
+        <Accordion
+          defaultOpen={defaultOpen}
+          triggerComponent={({ onClick, rotateClassName }) => (
+            <div
+              onClick={() => {
+                onClick();
+                setMapIsOpen(!mapIsOpen);
+              }}
+              className={styles.mazemapAccordionTrigger}
+            >
+              <FlexRow alignItems="center">
path: app/components/MazemapEmbed/MazemapAccordion.tsx
user: login: ivarnakken
body: ```suggestion
              <FlexRow alignItems="center" gap="var(--spacing-sm)">
```
Could benefit from some minor spacing 🤷🏼‍♂️ 
created_at: 2025-03-04T11:06:20Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,57 @@
+import { Accordion, Flex, Icon } from '@webkom/lego-bricks';
+import { ChevronRight } from 'lucide-react';
+import { useState } from 'react';
+import mazemapLogo from 'app/assets/mazemap.svg';
+import MazemapLink from 'app/components/MazemapEmbed/MazemapLink';
+import { MazemapEmbed } from 'app/components/MazemapEmbed/index';
+import styles from './MazemapAccordion.module.css';
+import type { ComponentProps } from 'react';
+
+type Props = ComponentProps<typeof MazemapEmbed> & {
+  defaultOpen?: boolean;
+};
+
+export const MazemapAccordion = ({ defaultOpen = false, ...props }: Props) => {
+  const [mapIsOpen, setMapIsOpen] = useState(defaultOpen);
+
+  return (
+    <>
+      <Flex column gap="var(--spacing-xs)" className={styles.mazemapAccordion}>
+        <Accordion
+          defaultOpen={defaultOpen}
+          triggerComponent={({ onClick, rotateClassName }) => (
+            <div
+              onClick={() => {
+                onClick();
+                setMapIsOpen(!mapIsOpen);
+              }}
+              className={styles.mazemapAccordionTrigger}
+            >
+              <Flex alignItems="center" gap="var(--spacing-sm)">
+                <img
+                  className={styles.mazemapImg}
+                  alt="MazeMap sin logo"
+                  src={mazemapLogo}
+                />
+                Kart
+              </Flex>
+              <Icon
+                onPress={() => {
+                  onClick();
+                  setMapIsOpen(!mapIsOpen);
+                }}
+                iconNode={<ChevronRight />}
+                className={rotateClassName}
+              />
+            </div>
+          )}
+        >
+          <MazemapEmbed {...props} className={styles.mazemapEmbed} />
+        </Accordion>
+      </Flex>
+      {mapIsOpen && (
+        <MazemapLink mazemapPoi={props.mazemapPoi} linkText={props.linkText} />
+      )}
path: app/components/MazemapEmbed/MazemapAccordion.tsx
user: login: itsisak
body: Cant this just be inside the accordion?
created_at: 2025-03-04T12:39:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,57 @@
+import { Accordion, Flex, Icon } from '@webkom/lego-bricks';
+import { ChevronRight } from 'lucide-react';
+import { useState } from 'react';
+import mazemapLogo from 'app/assets/mazemap.svg';
+import MazemapLink from 'app/components/MazemapEmbed/MazemapLink';
+import { MazemapEmbed } from 'app/components/MazemapEmbed/index';
+import styles from './MazemapAccordion.module.css';
+import type { ComponentProps } from 'react';
+
+type Props = ComponentProps<typeof MazemapEmbed> & {
+  defaultOpen?: boolean;
+};
+
+export const MazemapAccordion = ({ defaultOpen = false, ...props }: Props) => {
+  const [mapIsOpen, setMapIsOpen] = useState(defaultOpen);
+
+  return (
+    <>
+      <Flex column gap="var(--spacing-xs)" className={styles.mazemapAccordion}>
+        <Accordion
+          defaultOpen={defaultOpen}
+          triggerComponent={({ onClick, rotateClassName }) => (
+            <div
+              onClick={() => {
+                onClick();
+                setMapIsOpen(!mapIsOpen);
+              }}
+              className={styles.mazemapAccordionTrigger}
+            >
+              <Flex alignItems="center" gap="var(--spacing-sm)">
+                <img
+                  className={styles.mazemapImg}
+                  alt="MazeMap sin logo"
+                  src={mazemapLogo}
+                />
+                Kart
+              </Flex>
+              <Icon
+                onPress={() => {
+                  onClick();
+                  setMapIsOpen(!mapIsOpen);
+                }}
+                iconNode={<ChevronRight />}
+                className={rotateClassName}
+              />
+            </div>
+          )}
+        >
+          <MazemapEmbed {...props} className={styles.mazemapEmbed} />
+        </Accordion>
+      </Flex>
+      {mapIsOpen && (
+        <MazemapLink mazemapPoi={props.mazemapPoi} linkText={props.linkText} />
+      )}
path: app/components/MazemapEmbed/MazemapAccordion.tsx
user: login: eikhr
body: Yes, but that would require changing the css a bit to get it outside the accordion container. This is easier:)
created_at: 2025-03-04T12:41:15Z
author_association: MEMBER

PR comments:
user: login: linear[bot]
created_at: 2025-03-04T10:42:11Z
body: <p><a href="https://linear.app/abakus-webkom/issue/ABA-1315/mazemap-accordion-like-pizza-reactions">ABA-1315 Mazemap-accordion (like pizza reactions)</a></p>
author_association: NONE
user: login: vercel[bot]
created_at: 2025-03-04T10:42:12Z
body: [vc]: #myBfisG3JhuDcqjuDjlfHbnewqGpXQr4UoBPm9xI+vI=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJsZWdvLWJyaWNrcy1zdG9yeWJvb2siLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiIn0sImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9hYmFrdXMtbnRudS9sZWdvLWJyaWNrcy1zdG9yeWJvb2svNnVaVUE3OHpXZkpvSEFaZXBRczc4dTc1VnJIcyIsIm5leHRDb21taXRTdGF0dXMiOiJJR05PUkVEIiwicm9vdERpcmVjdG9yeSI6InBhY2thZ2VzL2xlZ28tYnJpY2tzIiwicHJldmlld1VybCI6ImxlZ28tYnJpY2tzLXN0b3J5Ym9vay1naXQtbWF6ZW1hcC1hYmFrdXMtbnRudS52ZXJjZWwuYXBwIn1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)


<details><summary>1 Skipped Deployment</summary>

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **lego-bricks-storybook** | ⬜️ Ignored ([Inspect](https://vercel.com/abakus-ntnu/lego-bricks-storybook/6uZUA78zWfJoHAZepQs78u75VrHs)) | [Visit Preview](https://lego-bricks-storybook-git-mazemap-abakus-ntnu.vercel.app) |  | Mar 4, 2025 0:36am |
</details>


author_association: NONE