Skip to content

Commit

Permalink
Merge pull request #1069 from near/feat/navigation-rework
Browse files Browse the repository at this point in the history
New Navigation Layout (Sidebar)
  • Loading branch information
calebjacob authored Mar 22, 2024
2 parents 5b73e3c + de556fa commit 719ee49
Show file tree
Hide file tree
Showing 57 changed files with 1,806 additions and 157 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ NEXT_PUBLIC_NOTIFICATIONS_APPLICATION_SERVER_KEY=
NEXT_PUBLIC_NOTIFICATIONS_GATEWAY_URL=
# commit modal bypass
NEXT_PUBLIC_COMMIT_MODAL_BYPASS_AUTHOR_IDS=near,discom.testnet,discom-dev.testnet
NEXT_PUBLIC_COMMIT_MODAL_BYPASS_SOURCES=
NEXT_PUBLIC_COMMIT_MODAL_BYPASS_SOURCES=
# sidebar or marketing layout
NEXT_PUBLIC_SIDEBAR_LAYOUT=true
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-tooltip": "^1.0.7",
"@sentry/nextjs": "^7.106.1",
"@web3-onboard/core": "^2.21.2",
"@web3-onboard/injected-wallets": "^2.10.11",
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions src/components/CookiePrompt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import styled from 'styled-components';

import { useBosComponents } from '@/hooks/useBosComponents';
import { useCookiePreferences } from '@/hooks/useCookiePreferences';

import { VmComponent } from './vm/VmComponent';

const Wrapper = styled.div`
position: fixed;
bottom: 0;
left: 0;
right: 0;
`;

export const CookiePrompt = () => {
const cookieData = useCookiePreferences();
const components = useBosComponents();
return (
<Wrapper>
<VmComponent
showLoadingSpinner={false}
src={components.nearOrg.cookiePrompt}
props={{ cookiesAcknowleged: cookieData }}
/>
</Wrapper>
);
};
91 changes: 84 additions & 7 deletions src/components/layouts/DefaultLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,96 @@
import type { ReactNode } from 'react';
import { useRouter } from 'next/router';
import { type ReactNode, useEffect, useState } from 'react';
import styled from 'styled-components';

import { sidebarLayoutEnabled as sidebarLayoutFeatureFlagEnabled } from '@/utils/config';

import { BosLoaderBanner } from '../BosLoaderBanner';
import { Navigation } from '../navigation/Navigation';
import { MarketingNavigation } from '../marketing-navigation/MarketingNavigation';
import { LargeScreenHeader } from '../sidebar-navigation/LargeScreenHeader';
import { SidebarNavigation } from '../sidebar-navigation/SidebarNavigation';
import { useNavigationStore } from '../sidebar-navigation/store';
import { SMALL_SCREEN_LAYOUT_MAX_WIDTH } from '../sidebar-navigation/utils';

interface Props {
children: ReactNode;
}

const Wrapper = styled.div<{
$animate: boolean;
$sidebar: boolean;
}>`
--sidebar-expand-transition-speed: ${(p) => (p.$animate ? '300ms' : '0ms')};
--sidebar-width-expanded: 256px;
--sidebar-width-collapsed: 68px;
--header-height: 64px;
display: flex;
min-height: 100vh;
min-width: 0;
justify-content: stretch;
align-items: stretch;
flex-direction: ${(p) => (p.$sidebar ? 'row' : 'column')};
@media (max-width: ${SMALL_SCREEN_LAYOUT_MAX_WIDTH}px) {
--sidebar-width-expanded: 100vw;
flex-direction: column;
}
`;

const Content = styled.div`
display: flex;
flex-direction: column;
flex-grow: 1;
justify-content: stretch;
align-items: stretch;
min-width: 0;
`;

