Skip to content
This repository has been archived by the owner on Dec 21, 2023. It is now read-only.

Card social buttons #641

Merged
merged 2 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/storybook-react-native/.storybook/storybook.requires.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const getStories = () => {
require("../../../packages/design-system/activity/activity.stories.tsx"),
require("../../../packages/design-system/avatar/avatar.stories.tsx"),
require("../../../packages/design-system/bottom-sheet/bottom-sheet.stories.tsx"),
require("../../../packages/design-system/card/social/button.stories.tsx"),
require("../../../packages/design-system/card/social/index.stories.tsx"),
require("../../../packages/design-system/checkbox/checkbox.stories.tsx"),
require("../../../packages/design-system/data-pill/data-pill.stories.tsx"),
require("../../../packages/design-system/input/input.stories.tsx"),
Expand Down
3 changes: 3 additions & 0 deletions packages/design-system/card/card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Media } from "design-system/card/media";
import { View } from "design-system/view";
import { Activity } from "design-system/activity";
import { Social } from "design-system/card/social";

type Props = {
act: any;
Expand All @@ -9,11 +10,13 @@ type Props = {

function Card({ act, variant }: Props) {
const { id, nfts, actor } = act;
const single = act.nfts?.length === 1;

return (
<View tw="bg-white dark:bg-black">
{variant === "activity" && <Activity activity={act} />}
<Media nfts={nfts} />
{single && <Social nft={nfts[0]} />}
</View>
);
}
Expand Down
52 changes: 52 additions & 0 deletions packages/design-system/card/social/button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Meta } from "@storybook/react";
import { View } from "design-system/view";

import { Button } from "./button";

export default {
component: Button,
title: "Components/Card/Social/Button",
} as Meta;

export const Basic: React.VFC<{}> = () => {
return (
<View tw="p-1 bg-white dark:bg-black">
<View tw="flex-row mb-2">
<Button variant="like" state="default" count={42400} />
<View tw="ml-2" />
<Button variant="comment" state="default" count={200} />
<View tw="ml-2" />
<Button variant="boost" state="default" count={15} />
</View>

<View tw="flex-row mb-2">
<Button variant="like" state="hover" count={42400} />
<View tw="ml-2" />
<Button variant="comment" state="hover" count={200} />
<View tw="ml-2" />
<Button variant="boost" state="hover" count={15} />
</View>

<View tw="flex-row mb-2">
<Button variant="like" state="tap" count={42400} active={true} />
<View tw="ml-2" />
<Button variant="comment" state="tap" count={200} active={true} />
<View tw="ml-2" />
<Button variant="boost" state="tap" count={15} active={true} />
</View>

<View tw="flex-row mb-2">
<Button variant="like" state="disabled" count={42400} disabled={true} />
<View tw="ml-2" />
<Button
variant="comment"
state="disabled"
count={200}
disabled={true}
/>
<View tw="ml-2" />
<Button variant="boost" state="disabled" count={15} disabled={true} />
</View>
</View>
);
};
170 changes: 170 additions & 0 deletions packages/design-system/card/social/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { useMemo } from "react";

import { Pressable, Text } from "design-system";
import { HeartFilled, MessageFilled, Boost } from "design-system/icon";
import { tw } from "design-system/tailwind";
import { useOnPress, useOnHover } from "design-system/hooks";

type Props = {
variant: "like" | "comment" | "boost";
count: number;
state?: "default" | "hover" | "tap" | "disabled";
active?: boolean;
disabled?: boolean;
onPress?: () => void;
};

function Button({
variant,
state = "default",
count,
active = false,
onPress,
disabled,
}: Props) {
const { onPressIn, onPressOut, pressed } = useOnPress();
const { onHoverIn, onHoverOut, hovered } = useOnHover();
const isHovered = hovered.value || state === "hover";
const isDisabled = disabled || state === "disabled";
const isHoverable = !isDisabled;
const isPressed = active || pressed.value || state === "tap";

const Icon =
variant === "like"
? HeartFilled
: variant === "comment"
? MessageFilled
: Boost;
const backgroundColor = "bg-gray-100";
const backgroundHoverColor = getBackgroundHoverColor(variant);
const iconActiveColor = getIconActiveColor(variant);
const textActiveColor = getTextActiveColor(variant);
const hoverColor = getHoverColor(variant);
const defaultColor = active
? textActiveColor
: tw.style("text-gray-600 dark:text-gray-400");

// TODO: animate color with Moti and useDerivedValue
const textStyle = useMemo(
() => ({
color:
isHoverable && isHovered
? hoverColor
: active
? textActiveColor.color
: defaultColor.color,
}),
[isHoverable, isHovered, hoverColor, active, textActiveColor, defaultColor]
);

return (
<Pressable
tw={[
"h-8 p-2 flex-row items-center rounded-full dark:bg-gray-900",
isHovered ? backgroundHoverColor : backgroundColor,
isPressed && !isDisabled ? "dark:bg-gray-800" : "",
isDisabled ? "opacity-40" : "", // TODO: add `cursor-not-allowed` utility to twrnc
]}
onHoverIn={onHoverIn}
onHoverOut={onHoverOut}
onPressIn={onPressIn}
onPressOut={onPressOut}
onPress={onPress}
disabled={isDisabled}
>
<Icon
width={16}
height={16}
color={
active
? iconActiveColor
: isHovered && !isDisabled
? hoverColor
: tw.color("gray-400")
}
/>
<Text
variant="text-13"
tw="ml-1 font-bold"
// @ts-ignore
sx={textStyle}
>
{count > 0 ? formatNumber(count) : formatString(variant)}
</Text>
</Pressable>
);
}

// Format big numbers
function formatNumber(number: number) {
if (number > 1000000) {
return `${(number / 1000000).toFixed(1)}m`;
} else if (number > 1000) {
return `${(number / 1000).toFixed(1)}k`;
} else {
return number;
}
}

// Capitalize first letter of string
function formatString(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}

// Get background hover color
function getBackgroundHoverColor(variant: Props["variant"]) {
switch (variant) {
case "like":
return "bg-red-50";
case "comment":
return "bg-indigo-50";
case "boost":
return "bg-green-50";
default:
return "";
}
}

// Get icon active color
function getIconActiveColor(variant: Props["variant"]) {
switch (variant) {
case "like":
return tw.color("red-500");
case "comment":
return tw.color("indigo-600");
case "boost":
return tw.color("green-600");
default:
return tw.color("gray-400");
}
}

// Get text active color
function getTextActiveColor(variant: Props["variant"]) {
switch (variant) {
case "like":
return tw.style("text-red-500");
case "comment":
return tw.style("text-indigo-600 dark:text-indigo-500");
case "boost":
return tw.style("text-green-600 dark:text-green-500");
default:
return tw.style("text-gray-600 dark:text-gray-400");
}
}

// Get hover color
function getHoverColor(variant: Props["variant"]) {
switch (variant) {
case "like":
return tw.color("red-500");
case "comment":
return tw.color("indigo-500");
case "boost":
return tw.color("green-500");
default:
return "";
}
}

export { Button };
133 changes: 133 additions & 0 deletions packages/design-system/card/social/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { Meta } from "@storybook/react";
import { View } from "design-system/view";

import { Social } from "./index";

export default {
component: Social,
title: "Components/Card/Social/Index",
} as Meta;

export const Basic: React.VFC<{}> = () => {
const activity = {
id: 827316,
type: "like",
timestamp: "2021-11-27T00:16:59.797",
actor_id: 147991,
nfts: [
{
activity_id: 827316,
nft_id: 17625054,
contract_address: "0x8a13628dd5d600ca1e8bf9dbc685b735f615cb90",
token_id: "1",
like_count: 31,
token_name: "Showtime Genesis Team",
token_description:
"History in the making: this is the first NFT ever created on Showtime, on the Polygon network!\n\nTo celebrate this inaugural item, we are creating five editions to give out to each member of the original Showtime team (in alphabetical order): Alex Kilkka, Clare Maguire, Alex Masmej, Miguel Piedrafita and Blaze Pollard.\n\nArtwork: Showtime Logo (original concept from Emma Salinas, designed by Blaze Pollard).",
token_img_url:
"https://lh3.googleusercontent.com/Pxg4ZXLMXPcgTZ-PbAxWcni3Cqfx2GrB7lZiFz1ryG_EE7ZdjmhOmfGjwLQE41iuUERbM7ByBc3PELYCE14nwcXHxspBMl84n6AQ",
token_img_original_url:
"https://ipfs.io/ipfs/QmS3bHrWy58Gz5FMDmhgCQxiiAJ6Ct5MoQxhj2KRgFDkok",
token_has_video: 0,
token_animation_url: null,
animation_preview_url: null,
blurhash:
"yPG8^6CN06W?-,kDM~K#%KX6kBfjj[fj06X6^}j@IYa|kAW?kBj@fQazfQf7%cj@IXazt5jat5j^fkazfkj@fQj@j[fjt5j@M~a|az",
token_background_color: null,
token_aspect_ratio: "1.00000",
token_hidden: 0,
creator_id: 147991,
creator_name: "Alex Masmej",
creator_address: "alexmasmej.eth",
creator_address_nonens: "0xD3e9D60e4E4De615124D5239219F32946d10151D",
creator_img_url:
"https://storage.googleapis.com/nft-public-profile-pics/147991_1619920081.jpg",
multiple_owners: 1,
owner_id: null,
owner_name: null,
owner_address: null,
owner_img_url: null,
token_created: "2021-09-01T04:56:29",
token_creator_followers_only: 0,
creator_username: "am",
creator_verified: 1,
owner_username: null,
owner_verified: null,
comment_count: 11,
owner_count: 5,
token_count: 5,
token_ko_edition: null,
token_edition_identifier: null,
source_url:
"https://lh3.googleusercontent.com/Pxg4ZXLMXPcgTZ-PbAxWcni3Cqfx2GrB7lZiFz1ryG_EE7ZdjmhOmfGjwLQE41iuUERbM7ByBc3PELYCE14nwcXHxspBMl84n6AQ",
still_preview_url:
"https://lh3.googleusercontent.com/Pxg4ZXLMXPcgTZ-PbAxWcni3Cqfx2GrB7lZiFz1ryG_EE7ZdjmhOmfGjwLQE41iuUERbM7ByBc3PELYCE14nwcXHxspBMl84n6AQ",
mime_type: "image/png",
chain_identifier: "137",
token_listing_identifier: null,
},
{
activity_id: 827316,
nft_id: 76208186,
contract_address: "0x09F3a26302e1c45f0d78Be5D592f52b6fca43811",
token_id: "38",
like_count: 2,
token_name: "test nft",
token_description: "hello world",
token_img_url:
"https://lh3.googleusercontent.com/8GXYkSoSJIaHGwjrLqGxomotSEB_YIHcabU_3Dc-kxCxp3LX-1xOzpuD2mh5Y81IqZdEVq03OJ6uXNpTcpYv15mid7y4f8a0x4k",
token_img_original_url:
"https://gateway.pinata.cloud/ipfs/QmWsEdu43Ww4htaHj8goo2rP8p3AQoK6FQAgG94TTDX95x",
token_has_video: 0,
token_animation_url: null,
animation_preview_url: null,
blurhash:
"yF9},H,m=Rr;=Rwa=Q;xoLs8jusRjbn#=Qn$WnoMbEa}WT,sn%WVa|bFj[a|=Qn$WTfRWnj[Wn$PjsWpjua|fQa|=Pn$WUa}WUa}WU",
token_background_color: null,
token_aspect_ratio: "0.92634",
token_hidden: 0,
creator_id: 162363,
creator_name: "Miguel Piedrafita",
creator_address: "m1guelpf.eth",
creator_address_nonens: "0xE340b00B6B622C136fFA5CFf130eC8edCdDCb39D",
creator_img_url:
"https://lh3.googleusercontent.com/azf5UI4ZzMgQbNWn5E9BiKIdP2gT-6BcJ1-24hVix73eapPxPxDkbgLqRJ5T1uOuW35cshX8KOVdxzeGJZO49lMf6qC8zgX8Zf5i",
multiple_owners: 0,
owner_id: 162363,
owner_name: "Miguel Piedrafita",
owner_address: "m1guelpf.eth",
owner_img_url:
"https://lh3.googleusercontent.com/azf5UI4ZzMgQbNWn5E9BiKIdP2gT-6BcJ1-24hVix73eapPxPxDkbgLqRJ5T1uOuW35cshX8KOVdxzeGJZO49lMf6qC8zgX8Zf5i",
token_created: "2021-11-24T22:37:36",
token_creator_followers_only: 0,
creator_username: "m1guelpf",
creator_verified: 1,
owner_username: "m1guelpf",
owner_verified: 1,
comment_count: 0,
owner_count: 1,
token_count: 15,
token_ko_edition: null,
token_edition_identifier: null,
source_url:
"https://lh3.googleusercontent.com/8GXYkSoSJIaHGwjrLqGxomotSEB_YIHcabU_3Dc-kxCxp3LX-1xOzpuD2mh5Y81IqZdEVq03OJ6uXNpTcpYv15mid7y4f8a0x4k",
still_preview_url:
"https://lh3.googleusercontent.com/8GXYkSoSJIaHGwjrLqGxomotSEB_YIHcabU_3Dc-kxCxp3LX-1xOzpuD2mh5Y81IqZdEVq03OJ6uXNpTcpYv15mid7y4f8a0x4k",
mime_type: "image/png",
chain_identifier: "80001",
token_listing_identifier: null,
},
],
actor: {
username: "am",
verified: 1,
profile_id: 147991,
name: "Alex Masmej",
wallet_address: "alexmasmej.eth",
img_url:
"https://storage.googleapis.com/nft-public-profile-pics/147991_1619920081.jpg",
},
};

return <Social nft={activity.nfts[0]} />;
};
Loading