diff --git a/src/app/_components/Footer/StacksSmiley.tsx b/src/app/_components/Footer/StacksSmiley.tsx
new file mode 100644
index 000000000..91d2a2b2b
--- /dev/null
+++ b/src/app/_components/Footer/StacksSmiley.tsx
@@ -0,0 +1,23 @@
+import { StacksSmileyIcon } from '@/ui/icons/StacksSmileyIcon';
+import { Box, BoxProps, Icon } from '@chakra-ui/react';
+import { useState } from 'react';
+
+export const StacksSmiley = (boxProps: BoxProps) => {
+ const [isHovered, setIsHovered] = useState(false);
+ return (
+ setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
+ {...boxProps}
+ >
+
+
+
+
+ );
+};
diff --git a/src/app/_components/NewFooter.tsx b/src/app/_components/NewFooter.tsx
new file mode 100644
index 000000000..f973f2b33
--- /dev/null
+++ b/src/app/_components/NewFooter.tsx
@@ -0,0 +1,231 @@
+import { ExplorerLink } from '@/common/components/ExplorerLinks';
+import { HiroIcon } from '@/ui/icons/HiroIcon';
+import { StacksNameAndLogoIcon } from '@/ui/icons/StacksNameAndLogoIcon';
+import { Box, Flex, Grid, Icon, Stack, Text } from '@chakra-ui/react';
+
+import { PAGE_MAX_WIDTH } from '../../common/constants/constants';
+import { Link } from '../../ui/Link';
+import { StacksSmiley } from './Footer/StacksSmiley';
+
+interface Link {
+ label: string;
+ href: string;
+}
+
+const rightSideLinks: Link[] = [
+ {
+ label: 'Home',
+ href: '/',
+ },
+ {
+ label: 'Blocks',
+ href: '/blocks',
+ },
+ {
+ label: 'Transactions',
+ href: '/transactions',
+ },
+ {
+ label: 'sBTC',
+ href: '/token/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token',
+ },
+ {
+ // This page is not implemented yet
+ label: 'Stacking',
+ href: '/stacking',
+ },
+ {
+ // This page is not implemented yet
+ label: 'Mempool',
+ href: '/mempool',
+ },
+ {
+ label: 'Signers',
+ href: '/signers',
+ },
+ {
+ label: 'Tokens',
+ href: '/tokens',
+ },
+ {
+ // This page is not implemented yet
+ label: 'NFTs',
+ href: '/nfts',
+ },
+ {
+ // This page is not implemented yet
+ label: 'Analytics',
+ href: '/analytics',
+ },
+ {
+ label: 'Search',
+ href: '/search',
+ },
+];
+
+const leftSideLinks: Link[] = [
+ {
+ label: 'Sandbox',
+ href: '/sandbox/deploy',
+ },
+ {
+ label: 'Status Center',
+ href: 'https://status.hiro.so/',
+ },
+ {
+ label: 'Support',
+ href: '/support',
+ },
+];
+
+const xPadding = 8;
+
+const TopFooterContent = () => {
+ return (
+ <>
+
+
+
+ {rightSideLinks.map(link => (
+
+ {link.label}
+
+ ))}
+
+
+
+ {leftSideLinks.map(link => (
+
+ {link.label}
+
+ ))}
+
+
+
+
+
+ {rightSideLinks.concat(leftSideLinks).map(link => (
+
+ {link.label}
+
+ ))}
+
+
+ >
+ );
+};
+
+const BottomFooterContent = () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
+
+const BottomLinks = () => {
+ return (
+
+
+
+
+ This Stacks Explorer is built and maintained by{' '}
+
+ Hiro
+
+
+
+
+ Terms of Use
+
+
+ Privacy Policy
+
+
+ Market data provided by{' '}
+
+ LunarCrush
+
+
+
+ );
+};
+
+export const NewFooter = () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/app/_components/PageWrapper.tsx b/src/app/_components/PageWrapper.tsx
index af27895f1..d12e7db48 100644
--- a/src/app/_components/PageWrapper.tsx
+++ b/src/app/_components/PageWrapper.tsx
@@ -1,5 +1,6 @@
'use client';
+import { isRedesignUrl } from '@/common/utils/url-utils';
import { Stack } from '@chakra-ui/react';
import styled from '@emotion/styled';
import { ReactNode } from 'react';
@@ -11,6 +12,7 @@ import { TokenPrice } from '../../common/types/tokenPrice';
import { Footer } from './Footer';
import { NavBar } from './NavBar';
import { NetworkModeToast } from './NetworkModeToast';
+import { NewFooter } from './NewFooter';
import { CMSStatusBars } from './StatusBar/CMSStatusBars';
import { IncidentsStatusBarWithErrorBoundary } from './StatusBar/IncidentsStatusBar';
import { NonHiroNetworkWarningBar } from './StatusBar/NonHiroNetworkWarningBar';
@@ -82,6 +84,7 @@ export function PageWrapper({
statusBarContent: IncidentContent | null;
serverThemeCookie: string;
}) {
+ const redesignUrl = isRedesignUrl();
return (
<>
@@ -99,7 +102,7 @@ export function PageWrapper({
>
{children}
-
+ {redesignUrl ? : }
diff --git a/src/app/txid/[txId]/TxDetails/__tests__/Broadcast.test.tsx b/src/app/txid/[txId]/TxDetails/__tests__/Broadcast.test.tsx
deleted file mode 100644
index a64e881f3..000000000
--- a/src/app/txid/[txId]/TxDetails/__tests__/Broadcast.test.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { renderWithChakraProviders } from '@/common/utils/test-utils/render-utils';
-import '@testing-library/jest-dom/extend-expect';
-
-import { Transaction } from '@stacks/stacks-blockchain-api-types';
-
-import '../../../../../common/utils/test-utils/matchMedia.mock';
-import { Broadcast } from '../Broadcast';
-
-describe('', () => {
- it('renders correctly', () => {
- const hardcodedDate = new Date('2023-01-01T12:00:00Z');
-
- const mockTx = {
- receipt_time: Math.floor(hardcodedDate.getTime() / 1000),
- } as unknown as Transaction;
-
- const { asFragment } = renderWithChakraProviders();
- expect(asFragment()).toMatchSnapshot();
- });
-});
diff --git a/src/app/txid/[txId]/TxDetails/__tests__/__snapshots__/Broadcast.test.tsx.snap b/src/app/txid/[txId]/TxDetails/__tests__/__snapshots__/Broadcast.test.tsx.snap
deleted file mode 100644
index 9466abe58..000000000
--- a/src/app/txid/[txId]/TxDetails/__tests__/__snapshots__/Broadcast.test.tsx.snap
+++ /dev/null
@@ -1,144 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[` renders correctly 1`] = `
-
-
-
-`;
diff --git a/src/common/utils/url-utils.ts b/src/common/utils/url-utils.ts
index f6084d229..3afaeb231 100644
--- a/src/common/utils/url-utils.ts
+++ b/src/common/utils/url-utils.ts
@@ -9,3 +9,12 @@ const isImage = (url: string): boolean => {
const extension = urlWithoutParams.split('.').pop();
return !!extension && ['png', 'jpg', 'jpeg', 'gif', 'svg'].includes(extension);
};
+
+export const isRedesignUrl = (): boolean => {
+ if (typeof window === 'undefined') {
+ return false;
+ }
+ const queryParams = new URLSearchParams(window.location.search);
+ const redesignParam = queryParams.get('redesign');
+ return !!redesignParam;
+};
diff --git a/src/ui/icons/HiroIcon.tsx b/src/ui/icons/HiroIcon.tsx
new file mode 100644
index 000000000..061057daa
--- /dev/null
+++ b/src/ui/icons/HiroIcon.tsx
@@ -0,0 +1,32 @@
+import { Icon, IconProps } from '@chakra-ui/react';
+
+export const HiroIcon = ({ color, ...rest }: IconProps) => {
+ return (
+
+
+
+ );
+};
diff --git a/src/ui/icons/StacksNameAndLogoIcon.tsx b/src/ui/icons/StacksNameAndLogoIcon.tsx
new file mode 100644
index 000000000..7fec41ef5
--- /dev/null
+++ b/src/ui/icons/StacksNameAndLogoIcon.tsx
@@ -0,0 +1,80 @@
+import { IconBase, IconWeight } from '@phosphor-icons/react';
+import { ReactElement, forwardRef } from 'react';
+
+interface StacksNameAndLogoIconWeightProps {
+ color: string;
+}
+
+const createWeight = ({ color }: StacksNameAndLogoIconWeightProps): ReactElement => (
+
+);
+
+const weights = new Map ReactElement>([
+ ['regular', createWeight],
+]);
+
+interface StacksNameAndLogoIconProps extends StacksNameAndLogoIconWeightProps {
+ weight?: IconWeight;
+}
+
+export const StacksNameAndLogoIcon = forwardRef(
+ (props, ref) => {
+ const { color, weight = 'regular', ...restProps } = props;
+ const weightFn = weights.get(weight);
+ const weightElement = weightFn?.({ color });
+
+ if (!weightElement) return null;
+
+ return (
+
+ );
+ }
+);
+
+StacksNameAndLogoIcon.displayName = 'StacksNameAndLogoIcon';
diff --git a/src/ui/icons/StacksSmileyIcon.tsx b/src/ui/icons/StacksSmileyIcon.tsx
new file mode 100644
index 000000000..95d906ea9
--- /dev/null
+++ b/src/ui/icons/StacksSmileyIcon.tsx
@@ -0,0 +1,293 @@
+import { IconBase, IconWeight } from '@phosphor-icons/react';
+import { ReactElement, forwardRef } from 'react';
+
+interface StacksSmileyIconWeightProps {
+ circleColor: string;
+ linearGradientColor: string;
+ laserEyesOn?: boolean;
+}
+
+const createWeight = ({
+ circleColor,
+ linearGradientColor,
+ laserEyesOn,
+}: StacksSmileyIconWeightProps): ReactElement => (
+
+);
+
+const weights = new Map ReactElement>([
+ ['regular', createWeight],
+]);
+
+interface StacksSmileyIconProps extends StacksSmileyIconWeightProps {
+ weight?: IconWeight;
+}
+
+export const StacksSmileyIcon = forwardRef((props, ref) => {
+ const { circleColor, linearGradientColor, laserEyesOn, weight = 'regular', ...restProps } = props;
+ const weightFn = weights.get(weight);
+ const weightElement = weightFn?.({ circleColor, linearGradientColor, laserEyesOn });
+
+ if (!weightElement) return null;
+
+ return (
+
+ );
+});
+
+StacksSmileyIcon.displayName = 'StacksSmileyIcon';
diff --git a/src/ui/theme/recipes/LinkRecipe.ts b/src/ui/theme/recipes/LinkRecipe.ts
index 94a101a2b..ced9d9354 100644
--- a/src/ui/theme/recipes/LinkRecipe.ts
+++ b/src/ui/theme/recipes/LinkRecipe.ts
@@ -1,5 +1,3 @@
-'use client';
-
import { defineRecipe } from '@chakra-ui/react';
export const linkRecipe = defineRecipe({
diff --git a/src/ui/theme/semanticTokens.ts b/src/ui/theme/semanticTokens.ts
index 87e896217..af85615e2 100644
--- a/src/ui/theme/semanticTokens.ts
+++ b/src/ui/theme/semanticTokens.ts
@@ -243,6 +243,20 @@ export const CURRENT_SEMANTIC_TOKENS = {
},
},
},
+ stacksSmiley: {
+ eyeColor: {
+ value: { base: '#FD6112', _dark: '#141414' },
+ },
+ circleColor: {
+ value: { base: '#F7F6F5', _dark: '#0C0C0D' },
+ },
+ linearGradientColor: {
+ value: { base: '#E5E0DC', _dark: '#3C3A38' },
+ },
+ },
+ stacksNameAndLogo: {
+ value: { base: '{colors.neutral.sand-1000}', _dark: '{colors.neutral.sand-50}' },
+ },
},
};
diff --git a/src/ui/theme/sizes.ts b/src/ui/theme/sizes.ts
index f9b9f9975..137670420 100644
--- a/src/ui/theme/sizes.ts
+++ b/src/ui/theme/sizes.ts
@@ -19,9 +19,11 @@ import { SPACE } from './space';
// };
export const CURRENT_SIZES = {
- 4.5: { value: '1.125rem' },
- 60: { value: '3.75rem' },
- 150: { value: '9.375rem' },
+ 3.5: { value: '0.875rem' }, // 14px
+ 4.5: { value: '1.125rem' }, // 18px
+ 18: { value: '4.5rem' }, // 72px
+ 60: { value: '3.75rem' }, // 60px
+ 150: { value: '9.375rem' }, // 150px
};
export const NEW_SIZES = {
diff --git a/src/ui/theme/space.ts b/src/ui/theme/space.ts
index ad5f6ab46..6b6dd041f 100644
--- a/src/ui/theme/space.ts
+++ b/src/ui/theme/space.ts
@@ -43,6 +43,7 @@ export const NEW_SPACE = {
1: { value: '0.25rem' }, // 4px
2: { value: '0.5rem' }, // 8px
3: { value: '0.75rem' }, // 12px
+ 3.5: { value: '0.875rem' }, // 14px
4: { value: '1rem' }, // 16px
4.5: { value: '1.125rem' },
5: { value: '1.25rem' }, // 20px