export function DefaultLayout({ children }: Props) {
const router = useRouter();
const [sidebarLayoutTestOverrideEnabled, setSidebarLayoutTestOverrideEnabled] = useState(false);
const [sidebarLayoutShouldAnimate, setSidebarLayoutShouldAnimate] = useState(false);
const sidebarLayoutEnabled = sidebarLayoutTestOverrideEnabled || sidebarLayoutFeatureFlagEnabled;
const sidebarLayoutHasInitialized = useNavigationStore((store) => store.hasInitialized);

useEffect(() => {
/*
This logic is only needed for short term testing.
Add "?sidebar=true" to any URL to temporarily enable the sidebar layout.
*/

if (router.query.sidebar === 'true') {
setSidebarLayoutTestOverrideEnabled(true);
}
}, [router.query]);

useEffect(() => {
/*
We need to temporarily disable transition animations for the sidebar
until the expanded preference has resolved from local storage. Without
this logic, the sidebar would animate to collapsed on page load if the
user prefers the sidebar collapsed - the sidebar should initialize in
its proper collapsed or expanded state with animating on page load.
*/

if (sidebarLayoutHasInitialized) {
setTimeout(() => {
setSidebarLayoutShouldAnimate(true);
}, 100);
}
}, [sidebarLayoutHasInitialized]);

return (
<>
<Navigation />
<BosLoaderBanner />
<Wrapper $animate={sidebarLayoutShouldAnimate} $sidebar={sidebarLayoutEnabled}>
{sidebarLayoutEnabled ? <SidebarNavigation /> : <MarketingNavigation />}

<Content>
{sidebarLayoutEnabled && <LargeScreenHeader />}

<BosLoaderBanner />

{children}
</>
{children}
</Content>
</Wrapper>
);
}
15 changes: 15 additions & 0 deletions src/components/lib/Container/Container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styled from 'styled-components';

export const RootContentContainer = styled.div`
/*
NOTE: We don't want to set max-width or padding on this root container. If we did,
it would be impossible for application/component developers to have UI that bleeds
to the edge for designs that require background colors or images. The developer of
the components is responsible for setting an appropriate max-width and/or padding.
*/
flex-grow: 1;
width: 100%;
position: relative;
overflow: hidden;
`;
1 change: 1 addition & 0 deletions src/components/lib/Container/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Container';
84 changes: 84 additions & 0 deletions src/components/lib/Tooltip/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Tooltip

Implemented via Radix primitives: https://www.radix-ui.com/docs/primitives/components/tooltip

_If the current props and Stitches style overrides aren't enough to cover your use case, feel free to implement your own component using the Radix primitives directly._

## Example

Simply wrap the element you desire to have a tooltip with the `<Tooltip>` component:

```tsx
import { Tooltip } from '@/components/lib/Tooltip';

...

<Tooltip content="I am the tooltip message.">
<Button>Curious Button</Button>
</Tooltip>
```

## Props

To simplify usage of the Radix tooltip primitives, the component abstracts away the need for using `Root`, `Trigger`, and `Content` - all you need to do is use the single `<Tooltip>` component as shown above.

