Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Icon with activity sub-icon #654

Draft
wants to merge 4 commits into
base: dev
Choose a base branch
from
Draft

Conversation

camerow
Copy link
Collaborator

@camerow camerow commented Nov 25, 2024

Work in progress on adding an icon with activity sub icon.

  • Need to fix some shadow issues, but overall it is nearly done.
Screenshot 2024-11-25 at 2 40 48 PM Screenshot 2024-11-25 at 2 41 13 PM Screenshot 2024-11-25 at 2 41 28 PM

return (
<AccountCardLayout
onPress={onPress}
icon={<PlusIcon />}
icon={<PlusIcon color={theme.colors['ink.background-primary']} />}
Copy link
Collaborator Author

@camerow camerow Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed this color bug while i was exploring icons. It was black on black rather than black bg and white icon color.

@@ -7,7 +12,8 @@ interface TokenIconProps {
export function TokenIcon({ ticker }: TokenIconProps) {
switch (ticker) {
case 'STX':
return <StxAvatarIcon />;
return <IconWithActivity avatar={<StxAvatarIcon />} activity="error" />;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Revert this change, just added for quick testing.

@@ -7,7 +7,7 @@
"build": "pnpm panda && pnpm build:native && pnpm build:web",
"build-storybook:web": "storybook build -c ./src/.storybook-web",
"build:native": "tsup --config tsup.config.native.ts",
"build:watch": "concurrently \"pnpm panda:watch\" \"pnpm build:native --watch --preserveWatchOutput\" \"pnpm build:web --watch\" ",
"build:watch": "concurrently \"pnpm panda --watch\" \"pnpm build:native --watch\" \"pnpm build:web --watch\" ",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect syntax here, small fix while I was building the ui package.

activity,
}: {
avatar: React.JSX.Element;
activity?: ActivityIconType;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no activity maybe we should not add anything instead of defaulting to send?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree here, why would we default to send?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still a draft, not intentionally left to be that way. I'll update to omit the icon if not provided as a optional prop.

@@ -0,0 +1,19 @@
import { View } from 'react-native';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes we need to show an activity type icon on top of a protocol item, and sometimes we need to show a protocol icon on top for example here:
Screenshot 2024-11-26 at 09 23 58

NOTE the design is wrong for the first two items - Stacks + Btc.

For subsequent tokens like sBTC, ALEX Lab etc. we need to show a base protocol icon on top of their specific item.

Maybe we can extend this component to be more broad and handle both activity and protocol sub-icons

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that sounds good, should be somewhat easy to achieve.

To that point I notice we are hard coding our protocol icons - I would love to see us use something more generic like a <ProtocolIcon symbol="btc | stx | ..." />

Copy link
Contributor

@pete-watters pete-watters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work so far here @camerow , I added a couple of suggestions but it's looking good overall

export const ArrowDownIcon = forwardRef<Component, IconProps>(({ variant, ...props }, ref) => {
return (
<Icon ref={ref} {...props}>
{variants[variant ?? 'default']}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it nec to make this change when all other icons use a different code pattern?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, was just playing with patterns and thinking about suggesting a different way of doing this down the line.

Actually as I was looking at this I was wondering why we don't just have a single component that can render any icon, eg <LeatherIcon icon="icon-name" variant="small" {...props} /> - I find that pattern makes adding icons much easier as you just have a lookup table / function and all new icons can just be added there.

Was the idea with this implementation that it allows for better tree-shaking?

I can revert it to how the others do it for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of our components are based off Radix. https://www.radix-ui.com/icons

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was thinking on this, might be best to get @tigranpetrossian opinion here bc he is mostly owning the UI library? I don't have a strong opinion if others prefer a diff setup. It would just be quite a chunk of work to refactor as they are currently used this way in both web and mobile.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Will's proposed API will be quite an improvement. Radix has a different approach because it's a public set, and developers might only need a handful of icons. We on the other hand own our icon set, so having all the options under your fingertips in an autocomplete box is probably going to be much a better DX.
I'm going to add and track this under the umbrella issue for icon refactoring, some of which I added based on this PR. Within this PR it's best to keep icons as is though, just for consistency and to make the refactoring easier.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, sounds good to me. 👍

@@ -16,7 +16,7 @@ export const Icon = forwardRef<Component, IconProps>(({ children, ...props }, re
return (
<>
{React.cloneElement(child, {
color: theme.colors['ink.action-primary-default'],
color: props.color ?? theme.colors['ink.action-primary-default'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change nec? We have always been able to override the icon color w/out this. This should just set the default color?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does make the fallback color more explicit and thus easier to debug.

Of course it can always be overriden without this, but the underlying svg usually has something like stroke="currentColor" and it's not obvious to me what that default is - having something explicitly set rather than a side effect seems like an improvement.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of research says:

In React Native SVG, currentColor behaves similarly, but it inherits the color property from the nearest ancestor element.

Which isn't a desirable behavior - some sane default makes sense to me.

Copy link
Contributor

@fbwoolf fbwoolf Nov 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to find the resource I used when implementing this with react-native-svg-transformer. I know it was the suggested way to set the svg currentColor using a theme color. I'm not totally following your explanation tbh.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change nec? We have always been able to override the icon color w/out this. This should just set the default color?

I think I misunderstood your original comment - I thought it was regarding theme.colors['ink.action-primary-default'] which had already been there, you're right this isn't necessary given that the props are spread as the final argument.

@camerow camerow force-pushed the ui/asset-icon-with-activity branch from 4a8e6ab to 213b23b Compare November 26, 2024 20:32
export const PlusIcon = forwardRef<Component, IconProps>(({ variant, ...props }, ref) => {
if (variant === 'small')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 All our icons follow this pattern, it's definitely time to re-visit, but ideally not one by one.
This can be rolled back for now. I'm putting together a list of improvements in Linear that will include this.

@@ -16,7 +16,7 @@ export const Icon = forwardRef<Component, IconProps>(({ children, ...props }, re
return (
<>
{React.cloneElement(child, {
color: theme.colors['ink.action-primary-default'],
color: props.color ?? theme.colors['ink.action-primary-default'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Created an issue to add theme-aware color support for icons.

Comment on lines 19 to 44
<View
style={{
position: 'absolute',
bottom: -4,
right: -6,
height: 24,
width: 24,
backgroundColor: theme.colors['ink.text-primary'],
borderColor: theme.colors['ink.background-primary'],
borderWidth: 3,
borderRadius: 1000,
justifyContent: 'center',
alignItems: 'center',
}}
>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<View
style={{
position: 'absolute',
bottom: -4,
right: -6,
height: 24,
width: 24,
backgroundColor: theme.colors['ink.text-primary'],
borderColor: theme.colors['ink.background-primary'],
borderWidth: 3,
borderRadius: 1000,
justifyContent: 'center',
alignItems: 'center',
}}
>
<Box
position="absolute"
bottom={-4}
right={-6}
justifyContent="center"
alignItems="center"
width={24}
height={24}
bg="ink.action-primary-default"
borderColor="ink.background-primary"
borderWidth={3}
borderRadius="round"
>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In near future it's worth moving this logic over to Avatar, as I think the intention is to use secondary icons on other avatars for list items too. Will require refactoring both the web and native versions.

export const ArrowDownIcon = forwardRef<Component, IconProps>(({ variant, ...props }, ref) => {
return (
<Icon ref={ref} {...props}>
{variants[variant ?? 'default']}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Will's proposed API will be quite an improvement. Radix has a different approach because it's a public set, and developers might only need a handful of icons. We on the other hand own our icon set, so having all the options under your fingertips in an autocomplete box is probably going to be much a better DX.
I'm going to add and track this under the umbrella issue for icon refactoring, some of which I added based on this PR. Within this PR it's best to keep icons as is though, just for consistency and to make the refactoring easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants