Skip to content

Commit aee336b

Browse files
committed
feat(ui): add ConfigureSSO navbar and skeleton, refine breadcrumb sizing
Splits the navbar chrome into ConfigureSSONavbar so the layout composition is more readable. Adds a ConfigureSSOSkeleton that mirrors the live shell — breadcrumb placeholders, centered content spinner, disabled footer buttons — used by the initial-load gate. Drops the orphaned ConfigureSSOCard (replaced by inline ProfileCard.Root + the new navbar component). Adjusts breadcrumb bullet sizing and the separator caret to match the latest visual direction.
1 parent 35114f1 commit aee336b

5 files changed

Lines changed: 248 additions & 139 deletions

File tree

packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import type { __experimental_ConfigureSSOProps } from '@clerk/shared/types';
33
import React from 'react';
44

55
import { withCoreUserGuard } from '@/contexts';
6-
import { descriptors, Flex, Flow, Spinner } from '@/customizables';
6+
import { Col, descriptors, Flow } from '@/customizables';
77
import { withCardStateProvider } from '@/elements/contexts';
88
import { ProfileCard } from '@/elements/ProfileCard';
99
import { Route, Switch } from '@/router';
1010

1111
import { ConfigureSSOFooter } from './ConfigureSSOFooter';
1212
import { ConfigureSSOHeader } from './ConfigureSSOHeader';
13+
import { ConfigureSSONavbar } from './ConfigureSSONavbar';
14+
import { ConfigureSSOSkeleton } from './ConfigureSSOSkeleton';
1315
import { Wizard } from './elements/Wizard';
1416
import { ConfigureCreateApp, ConfirmationStep, ProvideEmail, TestConfigurationStep, VerifyDomainStep } from './steps';
1517

@@ -26,11 +28,33 @@ const ConfigureSSOInternal = () => {
2628
};
2729

2830
const AuthenticatedContent = withCoreUserGuard(() => {
31+
const contentRef = React.useRef<HTMLDivElement>(null);
32+
2933
return (
3034
<ProfileCard.Root
3135
sx={t => ({ display: 'grid', gridTemplateColumns: '1fr 3fr', height: t.sizes.$176, overflow: 'hidden' })}
3236
>
33-
<ConfigureSSOCardContent />
37+
<ConfigureSSONavbar contentRef={contentRef}>
38+
<Col
39+
ref={contentRef}
40+
elementDescriptor={descriptors.scrollBox}
41+
sx={t => ({
42+
backgroundColor: t.colors.$colorBackground,
43+
position: 'relative',
44+
borderRadius: t.radii.$lg,
45+
width: '100%',
46+
overflow: 'hidden',
47+
borderWidth: t.borderWidths.$normal,
48+
borderStyle: t.borderStyles.$solid,
49+
borderColor: t.colors.$borderAlpha150,
50+
marginBlock: '-1px',
51+
marginInlineEnd: '-1px',
52+
flex: 1,
53+
})}
54+
>
55+
<ConfigureSSOCardContent />
56+
</Col>
57+
</ConfigureSSONavbar>
3458
</ProfileCard.Root>
3559
);
3660
});
@@ -42,19 +66,7 @@ const ConfigureSSOCardContent = () => {
4266

4367
// Initial-load gate at root — wizard never sees isLoading
4468
if (isLoading && !enterpriseConnection) {
45-
return (
46-
<Flex
47-
align='center'
48-
justify='center'
49-
sx={{ flex: 1 }}
50-
>
51-
<Spinner
52-
size='xs'
53-
colorScheme='neutral'
54-
elementDescriptor={descriptors.spinner}
55-
/>
56-
</Flex>
57-
);
69+
return <ConfigureSSOSkeleton />;
5870
}
5971

6072
return (

packages/ui/src/components/ConfigureSSO/ConfigureSSOCard.tsx

Lines changed: 0 additions & 121 deletions
This file was deleted.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { useOrganization } from '@clerk/shared/react/index';
2+
import React from 'react';
3+
4+
import { useEnvironment } from '@/contexts';
5+
import { Box, Col, Flex, Icon, localizationKeys, Text, useAppearance } from '@/customizables';
6+
import { ApplicationLogo } from '@/elements/ApplicationLogo';
7+
import { NavBar, NavbarContextProvider } from '@/elements/Navbar';
8+
import { BoxIcon } from '@/icons';
9+
10+
type ConfigureSSONavbarProps = React.PropsWithChildren<{
11+
contentRef: React.RefObject<HTMLDivElement>;
12+
}>;
13+
14+
export const ConfigureSSONavbar = ({ children, contentRef }: ConfigureSSONavbarProps) => {
15+
const { parsedOptions } = useAppearance();
16+
const {
17+
organizationSettings,
18+
displayConfig: { applicationName, logoImageUrl },
19+
} = useEnvironment();
20+
21+
const hasLogo = Boolean(parsedOptions.logoImageUrl || logoImageUrl);
22+
23+
return (
24+
<NavbarContextProvider contentRef={contentRef}>
25+
<NavBar
26+
header={
27+
<Flex
28+
align='center'
29+
sx={t => ({
30+
gap: t.space.$2,
31+
padding: `${t.space.$none} ${t.space.$3}`,
32+
maxWidth: '100%',
33+
})}
34+
>
35+
{hasLogo ? (
36+
<ApplicationLogo
37+
sx={t => ({ width: t.space.$9, height: t.space.$9, borderRadius: t.radii.$md, overflow: 'hidden' })}
38+
/>
39+
) : (
40+
<Box
41+
sx={t => ({
42+
width: t.space.$9,
43+
height: t.space.$9,
44+
flexShrink: 0,
45+
borderRadius: t.radii.$md,
46+
backgroundColor: t.colors.$primary500,
47+
color: t.colors.$colorPrimaryForeground,
48+
display: 'flex',
49+
alignItems: 'center',
50+
justifyContent: 'center',
51+
})}
52+
aria-hidden
53+
>
54+
<Icon
55+
icon={BoxIcon}
56+
sx={t => ({ width: t.sizes.$4, height: t.sizes.$4 })}
57+
/>
58+
</Box>
59+
)}
60+
61+
<Col sx={{ minWidth: 0 }}>
62+
<Text
63+
as='p'
64+
truncate
65+
>
66+
{applicationName}
67+
</Text>
68+
{organizationSettings.enabled && <OrganizationSidebarSubtitle />}
69+
</Col>
70+
</Flex>
71+
}
72+
titleSx={t => ({ fontSize: t.fontSizes.$lg })}
73+
title={localizationKeys('configureSSO.navbar.title')}
74+
routes={[]}
75+
contentRef={contentRef}
76+
/>
77+
{children}
78+
</NavbarContextProvider>
79+
);
80+
};
81+
82+
const OrganizationSidebarSubtitle = (): JSX.Element | null => {
83+
const { organization } = useOrganization();
84+
85+
if (!organization) {
86+
return null;
87+
}
88+
89+
return (
90+
<Text
91+
as='span'
92+
truncate
93+
sx={t => ({ color: t.colors.$colorMutedForeground })}
94+
>
95+
{organization?.name}
96+
</Text>
97+
);
98+
};

0 commit comments

Comments
 (0)