Skip to content

Commit

Permalink
style(suite): Style Contacts table
Browse files Browse the repository at this point in the history
  • Loading branch information
jvaclavik committed Dec 11, 2024
1 parent 75d81e7 commit 8aae04d
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 123 deletions.
2 changes: 2 additions & 0 deletions packages/components/src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { TableBody } from './TableBody';
import { useScrollShadow } from '../../utils/useScrollShadow';
import { useElevation } from '../ElevationContext/ElevationContext';
import { TextPropsKeys, TextProps } from '../typography/utils';
import { TableFooter } from './TableFooter';

export const allowedTableFrameProps = [
'margin',
Expand Down Expand Up @@ -104,3 +105,4 @@ Table.Row = TableRow;
Table.Cell = TableCell;
Table.Header = TableHeader;
Table.Body = TableBody;
Table.Footer = TableFooter;
9 changes: 9 additions & 0 deletions packages/components/src/components/Table/TableFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ReactNode } from 'react';

export interface TableFooterProps {
children: ReactNode;
}

export const TableFooter = ({ children }: TableFooterProps) => {
return <tbody>{children}</tbody>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { uiVariants } from '../../../config/types';
export const allowedTextTextProps = [
'typographyStyle',
'textWrap',
'overflowWrap',
'align',
'ellipsisLineCount',
] as const satisfies TextPropsKeys[];
Expand Down
17 changes: 17 additions & 0 deletions packages/components/src/components/typography/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import { UIHorizontalAlignment, uiHorizontalAlignments } from '../../config/type
export const textWraps = ['balance', 'break-word', 'pretty'];
export type TextWrap = (typeof textWraps)[number];

export const overflowWraps = ['normal', 'break-word', 'anywhere'];
export type OverflowWrap = (typeof overflowWraps)[number];

export type TextProps = {
typographyStyle?: TypographyStyle;
textWrap?: TextWrap;
overflowWrap?: OverflowWrap;
align?: UIHorizontalAlignment;
ellipsisLineCount?: number;
};
Expand All @@ -29,6 +33,7 @@ export const pickAndPrepareTextProps = (

export const withTextProps = ({
$textWrap,
$overflowWrap,
$typographyStyle,
$align,
$ellipsisLineCount = 0,
Expand All @@ -38,6 +43,10 @@ export const withTextProps = ({
css`
text-wrap: ${$textWrap};
`}
${$overflowWrap &&
css`
overflow-wrap: ${$overflowWrap};
`}
${$typographyStyle
? css`
${typography[$typographyStyle]}
Expand Down Expand Up @@ -72,6 +81,13 @@ const getStorybookType = (key: TextPropsKeys) => {
type: 'select',
},
};
case 'overflowWrap':
return {
options: [undefined, ...overflowWraps],
control: {
type: 'select',
},
};
case 'typographyStyle':
return {
options: [undefined, ...typographyStyles],
Expand Down Expand Up @@ -119,6 +135,7 @@ export const getTextPropsStory = (allowedTextProps: Array<TextPropsKeys>) => {
return {
args: {
...(allowedTextProps.includes('textWrap') ? { textWrap: undefined } : {}),
...(allowedTextProps.includes('overflowWrap') ? { overflowWrap: undefined } : {}),
...(allowedTextProps.includes('typographyStyle') ? { typographyStyle: undefined } : {}),
...(allowedTextProps.includes('align') ? { align: undefined } : {}),
...(allowedTextProps.includes('ellipsisLineCount') ? { hasEllipsis: undefined } : {}),
Expand Down
213 changes: 90 additions & 123 deletions packages/suite/src/views/contacts/index.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,18 @@
import styled from 'styled-components';
import { verify } from 'bitcoinjs-message';

import TrezorConnect from '@trezor/connect';
import { Banner, Button } from '@trezor/components';
import { Banner, Button, Card, Dropdown, Row, Table, Text } from '@trezor/components';
import { selectDevice } from '@suite-common/wallet-core';
import { TrezorDevice } from '@suite-common/suite-types';
import { spacings } from '@trezor/theme';

import { useDispatch, useSelector } from 'src/hooks/suite';
import { getDeviceState, selectContactsForDevice } from 'src/reducers/suite/contactsReducer';
import { selectContactsForDevice } from 'src/reducers/suite/contactsReducer';
import * as contactsActions from 'src/actions/suite/contactsActions';
import { Contact } from 'src/types/suite';

import { SettingsLayout } from '../../components/settings';

const ContactsWrapper = styled.div`
> div {
display: flex;
flex-direction: column;
gap: 16px;
> div {
display: flex;
flex-direction: row;
> * {
display: flex;
flex: 0.25;
overflow: hidden;
> div {
overflow: hidden;
text-overflow: ellipsis;
}
}
&:first-child {
font-weight: bold;
}
}
}
> :last-child {
margin-top: 16px;
display: flex;
flex-direction: row;
}
`;
import { useAddContactButton } from './useAddContactButton';

const ContactItem = ({
contact: { address, label, signature },
Expand All @@ -55,22 +22,39 @@ const ContactItem = ({
remove: () => void;
}) => {
return (
<div>
<div>
<div>{address}</div>
</div>
<div>
<div>{label}</div>
</div>
<div>
<div>{signature}</div>
</div>
<div>
<Button size="tiny" onClick={remove}>
Remove
</Button>
</div>
</div>
<Table.Row>
<Table.Cell>
<Text typographyStyle="highlight">{label}</Text>
</Table.Cell>
<Table.Cell>
<Text variant="tertiary" typographyStyle="hint" overflowWrap="anywhere">
{address}
</Text>
</Table.Cell>
<Table.Cell>
<Text variant="tertiary" typographyStyle="hint" overflowWrap="anywhere">
{signature}
</Text>
</Table.Cell>
<Table.Cell align="right">
<Dropdown
alignMenu="bottom-right"
items={[
{
key: '1',
label: 'Contact',
options: [
{
label: 'Delete',
icon: 'userMinusFilled',
onClick: remove,
},
],
},
]}
/>
</Table.Cell>
</Table.Row>
);
};

Expand All @@ -81,68 +65,35 @@ const ContactList = ({
contacts: Contact[];
remove: (contact: Contact) => void;
}) => {
return (
<div>
<div>
<div>Address</div>
<div>Label</div>
<div>Signature</div>
<div>Remove</div>
</div>
{contacts.map((contact, i) => (
<ContactItem key={i} contact={contact} remove={() => remove(contact)} />
))}
</div>
);
};

const AddContactButton = () => {
const dispatch = useDispatch();
const device = useSelector(selectDevice);

const addContact = async () => {
const deviceState = device && getDeviceState(device);
if (!deviceState) {
alert('No device selected or device unacquired');

return;
}

const address = prompt("Recipient's address or public key");
const label = prompt('Label for this recipient');

if (!address || !label) {
alert('Missing data');

return;
}

const message = `${label}/${address}`;

const response = await TrezorConnect.signMessage({
device,
path: "m/44'/1'/0'/0/0",
coin: 'test',
message,
useEmptyPassphrase: device.useEmptyPassphrase,
});

if (!response.success) {
alert(`Signing failed: ${response.payload.error}`);

return;
}

const { signature } = response.payload;

const contact = { address, label, signature, deviceState };
dispatch(contactsActions.addContact(contact));
};
const onAdd = useAddContactButton();

return (
<Button size="small" onClick={addContact}>
Add contact
</Button>
<Card paddingType="none" overflow="hidden">
<Table isRowHighlightedOnHover margin={{ top: spacings.xs }}>
<Table.Header>
<Table.Row>
<Table.Cell>Label</Table.Cell>
<Table.Cell>Address</Table.Cell>
<Table.Cell>Signature</Table.Cell>
<Table.Cell />
</Table.Row>
</Table.Header>
<Table.Body>
{contacts.map((contact, i) => (
<ContactItem key={i} contact={contact} remove={() => remove(contact)} />
))}
</Table.Body>
<Table.Footer>
<Table.Row hasBorderTop={true} isHighlightedOnHover={false}>
<Table.Cell colSpan={4}>
<Button onClick={onAdd} size="small" icon="plus">
Add new contact
</Button>
</Table.Cell>
</Table.Row>
</Table.Footer>
</Table>
</Card>
);
};

Expand Down Expand Up @@ -170,7 +121,7 @@ const FindContactButton = ({ contacts }: { contacts: Contact[] }) => {
};

return (
<Button size="small" onClick={findContact}>
<Button variant="tertiary" onClick={findContact} icon="magnifyingGlass">
Find contact
</Button>
);
Expand All @@ -197,15 +148,16 @@ const GetMyPubkeyButton = () => {
};

return (
<Button size="small" onClick={getMyPubkey}>
Get my identity pubkey
<Button variant="tertiary" onClick={getMyPubkey} icon="eye">
Show your identity
</Button>
);
};

const Contacts = ({ device }: { device: TrezorDevice }) => {
const contacts = useSelector(selectContactsForDevice(device));
const dispatch = useDispatch();
const onAdd = useAddContactButton();

const removeContact = (contact: Contact) => {
const confirmed = confirm('Do you want to remove this contact?');
Expand All @@ -215,26 +167,41 @@ const Contacts = ({ device }: { device: TrezorDevice }) => {
};

return (
<ContactsWrapper>
<>
{contacts.length ? (
<ContactList contacts={contacts} remove={removeContact} />
) : (
'No contacts yet'
<Banner
variant="info"
icon
rightContent={
<Banner.Button icon="plus" onClick={onAdd}>
Add new contact
</Banner.Button>
}
>
You have no contacts yet
</Banner>
)}
<div>
<AddContactButton />
<FindContactButton contacts={contacts} />
<GetMyPubkeyButton />
<Row gap={spacings.sm}>
<GetMyPubkeyButton />
<FindContactButton contacts={contacts} />
</Row>
</div>
</ContactsWrapper>
</>
);
};

export const SettingsContacts = () => {
const device = useSelector(selectDevice);

if (!device) {
return <Banner>Connect your device to see contacts</Banner>;
return (
<Banner variant="warning" icon>
Connect your device to see your contacts.
</Banner>
);
}

return (
Expand Down
Loading

0 comments on commit 8aae04d

Please sign in to comment.