To pass a [Root](https://www.radix-ui.com/docs/primitives/components/tooltip#root) option, use the `root={{}}` property like so:

```tsx
<Tooltip
content="I am the tooltip message."
root={{
delayDuration: 500,
}}
>
...
</Tooltip>
```

To pass a [Content](https://www.radix-ui.com/docs/primitives/components/tooltip#content) option, pass it as you normally would like so:

```tsx
<Tooltip content="I am the tooltip message." side="left" align="end">
...
</Tooltip>
```

## Content

The `content` prop can be passed a string to render a default message:

```tsx
<Tooltip content="I am the tooltip message.">...</Tooltip>
```

A `ReactNode` can also be passed if you want to use a custom set of elements for the message.

```tsx
<Tooltip
content={
<>
<FeatherIcon icon="eye" /> I have an icon.
</>
}
>
...
</Tooltip>
```

## Disabled

Sometimes you might need to temporarily disable the tooltip from appearing. You can use the `disabled` prop to prevent the tooltip from showing while still letting the child element be interacted with:

```tsx
<Tooltip content="I am the tooltip message." disabled={shouldDisableTooltip}>
<Button>Curious Button</Button>
</Tooltip>
```

You can also disable the tooltip for touch screens:

```tsx
<Tooltip content="I will not show on touch screen devices." disabledTouchScreen>
<Button>Curious Button</Button>
</Tooltip>
```
42 changes: 42 additions & 0 deletions src/components/lib/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as Primitive from '@radix-ui/react-tooltip';
import type { ComponentProps, ReactElement, ReactNode } from 'react';

import * as S from './styles';

type RootProps = Omit<ComponentProps<typeof Primitive.Root>, 'children'>;
type ContentProps = ComponentProps<typeof Primitive.Content>;

type Props = ContentProps & {
children: ReactElement;
content: ReactNode;
disabled?: boolean;
root?: RootProps;
};

export const Tooltip = ({
children,
content,
disabled,
root = { disableHoverableContent: true },
side = 'top',
sideOffset = 3,
...props
}: Props) => {
const delayDuration = root?.delayDuration || 300;

return (
<Primitive.Provider>
<Primitive.Root delayDuration={delayDuration} open={disabled ? false : undefined} {...root}>
<Primitive.Trigger asChild>{children}</Primitive.Trigger>

<Primitive.Portal>
<S.Content side={side} sideOffset={sideOffset} {...props} ref={undefined}>
{content}
<S.ArrowBorder />
<S.ArrowFill />
</S.Content>
</Primitive.Portal>
</Primitive.Root>
</Primitive.Provider>
);
};
1 change: 1 addition & 0 deletions src/components/lib/Tooltip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Tooltip';
36 changes: 36 additions & 0 deletions src/components/lib/Tooltip/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as Primitive from '@radix-ui/react-tooltip';
import styled from 'styled-components';

export const Content = styled(Primitive.Content)`
border-radius: 0.25rem;
padding: 0.3rem 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
color: var(--sand12);
background-color: var(--white);
z-index: 2000;
max-width: 20rem;
font-size: 0.8rem;
line-height: 1.5;
word-break: break-word;
font-family: sans-serif;
box-shadow: 0 0 0 1px var(--sand6), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
`;

export const ArrowBorder = styled(Primitive.Arrow)`
fill: var(--sand6);
stroke: var(--sand6);
stroke-width: 2px;
margin-top: 1px;
margin-right: 1px;
[data-side='bottom'] &,
[data-side='left'] & {
margin-right: -1px;
}
`;

export const ArrowFill = styled(Primitive.Arrow)`
fill: var(--white);
`;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
import { DesktopNavigation } from './desktop/DesktopNavigation';
import { MobileNavigation } from './mobile/MobileNavigation';

export const Navigation = () => {
export const MarketingNavigation = () => {
const [matches, setMatches] = useState(true);

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import styled from 'styled-components';

import { VmComponent } from '@/components/vm/VmComponent';
import { useBosComponents } from '@/hooks/useBosComponents';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import styled from 'styled-components';
import { useCurrentComponentStore } from '@/stores/current-component';
import { recordMouseEnter } from '@/utils/analytics';

import { navigationCategories } from '../categories';
import { CurrentComponent } from '../CurrentComponent';
import { navigationCategories } from '../navigation-categories';

const Wrapper = styled.div`
position: relative;
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import styled from 'styled-components';

import { useCurrentComponentStore } from '@/stores/current-component';

import { navigationCategories } from '../categories';
import { CurrentComponent } from '../CurrentComponent';
import { navigationCategories } from '../navigation-categories';

type Props = {
onCloseMenu: () => void;
Expand Down
File renamed without changes.
8 changes: 1 addition & 7 deletions src/components/near-org/ComponentWrapperPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,7 @@ export function ComponentWrapperPage(props: Props) {
return (
<>
{props.meta && <MetaTags {...props.meta} />}
<div
style={{
paddingTop: 'var(--body-top-padding)',
}}
>
<VmComponent src={props.src} props={props.componentProps} />
</div>
<VmComponent src={props.src} props={props.componentProps} />
</>
);
}
Loading

0 comments on commit 719ee49

Please sign in to comment.