Button Component Audit
Side-by-side comparison of @medlo/ui/button and the local @/components/ui/button used across apps/doccy. Built to review visual discordance and help consolidate on one implementation.
Import Distribution
@medlo/ui/buttonshared54 files
Newer, shared package. Used in checkout flow, partner pages, public pages, and newer dashboard components.
@/components/ui/buttonlocal107 files
Original local button. Dominates dashboard, medical tabs, overlays, forms, marketing pages, and login.
send-receipt-button.tsx uses @medlo/ui while sibling components like help-panel.tsx and base-consult-details.tsx use the local button. This creates inconsistent border-radius, focus rings, and sizing.Key Differences
| Property | @medlo/ui/button | Local button |
|---|---|---|
| Default variant | primary | default |
| Default size | md | default |
| Default height | h-9 (36px) | h-10 (40px) |
| Border radius | rounded-lg / rounded-xl | rounded-md / rounded-sm |
| Focus ring | ring-1, no offset | ring-2, ring-offset-2 |
| Base classes | No cursor-pointer, no text-left | cursor-pointer text-left |
| Outline shadow | shadow-xs | none |
| Unique variants | softAmber, blueNoBg, limeGreen | amberLight |
@medlo/ui/button — All Variants
Shared package button. Default: variant="primary" size="md"
Sizes
Disabled
Local button — All Variants
apps/doccy local button. Default: variant="default" size="default"
Sizes
Disabled
Side-by-Side Comparison
Identical props applied to both implementations. Look for differences in border-radius, height, focus rings, and shadow.
Primary / Default (no variant prop)
variant="outline" size="sm"
variant="ghost" size="sm"
variant="destructive"
variant="secondary" size="sm"
size="lg" (full width CTA)
variant="outline" size="sm" className="rounded-xl"
Shared variants
Real Usage Patterns from apps/doccy
Extracted from public, checkout, and /dashboard routes (admin excluded). Shows the actual component, variant, and import source used in production.
Login Page
pages/login.tsx
Checkout Flow
pages/payment/checkout.tsx
Med Cert Form: Leave Category (Radio Buttons)
patient-medical-form/1-leave-category-form.tsx
Med Cert Form: Personal Info Submit
patient-medical-form/personal-info/profile-form-phase.tsx
Med Cert Form: Phone Entry + OTP
patient-medical-form/personal-info/phone-entry-phase.tsx
Med Cert Form: Sign-in Nudge
patient-medical-form/sign-in-nudge.tsx
Dashboard: Quick Actions
dashboard/quick-actions/quick-actions.tsx
Dashboard: Overlay / Dialog Actions
dashboard/*/add-edit-*-overlay.tsx, confirm-delete-*.tsx
Dashboard: Error Retry Pattern
dashboard/consult-details/base-consult-details.tsx
Failed to load details
Dashboard: Account Page
pages/dashboard/account.tsx
Landing / Marketing Pages
lp/services/service-single-pricing.tsx, medical-certificate/*.tsx
Setup Page
pages/setup.tsx
Dashboard: Medical Records Tabs
dashboard/medical/*.tsx
Dashboard: Consult Decision Card
dashboard/consult-details/consult-decision-card.tsx
Explicit Consent Blocker
components/explicit-consent-blocker.tsx
Dashboard: Contact Verification OTP
dashboard/consult-flow/contact-details-summary.tsx
Import Source by Route Area (non-admin)
| Route area | @medlo/ui/button | Local button | Notes |
|---|---|---|---|
| pages/login, login-doctor | 0 | 2 | All local |
| pages/setup, setup-final | 1 | 1 | Split |
| pages/payment/* | 3 | 2 | Checkout uses @medlo/ui, success uses local |
| pages/medical-certificate/* | 0 | 4 | All local |
| pages/dashboard/* | 0 | 2 | All local |
| components/patient-medical-form/* | 5 | 4 | Mixed: personal-info phases use @medlo/ui, form steps use local |
| components/dashboard/quick-actions | 0 | 1 | Local |
| components/dashboard/consult-details/* | 1 | 5 | send-receipt uses @medlo/ui, all others local |
| components/dashboard/consult-flow/* | 0 | 5 | All local |
| components/dashboard/medical/* | 0 | 11 | All local |
| components/dashboard/lifestyle/* | 0 | 3 | All local |
| components/dashboard/patient/* | 0 | 3 | All local |
| components/lp/services/* | 0 | 3 | All local |
| components/marketing-* | 0 | 2 | All local |
| components/live-media/* | 0 | 4 | All local |
| components/nav/* | 0 | 2 | All local |
| components/ (root level) | 4 | 8 | Mixed |
Consolidation Considerations
1. Default height mismatch: @medlo/ui default is h-9 (36px), local is h-10 (40px). Consolidating would shift layout in many dashboard components.
2. Border radius divergence: @medlo/ui uses rounded-lg/xl, local uses rounded-md/sm. The sharper local corners appear throughout the dashboard; the rounder @medlo/ui corners appear in checkout and newer flows.
3. Focus ring style: @medlo/ui uses ring-1 (thinner, no offset), local uses ring-2 with offset-2. Accessibility implications worth checking.
4. Unique variants: @medlo/ui has limeGreen, softAmber, blueNoBg not in local. Local has amberLight not in @medlo/ui. Migration needs these to exist in the target.
5. cursor-pointer in base: Local button adds cursor-pointer and text-left to base styles. @medlo/ui omits these. Consolidating to @medlo/ui would lose explicit cursor-pointer (though Tailwind v4 base already sets it on buttons).