Skip to content

Commit 63e89a2

Browse files
Merge pull request #118 from valory-xyz/style/connect-ui-figma-alignment
style(connect-ui): align Profile UI with Figma
2 parents 61f9410 + 007cfa7 commit 63e89a2

9 files changed

Lines changed: 409 additions & 61 deletions

File tree

apps/connect-ui/src/App.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import { CodingTool } from './components/CodingTool/CodingTool';
77
import { GetStarted } from './components/GetStarted/GetStarted';
88
import { TransactionMode } from './components/TransactionMode/TransactionMode';
99
import { WhitelistedAddresses } from './components/WhitelistedAddresses/WhitelistedAddresses';
10+
import { COLOR } from './constants/theme';
1011
import { useSettings } from './hooks/useSettings';
12+
import { GlobalStyles as ConnectGlobalStyles } from './ui/GlobalStyles';
1113

1214
const Panel = styled.div`
1315
flex: 1;
1416
background-color: white;
15-
border-left: 1px solid #e4e4e4;
16-
border-right: 1px solid #e4e4e4;
17+
border-left: 1px solid ${COLOR.BORDER};
18+
border-right: 1px solid ${COLOR.BORDER};
1719
`;
1820

1921
const Profile = () => {
@@ -54,6 +56,7 @@ const App = () => {
5456
</Panel>
5557
</Flex>
5658
<GlobalStyles />
59+
<ConnectGlobalStyles />
5760
</AntdApp>
5861
</ErrorBoundary>
5962
);

apps/connect-ui/src/components/CodingTool/CodingTool.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Select } from 'antd';
2+
import styled from 'styled-components';
23

4+
import { COLOR } from '../../constants/theme';
35
import { useUpdateSettings } from '../../hooks/useUpdateSettings';
46
import { ConnectSettings, Harness } from '../../types';
57
import { Section } from '../../ui/Section';
@@ -9,6 +11,31 @@ const HARNESS_OPTIONS: { value: Harness; label: string }[] = [
911
{ value: 'claude_code_cli', label: 'Claude Code CLI' },
1012
];
1113

14+
// Filled, rounded gray control per Figma — no border, subtle gray fill that
15+
// darkens on hover, 36px tall (Select `controlHeight` token in theme.ts).
16+
const StyledSelect = styled(Select<Harness>)`
17+
width: max-content;
18+
19+
.ant-select-selector {
20+
border-radius: 10px !important;
21+
background-color: ${COLOR.SELECT_BG} !important;
22+
border-color: transparent !important;
23+
box-shadow: none !important;
24+
}
25+
26+
.ant-select-selection-item {
27+
font-size: 14px;
28+
}
29+
30+
&:hover .ant-select-selector {
31+
background-color: ${COLOR.SELECT_BG_HOVER} !important;
32+
}
33+
34+
.ant-select-arrow {
35+
color: ${COLOR.SELECT_ARROW};
36+
}
37+
`;
38+
1239
type CodingToolProps = {
1340
settings: ConnectSettings;
1441
};
@@ -20,13 +47,14 @@ export const CodingTool = ({ settings }: CodingToolProps) => {
2047

2148
return (
2249
<Section title="Coding tool" description="Choose where you run your Connect agent.">
23-
<Select<Harness>
50+
<StyledSelect
2451
variant="filled"
2552
value={settings.harness}
2653
options={HARNESS_OPTIONS}
2754
loading={isPending}
2855
onChange={(value) => mutate({ harness: value })}
2956
popupMatchSelectWidth={false}
57+
popupClassName="connect-harness-popup"
3058
/>
3159
</Section>
3260
);

apps/connect-ui/src/components/GetStarted/GetStarted.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ export const GetStarted = () => {
2222
description="Work with your Connect agent from your coding tool."
2323
>
2424
<Flex vertical align="flex-start" gap={12}>
25-
<Button icon={<GradientDot />} loading={isPending} onClick={() => mutate()}>
25+
<Button
26+
icon={<GradientDot />}
27+
loading={isPending}
28+
onClick={() => mutate()}
29+
style={{ fontSize: 14, width: 204 }}
30+
>
2631
New Connect Session
2732
</Button>
2833
{error && <Alert type="error" showIcon closable onClose={reset} message={error.message} />}

apps/connect-ui/src/components/PasswordModal/PasswordModal.tsx

Lines changed: 95 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,95 @@ import { Alert, Button, Flex, Input, Modal, Typography } from 'antd';
22
import { useState } from 'react';
33
import styled from 'styled-components';
44

5+
import { COLOR } from '../../constants/theme';
56
import { useUpdateSettings } from '../../hooks/useUpdateSettings';
67
import { SettingsPatch } from '../../types';
78

89
const { Text } = Typography;
910

11+
// Modal chrome per Figma: 464px wide, 24px padding, 12px (Spacing/md) radius,
12+
// 3px translucent-white border, 20px/500/28px title, black close icon, and a
13+
// 12px gap between the footer buttons.
14+
const StyledModal = styled(Modal)`
15+
.ant-modal-content {
16+
padding: 24px;
17+
border-radius: 12px;
18+
border: 3px solid rgba(255, 255, 255, 0.25);
19+
}
20+
21+
.ant-modal-header {
22+
margin-bottom: 24px;
23+
}
24+
25+
.ant-modal-title {
26+
font-weight: 500;
27+
font-size: 20px;
28+
line-height: 28px;
29+
color: ${COLOR.TEXT_TITLE};
30+
}
31+
32+
.ant-modal-close {
33+
top: 24px;
34+
inset-inline-end: 24px;
35+
color: ${COLOR.BLACK};
36+
}
37+
38+
.ant-modal-close-icon {
39+
color: ${COLOR.BLACK};
40+
}
41+
42+
.ant-modal-body {
43+
margin-bottom: 24px;
44+
}
45+
46+
.ant-modal-footer {
47+
margin-top: 0;
48+
display: flex;
49+
justify-content: flex-end;
50+
gap: 12px;
51+
}
52+
53+
.ant-modal-footer > .ant-btn + .ant-btn {
54+
margin-inline-start: 0;
55+
}
56+
`;
57+
58+
// Explanatory body copy — 16px / 400 / 24px, rgba(54, 63, 73, 1).
59+
const BodyText = styled.p`
60+
margin: 0;
61+
font-weight: 400;
62+
font-size: 16px;
63+
line-height: 24px;
64+
color: ${COLOR.TEXT_SECONDARY};
65+
`;
66+
67+
// Field label — 14px tertiary, matching Pearl's password fields.
68+
const PasswordLabel = styled.label`
69+
font-size: 14px;
70+
line-height: 20px;
71+
color: ${COLOR.TEXT_TERTIARY};
72+
`;
73+
74+
// Password field styled like Pearl's (olas-operate-app): small size, 6px 12px
75+
// padding, 16px text.
76+
const PasswordField = styled(Input.Password)`
77+
padding: 6px 12px;
78+
79+
input.ant-input {
80+
font-size: 16px;
81+
}
82+
`;
83+
1084
// Disabled state per design: brand fill at 40% opacity with inset shadows,
1185
// instead of antd's washed-out gray.
1286
const ConfirmButton = styled(Button)`
1387
&:disabled {
1488
border-radius: 10px;
1589
opacity: 0.4;
16-
color: #ffffff;
90+
color: ${COLOR.WHITE};
1791
border-color: transparent;
18-
background: linear-gradient(0deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%), #7e22ce;
92+
background:
93+
linear-gradient(0deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%), ${COLOR.PRIMARY};
1994
background-blend-mode: overlay, normal;
2095
box-shadow:
2196
0 -1px 0 0 rgba(0, 0, 0, 0.05) inset,
@@ -50,10 +125,12 @@ export const PasswordModal = ({
50125
};
51126

52127
return (
53-
<Modal
128+
<StyledModal
54129
open
130+
width={464}
55131
title={title}
56132
onCancel={onClose}
133+
styles={{ mask: { backgroundColor: COLOR.MASK } }}
57134
footer={[
58135
<Button key="cancel" onClick={onClose}>
59136
Cancel
@@ -69,18 +146,22 @@ export const PasswordModal = ({
69146
</ConfirmButton>,
70147
]}
71148
>
72-
<Flex vertical gap={12}>
73-
<Text>{body}</Text>
74-
<label htmlFor="connect-password">
75-
Enter your password <Text type="danger">*</Text>
76-
</label>
77-
<Input.Password
78-
id="connect-password"
79-
value={password}
80-
onChange={(e) => setPassword(e.target.value)}
81-
/>
149+
<Flex vertical gap={24}>
150+
<BodyText>{body}</BodyText>
151+
<Flex vertical gap={4}>
152+
<PasswordLabel htmlFor="connect-password">
153+
Enter your password <Text type="danger">*</Text>
154+
</PasswordLabel>
155+
<PasswordField
156+
id="connect-password"
157+
size="small"
158+
placeholder="Enter your password"
159+
value={password}
160+
onChange={(e) => setPassword(e.target.value)}
161+
/>
162+
</Flex>
82163
{error && <Alert type="error" showIcon message={error.message} />}
83164
</Flex>
84-
</Modal>
165+
</StyledModal>
85166
);
86167
};

apps/connect-ui/src/components/TransactionMode/TransactionMode.tsx

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { InfoCircleOutlined } from '@ant-design/icons';
2-
import { Alert, Flex, Typography } from 'antd';
2+
import { Alert, Flex } from 'antd';
33
import { useState } from 'react';
44
import styled from 'styled-components';
55

6+
import { COLOR } from '../../constants/theme';
67
import { ConnectSettings, TransactionMode as Mode } from '../../types';
78
import { Section } from '../../ui/Section';
89
import { PasswordModal } from '../PasswordModal/PasswordModal';
910

10-
const { Text } = Typography;
11-
1211
const MODES: { value: Mode; title: string; description: string }[] = [
1312
{
1413
value: 'restricted',
@@ -39,16 +38,27 @@ const MODAL_COPY: Record<Mode, { title: string; body: string; confirm: string }>
3938
const UnrestrictedOnAlert = styled(Alert)`
4039
padding: 12px;
4140
align-items: flex-start;
42-
background-color: #ebedff;
43-
border-color: #dbe0ff;
41+
background-color: ${COLOR.INFO_BG};
42+
border: 1px solid ${COLOR.INFO_BORDER};
4443
4544
.ant-alert-icon {
46-
color: #4d63ff;
45+
font-size: 20px;
46+
color: ${COLOR.INFO_ICON};
47+
}
48+
49+
.ant-alert-message {
50+
margin-bottom: 4px;
51+
font-weight: 500;
52+
font-size: 14px;
53+
line-height: 20px;
54+
color: ${COLOR.INFO_TEXT};
4755
}
4856
49-
.ant-alert-message,
5057
.ant-alert-description {
51-
color: #0016b2;
58+
font-weight: 400;
59+
font-size: 14px;
60+
line-height: 20px;
61+
color: ${COLOR.INFO_TEXT};
5262
}
5363
`;
5464

@@ -62,8 +72,8 @@ const ModeCard = styled.button<{ $selected: boolean }>`
6272
border-radius: 10px;
6373
cursor: pointer;
6474
font: inherit;
65-
border: 1px solid ${({ $selected }) => ($selected ? '#D3ADF7' : '#E4E4E4')};
66-
background-color: ${({ $selected }) => ($selected ? '#F9F0FF' : 'transparent')};
75+
border: 1px solid ${({ $selected }) => ($selected ? COLOR.MODE_SELECTED_BORDER : COLOR.BORDER)};
76+
background-color: ${({ $selected }) => ($selected ? COLOR.MODE_SELECTED_BG : 'transparent')};
6777
`;
6878

6979
const RadioDot = styled.span<{ $selected: boolean }>`
@@ -74,7 +84,24 @@ const RadioDot = styled.span<{ $selected: boolean }>`
7484
margin-top: 2px;
7585
border-radius: 50%;
7686
background-color: white;
77-
border: ${({ $selected }) => ($selected ? '5px solid #7E22CE' : '1px solid #D9D9D9')};
87+
border: ${({ $selected }) =>
88+
$selected ? `5px solid ${COLOR.PRIMARY}` : `1px solid ${COLOR.RADIO_BORDER}`};
89+
`;
90+
91+
// Card title — 14px / 500 / 20px (no <strong>, per design).
92+
const ModeTitle = styled.span`
93+
font-weight: 500;
94+
font-size: 14px;
95+
line-height: 20px;
96+
color: ${COLOR.TEXT_PRIMARY};
97+
`;
98+
99+
// Card hint — 14px / 400 / 20px, rgba(97, 112, 132, 1).
100+
const ModeDescription = styled.span`
101+
font-weight: 400;
102+
font-size: 14px;
103+
line-height: 20px;
104+
color: ${COLOR.TEXT_TERTIARY};
78105
`;
79106

80107
type TransactionModeProps = {
@@ -109,8 +136,8 @@ export const TransactionMode = ({ settings }: TransactionModeProps) => {
109136
>
110137
<RadioDot $selected={isSelected} />
111138
<Flex vertical gap={4}>
112-
<Text strong>{mode.title}</Text>
113-
<Text type="secondary">{mode.description}</Text>
139+
<ModeTitle>{mode.title}</ModeTitle>
140+
<ModeDescription>{mode.description}</ModeDescription>
114141
</Flex>
115142
</ModeCard>
116143
);

apps/connect-ui/src/components/WhitelistedAddresses/WhitelistedAddresses.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
1-
import { Flex, Typography } from 'antd';
1+
import { Flex } from 'antd';
2+
import styled from 'styled-components';
23

4+
import { COLOR } from '../../constants/theme';
35
import { Section } from '../../ui/Section';
46

5-
const { Text } = Typography;
7+
// Destination name — 14px, medium weight (no <strong>, per design).
8+
const DestinationName = styled.span`
9+
font-weight: 450;
10+
font-size: 14px;
11+
line-height: 20px;
12+
color: ${COLOR.TEXT_PRIMARY};
13+
`;
14+
15+
// Destination hint — 12px, rgba(97, 112, 132, 1).
16+
const DestinationDescription = styled.span`
17+
font-weight: 400;
18+
font-size: 12px;
19+
line-height: 18px;
20+
color: ${COLOR.TEXT_TERTIARY};
21+
`;
622

723
// The raw whitelist is BE-owned and deliberately not rendered — instead we
824
// describe what the whitelisted addresses refer to. Update this list when the
@@ -22,8 +38,8 @@ export const WhitelistedAddresses = () => (
2238
<Flex vertical gap={16}>
2339
{WHITELISTED_DESTINATIONS.map((destination) => (
2440
<Flex key={destination.name} vertical gap={4}>
25-
<Text strong>{destination.name}</Text>
26-
<Text type="secondary">{destination.description}</Text>
41+
<DestinationName>{destination.name}</DestinationName>
42+
<DestinationDescription>{destination.description}</DestinationDescription>
2743
</Flex>
2844
))}
2945
</Flex>

0 commit comments

Comments
 (0)