Skip to content

Commit 5bcbfcf

Browse files
authored
feat: update subscription info in dashboard (#7044)
* feat(ui): adjust sidebar * chore: cleanup * fix: show 'Personal' instead of username * fix: skeleton loading * fix: second usage of workspace selector * chore: sidebar refactor * feat: add upgrade cta * feat: standardize badge * feat: switch badge logic for editor (#7048)
1 parent b9f64af commit 5bcbfcf

File tree

12 files changed

+262
-397
lines changed

12 files changed

+262
-397
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react';
2+
import { Icon, IconNames, Stack, Text } from '@codesandbox/components';
3+
4+
export interface BadgeProps {
5+
color?: 'accent' | 'neutral';
6+
icon?: IconNames;
7+
}
8+
9+
// TODO: Move to component system
10+
export const Badge: React.FC<BadgeProps> = ({
11+
color = 'neutral',
12+
icon,
13+
children,
14+
}) => (
15+
<Stack
16+
css={{
17+
alignItems: 'center',
18+
padding: icon ? '4px 8px' : '1px 6px',
19+
userSelect: 'none',
20+
21+
borderRadius: '999px',
22+
23+
backgroundColor: color === 'accent' ? '#653FFD80' : '#2e2e2e',
24+
color: color === 'accent' ? '#fff' : 'inherit',
25+
fontSize: 11,
26+
lineHeight: 16,
27+
}}
28+
gap={1}
29+
>
30+
{icon && <Icon size={12} name={icon} />}
31+
<Text>{children}</Text>
32+
</Stack>
33+
);
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
11
import React from 'react';
2-
import { Icon, Stack, Text } from '@codesandbox/components';
2+
import { Badge } from './Badge';
33

4+
// TODO: Drop in favor of standardized Badge instances
45
export const CloudBetaBadge: React.FC<{ hideIcon?: boolean }> = ({
56
hideIcon,
6-
}) => (
7-
<Stack
8-
css={{
9-
alignItems: 'center',
10-
padding: hideIcon ? '3px 10px' : '6px 10px',
11-
background: '#2e2e2e',
12-
borderRadius: '999px',
13-
}}
14-
gap={2}
15-
>
16-
{!hideIcon && <Icon size={12} name="cloud" />}
17-
<Text size={1}>Beta</Text>
18-
</Stack>
19-
);
7+
}) => <Badge icon={hideIcon ? undefined : 'cloud'}>Beta</Badge>;

packages/app/src/app/components/WorkspaceSelect/WorkspaceSelect.tsx

Lines changed: 56 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,30 @@ import React from 'react';
22
import { useActions, useAppState } from 'app/overmind';
33
import { Text, Menu, Stack, Icon, Tooltip } from '@codesandbox/components';
44
import { sortBy } from 'lodash-es';
5-
import css from '@styled-system/css';
65
import { TeamAvatar } from 'app/components/TeamAvatar';
7-
import { SubscriptionType } from 'app/graphql/types';
8-
import { MenuItem, Badge } from './elements';
9-
10-
type Team = {
11-
id: string;
12-
name: string;
13-
avatarUrl: string | null;
14-
};
6+
import { Badge } from 'app/components/Badge';
157

168
interface WorkspaceSelectProps {
17-
activeAccount: Team;
189
disabled?: boolean;
19-
onSelect: (account: Team) => void;
10+
onSelect: (teamId: string) => void;
11+
selectedTeamId: string;
2012
}
2113

