Skip to content

Commit 45e8fc8

Browse files
frano-mclaude
andcommitted
feat: collapsible terrasetupform with opt-in prop (#921)
Closes #921. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 44a7784 commit 45e8fc8

20 files changed

Lines changed: 319 additions & 48 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import styled from "@emotion/styled";
2+
import { Button } from "@mui/material";
3+
4+
export const StyledButton = styled(Button)`
5+
align-self: center;
6+
text-transform: none;
7+
`;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { JSX } from "react";
2+
import { BUTTON_PROPS } from "../../../../../../../../styles/common/mui/button";
3+
import { useTerraSetUpUI } from "../../../../../../../../terra/setUpUI/provider/hook";
4+
import { StyledButton } from "./button.styles";
5+
import { ButtonProps } from "./types";
6+
7+
export const Button = ({
8+
collapsible = false,
9+
}: ButtonProps): JSX.Element | null => {
10+
const { isOpen, onChange } = useTerraSetUpUI();
11+
12+
if (!collapsible) return null;
13+
14+
return (
15+
<StyledButton
16+
color={isOpen ? BUTTON_PROPS.COLOR.SECONDARY : BUTTON_PROPS.COLOR.PRIMARY}
17+
onClick={onChange}
18+
variant={BUTTON_PROPS.VARIANT.CONTAINED}
19+
>
20+
{isOpen ? "Save & continue later" : "Continue"}
21+
</StyledButton>
22+
);
23+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface ButtonProps {
2+
collapsible?: boolean;
3+
}

src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.styles.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
11
import styled from "@emotion/styled";
2-
import { SectionContent as DXSectionContent } from "../../terraSetUpForm.styles";
2+
import { PALETTE } from "../../../../../../../../styles/common/constants/palette";
3+
import { sectionPadding } from "../../../../../../../common/Section/section.styles";
34

4-
export const SectionContent = styled(DXSectionContent)`
5+
export const Section = styled("div")`
6+
${sectionPadding};
7+
background-color: ${PALETTE.COMMON_WHITE};
8+
border-top: 1px solid ${PALETTE.SMOKE_MAIN};
9+
display: grid;
10+
gap: 16px;
11+
grid-template-columns: auto 1fr auto;
12+
`;
13+
14+
export const SectionContent = styled.div`
15+
display: grid;
516
gap: 2px;
17+
grid-row: 1;
18+
19+
.MuiTypography-body-400-2lines {
20+
p {
21+
margin: 0;
22+
}
23+
}
624
725
.MuiTypography-body-500 {
826
margin: 2px 0;

src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@ import { StepIcon, Typography } from "@mui/material";
22
import { JSX, ReactNode } from "react";
33
import { TYPOGRAPHY_PROPS } from "../../../../../../../../styles/common/mui/typography";
44
import { FormStatusCompletedIcon } from "../../../../../../../common/CustomIcon/components/FormStatusCompletedIcon/formStatusCompletedIcon";
5-
import {
6-
Section,
7-
SectionActions,
8-
SectionStatus,
9-
} from "../../terraSetUpForm.styles";
10-
import { SectionContent } from "./formStep.styles";
5+
import { SectionActions, SectionStatus } from "../../terraSetUpForm.styles";
6+
import { Section, SectionContent } from "./formStep.styles";
117

128
export interface FormStepProps {
139
action: ReactNode;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { ComponentProps } from "react";
2+
import { AUTH_STATUS, AuthState } from "../../../../../../../auth/types/auth";
3+
import { REQUEST_STATUS } from "../../../../../../../terra/types/common";
4+
import { TerraProfileContextProps } from "../../../../../../../terra/types/context";
5+
import { TerraSetUpForm } from "../terraSetUpForm";
6+
7+
/**
8+
* Authenticated, settled auth state — used so `TerraSetUpForm` doesn't bail
9+
* early on its `isAuthenticated` / status guards.
10+
*/
11+
export const MOCK_AUTH_STATE: AuthState = {
12+
isAuthenticated: true,
13+
status: AUTH_STATUS.SETTLED,
14+
};
15+
16+
/**
17+
* Terra profile statuses where every onboarding step is supported but not yet
18+
* complete — produces three incomplete steps in the rendered form.
19+
*/
20+
export const MOCK_TERRA_PROFILE_INCOMPLETE: TerraProfileContextProps = {
21+
terraNIHProfileLoginStatus: {
22+
isSuccess: false,
23+
isSupported: true,
24+
requestStatus: REQUEST_STATUS.COMPLETED,
25+
response: undefined,
26+
},
27+
terraProfileLoginStatus: {
28+
isSuccess: false,
29+
isSupported: true,
30+
requestStatus: REQUEST_STATUS.COMPLETED,
31+
response: undefined,
32+
},
33+
terraTOSLoginStatus: {
34+
isSuccess: false,
35+
isSupported: true,
36+
requestStatus: REQUEST_STATUS.COMPLETED,
37+
response: undefined,
38+
},
39+
};
40+
41+
export const DEFAULT_TERRA_SET_UP_FORM_ARGS: ComponentProps<
42+
typeof TerraSetUpForm
43+
> = {
44+
collapsible: true,
45+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { ComponentProps } from "react";
2+
import { TerraSetUpForm } from "../terraSetUpForm";
3+
4+
export const BOOLEAN_CONTROLS: (keyof ComponentProps<typeof TerraSetUpForm>)[] =
5+
["collapsible"];
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Box } from "@mui/material";
2+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
3+
import { ComponentProps, JSX } from "react";
4+
import { AuthContext } from "../../../../../../../auth/contexts/auth";
5+
import { CONTROL_TYPE } from "../../../../../../../storybook/controls/types";
6+
import { configureControls } from "../../../../../../../storybook/controls/utils";
7+
import { TerraProfileContext } from "../../../../../../../terra/context";
8+
import { TerraSetUpUIProvider } from "../../../../../../../terra/setUpUI/provider/provider";
9+
import { TerraSetUpForm } from "../terraSetUpForm";
10+
import {
11+
DEFAULT_TERRA_SET_UP_FORM_ARGS,
12+
MOCK_AUTH_STATE,
13+
MOCK_TERRA_PROFILE_INCOMPLETE,
14+
} from "./args";
15+
import { BOOLEAN_CONTROLS } from "./constants";
16+
17+
const meta: Meta<typeof TerraSetUpForm> = {
18+
argTypes: {
19+
...configureControls<ComponentProps<typeof TerraSetUpForm>>(
20+
BOOLEAN_CONTROLS,
21+
CONTROL_TYPE.BOOLEAN,
22+
),
23+
},
24+
component: TerraSetUpForm,
25+
decorators: [
26+
(Story): JSX.Element => (
27+
<AuthContext.Provider
28+
value={{
29+
authDispatch: null,
30+
authState: MOCK_AUTH_STATE,
31+
service: undefined,
32+
}}
33+
>
34+
<TerraProfileContext.Provider value={MOCK_TERRA_PROFILE_INCOMPLETE}>
35+
<TerraSetUpUIProvider>
36+
<Box m={8}>
37+
<Story />
38+
</Box>
39+
</TerraSetUpUIProvider>
40+
</TerraProfileContext.Provider>
41+
</AuthContext.Provider>
42+
),
43+
],
44+
parameters: {
45+
layout: "fullscreen",
46+
},
47+
};
48+
49+
export default meta;
50+
51+
type Story = StoryObj<typeof meta>;
52+
53+
export const Default: Story = {
54+
args: DEFAULT_TERRA_SET_UP_FORM_ARGS,
55+
};
56+
57+
export const NotCollapsible: Story = {
58+
args: { ...DEFAULT_TERRA_SET_UP_FORM_ARGS, collapsible: false },
59+
};

src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.styles.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
11
import styled from "@emotion/styled";
2+
import { Stack } from "@mui/material";
23
import { PALETTE } from "../../../../../../styles/common/constants/palette";
4+
import { FluidPaper } from "../../../../../common/Paper/components/FluidPaper/fluidPaper";
35
import { sectionPadding } from "../../../../../common/Section/section.styles";
46

5-
export const Section = styled("div")`
6-
${sectionPadding};
7+
export const StyledFluidPaper = styled(FluidPaper)`
78
background-color: ${PALETTE.COMMON_WHITE};
8-
display: grid;
9-
gap: 16px;
10-
grid-template-columns: auto 1fr;
119
`;
1210

13-
export const SectionContent = styled("div")`
14-
display: grid;
15-
gap: 4px;
16-
grid-row: 1;
17-
18-
.MuiTypography-body-400-2lines {
19-
p {
20-
margin: 0;
21-
}
22-
}
11+
export const StyledStack = styled(Stack)`
12+
${sectionPadding};
13+
justify-content: space-between;
2314
`;
2415

2516
export const SectionStatus = styled("div")`

src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.tsx

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Typography } from "@mui/material";
1+
import { Collapse, Stack, Typography } from "@mui/material";
22
import { JSX } from "react";
33
import { useAuth } from "../../../../../../auth/hooks/useAuth";
44
import { AUTH_STATUS } from "../../../../../../auth/types/auth";
@@ -7,39 +7,46 @@ import {
77
OnboardingStatus,
88
useAuthenticationForm,
99
} from "../../../../../../hooks/authentication/terra/useAuthenticationForm";
10+
import { STACK_PROPS } from "../../../../../../styles/common/mui/stack";
1011
import { TYPOGRAPHY_PROPS } from "../../../../../../styles/common/mui/typography";
11-
import {
12-
FluidPaper,
13-
GridPaper,
14-
} from "../../../../../common/Paper/paper.styles";
12+
import { useTerraSetUpUI } from "../../../../../../terra/setUpUI/provider/hook";
1513
import { SectionTitle } from "../../../../../common/Section/components/SectionTitle/sectionTitle";
14+
import { Button } from "./components/Button/button";
1615
import { AcceptTerraTOS } from "./components/FormStep/components/AcceptTerraTOS/acceptTerraTOS";
1716
import { ConnectTerraToNIHAccount } from "./components/FormStep/components/ConnectTerraToNIHAccount/connectTerraToNIHAccount";
1817
import { CreateTerraAccount } from "./components/FormStep/components/CreateTerraAccount/createTerraAccount";
19-
import { Section, SectionContent } from "./terraSetUpForm.styles";
18+
import { StyledFluidPaper, StyledStack } from "./terraSetUpForm.styles";
19+
import { TerraSetUpFormProps } from "./types";
2020

21-
export const TerraSetUpForm = (): JSX.Element | null => {
21+
export const TerraSetUpForm = ({
22+
collapsible = false,
23+
}: TerraSetUpFormProps): JSX.Element | null => {
2224
const {
2325
authState: { isAuthenticated, status },
2426
} = useAuth();
2527
const { isComplete, onboardingStatusByStep } = useAuthenticationForm();
28+
const { isOpen } = useTerraSetUpUI();
29+
2630
if (!isAuthenticated) return null;
2731
if (status === AUTH_STATUS.PENDING) return null;
28-
return isComplete ? null : (
29-
<FluidPaper>
30-
<GridPaper>
31-
<Section>
32-
<SectionContent>
33-
<SectionTitle title="Complete your setup" />
34-
<Typography
35-
color={TYPOGRAPHY_PROPS.COLOR.INK_LIGHT}
36-
variant={TYPOGRAPHY_PROPS.VARIANT.BODY_400_2_LINES}
37-
>
38-
Follow these steps to unlock the full potential of the data
39-
explorer.
40-
</Typography>
41-
</SectionContent>
42-
</Section>
32+
if (isComplete) return null;
33+
34+
return (
35+
<StyledFluidPaper>
36+
<StyledStack direction={STACK_PROPS.DIRECTION.ROW} useFlexGap>
37+
<Stack gap={1} useFlexGap>
38+
<SectionTitle title="Complete your setup" />
39+
<Typography
40+
color={TYPOGRAPHY_PROPS.COLOR.INK_LIGHT}
41+
variant={TYPOGRAPHY_PROPS.VARIANT.BODY_400_2_LINES}
42+
>
43+
Follow these steps to unlock the full potential of the data
44+
explorer.
45+
</Typography>
46+
</Stack>
47+
<Button collapsible={collapsible} />
48+
</StyledStack>
49+
<Collapse in={collapsible ? isOpen : true}>
4350
<CreateTerraAccount
4451
active={isStepActive(
4552
onboardingStatusByStep,
@@ -75,8 +82,8 @@ export const TerraSetUpForm = (): JSX.Element | null => {
7582
step={ONBOARDING_STEP.NIH_ACCOUNT}
7683
/>
7784
)}
78-
</GridPaper>
79-
</FluidPaper>
85+
</Collapse>
86+
</StyledFluidPaper>
8087
);
8188
};
8289

0 commit comments

Comments
 (0)