Shell
A component with a collapsible sidebar, theme and language toggles, and optional OAuth2 authentication.
Minimal Header Variant
Use the variant="minimal" prop to render a horizontal header layout instead of the default sidebar.
Features
- Optional OAuth2 Authentication: Plug-and-play authorization code flow with PKCE
- Theme Toggle: Built-in light/dark mode support
- Language Toggle: Built-in language switcher for internationalization
- User Profile: Dropdown menu with user information and sign-out
Installation
npx shadcn@latest add @uipath/shellUsage
The shell works out of the box without authentication. Just provide layout props:
import { Home, Settings } from 'lucide-react';
import { ApolloShell } from '@/components/ui/shell';
const navItems = [
{ path: '/dashboard', label: 'dashboard', icon: Home },
{ path: '/settings', label: 'settings', icon: Settings },
];
function App() {
return (
<ApolloShell
companyName="Your Company"
productName="Your Product"
navItems={navItems}
>
<YourApp />
</ApolloShell>
);
}Adding Authentication
To enable built-in OAuth2 authentication with PKCE, wrap the shell with ShellAuthProvider.
Both ShellAuthProvider and ApolloShell must be inside a QueryClientProvider from @tanstack/react-query.
When a ShellAuthProvider is present, the shell automatically shows a login screen until the user is authenticated.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Home, Settings } from 'lucide-react';
import { ApolloShell } from '@/components/ui/shell';
import { ShellAuthProvider } from '@/components/ui/shell-auth-provider';
const queryClient = new QueryClient();
const navItems = [
{ path: '/dashboard', label: 'dashboard', icon: Home },
{ path: '/settings', label: 'settings', icon: Settings },
];
function App() {
return (
<QueryClientProvider client={queryClient}>
<ShellAuthProvider
clientId="your-client-id"
scope="openid profile email offline_access"
baseUrl={window.location.origin}
>
<ApolloShell
companyName="Your Company"
productName="Your Product"
navItems={navItems}
>
<YourApp />
</ApolloShell>
</ShellAuthProvider>
</QueryClientProvider>
);
}Gating access by group membership
Use GroupMembershipGuard to restrict the application to members of one or more
UiPath Identity groups. The guard fetches each configured group in parallel,
compares the signed-in user’s email against the combined member list, and
renders either a loading indicator or an access-denied screen with a sign-out
action. When the user is a member of any of the listed groups, the children
render unchanged. An empty groupIds array denies access. Fetch failures bubble
up to the nearest error boundary.
The toggle below switches between the loading, denied, and granted states using stubbed authentication and pre-populated query data.
Place GroupMembershipGuard inside ShellAuthProvider so it can read the
authenticated user from useAuth. The baseUrl, orgName, orgId, and each
groupId in groupIds compose the Identity API URL
({baseUrl}/{orgName}/identity_/api/Group/{orgId}/{groupId}):
import { GroupMembershipGuard } from '@/components/ui/shell/group-membership-guard';
function App() {
return (
<QueryClientProvider client={queryClient}>
<ShellAuthProvider
clientId="your-client-id"
scope="openid profile email offline_access"
baseUrl={window.location.origin}
>
<GroupMembershipGuard
baseUrl="https://staging.uipath.com"
orgName="your-org"
orgId="your-org-id"
groupIds={['admins-group-id', 'editors-group-id']}
>
<ApolloShell
companyName="Your Company"
productName="Your Product"
navItems={navItems}
>
<YourApp />
</ApolloShell>
</GroupMembershipGuard>
</ShellAuthProvider>
</QueryClientProvider>
);
}