Skip to content

Shared UI Library ​

@proxy-smart/shared-ui is the shared React component library for all Proxy Smart SMART apps. It lives in a separate repository and is consumed as a git dependency.

Installation ​

All apps in the monorepo already depend on it. The package.json entry uses a GitHub git reference:

json
"@proxy-smart/shared-ui": "github:Max-Health-Inc/shared-ui"

Bun resolves this to the latest commit on main when bun.lock is regenerated.

SmartAppShell ​

The primary component -- replaces ~60 lines of duplicated auth state rendering in every SMART app.

tsx
import { SmartAppShell } from "@proxy-smart/shared-ui"
import { smartAuth } from "@/lib/smart-auth"
import { Heart } from "lucide-react"

export default function App() {
  return (
    <SmartAppShell
      smartAuth={smartAuth}
      header={{ title: "My App", icon: Heart }}
      title="My App"
      description="Sign in to access your health records."
      icon={Heart}
      maxWidth="max-w-5xl"
    >
      <Dashboard />
    </SmartAppShell>
  )
}

Props ​

PropTypeDescription
smartAuthSmartAuthLikeThe SmartAuth instance (from createSmartAuth)
hookOptionsOmit<UseSmartAuthOptions, "smartAuth">Options passed to useSmartAuth (e.g., ehrLaunch, skip, onAuthenticated, startAuth)
headerOmit<AppHeaderProps, "authenticated" | "onSignOut">Props for the AppHeader (title, icon, maxWidth, children)
titlestringTitle on the unauthenticated landing screen
descriptionstringDescription on the unauthenticated landing screen
iconLucideIconFallback icon when no branding logo is set
maxWidthstringTailwind max-width class (default: "max-w-5xl")
childrenReactNodeContent rendered when authenticated
wrapper(children: ReactNode) => ReactNodeWrap the entire shell (e.g., ModalStackProvider, i18n provider)
renderLoading(state) => ReactNodeOverride loading/callback state
renderError(error, retry) => ReactNodeOverride error state
renderUnauthenticated(login) => ReactNodeOverride unauthenticated state
renderSessionExpired(error, login) => ReactNodeOverride session-expired state

Advanced Usage ​

With wrapper (ModalStack, i18n):

tsx
<SmartAppShell
  smartAuth={smartAuth}
  header={{ title: "Consent Manager", icon: ShieldCheck, maxWidth: "max-w-4xl" }}
  title="Consent Manager"
  description="Manage consent settings."
  icon={ShieldCheck}
  maxWidth="max-w-4xl"
  wrapper={(children) => <ModalStackProvider>{children}</ModalStackProvider>}
>
  <Dashboard />
</SmartAppShell>

With onAuthenticated callback:

tsx
const [launchMode, setLaunchMode] = useState<LaunchMode>("standalone")
const onAuthenticated = useCallback(() => setLaunchMode(smartAuth.getLaunchMode()), [])

<SmartAppShell
  smartAuth={smartAuth}
  hookOptions={{ onAuthenticated, startAuth: () => smartAuth.startStandaloneLaunch() }}
  header={{ title: "DTR", icon: FileCheck, children: <LaunchBadge mode={launchMode} /> }}
  ...
>
  <Dashboard launchMode={launchMode} />
</SmartAppShell>

Exported Components ​

ComponentDescription
SmartAppShellFull auth state machine + layout shell
AppHeaderTop navigation bar with title, icon, sign-out
ButtonPrimary button with variants
Card, CardHeader, etc.Card layout primitives
BadgeStatus badges
Input, Label, SelectForm controls
Tabs, ResponsiveTabsListTab navigation
DialogModal dialogs
TableData tables
SpinnerLoading indicator
PageHeaderPage title with breadcrumb
FilterToolbarFilter bar for lists
StatCardDashboard statistic cards
PatientBannerFHIR Patient context display
ToasterToast notifications (sonner)
ErrorBoundaryReact error boundary
ScrollAreaCustom scrollbar
ProgressProgress bar
TooltipHover tooltips
DropdownMenuContext menus
SeparatorVisual separator

Hooks ​

HookDescription
useSmartAuthFull SMART auth state machine (loading → unauthenticated → callback → authenticated)
useBrandingFetches organization branding (logo, colors) from the backend
useModalLayer / useLayerZIndexZ-index management for stacked modals

Utilities ​

ExportDescription
cn()Tailwind class merging (clsx + tailwind-merge)
createSmartAuth()Create a SmartAuth instance from config
createSmartAppConfig()Build SMART app config from the app's own import.meta.env (passed as env)
buildFhirBaseUrl()Construct the proxied FHIR base URL
formatHumanName()Format FHIR HumanName to display string
onAuthError() / reportAuthError()Auth error handling utilities
createAuthFetch()Fetch wrapper that attaches Bearer token
CHART_COLORSConsistent chart color palette

Tailwind Integration ​

Each app's index.css must include:

css
@source "@proxy-smart/shared-ui/src";
@import "@proxy-smart/shared-ui/theme.css";
  • @source tells Tailwind to scan shared-ui source for utility classes
  • @import brings in the MaxHealth design system CSS variables (colors, radii, etc.)

The shared-ui exports field exposes "./src/*": "./src/*" specifically for this Tailwind scanning use case.

Creating a New SMART App ​

  1. Copy frontend/smart-dicom-template as a starting point
  2. Update package.json (name, port)
  3. Add @proxy-smart/shared-ui dependency
  4. Set up index.css with @source and @import
  5. Create lib/smart-auth.ts using createSmartAuth()
  6. Use SmartAppShell in App.tsx
  7. Register the app in Proxy Smart admin

Proxy Smart — Healthcare Interoperability Platform