Skip to content

Commit

Permalink
Merge pull request #81 from inkonchain/feat/wallet
Browse files Browse the repository at this point in the history
feat: implement basic wallet column
  • Loading branch information
fran-ink authored Mar 3, 2025
2 parents 5119267 + 0b68d61 commit 6a05f6f
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 24 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"dependencies": {
"@hookform/resolvers": "3.9.1",
"@inkonchain/ink-kit": "0.9.1-beta.16",
"@inkonchain/ink-kit": "0.9.1-beta.18",
"@next/third-parties": "15.1.6",
"@octokit/auth-app": "7.1.3",
"@octokit/rest": "21.0.2",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

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

16 changes: 16 additions & 0 deletions src/app/[locale]/_components/LayoutColumns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { OnlyWithFeatureFlag } from "@/components/OnlyWithFeatureFlag";

import { WalletPanel } from "./Wallet/WalletPanel";

export function LayoutColumns({ children }: { children: React.ReactNode }) {
return (
<OnlyWithFeatureFlag flag="walletColumn" otherwise={children}>
<div className="grid grid-cols-1 lg:grid-cols-[minmax(0,1fr)_396px] gap-4 w-full">
<div>{children}</div>
<div>
<WalletPanel />
</div>
</div>
</OnlyWithFeatureFlag>
);
}
102 changes: 102 additions & 0 deletions src/app/[locale]/_components/Wallet/WalletPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"use client";
import { toast } from "react-toastify";
import { Button, InkIcon } from "@inkonchain/ink-kit";
import { useEnsAddress } from "wagmi";

import { ConnectWalletButton } from "@/components/ConnectWalletButton";
import { useWallet } from "@/contexts/WalletProvider";
import { truncateAddress, truncateEnsName } from "@/util/formatWallet";

export function WalletPanel() {
const { isConnected, address } = useWallet();

function notYet() {
toast.info("Not yet implemented");
}

return (
<div className="flex flex-col gap-4 container mx-auto">
<div className="min-h-[244px] relative ink:bg-button-secondary ink:backdrop-blur-sm flex flex-col justify-between ink:rounded-sm">
{!isConnected && (
<div className="absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100 transition-opacity duration-150 hover:backdrop-blur-sm">
<ConnectWalletButton variant="primary" />
</div>
)}
<div className="flex items-center justify-between p-5 px-6 gap-4">
<div className="ink:text-h5 ink:text-text-muted">Balance</div>
{isConnected && (
<Button
className="ink:text-text-muted"
variant="transparent"
size="md"
onClick={() => {
navigator.clipboard.writeText(address || "");
toast.info("Copied to clipboard");
}}
iconRight={<InkIcon.Copy />}
>
<EnsOrAddress address={address || ""} />
</Button>
)}
</div>
<div className="flex-1" />
<div className="flex items-center justify-between p-6">
<div className="ink:text-h3 ink:text-text-muted">$0.00</div>
<div className="">
<InkIcon.Logo.Ink className="size-10 text-(--ink-button-secondary)" />
</div>
</div>
</div>
<div className="flex justify-evenly gap-6">
<WalletPanelButton
icon={<InkIcon.Arrow className="size-5" />}
label="Receive"
onClick={notYet}
/>
<WalletPanelButton
icon={<InkIcon.Arrow className="size-5 rotate-180" />}
label="Send"
onClick={notYet}
/>
<WalletPanelButton
icon={<InkIcon.Bridge className="size-5" />}
label="Bridge"
onClick={notYet}
/>
<WalletPanelButton
icon={<InkIcon.Deposit className="size-5" />}
label="Deposit"
onClick={notYet}
/>
</div>
</div>
);
}

const EnsOrAddress = ({ address }: { address: string }) => {
const { data: ens } = useEnsAddress();
return (
<div className="truncate">
{ens ? truncateEnsName(ens) : truncateAddress(address)}
</div>
);
};

const WalletPanelButton = ({
icon,
label,
onClick,
}: {
icon: React.ReactNode;
label: string;
onClick: () => void;
}) => {
return (
<div className="flex flex-col items-center gap-2">
<Button size="lg" rounded="full" variant="secondary" onClick={onClick}>
{icon}
</Button>
<div className="ink:text-caption-1-bold ink:text-text-muted">{label}</div>
</div>
);
};
2 changes: 1 addition & 1 deletion src/app/[locale]/apps/_components/AppsCategoryFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const AppsCategoryFilter = ({
[selected, query]
);
return (
<ScrollWithGradient className="flex overflow-x-scroll flex-1 w-full sm:w-auto no-scrollbar">
<ScrollWithGradient className="flex overflow-x-scroll flex-1 w-full sm:w-auto no-scrollbar min-w-sm">
<SegmentedControl
variant="tag"
variableTabWidth
Expand Down
4 changes: 2 additions & 2 deletions src/app/[locale]/apps/_components/AppsContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export function AppsContent({ currentCategory }: AppsContentProps) {
/>
</div>

<div className="flex items-center justify-between gap-4 flex-col sm:flex-row flex-1">
<div className="flex items-center justify-between gap-4 flex-row flex-1 flex-wrap">
<AppsCategoryFilter
selected={filters.categories?.[0]}
setSelected={(value) => {
Expand All @@ -197,7 +197,7 @@ export function AppsContent({ currentCategory }: AppsContentProps) {
});
}}
/>
<div className="flex items-center gap-2">
<div className="flex items-center gap-2 gap-y-4 flex-wrap">
<AppsTagsFilter
selected={filters.tags}
setSelected={(value) => {
Expand Down
11 changes: 10 additions & 1 deletion src/app/[locale]/apps/_components/AppsGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Tag } from "@inkonchain/ink-kit";
import Image from "next/image";
import { useTranslations } from "next-intl";

import { useFeatureFlag } from "@/hooks/useFeatureFlag";
import { classNames } from "@/util/classes";

import { AppLinks } from "./AppLinks";
Expand All @@ -14,14 +15,22 @@ export const AppsGrid: React.FC<{
noAppsFound: React.ReactNode;
network: InkAppNetwork;
}> = ({ apps, featuredApps, noAppsFound, network }) => {
const walletColumn = useFeatureFlag("walletColumn");
return (
<div className="w-full">
{apps.length === 0 ? (
<div className="min-h-[300px] flex flex-col gap-4 justify-center items-center">
{noAppsFound}
</div>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 hd:grid-cols-4 gap-2 w-full">
<div
className={classNames(
"grid gap-2 w-full",
walletColumn
? "grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 hd:grid-cols-4"
: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 hd:grid-cols-4"
)}
>
{featuredApps.map((app) => (
<AppCard key={app.id} app={app} network={network} featured />
))}
Expand Down
12 changes: 11 additions & 1 deletion src/app/[locale]/community/_components/LetsGetSocial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import { useTranslations } from "next-intl";

import { FlyWhenIntoView } from "@/components/FlyWhenIntoView";
import { newLayoutSectionClasses } from "@/components/styles/container";
import { useFeatureFlag } from "@/hooks/useFeatureFlag";
import { EXTERNAL_LINKS, Link } from "@/routing";
import { classNames } from "@/util/classes";

import { PageHeader } from "../../_components/PageHeader";

export const LetsGetSocial = () => {
const t = useTranslations("Community");
const walletColumn = useFeatureFlag("walletColumn");

return (
<FlyWhenIntoView className={newLayoutSectionClasses()}>
Expand All @@ -20,7 +23,14 @@ export const LetsGetSocial = () => {
size="section"
/>
</div>
<div className="grid lg:grid-cols-4 sm:grid-cols-2 gap-6 self-center">
<div
className={classNames(
"grid gap-6 self-center",
walletColumn
? "xl:grid-cols-4 sm:grid-cols-2"
: "lg:grid-cols-4 sm:grid-cols-2"
)}
>
<Card className="w-full" variant="secondary" clickable asChild>
<Link
href={EXTERNAL_LINKS.twitter}
Expand Down
3 changes: 2 additions & 1 deletion src/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { COOKIE_CONSENT } from "@/integrations/consent";

import { inter, plus_jakarta_sans } from "../fonts";

import { LayoutColumns } from "./_components/LayoutColumns";
import { MainPageBackground } from "./_components/MainPageBackground";
import { RoutedLayout } from "./_components/RoutedLayout";

Expand Down Expand Up @@ -75,7 +76,7 @@ export default async function LocaleLayout({
<RoutedLayout>
<div className="relative pt-0 overflow-hidden flex flex-col gap-8 w-full items-center">
<div className="flex flex-col w-full items-center min-h-[80vh]">
{children}
<LayoutColumns>{children}</LayoutColumns>
</div>
<Footer />
</div>
Expand Down
19 changes: 7 additions & 12 deletions src/components/ConnectWalletButton.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
"use client";

import { Button, InkIcon } from "@inkonchain/ink-kit";
import { Button, ButtonProps, InkIcon } from "@inkonchain/ink-kit";
import { ConnectButton } from "@rainbow-me/rainbowkit";
import Image from "next/image";

import { classNames } from "@/util/classes";

const truncateEnsName = (ensName: string, maxLength = 16) => {
if (!ensName || !ensName.endsWith(".eth")) return ensName;

const namePart = ensName.slice(0, -4); // Remove .eth
if (namePart.length <= maxLength) return ensName;
return `${namePart.slice(0, maxLength)}...eth`;
};
import { truncateEnsName } from "@/util/formatWallet";

interface ConnectWalletButtonProps {
className?: string;
connectLabel?: string;
shrinkOnMobile?: boolean;
noIcon?: boolean;
size?: "md" | "lg";
variant?: ButtonProps["variant"];
}

export const ConnectWalletButton: React.FC<ConnectWalletButtonProps> = ({
Expand All @@ -28,6 +22,7 @@ export const ConnectWalletButton: React.FC<ConnectWalletButtonProps> = ({
shrinkOnMobile = false,
size = "md",
noIcon = false,
variant = "transparent",
}) => {
return (
<ConnectButton.Custom>
Expand Down Expand Up @@ -59,7 +54,7 @@ export const ConnectWalletButton: React.FC<ConnectWalletButtonProps> = ({
type="button"
className={classNames(className)}
size={size}
variant="transparent"
variant={variant}
>
{!noIcon && (
<div className={shrinkOnMobile ? "sm:hidden" : ""}>
Expand All @@ -83,7 +78,7 @@ export const ConnectWalletButton: React.FC<ConnectWalletButtonProps> = ({
className
)}
size={size}
variant="transparent"
variant={variant}
rounded="full"
>
<InkIcon.Profile className="size-6" enforce="inherit" />
Expand All @@ -99,7 +94,7 @@ export const ConnectWalletButton: React.FC<ConnectWalletButtonProps> = ({
className
)}
size={size}
variant="transparent"
variant={variant}
>
<div className="ink:-my-1 whitespace-nowrap">
{account.ensAvatar && account.ensName ? (
Expand Down
1 change: 1 addition & 0 deletions src/util/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const hardcodedFeatureFlags = {
fakeEvents: 0,
verifyPage: false,
grantsSection: false,
walletColumn: false,
};

export type FeatureFlagKey = keyof typeof hardcodedFeatureFlags;
Expand Down
11 changes: 11 additions & 0 deletions src/util/formatWallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const truncateEnsName = (ensName: string, maxLength = 16) => {
if (!ensName || !ensName.endsWith(".eth")) return ensName;

const namePart = ensName.slice(0, -4); // Remove .eth
if (namePart.length <= maxLength) return ensName;
return `${namePart.slice(0, maxLength)}...eth`;
};

export const truncateAddress = (address: string) => {
return `${address.slice(0, 4)}...${address.slice(-4)}`;
};

0 comments on commit 6a05f6f

Please sign in to comment.