2214
export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
23-
({ activeAccount, disabled, onSelect }) => {
15+
({ disabled, onSelect, selectedTeamId }) => {
2416
const state = useAppState();
2517
const { dashboard, user } = state;
2618
const { openCreateTeamModal } = useActions();
2719

28-
if (!dashboard.teams || !state.personalWorkspaceId) return null;
20+
if (dashboard.teams.length === 0 || !state.personalWorkspaceId) return null;
2921

3022
const personalWorkspace = dashboard.teams.find(
3123
t => t.id === state.personalWorkspaceId
3224
)!;
3325

26+
const selectedTeam = dashboard.teams.find(t => t.id === selectedTeamId);
27+
const isPersonalTeam = selectedTeamId === state.personalWorkspaceId;
28+
3429
const workspaces = [
3530
personalWorkspace,
3631
...sortBy(
@@ -47,60 +42,58 @@ export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
4742
: null
4843
}
4944
>
50-
<Stack css={css({ width: '100%', height: '100%' })}>
45+
<Stack css={{ flex: 1, height: '100%' }}>
5146
<Menu>
5247
<Stack
5348
as={Menu.Button}
5449
disabled={disabled}
5550
justify="space-between"
5651
align="center"
57-
css={css({
52+
css={{
5853
width: '100%',
59-
height: '100%',
60-
marginLeft: 0,
54+
cursor: 'default',
55+
color: '#C2C2C2',
56+
paddingLeft: '28px',
57+
height: '36px',
58+
borderRadius: '2px 0 0 2px',
6159
'&:hover': {
62-
backgroundColor: 'grays.600',
60+
backgroundColor: '#242424',
6361
},
64-
})}
62+
}}
6563
>
66-
<Stack gap={2} as="span" align="center">
67-
<Stack as="span" align="center" justify="center">
68-
<TeamAvatar
69-
avatar={
70-
state.activeTeamInfo?.avatarUrl || activeAccount.avatarUrl
71-
}
72-
name={activeAccount.name}
73-
/>
74-
</Stack>
75-
<Text size={14} weight="normal" maxWidth={140}>
76-
{activeAccount.name}
64+
<Stack align="center" gap={1} css={{ paddingRight: 4 }}>
65+
<Text
66+
size={16}
67+
maxWidth={selectedTeam.subscription ? 166 : 126}
68+
>
69+
{isPersonalTeam ? 'Personal' : selectedTeam.name}
7770
</Text>
71+
72+
{!selectedTeam.subscription && (
73+
<Badge color="accent">Free</Badge>
74+
)}
7875
</Stack>
7976

8077
<Icon name="chevronDown" size={8} />
8178
</Stack>
8279

8380
<Menu.List
84-
css={css({
81+
css={{
8582
width: '100%',
86-
marginTop: -2,
87-
backgroundColor: 'grays.600',
88-
})}
89-
style={{ backgroundColor: '#242424', borderColor: '#343434' }} // TODO: find a way to override reach styles without the selector mess
83+
marginLeft: 7,
84+
marginTop: 4,
85+
borderRadius: '2px',
86+
backgroundColor: '#242424',
87+
}}
9088
>
9189
{workspaces.map(team => (
92-
<MenuItem
90+
<Stack
9391
as={Menu.Item}
9492
key={team.id}
9593
align="center"
9694
gap={2}
97-
onSelect={() =>
98-
onSelect({
99-
name: team.name,
100-
id: team.id,
101-
avatarUrl: team.avatarUrl,
102-
})
103-
}
95+
css={{ borderBottom: '1px solid #343434' }}
96+
onSelect={() => onSelect(team.id)}
10497
>
10598
<TeamAvatar
10699
avatar={
@@ -112,40 +105,41 @@ export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
112105
size="small"
113106
style={{ overflow: 'hidden' }}
114107
/>
115-
<Stack align="center">
116-
<Text css={css({ width: '100%' })} size={3}>
117-
{team.name}
108+
<Stack
109+
align="center"
110+
justify="space-between"
111+
css={{ flex: 1 }}
112+
gap={1}
113+
>
114+
<Text css={{ width: '100%' }} size={3}>
115+
{team.id === state.personalWorkspaceId
116+
? 'Personal'
117+
: team.name}
118118
</Text>
119119

120-
{[
121-
SubscriptionType.TeamPro,
122-
SubscriptionType.PersonalPro,
123-
].includes(team.subscription?.type) && <Badge>Pro</Badge>}
120+
{!team.subscription && <Badge color="accent">Free</Badge>}
124121
</Stack>
125-
</MenuItem>
122+
</Stack>
126123
))}
127124

128125
<Stack
129126
as={Menu.Item}
130127
align="center"
131128
gap={2}
132-
css={css({
133-
height: 10,
129+
css={{
134130
textAlign: 'left',
135-
marginLeft: '1px',
136-
})}
137-
style={{ paddingLeft: 8 }}
131+
}}
138132
onSelect={openCreateTeamModal}
139133
>
140134
<Stack
141135
justify="center"
142136
align="center"
143-
css={css({
144-
size: 6,
145-
borderRadius: 'small',
146-
border: '1px solid',
147-
borderColor: 'grays.500',
148-
})}
137+
css={{
138+
width: 24,
139+
height: 24,
140+
borderRadius: '2px',
141+
border: '1px solid #999',
142+
}}
149143
>
150144
<Icon name="plus" size={10} />
151145
</Stack>

packages/app/src/app/components/WorkspaceSelect/elements.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export const SIDEBAR_WIDTH = 240;
1+
export const SIDEBAR_WIDTH = 250;
22
export const NEW_FOLDER_ID = '__NEW__';

0 commit comments

Comments
 (0)