diff --git a/package.json b/package.json index 736cbad1d..d39f28664 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-gtm-module": "^2.0.11", + "react-responsive-modal": "^6.2.0", "react-router-dom": "^6.2.1", "react-scripts": "5.0.0", "react-toastify": "^8.2.0", diff --git a/src/config/constants.ts b/src/config/constants.ts new file mode 100644 index 000000000..f1b718b26 --- /dev/null +++ b/src/config/constants.ts @@ -0,0 +1 @@ +export const SETTINGS_TITLE: string = 'Profile Settings' diff --git a/src/config/index.ts b/src/config/index.ts index 263a990b1..c76828baf 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1 +1,2 @@ +export * from './constants' export * from './environments' diff --git a/src/header/Header.module.scss b/src/header/Header.module.scss index 1be321e95..54a530f1a 100644 --- a/src/header/Header.module.scss +++ b/src/header/Header.module.scss @@ -28,4 +28,8 @@ @include xl { grid-template-columns: $left-col-width-xl 1fr auto; } + + @include xxl { + grid-template-columns: $left-col-width-xl 1fr auto; + } } diff --git a/src/header/utility-selectors/UtilitySelector/ProfileSelector/ProfileSelector.tsx b/src/header/utility-selectors/UtilitySelector/ProfileSelector/ProfileSelector.tsx index 6758ec4f7..909168150 100644 --- a/src/header/utility-selectors/UtilitySelector/ProfileSelector/ProfileSelector.tsx +++ b/src/header/utility-selectors/UtilitySelector/ProfileSelector/ProfileSelector.tsx @@ -1,5 +1,6 @@ import { FC, useContext } from 'react' +import { SETTINGS_TITLE } from '../../../../config' import { profileContext, ProfileContextData } from '../../../../lib' import '../../../../lib/styles/index.scss' @@ -23,7 +24,7 @@ const ProfileSelector: FC<{}> = () => { return (
{!isLoggedIn && } - {isLoggedIn && } + {isLoggedIn && }
) } diff --git a/src/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/ProfileLoggedIn.tsx b/src/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/ProfileLoggedIn.tsx index ebb5ce73d..b8d0fc6bb 100644 --- a/src/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/ProfileLoggedIn.tsx +++ b/src/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/ProfileLoggedIn.tsx @@ -2,37 +2,59 @@ import { Dispatch, FC, SetStateAction, useContext, useState } from 'react' import { Avatar, + ComponentVisible, IconOutline, logInfo, profileContext, ProfileContextData, + useHideClickOutside, } from '../../../../../lib' import { ProfilePanel } from './profile-panel' import styles from './ProfileLoggedIn.module.scss' -const ProfileLoggedIn: FC<{}> = () => { +interface ProfileLoggedInProps { + settingsTitle: string +} + +const ProfileLoggedIn: FC = (props: ProfileLoggedInProps) => { const { profile }: ProfileContextData = useContext(profileContext) const [profilePanelOpen, setProfilePanelOpen]: [boolean, Dispatch>] = useState(false) + const { + isComponentVisible, + ref, + setIsComponentVisible, + }: ComponentVisible = useHideClickOutside(false) + if (!profile) { logInfo('tried to render the logged in profile w/out a profile') return <> } function toggleProfilePanel(): void { - setProfilePanelOpen(!profilePanelOpen) + const toggleTo: boolean = !profilePanelOpen + setProfilePanelOpen(toggleTo) + setIsComponentVisible(toggleTo) + } + + if (!isComponentVisible && profilePanelOpen) { + setProfilePanelOpen(isComponentVisible) } return ( <> -
toggleProfilePanel()} > +
{profilePanelOpen && (
@@ -40,7 +62,13 @@ const ProfileLoggedIn: FC<{}> = () => {
)}
- {profilePanelOpen && } + {profilePanelOpen && ( + + )} ) } diff --git a/src/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.tsx b/src/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.tsx index 79719e486..616ae0b04 100644 --- a/src/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.tsx +++ b/src/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.tsx @@ -1,4 +1,4 @@ -import { FC, useContext } from 'react' +import { FC, MutableRefObject, useContext } from 'react' import { Link } from 'react-router-dom' import { @@ -12,32 +12,35 @@ import { import styles from './ProfilePanel.module.scss' interface ProfilePanelProps { + refObject: MutableRefObject + settingsTitle: string toggleProfilePanel: () => void } const ProfilePanel: FC = (props: ProfilePanelProps) => { const { profile }: ProfileContextData = useContext(profileContext) - const { getPath }: RouteContextData = useContext(routeContext) + const { getPath }: RouteContextData = useContext(routeContext) if (!profile) { // this should never happen return <> } - const settingsTitle: string = 'Settings' - return ( -
+
{profile.handle}
props.toggleProfilePanel()} - to={getPath(settingsTitle)} + to={getPath(props.settingsTitle)} > - {settingsTitle} + {props.settingsTitle} Log Out diff --git a/src/lib/avatar/Avatar.module.scss b/src/lib/avatar/Avatar.module.scss index 7c5c112db..c6868f8b4 100644 --- a/src/lib/avatar/Avatar.module.scss +++ b/src/lib/avatar/Avatar.module.scss @@ -1,19 +1,41 @@ @import '../../lib/styles'; -$avatar-size: 32px; +$avatar-size-sm: 32px; +$border-size-sm: $border; +$avatar-size-xl: 120px; +$border-size-xl: $pad-xs; .avatar-container { overflow: hidden; background-color: $tc-white; border-radius: 50%; - height: 36px; + + &.sm { + height: calc($avatar-size-sm + 2 * $border-size-sm); + width: calc($avatar-size-sm + 2 * $border-size-sm); + } + + &.xl { + height: calc($avatar-size-xl + 2 * $border-size-xl); + width: calc($avatar-size-xl + 2 * $border-size-xl); + } .avatar { - height: $avatar-size; - width: $avatar-size; background-color: $tc-white; border-radius: 50%; - border: 2px solid $tc-white; + border: solid $tc-white; + + &.sm { + border-width: $border-size-sm; + height: $avatar-size-sm; + width: $avatar-size-sm; + } + + &.xl { + border-width: $border-size-xl; + height: $avatar-size-xl; + width: $avatar-size-xl; + } } .avatar-letters { @@ -24,6 +46,14 @@ $avatar-size: 32px; color: $tc-white; background-color: $blue-100; @include font-weight-medium; - @extend .medium-subtitle; + + &.sm { + @extend .medium-subtitle; + } + + &.xl { + @extend h1; + padding: 0; + } } } diff --git a/src/lib/avatar/Avatar.tsx b/src/lib/avatar/Avatar.tsx index 3717ebc97..c8bb4eb56 100644 --- a/src/lib/avatar/Avatar.tsx +++ b/src/lib/avatar/Avatar.tsx @@ -4,10 +4,12 @@ import { FC } from 'react' import styles from './Avatar.module.scss' interface AvatarProps { + containerClass?: string firstName?: string handle?: string lastName?: string photoUrl?: string + size: 'sm' | 'xl' } const Avatar: FC = (props: AvatarProps) => { @@ -19,17 +21,21 @@ const Avatar: FC = (props: AvatarProps) => { const avatarElement: JSX.Element = !!props.photoUrl ? ( - {`${props.handle} + {`${props.handle} ) : ( - + {props.firstName?.charAt(0)} {props.lastName?.charAt(0)} ) return ( -
+
{avatarElement}
) diff --git a/src/lib/button/Button.module.scss b/src/lib/button/Button.module.scss index 42b220c24..a2fcfa0d7 100644 --- a/src/lib/button/Button.module.scss +++ b/src/lib/button/Button.module.scss @@ -13,7 +13,7 @@ line-height: 24px; &:focus { - outline: 2px solid $turq-140; + outline: $border solid $turq-140; } &.button-sm { @@ -98,6 +98,43 @@ } } + &.link { + margin: 0; + padding: 0; + display: flex; + align-items: center; + font-size: 16px; + color: $turq-160; + background-color: $tc-white; + border: none; + outline: none; + border-radius: 0; + + &:focus { + outline: $border solid $turq-140; + } + + &:hover { + color: $turq-120; + } + + &:active { + color: $turq-180; + } + + &.disabled { + color: $black-60; + background-color: $tc-white; + border-color: $black-5; + } + + svg { + margin-left: $pad-xs; + height: $pad-lg; + width: $pad-lg; + } + } + &.text { border-color: transparent; } diff --git a/src/lib/button/Button.tsx b/src/lib/button/Button.tsx index c2d406360..012614da2 100644 --- a/src/lib/button/Button.tsx +++ b/src/lib/button/Button.tsx @@ -2,10 +2,12 @@ import classNames from 'classnames' import { FC } from 'react' import { Link } from 'react-router-dom' +import { IconOutline } from '../svgs' + import styles from './Button.module.scss' export type ButtonSize = 'sm' | 'md' | 'lg' | 'xl' -export type ButtonStyle = 'primary' | 'secondary' | 'tertiary' | 'text' +export type ButtonStyle = 'link' | 'primary' | 'secondary' | 'tertiary' | 'text' export type ButtonType = 'button' | 'submit' export interface ButtonProps { @@ -61,6 +63,7 @@ const Button: FC = (props: ButtonProps) => { type={props.type || 'button'} > {props.label} + {props.buttonStyle === 'link' && } ) } diff --git a/src/lib/card/Card.module.scss b/src/lib/card/Card.module.scss new file mode 100644 index 000000000..293ae1e89 --- /dev/null +++ b/src/lib/card/Card.module.scss @@ -0,0 +1,21 @@ +@import '../styles'; + +.card { + padding: $pad-lg $pad-lg $pad-xxxxl $pad-lg; + border: solid $border-xs $black-10; + border-radius: $pad-sm; + + .card-title { + @include font-weight-semi-bold; + @include font-barlow; + text-transform: uppercase; + display: flex; + justify-content: space-between; + margin-bottom: $pad-xl; + + svg { + height: $pad-xl; + width: $pad-xl; + } + } +} diff --git a/src/lib/button/Buttons.test.tsx b/src/lib/card/Card.test.tsx similarity index 74% rename from src/lib/button/Buttons.test.tsx rename to src/lib/card/Card.test.tsx index 0dae599ff..2544dd797 100644 --- a/src/lib/button/Buttons.test.tsx +++ b/src/lib/card/Card.test.tsx @@ -1,6 +1,6 @@ import '@testing-library/jest-dom' -describe('