diff --git a/components/common/Button/index.module.scss b/components/common/Button/index.module.scss index b61e394d..407af421 100644 --- a/components/common/Button/index.module.scss +++ b/components/common/Button/index.module.scss @@ -46,6 +46,10 @@ flex-grow: 1; } + &.no-shrink { + flex-shrink: 0; + } + &.blended { background: transparent; } @@ -304,6 +308,15 @@ } } + &.notice { + background-color: var(--notice-button-bg); + color: var(--notice-button-text); + + &:hover { + background-color: var(--notice-button-bg-hover); + } + } + &.destructive { background: $error; color: white; diff --git a/components/party/PartyDropdown/index.tsx b/components/party/PartyDropdown/index.tsx index 52a2a8ca..eadea44e 100644 --- a/components/party/PartyDropdown/index.tsx +++ b/components/party/PartyDropdown/index.tsx @@ -1,5 +1,5 @@ // Libraries -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import { useRouter } from 'next/router' import { useSnapshot } from 'valtio' import { useTranslation } from 'next-i18next' @@ -33,12 +33,14 @@ interface Props { editable: boolean deleteTeamCallback: () => void remixTeamCallback: () => void + teamVisibilityCallback: () => void } const PartyDropdown = ({ editable, deleteTeamCallback, remixTeamCallback, + teamVisibilityCallback, }: Props) => { // Localization const { t } = useTranslation('common') @@ -81,6 +83,11 @@ const PartyDropdown = ({ // Methods: Event handlers + // Dialogs / Visibility + function visibilityCallback() { + teamVisibilityCallback() + } + // Alerts / Delete team function openDeleteTeamAlert() { setDeleteAlertOpen(true) @@ -125,6 +132,9 @@ const PartyDropdown = ({ const items = ( <> + + {t('dropdown.party.visibility')} + {t('dropdown.party.copy')} diff --git a/components/party/PartyHeader/index.module.scss b/components/party/PartyHeader/index.module.scss index 892feb5f..dd343bcf 100644 --- a/components/party/PartyHeader/index.module.scss +++ b/components/party/PartyHeader/index.module.scss @@ -18,6 +18,41 @@ } } + .notice { + align-items: center; + background: var(--notice-bg); + border-radius: $card-corner; + display: flex; + gap: $unit-2x; + font-size: $font-regular; + justify-content: space-between; + padding: $unit-4x; + overflow: hidden; + + @include breakpoint(small-tablet) { + flex-direction: column; + gap: $unit; + padding: $unit-2x; + } + + p { + color: var(--notice-text); + } + + .buttons { + justify-content: flex-end; + display: flex; + flex-shrink: 0; + gap: $unit; + + @include breakpoint(small-tablet) { + flex-direction: column; + justify-content: center; + width: 100%; + } + } + } + .details { box-sizing: border-box; display: block; diff --git a/components/party/PartyHeader/index.tsx b/components/party/PartyHeader/index.tsx index 4c889045..a78cb9b7 100644 --- a/components/party/PartyHeader/index.tsx +++ b/components/party/PartyHeader/index.tsx @@ -27,6 +27,8 @@ import SaveIcon from '~public/icons/Save.svg' import type { DetailsObject } from 'types' import styles from './index.module.scss' +import PartyVisibilityDialog from '../PartyVisibilityDialog' +import UrlCopiedToast from '~components/toasts/UrlCopiedToast' // Props interface Props { @@ -50,8 +52,10 @@ const PartyHeader = (props: Props) => { // State: Component const [detailsOpen, setDetailsOpen] = useState(false) + const [copyToastOpen, setCopyToastOpen] = useState(false) const [remixAlertOpen, setRemixAlertOpen] = useState(false) const [remixToastOpen, setRemixToastOpen] = useState(false) + const [visibilityDialogOpen, setVisibilityDialogOpen] = useState(false) const userClass = classNames({ [styles.user]: true, @@ -122,12 +126,29 @@ const PartyHeader = (props: Props) => { setDetailsOpen(open) } + // Dialogs: Visibility + function visibilityDialogCallback() { + setVisibilityDialogOpen(true) + } + + function handleVisibilityDialogChange(open: boolean) { + setVisibilityDialogOpen(open) + } + // Actions: Remix team function remixTeamCallback() { setRemixToastOpen(true) props.remixCallback() } + // Actions: Copy URL + function copyToClipboard() { + if (router.asPath.split('/')[1] === 'p') { + navigator.clipboard.writeText(window.location.href) + setCopyToastOpen(true) + } + } + // Alerts: Remix team function openRemixTeamAlert() { setRemixAlertOpen(true) @@ -146,6 +167,15 @@ const PartyHeader = (props: Props) => { setRemixToastOpen(false) } + // Toasts / Copy URL + function handleCopyToastOpenChanged(open: boolean) { + setCopyToastOpen(!open) + } + + function handleCopyToastCloseClicked() { + setCopyToastOpen(false) + } + // Rendering const userBlock = (username?: string, picture?: string, element?: string) => { @@ -298,6 +328,44 @@ const PartyHeader = (props: Props) => { ) } + // Render: Notice + const unlistedNotice = ( +
+

{t('party.notices.unlisted')}

+
+
+
+ ) + + const privateNotice = ( +
+

{t('party.notices.private')}

+
+
+
+ ) + // Render: Buttons const saveButton = () => { return ( @@ -358,6 +426,8 @@ const PartyHeader = (props: Props) => { return ( <>
+ {party.visibility == 2 && unlistedNotice} + {party.visibility == 3 && privateNotice}
@@ -399,6 +469,7 @@ const PartyHeader = (props: Props) => { editable={props.editable} deleteTeamCallback={props.deleteCallback} remixTeamCallback={props.remixCallback} + teamVisibilityCallback={visibilityDialogCallback} /> )}
@@ -412,6 +483,13 @@ const PartyHeader = (props: Props) => {
{renderTokens()}
+ + { onOpenChange={handleRemixToastOpenChanged} onCloseClick={handleRemixToastCloseClicked} /> + + ) }