Skip to content

Commit

Permalink
feat(apps-ui-kit): add Account component (#1157)
Browse files Browse the repository at this point in the history
* feat(apps-ui-kit): add Account component

* feat(apps-ui-kit): refine account component

* feat(apps-ui-kit): cleanup styels

* feat(apps-ui-kit): move to molecules and use Address component

* feat(apps-ui-kit): update classes

* feat(apps-ui-kit): improve code

* feat(apps-ui-kit): add missing props

* feat(apps-ui-kit): refine account

* feat(apps-ui-kit): add missing font family

---------

Co-authored-by: Marc Espin <[email protected]>
  • Loading branch information
evavirseda and marc2332 authored Jul 17, 2024
1 parent f40049c commit f303b0a
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 0 deletions.
132 changes: 132 additions & 0 deletions apps/ui-kit/src/lib/components/molecules/account/Account.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import React from 'react';
import cx from 'classnames';
import { Button, ButtonSize, ButtonType } from '../../atoms/button';
import { Address, Badge, BadgeType } from '../../atoms';
import { LockLocked, LockUnlocked, MoreHoriz } from '@iota/ui-icons';

interface AccountProps {
/**
* The title of the account.
*/
title: string;
/**
* The subtitle of the account.
*/
subtitle: string;
/**
* Whether the account is unlocked.
*/
isLocked?: boolean;
/**
* Handler for more options click.
*/
onOptionsClick: () => void;
/**
* Handler for the lock account icon click.
*/
onLockAccountClick: () => void;
/**
* Handle for the unlock account icon click.
*/
onUnlockAccountClick: () => void;
/**
* Function to render avatar content.
*/
avatarContent: ({ isLocked }: { isLocked?: boolean }) => React.JSX.Element;
/**
* The onCopy event of the Address (optional).
*/
onCopy?: (e: React.MouseEvent<SVGElement>) => void;
/**
* The onOpen event of the Address (optional).
*/
onOpen?: (e: React.MouseEvent<SVGElement>) => void;
/**
* Has copy icon (optional).
*/
isCopyable?: boolean;
/**
* Has open icon (optional).
*/
isExternal?: boolean;
/**
* The type of the badge.
*/
badgeType?: BadgeType;
/**
* The text of the badge.
*/
badgeText?: string;
}

export function Account({
title,
subtitle,
badgeType,
badgeText,
isLocked,
avatarContent,
onOptionsClick,
onLockAccountClick,
onUnlockAccountClick,
onCopy,
onOpen,
isCopyable,
isExternal,
}: AccountProps): React.JSX.Element {
const Avatar = avatarContent;

return (
<div className="state-layer group relative flex w-full items-center justify-between space-x-3 rounded-xl px-sm py-xs hover:cursor-pointer">
<div className="flex items-center space-x-3">
<Avatar isLocked={isLocked} />
<div className="flex flex-col items-start py-xs">
<div className="flex items-center space-x-2">
<span className="font-inter text-title-md text-neutral-10 dark:text-neutral-92">
{title}
</span>
{badgeType && badgeText && <Badge type={badgeType} label={badgeText} />}
</div>
<Address
text={subtitle}
onCopy={onCopy}
onOpen={onOpen}
isCopyable={isCopyable}
isExternal={isExternal}
/>
</div>
</div>
<div
className={cx(
'z-10 ml-auto flex items-center space-x-2 [&_button]:hidden group-hover:[&_button]:flex',
isLocked && '[&_button:last-child]:flex',
)}
>
<Button
size={ButtonSize.Small}
type={ButtonType.Ghost}
onClick={onOptionsClick}
icon={<MoreHoriz />}
/>
{isLocked ? (
<Button
size={ButtonSize.Small}
type={ButtonType.Ghost}
onClick={onUnlockAccountClick}
icon={<LockLocked />}
/>
) : (
<Button
size={ButtonSize.Small}
type={ButtonType.Ghost}
onClick={onLockAccountClick}
icon={<LockUnlocked />}
/>
)}
</div>
</div>
);
}
4 changes: 4 additions & 0 deletions apps/ui-kit/src/lib/components/molecules/account/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export { Account } from './Account';
1 change: 1 addition & 0 deletions apps/ui-kit/src/lib/components/molecules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

export * from './segmented-button';
export * from './title';
export * from './account';
69 changes: 69 additions & 0 deletions apps/ui-kit/src/storybook/stories/molecules/Account.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import type { Meta, StoryObj } from '@storybook/react';
import { Account, BadgeType } from '@/components';
import cx from 'classnames';

const meta = {
component: Account,
tags: ['autodocs'],
render: (props) => {
return (
<div className="w-1/2">
<Account {...props} />
</div>
);
},
} satisfies Meta<typeof Account>;

export default meta;

type Story = StoryObj<typeof meta>;

const Avatar = ({ isLocked }: { isLocked?: boolean }) => {
const circleFillClass = isLocked ? 'fill-neutral-80 dark:fill-neutral-30' : 'fill-primary-30';
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="33"
height="32"
viewBox="0 0 33 32"
fill="none"
>
<circle cx="16.5" cy="16" r="16" className={cx(circleFillClass)} />
</svg>
);
};

export const Default: Story = {
args: {
title: 'Account',
subtitle: '0x0d7...3f37',
isLocked: true,
avatarContent: Avatar,
},
argTypes: {
badgeType: {
control: 'select',
options: Object.values(BadgeType),
},
isLocked: {
control: 'boolean',
},
onOptionsClick: {
action: 'onOptionsClick',
control: 'none',
},
onLockAccountClick: {
action: 'onLockAccount',
control: 'none',
},
avatarContent: {
control: 'none',
},
badgeText: {
control: 'text',
},
},
};

0 comments on commit f303b0a

Please sign in to comment.