Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ed300bc
feat(ProviderCard): add condensed view support
garrity-miepub Apr 8, 2026
9f8a294
fix(ProviderCard): use data-slot selectors for Tooltip-wrapped sub-co…
garrity-miepub Apr 8, 2026
b1f0eb8
feat(ProviderDetailHeader): add condensed view support
garrity-miepub Apr 8, 2026
e676290
fix: address Copilot review on PR #168
garrity-miepub Apr 8, 2026
bba6b34
feat(ProviderOverview): add condensed view support
garrity-miepub Apr 8, 2026
ca97b97
fix(ProviderOverview): address Copilot review on PR #168
garrity-miepub Apr 8, 2026
a83c54d
feat(condensed): add ProviderSearchBar condensed view support
garrity-miepub Apr 9, 2026
da58fe0
fix(condensed): add missing data-slot to ProviderOverview skeleton st…
garrity-miepub Apr 9, 2026
a036b76
feat(condensed): add ProviderSearchFilters condensed view support
garrity-miepub Apr 9, 2026
99a60a4
fix(condensed): scope address selector to detail-content, narrow Serv…
garrity-miepub Apr 9, 2026
f6b20e2
feat(condensed): add ProviderSettings condensed view support
garrity-miepub Apr 9, 2026
2b71a0b
fix(condensed): wrap overview Cards in div for data-slot, fix setting…
garrity-miepub Apr 9, 2026
e1e6885
feat(condensed): add RecurringServiceCard condensed view support
garrity-miepub Apr 9, 2026
c7e88ad
feat(condensed): add ReportDashboard condensed view support
garrity-miepub Apr 9, 2026
fca5603
fix: address Copilot review — TabsContent data-slot wrappers and cn()…
garrity-miepub Apr 9, 2026
9c6e82c
feat(condensed): add condensed view support for ScheduleCalendar
garrity-miepub Apr 9, 2026
ac8fa20
feat(condensed): add condensed view support for ServiceAccordion
garrity-miepub Apr 9, 2026
5ffd9c0
fix(condensed): wrap ServiceCard data-slot in div, use cn() for class…
garrity-miepub Apr 9, 2026
9d918e1
feat(condensed): add condensed view support for ServicePricingManager
garrity-miepub Apr 9, 2026
a86f6e2
fix: use cn() for ReportDashboard className to avoid undefined class
garrity-miepub Apr 9, 2026
01bcee5
fix: remove ineffective gap on provider-overview (uses margin-based s…
garrity-miepub Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions src/components/ProviderCard/ProviderCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ const ProviderLogo: React.FC<{

if (!logoURL || hasError) {
return (
<div className={cn(logoContainerVariants({ variant }))}>
<div
data-slot="provider-card-logo"
className={cn(logoContainerVariants({ variant }))}
>
<div className="bg-primary-100 dark:bg-primary-900 flex h-12 w-12 items-center justify-center rounded-full">
<span className="text-primary-800 dark:text-primary-300 text-lg font-bold">
{name.charAt(0).toUpperCase()}
Expand All @@ -107,7 +110,10 @@ const ProviderLogo: React.FC<{
}

return (
<div className={cn(logoContainerVariants({ variant }))}>
<div
data-slot="provider-card-logo"
className={cn(logoContainerVariants({ variant }))}
>
<img
src={logoURL}
alt={`${name}'s logo`}
Expand Down Expand Up @@ -149,7 +155,10 @@ const DistanceBadge: React.FC<{ distance?: number }> = ({ distance }) => {

const SafeFromWildfiresNotice: React.FC = () => (
<Tooltip content="BlueHive has confirmed that this provider is operational and not impacted by the January 2025 wildfires.">
<div className="inline-flex items-center gap-1.5 rounded-md bg-green-100 px-2 py-1 text-xs text-green-700 dark:bg-green-900/30 dark:text-green-300">
<div
data-slot="provider-card-safe-notice"
className="inline-flex items-center gap-1.5 rounded-md bg-green-100 px-2 py-1 text-xs text-green-700 dark:bg-green-900/30 dark:text-green-300"
>
<svg className="h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
Expand All @@ -164,7 +173,10 @@ const SafeFromWildfiresNotice: React.FC = () => (

const VerifiedBadge: React.FC = () => (
<Tooltip content="This provider's information has been verified">
<span className="inline-flex items-center gap-1 text-xs text-green-700 dark:text-green-300">
<span
data-slot="provider-card-verified"
className="inline-flex items-center gap-1 text-xs text-green-700 dark:text-green-300"
>
<svg className="h-3.5 w-3.5" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
Expand Down Expand Up @@ -298,8 +310,10 @@ export const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(
tabIndex={interactive ? 0 : undefined}
role={interactive ? 'button' : undefined}
aria-label={`View ${provider.name}`}
data-testid="provider-card"
{...props}
data-slot="provider-card"
data-variant={variant}
data-testid="provider-card"
>
{/* Logo Section */}
{(variant === 'compact' || variant === 'featured') && (
Expand All @@ -319,6 +333,7 @@ export const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(

{/* Content Section */}
<div
data-slot="provider-card-content"
className={cn(
'flex flex-1 flex-col',
variant === 'compact' && 'p-4',
Expand All @@ -327,7 +342,10 @@ export const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(
)}
>
{/* Header: Name + Verified */}
<div className="mb-1 flex items-start justify-between gap-2">
<div
data-slot="provider-card-header"
className="mb-1 flex items-start justify-between gap-2"
>
<h3
className={cn(
'text-primary-800 dark:text-primary-300 line-clamp-2 font-semibold',
Expand All @@ -343,6 +361,7 @@ export const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(

{/* Address */}
<p
data-slot="provider-card-address"
className={cn(
'text-muted-foreground',
variant === 'featured' ? 'text-sm' : 'text-xs'
Expand Down Expand Up @@ -370,6 +389,7 @@ export const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(
{provider.workNumber && (
<a
href={`tel:${provider.workNumber}`}
data-slot="provider-card-phone"
data-phone-link
onClick={handlePhoneClick}
className={cn(
Expand All @@ -385,7 +405,10 @@ export const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(

{/* Services Badges */}
{displayServices && displayServices.length > 0 && (
<div className="mt-3 flex flex-wrap gap-1.5">
<div
data-slot="provider-card-services"
className="mt-3 flex flex-wrap gap-1.5"
>
{displayServices.map((service) => (
<Badge
key={service._id}
Expand All @@ -408,7 +431,10 @@ export const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(
<div className="flex-1" />

{/* Footer: Distance + Actions */}
<div className="mt-3 flex items-center justify-between">
<div
data-slot="provider-card-footer"
className="mt-3 flex items-center justify-between"
>
<div className="flex items-center gap-2">
{provider.safeFromWildfires && <SafeFromWildfiresNotice />}
{!provider.safeFromWildfires && (
Expand Down Expand Up @@ -468,6 +494,7 @@ export const ProviderCardGrid: React.FC<ProviderCardGridProps> = ({
if (loading) {
return (
<div
data-slot="provider-card-grid"
className={cn(
'grid gap-4',
variant === 'compact' && 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
Expand All @@ -484,7 +511,10 @@ export const ProviderCardGrid: React.FC<ProviderCardGridProps> = ({

if (providers.length === 0) {
return (
<div className={cn('py-12 text-center', className)}>
<div
data-slot="provider-card-grid"
className={cn('py-12 text-center', className)}
>
{emptyState || (
<div className="text-muted-foreground">
<svg
Expand Down Expand Up @@ -512,6 +542,7 @@ export const ProviderCardGrid: React.FC<ProviderCardGridProps> = ({

return (
<div
data-slot="provider-card-grid"
className={cn(
'grid gap-4',
variant === 'compact' && 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
Expand Down
32 changes: 27 additions & 5 deletions src/components/ProviderDetailHeader/ProviderDetailHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ export function ActionButtonsBar({

return (
<div
data-slot="provider-detail-actions"
className={cn(
'flex justify-center border-b border-gray-200 dark:border-gray-700',
className
Expand Down Expand Up @@ -200,7 +201,11 @@ export interface BreadcrumbProps {

export function Breadcrumb({ items, className }: BreadcrumbProps) {
return (
<nav aria-label="Breadcrumb" className={cn('py-2', className)}>
<nav
aria-label="Breadcrumb"
data-slot="provider-detail-breadcrumb"
className={cn('py-2', className)}
>
<ol className="flex flex-wrap items-center gap-1 text-sm">
{items.map((item, index) => (
<li key={item.href} className="flex items-center">
Expand Down Expand Up @@ -242,7 +247,10 @@ export function MobileBackButton({
className,
}: MobileBackButtonProps) {
return (
<div className={cn('py-2 sm:hidden', className)}>
<div
data-slot="provider-detail-back"
className={cn('py-2 sm:hidden', className)}
>
<a
href={href}
className="bg-primary-700 hover:bg-primary-800 inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors"
Expand Down Expand Up @@ -289,6 +297,7 @@ export function ProviderLogo({
if (!src || hasError) {
return (
<div
data-slot="provider-detail-logo"
className={cn(
logoSizeClasses[size],
'bg-primary-100 text-primary-700 dark:bg-primary-900/30 dark:text-primary-400 flex items-center justify-center rounded-lg font-bold',
Expand All @@ -308,6 +317,7 @@ export function ProviderLogo({
<img
src={src}
alt={`${name} logo`}
data-slot="provider-detail-logo"
className={cn(
logoSizeClasses[size],
'rounded-lg object-contain',
Expand Down Expand Up @@ -388,7 +398,10 @@ export function SocialMediaLinks({
}

return (
<div className={cn('flex flex-wrap items-center gap-3', className)}>
<div
data-slot="provider-detail-social"
className={cn('flex flex-wrap items-center gap-3', className)}
>
{socialLinks.map((link) => (
<a
key={link.key}
Expand Down Expand Up @@ -438,6 +451,7 @@ export function VerifiedBadge({

return (
<div
data-slot="provider-detail-verified"
className={cn(
'flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400',
className
Expand Down Expand Up @@ -704,6 +718,7 @@ export function ProviderDetailHeader({

return (
<div
data-slot="provider-detail-header"
className={cn(
headerVariants({ variant: variant ?? 'default' }),
className
Expand All @@ -720,7 +735,10 @@ export function ProviderDetailHeader({
)}

{/* Main Header Content */}
<div className="container mx-auto px-4 py-6">
<div
data-slot="provider-detail-content"
className="container mx-auto px-4 py-6"
>
{/* Breadcrumb (Desktop) */}
{showBreadcrumb && (
<Breadcrumb
Expand All @@ -741,7 +759,10 @@ export function ProviderDetailHeader({

{/* Details */}
<div className="flex-1">
<h1 className="mb-2 text-2xl font-bold text-gray-900 sm:text-3xl dark:text-white">
<h1
data-slot="provider-detail-name"
className="mb-2 text-2xl font-bold text-gray-900 sm:text-3xl dark:text-white"
>
{provider.name}
</h1>

Expand Down Expand Up @@ -806,6 +827,7 @@ export function CompactProviderHeader({
}: CompactProviderHeaderProps) {
return (
<div
data-slot="provider-detail-compact"
className={cn(
'rounded-lg bg-white p-4 shadow-sm dark:bg-gray-900',
className
Expand Down
24 changes: 17 additions & 7 deletions src/components/ProviderOverview/ProviderOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,12 @@ export function ProviderOverview({

if (isLoading) {
return (
<div className={`space-y-6 ${className}`}>
<div data-slot="provider-overview" className={`space-y-6 ${className}`}>
Comment thread
garrity-miepub marked this conversation as resolved.
Outdated
{/* Header skeleton */}
<div className="flex animate-pulse items-center gap-4">
<div
data-slot="provider-overview-header"
className="flex animate-pulse items-center gap-4"
>
Comment thread
garrity-miepub marked this conversation as resolved.
Outdated
<div className="h-12 w-12 rounded-lg bg-gray-200 dark:bg-gray-700" />
<div className="h-6 w-48 rounded bg-gray-200 dark:bg-gray-700" />
</div>
Expand All @@ -193,9 +196,12 @@ export function ProviderOverview({
}

return (
<div className={`space-y-6 ${className}`}>
<div data-slot="provider-overview" className={`space-y-6 ${className}`}>
{/* Header */}
<div className="flex items-center gap-4">
<div
data-slot="provider-overview-header"
className="flex items-center gap-4"
>
Comment thread
garrity-miepub marked this conversation as resolved.
{logoUrl ? (
<img
src={logoUrl}
Expand All @@ -220,7 +226,10 @@ export function ProviderOverview({
</div>

{/* Stats Grid */}
<div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
<div
data-slot="provider-overview-stats"
className="grid grid-cols-2 gap-4 lg:grid-cols-4"
>
<StatCard
label="Pending Orders"
value={stats.pendingOrders}
Expand Down Expand Up @@ -309,7 +318,7 @@ export function ProviderOverview({

{/* Quick Actions */}
{quickActions.length > 0 && (
<Card>
<Card data-slot="provider-overview-actions">
<CardHeader>
<CardTitle>Quick Actions</CardTitle>
Comment thread
garrity-miepub marked this conversation as resolved.
Outdated
</CardHeader>
Expand Down Expand Up @@ -353,7 +362,7 @@ export function ProviderOverview({

{/* Recent Activity */}
{recentActivity.length > 0 && (
<Card>
<Card data-slot="provider-overview-activity">
<CardHeader>
Comment thread
garrity-miepub marked this conversation as resolved.
Outdated
<CardTitle>Recent Activity</CardTitle>
</CardHeader>
Expand Down Expand Up @@ -432,6 +441,7 @@ function StatCard({ label, value, icon, color, onClick }: StatCardProps) {

return (
<div
data-slot="provider-overview-stat"
role={onClick ? 'button' : undefined}
tabIndex={onClick ? 0 : undefined}
onClick={onClick}
Expand Down
14 changes: 11 additions & 3 deletions src/components/ProviderSearchBar/ProviderSearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ export const ProviderSearchBar = React.forwardRef<

return (
<div
data-slot="provider-search"
className={cn(
'w-full',
searchBarVariants({ size, variant }),
Expand All @@ -430,6 +431,7 @@ export const ProviderSearchBar = React.forwardRef<
{...props}
>
<div
data-slot="provider-search-input"
className={cn(
'bg-background flex items-center gap-1 rounded-lg border',
'focus-within:ring-primary-500 focus-within:ring-2 focus-within:ring-offset-2',
Expand Down Expand Up @@ -499,7 +501,7 @@ export const ProviderSearchBar = React.forwardRef<

{/* Results Message */}
{showResults && (results || resultsLoading) && (
<div className="mt-3">
<div data-slot="provider-search-results" className="mt-3">
<SearchResultsMessage
results={results}
loading={resultsLoading}
Expand Down Expand Up @@ -535,9 +537,15 @@ export const HeroSearchBar: React.FC<HeroSearchBarProps> = ({
...props
}) => {
return (
<div className={cn('text-center', className)}>
<div
data-slot="provider-search-hero"
className={cn('text-center', className)}
>
{title && (
<h1 className="text-foreground mb-2 text-3xl font-bold md:text-4xl lg:text-5xl">
<h1
data-slot="provider-search-hero-title"
className="text-foreground mb-2 text-3xl font-bold md:text-4xl lg:text-5xl"
>
{title}
</h1>
)}
Expand Down
Loading
Loading