-
+ {!hideSocialLinks ? (
+
+ ) : null}
© {new Date().getFullYear()} Decentraland
diff --git a/src/components/Icons/DownloadIcon.tsx b/src/components/Icons/DownloadIcon.tsx
new file mode 100644
index 00000000..aa6dfe9f
--- /dev/null
+++ b/src/components/Icons/DownloadIcon.tsx
@@ -0,0 +1,24 @@
+import React from 'react'
+
+import './styles.css'
+
+const DownloadIcon = () => (
+
+)
+
+export default DownloadIcon
diff --git a/src/components/Navbar/MainMenu/MainMenu.tsx b/src/components/Navbar/MainMenu/MainMenu.tsx
index 6b0c6d0c..0fb1c4e4 100644
--- a/src/components/Navbar/MainMenu/MainMenu.tsx
+++ b/src/components/Navbar/MainMenu/MainMenu.tsx
@@ -1,10 +1,10 @@
-import React from 'react'
+import React, { useEffect, useRef, useState } from 'react'
import classNames from 'classnames'
import { MenuItem } from '../MenuItem/MenuItem'
import { NavbarPages } from '../Navbar.types'
import { MainMenuProps } from './MainMenu.types'
-import { getNavbarPagesUrls } from '../utils'
+import { getExtraButton, getNavbarPagesUrls, NavbarExtraButton } from '../utils'
import './MainMenu.css'
@@ -13,6 +13,22 @@ export const MainMenu = (props: MainMenuProps) => {
const urls = getNavbarPagesUrls()
+ // load extra button
+ const isMounted = useRef(false)
+ const [extraButton, setExtraButton] = useState
(null)
+ useEffect(() => {
+ isMounted.current = true
+ if (!extraButton) {
+ getExtraButton().then((button) => {
+ if (!isMounted.current) return
+ setExtraButton(button)
+ })
+ }
+ return () => {
+ isMounted.current = false
+ }
+ }, [extraButton, isMounted, setExtraButton])
+
return (
{
title={i18n.create}
mainUrl={urls[NavbarPages.CREATE]}
/>
-
)
}
diff --git a/src/components/Navbar/MenuItem/MenuItem.css b/src/components/Navbar/MenuItem/MenuItem.css
index 1d771f34..27fca789 100644
--- a/src/components/Navbar/MenuItem/MenuItem.css
+++ b/src/components/Navbar/MenuItem/MenuItem.css
@@ -12,6 +12,27 @@
fill: var(--text);
}
+.dui-navbar
+ .dui-navbar-wrapper
+ .item:not(.mobile).dui-menu-item.extra.has-background {
+ height: calc(100% - 24px);
+ padding: 12px;
+ margin-top: 12px;
+}
+
+.item.mobile.dui-menu-item.extra.has-background {
+ margin-top: 40px;
+ padding: 20px;
+ width: calc(100% - 50px - 40px);
+ border-radius: 8px;
+ justify-content: center;
+ border-bottom: none;
+}
+
+.item.mobile.dui-menu-item.extra.has-background .dui-icon-container.centered {
+ display: none;
+}
+
@media (max-width: 991px) {
.item.dui-menu-item.mobile {
cursor: pointer;
diff --git a/src/components/Navbar/MenuItem/MenuItem.tsx b/src/components/Navbar/MenuItem/MenuItem.tsx
index f7a72e4d..c76dfb2c 100644
--- a/src/components/Navbar/MenuItem/MenuItem.tsx
+++ b/src/components/Navbar/MenuItem/MenuItem.tsx
@@ -8,8 +8,17 @@ import { MenuItemProps } from './MenuItem.types'
import './MenuItem.css'
export const MenuItem = (props: MenuItemProps) => {
- const { activePage, section, title, onToggleShowSubMenu, isMobile, mainUrl } =
- props
+ const {
+ activePage,
+ section,
+ title,
+ onToggleShowSubMenu,
+ isMobile,
+ mainUrl,
+ textColor,
+ backgroundColor,
+ isExtraButton
+ } = props
const mainRedirect = useCallback(() => {
mainUrl && window.open(mainUrl, '_self')
@@ -19,7 +28,9 @@ export const MenuItem = (props: MenuItemProps) => {
{
- isMobile ? onToggleShowSubMenu(e, true, section) : mainRedirect()
+ isMobile && !isExtraButton
+ ? onToggleShowSubMenu(e, true, section)
+ : mainRedirect()
}}
onMouseEnter={(e: React.MouseEvent) =>
!isMobile && onToggleShowSubMenu(e, true, section)
@@ -27,7 +38,13 @@ export const MenuItem = (props: MenuItemProps) => {
onMouseLeave={(e: React.MouseEvent) =>
!isMobile && onToggleShowSubMenu(e, false, section)
}
- className={classNames('dui-menu-item', section, isMobile && 'mobile')}
+ className={classNames(
+ 'dui-menu-item',
+ section,
+ isMobile && 'mobile',
+ backgroundColor && 'has-background'
+ )}
+ style={{ color: textColor, backgroundColor }}
>
{title}
{isMobile && }
diff --git a/src/components/Navbar/MenuItem/MenuItem.types.ts b/src/components/Navbar/MenuItem/MenuItem.types.ts
index c8d9aff4..c5b8c6f0 100644
--- a/src/components/Navbar/MenuItem/MenuItem.types.ts
+++ b/src/components/Navbar/MenuItem/MenuItem.types.ts
@@ -11,4 +11,7 @@ export type MenuItemProps = {
) => void
mainUrl?: string
isMobile?: boolean
+ isExtraButton?: boolean
+ textColor?: string
+ backgroundColor?: string
}
diff --git a/src/components/Navbar/Navbar.defaults.ts b/src/components/Navbar/Navbar.defaults.ts
index 706a00ed..706ae892 100644
--- a/src/components/Navbar/Navbar.defaults.ts
+++ b/src/components/Navbar/Navbar.defaults.ts
@@ -3,11 +3,11 @@ import { ChainSelectori18n } from '../ChainSelector/ChainSelector.props'
import { NavbarMenuI18nProps, NavbarSubmenuProps } from './Navbar.types'
export const navbarMainTitlesI18N = {
- marketplace: 'marketplace',
+ marketplace: 'shop',
create: 'create',
- explore: 'explore',
learn: 'learn',
- governance: 'governance'
+ governance: 'vote',
+ explore: 'events'
} as NavbarMenuI18nProps
export const i18nChainSelectorDefault = {
@@ -89,8 +89,8 @@ export const navbarSubmenu = {
{
title: 'Scenes',
description: 'Create & publish scenes to LAND or Worlds',
- url: config.get('BUILDER_SCENES_URL'),
- eventTrackingName: 'builder_scenes'
+ url: config.get('CREATOR_HUB_URL'),
+ eventTrackingName: 'creator_hub_scenes'
}
],
column3Title: 'MANAGE',
diff --git a/src/components/Navbar/Navbar.types.ts b/src/components/Navbar/Navbar.types.ts
index 22b6f2f4..27d98190 100644
--- a/src/components/Navbar/Navbar.types.ts
+++ b/src/components/Navbar/Navbar.types.ts
@@ -9,10 +9,11 @@ export enum NavbarPages {
CREATE = 'create',
EXPLORE = 'explore',
LEARN = 'learn',
- GOVERNANCE = 'governance'
+ GOVERNANCE = 'governance',
+ EXTRA = 'extra'
}
-export type NavbarMenuI18nProps = Record
+export type NavbarMenuI18nProps = Record
export type NavbarSubMenuItemsProps = {
column1Title?: string
diff --git a/src/components/Navbar/utils.ts b/src/components/Navbar/utils.ts
index 4ae4a8f7..68bfe11d 100644
--- a/src/components/Navbar/utils.ts
+++ b/src/components/Navbar/utils.ts
@@ -10,3 +10,52 @@ export const getNavbarPagesUrls = () => {
[NavbarPages.GOVERNANCE]: config.get('GOVERNANCE_URL')
}
}
+
+export type NavbarExtraButton = {
+ text: string
+ link: string
+ visible: boolean
+ textColor?: `#${string}`
+ backgroundColor?: `#${string}`
+ id?: string
+ ttl: number
+}
+
+export type LocalStorageNavbarExtraButton = {
+ button: NavbarExtraButton
+ expiresAt: number
+}
+
+export const getExtraButton = async () => {
+ const cachedExtraButton = localStorage.getItem('navbarExtraButton')
+ if (cachedExtraButton) {
+ try {
+ const parsed = JSON.parse(
+ cachedExtraButton
+ ) as LocalStorageNavbarExtraButton
+ if (parsed.expiresAt > Date.now()) {
+ return parsed.button
+ }
+ } catch (error) {
+ // error parsing cached data, ignore and fetch from Contentful
+ }
+ }
+ try {
+ const SPACE_ID = config.get('CONTENTFUL_SPACE_ID')
+ const ENV = config.get('CONTENTFUL_ENV')
+ const ACCESS_TOKEN = config.get('CONTENTFUL_NAVBAR_ACCESS_TOKEN')
+ const ENTRY_ID = config.get('CONTENTFUL_NAVBAR_ENTRY_ID')
+ const CONTENTFUL_URL = `https://cdn.contentful.com/spaces/${SPACE_ID}/environments/${ENV}/entries/${ENTRY_ID}?access_token=${ACCESS_TOKEN}`
+ const response = await fetch(CONTENTFUL_URL)
+ const entry = await response.json()
+ const button = entry.fields as NavbarExtraButton
+ localStorage.setItem(
+ 'navbarExtraButton',
+ JSON.stringify({ button, expiresAt: Date.now() + button.ttl * 1000 })
+ )
+ return button
+ } catch (error) {
+ console.error(error)
+ return null
+ }
+}
diff --git a/src/components/UserMenu/UserMenu.css b/src/components/UserMenu/UserMenu.css
index e7d190a9..fa60a5e9 100644
--- a/src/components/UserMenu/UserMenu.css
+++ b/src/components/UserMenu/UserMenu.css
@@ -11,13 +11,21 @@
height: 100%;
}
-.dcl .user-menu__jump-in {
+.dcl .user-menu__download {
padding: 14px 32px;
margin-left: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ column-gap: 2px;
+}
+
+.dcl .user-menu__download svg g path {
+ fill: var(--text-on-primary);
}
@media (max-width: 991px) {
- .dcl .user-menu__jump-in {
+ .dcl .user-menu__download {
display: none;
}
}
diff --git a/src/components/UserMenu/UserMenu.i18n.ts b/src/components/UserMenu/UserMenu.i18n.ts
index 772ac3bd..8b6244c9 100644
--- a/src/components/UserMenu/UserMenu.i18n.ts
+++ b/src/components/UserMenu/UserMenu.i18n.ts
@@ -4,7 +4,7 @@ export const i18n = {
account: 'Account Settings',
activity: 'Activity',
guest: 'Guest',
- jumpIn: 'Jump In',
+ download: 'Download',
marketplaceAuthorizations: 'Marketplace Authorizations',
myAssets: 'My Assets',
myLists: 'My Lists',
diff --git a/src/components/UserMenu/UserMenu.tsx b/src/components/UserMenu/UserMenu.tsx
index 72479e28..d12756f7 100644
--- a/src/components/UserMenu/UserMenu.tsx
+++ b/src/components/UserMenu/UserMenu.tsx
@@ -14,6 +14,7 @@ import { Row } from '../Row/Row'
import './UserMenu.css'
import { useTabletAndBelowMediaQuery } from '../Media'
+import DownloadIcon from '../Icons/DownloadIcon'
export const UserMenu = React.memo((props: UserMenuProps) => {
const {
@@ -25,7 +26,7 @@ export const UserMenu = React.memo((props: UserMenuProps) => {
onClickSignIn,
onClickBalance,
onClickOpen,
- onClickJumpIn,
+ onClickDownload,
onClickUserMenuItem,
...signInProps
} = props
@@ -66,26 +67,26 @@ export const UserMenu = React.memo((props: UserMenuProps) => {
}
}, [setIsOpen])
- const handleClickJumpIn = useCallback(
+ const handleDownload = useCallback(
(event: React.MouseEvent) => {
event.preventDefault()
onClickUserMenuItem &&
onClickUserMenuItem(event, {
- type: UserMenuEventId.JUMP_IN,
+ type: UserMenuEventId.DOWNLOAD,
track_uuid: trackingId,
- url: config.get('EXPLORER_URL')
+ url: config.get('DOWNLOAD_URL')
})
setTimeout(
() => {
- onClickJumpIn
- ? onClickJumpIn(event)
- : window.open(config.get('EXPLORER_URL'), '_blank', 'noopener')
+ onClickDownload
+ ? onClickDownload(event)
+ : window.open(config.get('DOWNLOAD_URL'), '_blank', 'noopener')
},
onClickUserMenuItem ? 300 : 0
)
},
- [onClickJumpIn, onClickUserMenuItem, trackingId]
+ [onClickDownload, onClickUserMenuItem, trackingId]
)
const handleClickSignIn = useCallback(
@@ -163,17 +164,16 @@ export const UserMenu = React.memo((props: UserMenuProps) => {
{i18n.signIn}
) : null}
- {isSignedIn && (
-
- )}
+
>
)}
diff --git a/src/components/UserMenu/UserMenu.types.ts b/src/components/UserMenu/UserMenu.types.ts
index a888cd68..74fcd986 100644
--- a/src/components/UserMenu/UserMenu.types.ts
+++ b/src/components/UserMenu/UserMenu.types.ts
@@ -15,7 +15,7 @@ export type UserMenuProps = Omit<
event: React.MouseEvent