From d5b3e0e494116b5861a1da1e801bda9a3d7a9986 Mon Sep 17 00:00:00 2001 From: Silviu Marii Date: Tue, 23 May 2023 09:34:50 +0000 Subject: [PATCH] Merged PR 4247: Match Settings molecule Match Settings and ToolTip molecules. Passing as props the `active` useState of the tooltip is not possible as the same instance would be referenced for all tooltips. If anyone would a suggestion for addressing this problem I would love to hear it. ###QA In `/test` route press on Menu & Match Settings and check that the figma designs are respected. --- frontend/src/molecules/match-info/index.ts | 1 + .../match-info/match-info-description.tsx | 73 ++++++++++++++++ .../src/molecules/match-info/match-info.tsx | 49 +++++++++++ frontend/src/molecules/match-info/styles.ts | 17 ++++ .../match-settings-overview/index.ts | 1 + .../match-settings-overview.tsx | 87 +++++++++++++++++++ .../match-settings-overview/styles.ts | 24 +++++ .../molecules/power-up-description/index.ts | 1 + .../power-up-description.tsx | 37 ++++++++ .../molecules/power-up-description/styles.ts | 13 +++ .../src/molecules/power-up/power-up-small.tsx | 6 +- frontend/src/molecules/tooltip/index.ts | 3 + frontend/src/molecules/tooltip/styles.ts | 36 ++++++++ .../src/molecules/tooltip/tooltip-info.tsx | 46 ++++++++++ frontend/src/molecules/tooltip/tooltip.tsx | 32 +++++++ .../top-navigation/top-navigation.tsx | 1 - frontend/src/pages/test/test.tsx | 37 ++++---- 17 files changed, 439 insertions(+), 25 deletions(-) create mode 100644 frontend/src/molecules/match-info/index.ts create mode 100644 frontend/src/molecules/match-info/match-info-description.tsx create mode 100644 frontend/src/molecules/match-info/match-info.tsx create mode 100644 frontend/src/molecules/match-info/styles.ts create mode 100644 frontend/src/molecules/match-settings-overview/index.ts create mode 100644 frontend/src/molecules/match-settings-overview/match-settings-overview.tsx create mode 100644 frontend/src/molecules/match-settings-overview/styles.ts create mode 100644 frontend/src/molecules/power-up-description/index.ts create mode 100644 frontend/src/molecules/power-up-description/power-up-description.tsx create mode 100644 frontend/src/molecules/power-up-description/styles.ts create mode 100644 frontend/src/molecules/tooltip/index.ts create mode 100644 frontend/src/molecules/tooltip/styles.ts create mode 100644 frontend/src/molecules/tooltip/tooltip-info.tsx create mode 100644 frontend/src/molecules/tooltip/tooltip.tsx diff --git a/frontend/src/molecules/match-info/index.ts b/frontend/src/molecules/match-info/index.ts new file mode 100644 index 00000000..a704094d --- /dev/null +++ b/frontend/src/molecules/match-info/index.ts @@ -0,0 +1 @@ +export * from "./match-info"; diff --git a/frontend/src/molecules/match-info/match-info-description.tsx b/frontend/src/molecules/match-info/match-info-description.tsx new file mode 100644 index 00000000..296049d2 --- /dev/null +++ b/frontend/src/molecules/match-info/match-info-description.tsx @@ -0,0 +1,73 @@ +import { LightningIconSVG, RaisedHandIconSVG, RoundIconSVG, text } from "../../assets"; +import { BaseIcon, GeneralText, IconImage } from "../../atoms"; +import { color, fontWeights, spacing } from "../../design"; +import { MatchSettings } from "../../types"; +import { Die } from "../die"; +import { RowHeadingIcon } from "../text"; +import { HandImageWrapper } from "./styles"; + +export type MatchInfoSettings = "players" | "dice" | "powerUps" | "drawRoundOffset" | "healAction" | "sound" | undefined; + +export const findInfo = (matchSettingsType: MatchInfoSettings, matchSettings: MatchSettings) => { + switch (matchSettingsType) { + case "players": + return ( + + + + {text.param.xAmount(matchSettings.players)} + + + ); + case "dice": + return ( + } />} + iconPosition="row-reverse" + justifyContent="flex-end" + gap={spacing.xs} + transformText="none" + headingColor={color.black} + /> + ); + case "powerUps": + return ( + } iconColor={color.transparent} strokeColor={color.black} />} + iconPosition="row-reverse" + justifyContent="flex-end" + gap={spacing.xxs} + transformText="none" + headingColor={color.black} + /> + ); + case "drawRoundOffset": + return ( + <> + } /> + + {text.param.xRounds(matchSettings.drawRoundOffset)} + + + ); + case "healAction": + return ( + } iconColor={color.transparent} strokeColor={color.black} />} + iconPosition="row-reverse" + justifyContent="flex-end" + gap={spacing.xxs} + transformText="none" + headingColor={color.black} + /> + ); + default: + return <>; + } +}; diff --git a/frontend/src/molecules/match-info/match-info.tsx b/frontend/src/molecules/match-info/match-info.tsx new file mode 100644 index 00000000..a3d8bb1d --- /dev/null +++ b/frontend/src/molecules/match-info/match-info.tsx @@ -0,0 +1,49 @@ +import { FC } from "react"; +import { spacing } from "../../design"; +import { BaseRow, Heading6 } from "../../atoms"; +import { MatchSettings } from "../../types"; + +import { MatchInfoOverview } from "./styles"; +import { Tooltip } from "../tooltip"; +import { findInfo, MatchInfoSettings } from "./match-info-description"; + +interface MatchInfoProps { + matchSettingsType: MatchInfoSettings; + title: string; + hasTooltip?: boolean; + tooltipTitle?: string; + tooltipDescription?: string; + matchSettings: MatchSettings; +} + +/** + * @description - Match info molecule + * @param {matchSettingsType} - Type of match settings + * @param {title} - Title of match info + * @param {hasTooltip} - If there is a tooltip present + * @param {tooltipTitle} - Title of tooltip + * @param {tooltipDescription} - Description of tooltip + * @param {matchSettings} - Match settings + * @param {tooltipPosition} - Position of tooltip + */ + +export const MatchInfo: FC = ({ + title, + matchSettingsType, + hasTooltip, + tooltipDescription, + tooltipTitle, + matchSettings, +}) => { + return ( + + + {title} + {hasTooltip && } + + + {findInfo(matchSettingsType, matchSettings)} + + + ); +}; diff --git a/frontend/src/molecules/match-info/styles.ts b/frontend/src/molecules/match-info/styles.ts new file mode 100644 index 00000000..720f79ab --- /dev/null +++ b/frontend/src/molecules/match-info/styles.ts @@ -0,0 +1,17 @@ +import styled from "@emotion/styled"; +import { color, containerHeight, spacing } from "../../design"; +import { BaseColumn, BaseRow } from "../../atoms"; + +interface Props { + padding?: string; +} + +export const MatchInfoOverview = styled(BaseColumn)` + padding: ${({ padding }): string => padding ?? "0px"}; + background: ${color.lightGrey}; + min-height: ${containerHeight.sm}; +`; + +export const HandImageWrapper = styled(BaseRow)` + margin-top: ${spacing.xxs}; +`; diff --git a/frontend/src/molecules/match-settings-overview/index.ts b/frontend/src/molecules/match-settings-overview/index.ts new file mode 100644 index 00000000..aa122480 --- /dev/null +++ b/frontend/src/molecules/match-settings-overview/index.ts @@ -0,0 +1 @@ +export * from "./match-settings-overview"; diff --git a/frontend/src/molecules/match-settings-overview/match-settings-overview.tsx b/frontend/src/molecules/match-settings-overview/match-settings-overview.tsx new file mode 100644 index 00000000..044e400a --- /dev/null +++ b/frontend/src/molecules/match-settings-overview/match-settings-overview.tsx @@ -0,0 +1,87 @@ +import { FC } from "react"; +import { text } from "../../assets"; +import { buttonSize, color, spacing } from "../../design"; +import { TertiaryButton } from "../../molecules"; +import { getPowerUp } from "../../util"; +import { BaseRow, Heading1, Heading6, PopUpFooter } from "../../atoms"; +import { MatchInfoButtons, MatchSettingsOverviewComponent, Percentage, PowerUpContainer } from "./styles"; +import { MatchSettings } from "../../types"; +import { MatchInfo } from "../match-info"; +import { PowerUpDescription } from "../power-up-description"; +import { Tooltip } from "../tooltip"; + +interface MatchSettingsOverviewProps { + matchSettings: MatchSettings; +} + +/** + * @description The MatchSettingsOverview molecule displays the match settings of the current match. + * @param {MatchSettingsOverviewProps} props - The match settings props + * @param {plusAmount} - The amount of power-ups that are not visible + */ + +export const MatchSettingsOverview: FC = ({ matchSettings }) => { + const powerUpProbabilities = matchSettings.powerUpProbability.filter((powerUp) => powerUp.probability > 0); + const powerUps = matchSettings.powerUpProbability.map((powerUp) => getPowerUp(powerUp.id)); + return ( + + {text.match.matchSettings} + + + + + + + + + {text.match.powerUpTypeOnTheTable} + + + } + padding={buttonSize.xl} + /> + + {powerUpProbabilities.map((powerUpProbability, index) => { + const powerUp = powerUps[index]; + return ( + + {powerUp && } + {text.param.percentageAmount(powerUpProbability.probability)} + + ); + })} + + + ); +}; diff --git a/frontend/src/molecules/match-settings-overview/styles.ts b/frontend/src/molecules/match-settings-overview/styles.ts new file mode 100644 index 00000000..11e28f5c --- /dev/null +++ b/frontend/src/molecules/match-settings-overview/styles.ts @@ -0,0 +1,24 @@ +import styled from "@emotion/styled"; +import { containerWidth, spacing } from "../../design"; +import { BodyText, BaseRow } from "../../atoms"; + +export const MatchSettingsOverviewComponent = styled.section` + padding: ${spacing.xl}; + height: 100%; + width: ${containerWidth.xxxl}; + overflow-y: scroll; +`; + +export const MatchInfoButtons = styled(BaseRow)` + margin-top: ${spacing.md}; + margin-bottom: ${spacing.xl}; + width: ${containerWidth.xxxl}; +`; + +export const Percentage = styled(BodyText)` + padding: ${spacing.xs} 0px ${spacing.xs} ${spacing.xs}; +`; + +export const PowerUpContainer = styled(BaseRow)` + margin-bottom: ${spacing.ms}; +`; diff --git a/frontend/src/molecules/power-up-description/index.ts b/frontend/src/molecules/power-up-description/index.ts new file mode 100644 index 00000000..dbaf2ae4 --- /dev/null +++ b/frontend/src/molecules/power-up-description/index.ts @@ -0,0 +1 @@ +export * from "./power-up-description"; diff --git a/frontend/src/molecules/power-up-description/power-up-description.tsx b/frontend/src/molecules/power-up-description/power-up-description.tsx new file mode 100644 index 00000000..6950d8fd --- /dev/null +++ b/frontend/src/molecules/power-up-description/power-up-description.tsx @@ -0,0 +1,37 @@ +import { FC } from "react"; +import { LightningIconSVG } from "../../assets"; +import { color } from "../../design"; +import { PowerUp } from "../../types"; +import { Heading6, BodyText, BaseIcon, BaseRow } from "../../atoms"; +import { DescriptionContainer, PowerUpDescriptionWrapper } from "./styles"; +import { PowerUpSmall } from "../power-up"; + +interface PowerUpDescriptionProps { + powerUp: PowerUp; + hasLightningIcon?: boolean; + gap?: string; + plusAmount?: number; +} + +/** + * @description Molecule for power-up description. + * @param {powerUp} - Power-up object + * @param {hasLightningIcon} - If the power-up has a lightning icon + */ + +export const PowerUpDescription: FC = ({ powerUp, hasLightningIcon = false, plusAmount, gap }) => { + return ( + <> + + + + + {hasLightningIcon && } strokeColor={color.mediumGrey} />} + {powerUp.name} + + {powerUp.shortDescription} + + + + ); +}; diff --git a/frontend/src/molecules/power-up-description/styles.ts b/frontend/src/molecules/power-up-description/styles.ts new file mode 100644 index 00000000..e7156490 --- /dev/null +++ b/frontend/src/molecules/power-up-description/styles.ts @@ -0,0 +1,13 @@ +import styled from "@emotion/styled"; +import { spacing } from "../../design"; +import { GeneralContentWrapper } from "../../atoms"; + +export const DescriptionContainer = styled.div` + flex: 11; + padding: 0px 0px ${spacing.xs} ${spacing.xs}; +`; + +export const PowerUpDescriptionWrapper = styled(GeneralContentWrapper)` + margin-left: ${spacing.s}; + margin-top: 0px; +`; diff --git a/frontend/src/molecules/power-up/power-up-small.tsx b/frontend/src/molecules/power-up/power-up-small.tsx index b0ffcc8d..07353984 100644 --- a/frontend/src/molecules/power-up/power-up-small.tsx +++ b/frontend/src/molecules/power-up/power-up-small.tsx @@ -7,19 +7,21 @@ interface PowerUpSmallProps { powerUpName?: string; powerUpImage?: string; isEmpty?: boolean; + plusAmount?: number; } /** * @param {string} powerUpName - The name of the powerUp used for the alt text * @param {string} powerUpImage - Image of the powerUp * @param {string} isEmpty - If the powerUp is used to display the hidden amount of powerUps. No powerUp image is shown but a number. + * @param {number} plusAmount - The amount of powerUps that are not visible, isEmpty prop has to be true */ -export const PowerUpSmall: FC = ({ powerUpName, powerUpImage, isEmpty = false }) => { +export const PowerUpSmall: FC = ({ powerUpName, powerUpImage, isEmpty = false, plusAmount = 0 }) => { return ( - {isEmpty ? {text.param.plusAmount(4)} : } + {isEmpty ? {text.param.plusAmount(plusAmount)} : } ); diff --git a/frontend/src/molecules/tooltip/index.ts b/frontend/src/molecules/tooltip/index.ts new file mode 100644 index 00000000..8d4a9e46 --- /dev/null +++ b/frontend/src/molecules/tooltip/index.ts @@ -0,0 +1,3 @@ +export * from "./tooltip"; +export * from "./tooltip-info"; +export * from "./styles"; diff --git a/frontend/src/molecules/tooltip/styles.ts b/frontend/src/molecules/tooltip/styles.ts new file mode 100644 index 00000000..bb561734 --- /dev/null +++ b/frontend/src/molecules/tooltip/styles.ts @@ -0,0 +1,36 @@ +import styled from "@emotion/styled"; +import { tooltipAnimation } from "../../atoms"; +import { containerWidth, spacing, zIndex as designZIndex } from "../../design"; + +export const TooltipContainer = styled.section``; + +interface Props { + zIndex?: number; +} + +export const TooltipWrapper = styled.div` + position: relative; + z-index: ${({ zIndex }) => zIndex ?? designZIndex.background}; +`; + +export const TooltipContentWrapper = styled.div` + position: absolute; + animation: ${tooltipAnimation} 0.5s; + &.top { + top: "calc(${spacing.xxl} * -1)"; + } + &.bottom { + bottom: calc(${spacing.xxl} * -1); + } + &.left { + left: auto; + right: calc(100% - ${spacing.xxl} * 4); + top: 0%; + transform: translateX(0) translateY(0); + } + &.right { + left: -${containerWidth.md}; + top: 0%; + transform: translateX(0) translateY(0); + } +`; diff --git a/frontend/src/molecules/tooltip/tooltip-info.tsx b/frontend/src/molecules/tooltip/tooltip-info.tsx new file mode 100644 index 00000000..eb232d7d --- /dev/null +++ b/frontend/src/molecules/tooltip/tooltip-info.tsx @@ -0,0 +1,46 @@ +import React, { FC, ReactNode, useState } from "react"; +import { text } from "../../assets"; +import { zIndex as designZIndex } from "../../design"; +import { TooltipFrame } from "../pop-ups"; +import { TooltipContentWrapper, TooltipContainer, TooltipWrapper } from "./styles"; + +export type TooltipInfoPosition = "top" | "bottom" | "left" | "right"; +interface TooltipInfoProps { + title?: string; + description?: string; + position?: TooltipInfoPosition; + content: ReactNode; + children: React.ReactNode; + zIndex?: number; +} + +/** + * @description - This molecule is used to display a tooltip with a title and description. + * @param {string} title - The title of the tooltip + * @param {string} description - The description of the tooltip + * @param {string} position - The position of the tooltip + * @param {ReactNode} content - The content of the tooltip + * @param {ReactNode} children - The children of the tooltip + * @param {number} zIndex - The z-index of the tooltip + * @returns {ReactNode} - Returns the tooltip + */ + +export const TooltipInfo: FC = ({ title, description, children, position, zIndex = designZIndex.background }) => { + // TODO: Refactor this by using the ref of the parent in order to display only the correct tooltip + const [isTooltipActive, setIsTooltipActive] = useState(false); + const showTooltip = () => setIsTooltipActive(true); + const hideTooltip = () => setIsTooltipActive(false); + + return ( + + {children} + {isTooltipActive && ( + + + + + + )} + + ); +}; diff --git a/frontend/src/molecules/tooltip/tooltip.tsx b/frontend/src/molecules/tooltip/tooltip.tsx new file mode 100644 index 00000000..8d73aaf1 --- /dev/null +++ b/frontend/src/molecules/tooltip/tooltip.tsx @@ -0,0 +1,32 @@ +import { FC, ReactNode } from "react"; +import { InfoIconSVG } from "../../assets"; +import { BaseIcon } from "../../atoms"; +import { TooltipInfoPosition, TooltipInfo } from "./tooltip-info"; + +interface TooltipProps { + title?: string; + description?: string; + info?: ReactNode; + infoPosition?: TooltipInfoPosition; + zIndex?: number; + iconColor?: string; +} + +/** + * @description - This molecule is used to display a tooltip with a title and description. + * @param {string} title - The title of the tooltip + * @param {string} description - The description of the tooltip + * @param {string} info - The info of the tooltip + * @param {string} infoPosition - The position of the tooltip + * @param {ReactNode} content - The content of the tooltip + * @param {ReactNode} children - The children of the tooltip + * @param {number} zIndex - The z-index of the tooltip + */ + +export const Tooltip: FC = ({ title, info, zIndex, iconColor, description, infoPosition }) => { + return ( + + } pointer iconColor={iconColor} /> + + ); +}; diff --git a/frontend/src/molecules/top-navigation/top-navigation.tsx b/frontend/src/molecules/top-navigation/top-navigation.tsx index 2d07c905..6bb5beb2 100644 --- a/frontend/src/molecules/top-navigation/top-navigation.tsx +++ b/frontend/src/molecules/top-navigation/top-navigation.tsx @@ -61,7 +61,6 @@ export const TopNavigation: FC = ({ buttonText={text.general.contact} expand={() => setActiveDropdown("contact")} /> - {/* TODO: add sound, only in match situations */} setActiveDropdown("menu")} diff --git a/frontend/src/pages/test/test.tsx b/frontend/src/pages/test/test.tsx index f9b5a2c5..5d55cab3 100644 --- a/frontend/src/pages/test/test.tsx +++ b/frontend/src/pages/test/test.tsx @@ -86,6 +86,7 @@ import { CookieBanner, FloatingPlayer, HudPlayer, + PlayerMenu, } from "../../molecules"; import { getPowerUp, getPowerUpData, parseMessages, range } from "../../util"; import { Die } from "../../molecules/die"; @@ -106,8 +107,9 @@ import { MatchHeadingColumn, } from "./styles"; import { PowerUpCard, PowerUpSmall } from "../../molecules/power-up"; -import { ActiveDropdown } from "../../molecules/top-navigation"; -import { PlayerMenu } from "../../molecules/player-menu"; +import { ActiveDropdown, TopNavigation } from "../../molecules/top-navigation"; +import { MatchSettingsOverview } from "../../molecules/match-settings-overview"; +import { fakeMatchSettings } from "../../assets/fake-data/fake-match-settings"; import { sendMessage } from "../../service"; import { PlayerLineup } from "../../molecules/player-lineup"; import { PlayerLogo } from "../../molecules/player-logo"; @@ -206,6 +208,10 @@ export const Test: FC = () => { } }; + const handleSettings = () => { + setModalShown(true); + }; + const handleSendEvent = (e: React.MouseEvent | React.KeyboardEvent) => { e.stopPropagation(); if (e.currentTarget.value === "") return; @@ -370,18 +376,18 @@ export const Test: FC = () => {
- console.log("")} handleLeaveMatch={() => console.log("")} - handleSettings={() => console.log("")} + handleSettings={() => handleSettings()} handleRules={() => console.log("")} - totalDice={35} - stageNumber={1} - drawNumber={7} + // totalDice={35} + // stageNumber={1} + // drawNumber={7} />
{/* @@ -408,24 +414,11 @@ export const Test: FC = () => { */} setModalShown(!isModalShown)} /> {"im a modal with a close button"}} + component={} isVisible={isModalShown} isContained onClose={() => setModalShown(!isModalShown)} /> - setModalShownNoButton(!isModalShownNoButton)} /> - - {"im a modal without a close button"} -
-
- setModalShownNoButton(!isModalShownNoButton)} /> - - } - isVisible={isModalShownNoButton} - isContained - />