Skip to content

Commit 8c64077

Browse files
tristandubbeldolarclaraalexnm
authored
feat: trial support release (#7075)
* feat(dashboard): team creation steps (#7038) * create steps for new team flow * fixup * update Stack to use align and justify props + rename onTeamCreation to onComplete * feat(trial): create team and subscribe to pro (#7040) * add npm icon * create getPrices action * wip: TeamSubscription component * extract useCreateCheckout * add create checkout to team subscription step in new team flow * fix * feat(trial): Add onboarding questions (#7037) * Update plugin to potentially fix input requires label error * Start creating isolated styled components * Use new components and update styles * Replace styled with dashboard InputText element * Move styles to styled component * Create button abstraction for dashboard * Update wrapper component * Add more TOQ_DEBUG flags * Add key to option * Clean up handle sign in with providers * Separate views into different files * Split login between modal and page * Comment modal header * Remove comment * Support placeholder for InputSelect * Rename button to styled * Replace styled function with Element and css prop * Uppercase for consts * Add target blank * fix(trial): redirect to the dashboard home page for the created team (#7043) * feat(trial): Create team (#7039) * Update plugin to potentially fix input requires label error * Start creating isolated styled components * Use new components and update styles * Replace styled with dashboard InputText element * Move styles to styled component * Create button abstraction for dashboard * Update wrapper component * Add more TOQ_DEBUG flags * Add key to option * Clean up handle sign in with providers * Separate views into different files * Split login between modal and page * Comment modal header * Remove comment * Support placeholder for InputSelect * Add external link and camera icons * Style create team modal * Add link * Fix link with href instead of to * feat(trial): Show create team modal after new signup (#7051) * Add debug flag for duplicate account page * Onboarding form field updates * Add isInvalid prop to input * Show create team modal after new user signed up * Change var to uppercase to imply const * Undo localstorage entry rename as it will trigger the modal again * Fix property order * Add aria attrs for validation and describing input with error * feat(trial): Invite team members (#7049) * Textarea component * Teammember invite step styles * Fix typo * Email submission WIP * Validate emails and send invitations * Trigger onComplete after sending invites * feat(dashboard): recent page empty state (#7053) * adds loading option to page headers * update recent page title if empty * wip * wip * open/select templates * adjust styling * fix section title * prevent columns from stretching * feat(trial): save "role" and "usage" and add it to amplitude (#7059) * feat: save users role and usage on signup * add metadata when identifying user * handle subscription status when trialing (#7061) * signin: update usage options (#7062) * feat(trial): tracking (#7068) * track: open workspace select * track: select workspace * track: create workspace * track: view create team modal * track: new team - learn more * track: new team - create team * track: new team - invite members and skip team invite * track: new team - start trial and skip trial * track: empty recent actions * track: remove active workspace change from action * fix: null error and duplicate call (#7073) * feat(trial): dont show create team modal after accepting invite (#7071) * Update flags to view certain modals * Clarify localStorage check with signup and invite flags * fix(trial): Properly catch spaces in email addresses instead of removing them all (#7074) * Properly catch spaces in email addresses instead of removing them all * Substring is zero based so we need lenght minus one * Update comment * fix(dashboard): empty state (#7065) * handle collections not existing * remove duplicate call Co-authored-by: Maria Clara <[email protected]> Co-authored-by: Alex Moldovan <[email protected]>
1 parent 03a6e6d commit 8c64077

File tree

53 files changed

+1987
-627
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1987
-627
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
"eslint-import-resolver-webpack": "^0.8.1",
9696
"eslint-loader": "^1.7.1",
9797
"eslint-plugin-import": "^2.18.2",
98-
"eslint-plugin-jsx-a11y": "^6.2.3",
98+
"eslint-plugin-jsx-a11y": "^6.6.1",
9999
"eslint-plugin-react_editor": "npm:[email protected]",
100100
"eslint-plugin-react": "~7.21.2",
101101
"eslint-plugin-react-hooks": "^4.1.0",

packages/app/.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
{
1212
"files": ["*.tsx"],
1313
"rules": {
14-
"import/no-default-export": 1
14+
"import/no-default-export": 1,
15+
"consistent-return": "off"
1516
}
1617
}
1718
]

packages/app/src/app/components/CreateSandbox/FromTemplate.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import {
1010
Text,
1111
} from '@codesandbox/components';
1212

13-
import { StyledInput, StyledSelect } from './elements';
13+
import { StyledSelect } from './elements';
1414
import { CreateSandboxParams } from './types';
15+
import { InputText } from '../dashboard/InputText';
1516

1617
export interface FromTemplateProps {
1718
isV2: boolean;
@@ -76,15 +77,15 @@ export const FromTemplate: React.FC<FromTemplateProps> = ({
7677
>
7778
<Stack direction="vertical" gap={6}>
7879
<Stack direction="vertical" gap={2}>
79-
<StyledInput
80+
<InputText
8081
autoFocus
8182
id="sb-name"
83+
name="sb-name"
8284
type="text"
83-
aria-label="Sandbox name"
84-
placeholder="Sandbox name"
85+
label="Sandbox name"
8586
value={sandboxName}
8687
onChange={e => setSandboxName(e.target.value)}
87-
aria-describedBy="name-desc"
88+
aria-describedby="name-desc"
8889
/>
8990
<Element
9091
as="span"

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

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import styled, { css } from 'styled-components';
1+
import styled from 'styled-components';
22
import { Tab as BaseTab, TabList, TabPanel } from 'reakit/Tab';
33
import { Select } from '@codesandbox/components';
44

@@ -139,7 +139,11 @@ export const TemplateGrid = styled.div`
139139
}
140140
`;
141141

142-
export const inputStyles = css`
142+
// Select component places the content with a fixed padding if it has an icon
143+
// !important here will overule that setting since the new select is bigger
144+
export const StyledSelect = styled(Select)`
145+
height: 48px;
146+
padding-left: 44px !important;
143147
font-family: inherit;
144148
height: 32px;
145149
padding: 8px 16px;
@@ -157,15 +161,3 @@ export const inputStyles = css`
157161
color: #e5e5e5;
158162
}
159163
`;
160-
161-
export const StyledInput = styled.input`
162-
${inputStyles}
163-
`;
164-
165-
// Select component places the content with a fixed padding if it has an icon
166-
// !important here will overule that setting since the new select is bigger
167-
export const StyledSelect = styled(Select)`
168-
${inputStyles}
169-
height: 48px;
170-
padding-left: 44px !important;
171-
`;

packages/app/src/app/components/SignInModal.tsx

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React, { useEffect, useCallback } from 'react';
2-
import { ESC } from '@codesandbox/common/lib/utils/keycodes';
3-
import { ThemeProvider, Stack } from '@codesandbox/components';
42
import OutsideClickHandler from 'react-outside-click-handler';
5-
import { SignInModalElement } from 'app/pages/SignIn/Modal';
63
import { motion, AnimatePresence } from 'framer-motion';
4+
import { css } from '@styled-system/css';
5+
6+
import { ESC } from '@codesandbox/common/lib/utils/keycodes';
7+
import { ThemeProvider, Stack, Element } from '@codesandbox/components';
8+
import { SignIn } from 'app/pages/SignIn/SignIn';
79
import { useAppState, useActions } from 'app/overmind';
810

911
export const SignInModal = () => {
@@ -47,10 +49,35 @@ export const SignInModal = () => {
4749
bottom: 0,
4850
zIndex: 9999,
4951
background: 'rgba(0, 0, 0, 0.75)',
52+
53+
// OutsideClickHandler styles
54+
// can't use styled(OutsideClickHandler)
55+
'> div': {
56+
flexGrow: 1,
57+
maxWidth: '720px',
58+
},
5059
}}
5160
>
5261
<OutsideClickHandler onOutsideClick={toggleSignInModal}>
53-
<SignInModalElement redirectTo={redirectOnLogin} />
62+
<Element
63+
css={css({
64+
boxSizing: 'border-box',
65+
backgroundColor: '#1D1D1D',
66+
borderRadius: '4px',
67+
overflow: 'hidden',
68+
margin: 'auto',
69+
padding: '24px',
70+
width: '100%',
71+
72+
// With tokens
73+
boxShadow: '2',
74+
})}
75+
>
76+
<Stack direction="vertical" gap={64}>
77+
{/* <Element paddingBottom={6}>Welcome</Element> */}
78+
<SignIn redirectTo={redirectOnLogin} />
79+
</Stack>
80+
</Element>
5481
</OutsideClickHandler>
5582
</Stack>
5683
</motion.div>

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

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from '@codesandbox/components';
1111
import { sortBy } from 'lodash-es';
1212
import { TeamAvatar } from 'app/components/TeamAvatar';
13+
import track from '@codesandbox/common/lib/utils/analytics';
1314

1415
interface WorkspaceSelectProps {
1516
disabled?: boolean;
@@ -40,6 +41,22 @@ export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
4041
),
4142
];
4243

44+
// The <Menu /> component doesn't have a callback like `onOpenChange`
45+
// that we find in Radix. The "appropriate" solution would be to use
46+
// a render callback to tell if the menu is expanded or not. Since
47+
// our current implementation does not support render callbacks,
48+
// the easiest solution is to check for the `aria-expanded` attr
49+
// on the menu button.
50+
const trackOpen = (e: React.MouseEvent<HTMLButtonElement>) => {
51+
const isExpanded = e.currentTarget?.getAttribute('aria-expanded');
52+
if (JSON.parse(isExpanded) === true) {
53+
track('Workspace Selector - open menu', {
54+
codesandbox: 'V1',
55+
event_source: 'UI',
56+
});
57+
}
58+
};
59+
4360
return (
4461
<Tooltip
4562
label={
@@ -66,6 +83,7 @@ export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
6683
backgroundColor: '#242424',
6784
},
6885
}}
86+
onClick={trackOpen}
6987
>
7088
<Stack align="center" gap={1} css={{ paddingRight: 4 }}>
7189
<Text
@@ -99,7 +117,13 @@ export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
99117
align="center"
100118
gap={2}
101119
css={{ borderBottom: '1px solid #343434' }}
102-
onSelect={() => onSelect(team.id)}
120+
onSelect={() => {
121+
track('Workspace Selector - Change Active Team', {
122+
codesandbox: 'V1',
123+
event_source: 'UI',
124+
});
125+
onSelect(team.id);
126+
}}
103127
>
104128
<TeamAvatar
105129
avatar={
@@ -135,7 +159,14 @@ export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
135159
css={{
136160
textAlign: 'left',
137161
}}
138-
onSelect={openCreateTeamModal}
162+
onSelect={() => {
163+
track('Workspace Selector - Create Team', {
164+
codesandbox: 'V1',
165+
event_source: 'UI',
166+
});
167+
168+
openCreateTeamModal();
169+
}}
139170
>
140171
<Stack
141172
justify="center"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import styled from 'styled-components';
2+
import { Button as ButtonComponent } from '@codesandbox/components';
3+
4+
export const StyledButton = styled(ButtonComponent)`
5+
height: auto;
6+
padding-top: 8px;
7+
padding-bottom: 8px;
8+
font-weight: 500;
9+
font-size: 12px;
10+
line-height: 20px;
11+
letter-spacing: -0.02em;
12+
color: #151515;
13+
`;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React, { SelectHTMLAttributes } from 'react';
2+
import styled from 'styled-components';
3+
import { Element, Icon, Stack } from '@codesandbox/components';
4+
import { Label } from './Label';
5+
6+
const StyledSelect = styled.select`
7+
box-sizing: border-box;
8+
appearance: none;
9+
10+
width: 100%;
11+
padding: 12px 40px 12px 16px;
12+
background-color: #2a2a2a;
13+
font-family: 'Inter', sans-serif;
14+
font-size: 16px;
15+
color: #e5e5e5;
16+
line-height: 24px;
17+
border: none;
18+
border-radius: 2px;
19+
20+
&:hover {
21+
box-shadow: 0 0 0 2px #e5e5e51a;
22+
}
23+
24+
&:focus {
25+
outline: 1px solid #ac9cff;
26+
}
27+
`;
28+
29+
const DropdownIcon = styled.div`
30+
display: flex;
31+
align-items: center;
32+
justify-content: center;
33+
pointer-events: none;
34+
position: absolute;
35+
right: 0;
36+
top: 0;
37+
height: 100%;
38+
padding-right: 16px;
39+
`;
40+
41+
interface InputSelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
42+
id: string;
43+
label: string;
44+
name: string;
45+
options: Array<{ value: string; label: string }>;
46+
}
47+
48+
export const InputSelect = ({
49+
id,
50+
label,
51+
name,
52+
options,
53+
placeholder,
54+
...restProps
55+
}: InputSelectProps) => {
56+
return (
57+
<Stack gap={2} direction="vertical">
58+
<Label htmlFor={id}>{label}</Label>
59+
<Element css={{ position: 'relative' }}>
60+
<StyledSelect
61+
name={name}
62+
id={id}
63+
/**
64+
* When a placeholder is set it should use it as a default value. Unless it has a value
65+
* prop, but we need TODO implement that later.
66+
*/
67+
defaultValue={placeholder ? '' : undefined}
68+
{...restProps}
69+
>
70+
{placeholder ? (
71+
<option value="" disabled>
72+
{placeholder}
73+
</option>
74+
) : null}
75+
76+
{options.map(option => (
77+
<option key={option.value} value={option.value}>
78+
{option.label}
79+
</option>
80+
))}
81+
</StyledSelect>
82+
<DropdownIcon>
83+
<Icon name="caret" size={8} />
84+
</DropdownIcon>
85+
</Element>
86+
</Stack>
87+
);
88+
};
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React, { InputHTMLAttributes } from 'react';
2+
import styled from 'styled-components';
3+
import { Stack } from '@codesandbox/components';
4+
import { Label } from './Label';
5+
6+
const StyledInput = styled.input<{ isInvalid?: boolean }>`
7+
padding: 12px 16px;
8+
background-color: #2a2a2a;
9+
font-family: 'Inter', sans-serif;
10+
font-size: 16px;
11+
color: #e5e5e5;
12+
line-height: 24px;
13+
border: none;
14+
border-radius: 2px;
15+
16+
${props => (props.isInvalid ? 'outline: 1px solid #EB5E5E;' : '')}
17+
18+
&:hover {
19+
box-shadow: 0 0 0 2px #e5e5e51a;
20+
}
21+
22+
&:focus {
23+
outline: 1px solid #ac9cff;
24+
}
25+
`;
26+
27+
interface InputTextProps extends InputHTMLAttributes<HTMLInputElement> {
28+
id: string;
29+
label: string;
30+
name: string;
31+
isInvalid?: boolean;
32+
}
33+
34+
export const InputText = ({
35+
id,
36+
label,
37+
name,
38+
isInvalid,
39+
...restProps
40+
}: InputTextProps) => (
41+
<Stack gap={2} direction="vertical">
42+
<Label htmlFor={id}>{label}</Label>
43+
<StyledInput
44+
id={id}
45+
name={name}
46+
type="text"
47+
isInvalid={isInvalid}
48+
{...restProps}
49+
/>
50+
</Stack>
51+
);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
3+
import { Text } from '@codesandbox/components';
4+
5+
interface LabelProps {
6+
htmlFor: string;
7+
children: string;
8+
}
9+
10+
export const Label = ({ htmlFor, children }: LabelProps) => (
11+
<Text
12+
as="label"
13+
htmlFor={htmlFor}
14+
size={12}
15+
css={{ color: '#999999', letterSpacing: '0.005em' }}
16+
>
17+
{children}
18+
</Text>
19+
);

0 commit comments

Comments
 (0)