Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bf3856c
feat(BusinessHours): add condensed view support
garrity-miepub Apr 7, 2026
77525cb
fix(BusinessHours): scope condensed CSS and add missing title slot
garrity-miepub Apr 7, 2026
e818e59
feat(EmployerContactCard): add condensed view support
garrity-miepub Apr 7, 2026
1afd179
fix: address Copilot review comments (round 3)
garrity-miepub Apr 7, 2026
0906dc8
feat(EmployerList): add condensed view support
garrity-miepub Apr 7, 2026
db5ff51
fix: address Copilot review comments (round 4)
garrity-miepub Apr 7, 2026
091076d
feat: add condensed view support for EmployerPricingCard
garrity-miepub Apr 7, 2026
b01b954
feat: add condensed view support for EmployerView
garrity-miepub Apr 7, 2026
062c840
chore: remove deprecated baseUrl from tsconfig (TS 5.9+)
garrity-miepub Apr 7, 2026
6fec5b7
fix: add flex-column layout for gap-based condensed spacing
garrity-miepub Apr 7, 2026
84082b1
feat: add condensed view support for HelpSupportPanel
garrity-miepub Apr 7, 2026
2b452e9
feat: add condensed view support for InvoiceList
garrity-miepub Apr 7, 2026
2e2a3a1
fix: address Copilot review — use data-slots instead of class selectors
garrity-miepub Apr 7, 2026
24000cc
feat: add condensed view support for InvoicePaymentPage
garrity-miepub Apr 7, 2026
d522f85
fix: replace Tailwind class selectors with structural selectors and d…
garrity-miepub Apr 7, 2026
a03029d
fix: address Copilot review — InvoicePaymentPage selector improvements
garrity-miepub Apr 7, 2026
c2770c2
feat: add condensed view support for InvoiceView
garrity-miepub Apr 7, 2026
bc5d7fc
fix: add root data-slot to InvoicePaymentPage not-found and success b…
garrity-miepub Apr 7, 2026
276a7ae
feat: add condensed view support for NotificationCenter
garrity-miepub Apr 7, 2026
cb17340
fix: prevent badge clipping in condensed NotificationCenter
garrity-miepub Apr 7, 2026
7799be2
fix: replace Tailwind class selectors with structural selectors
garrity-miepub Apr 7, 2026
6298ec1
fix: replace remaining Tailwind class selectors with structural selec…
garrity-miepub Apr 7, 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
98 changes: 79 additions & 19 deletions src/components/BusinessHours/BusinessHours.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ interface OpenStatusBadgeProps {
export function OpenStatusBadge({ isOpen, className }: OpenStatusBadgeProps) {
return (
<span
data-slot="business-hours-status"
className={cn(
'inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-sm font-medium',
isOpen
Expand Down Expand Up @@ -398,10 +399,12 @@ function DayScheduleRow({

return (
<div
data-slot="business-hours-day-row"
className={cn(dayRowVariants({ isToday: isToday && highlightToday }))}
data-cy={`provider-day-${dayHours.day}`}
>
<span
data-slot="business-hours-day-name"
className={cn(
'min-w-[80px] font-medium',
isToday && highlightToday && 'text-primary-900 dark:text-primary-300'
Expand All @@ -416,6 +419,7 @@ function DayScheduleRow({
</span>

<div
data-slot="business-hours-day-hours"
className={cn('text-right', hasMultipleRanges && 'flex flex-col gap-1')}
data-cy={`provider-hours-${dayHours.day}`}
>
Expand Down Expand Up @@ -474,17 +478,29 @@ export function BusinessHours({
// If we only have text hours, render those
if (!schedule.officeHours && schedule.officeHoursText) {
return (
<div className={cn(containerVariants({ variant, size }), className)}>
<div
data-slot="business-hours"
className={cn(containerVariants({ variant, size }), className)}
>
{showHeader && (
<div className="mb-3 flex items-center justify-between">
<div className="flex items-center gap-2 font-medium text-neutral-900 dark:text-white">
<div
data-slot="business-hours-header"
className="mb-3 flex items-center justify-between"
>
<div
data-slot="business-hours-title"
className="flex items-center gap-2 font-medium text-neutral-900 dark:text-white"
>
<ClockIcon className="text-neutral-500" />
{headerText}
</div>
{showStatus && <OpenStatusBadge isOpen={false} />}
</div>
)}
<pre className="m-0 font-sans whitespace-pre-wrap text-neutral-700 dark:text-neutral-300">
<pre
data-slot="business-hours-text"
className="m-0 font-sans whitespace-pre-wrap text-neutral-700 dark:text-neutral-300"
>
{schedule.officeHoursText}
</pre>
</div>
Expand All @@ -494,11 +510,22 @@ export function BusinessHours({
// No hours available
if (!schedule.officeHours || schedule.officeHours.length === 0) {
return (
<div className={cn(containerVariants({ variant, size }), className)}>
<div
data-slot="business-hours"
className={cn(containerVariants({ variant, size }), className)}
>
{showHeader && (
<div className="mb-3 flex items-center gap-2 font-medium text-neutral-900 dark:text-white">
<ClockIcon className="text-neutral-500" />
{headerText}
<div
data-slot="business-hours-header"
className="mb-3 flex items-center gap-2"
>
<div
data-slot="business-hours-title"
className="flex items-center gap-2 font-medium text-neutral-900 dark:text-white"
>
<ClockIcon className="text-neutral-500" />
{headerText}
</div>
</div>
)}
<p className="text-neutral-500 italic dark:text-neutral-400">
Expand All @@ -509,10 +536,19 @@ export function BusinessHours({
}

return (
<div className={cn(containerVariants({ variant, size }), className)}>
<div
data-slot="business-hours"
className={cn(containerVariants({ variant, size }), className)}
>
{variant === 'card' && (
<div className="flex items-center justify-between border-b border-neutral-200 bg-neutral-50 px-4 py-3 dark:border-neutral-700 dark:bg-neutral-800">
<div className="flex items-center gap-2 font-medium text-neutral-900 dark:text-white">
<div
data-slot="business-hours-header"
className="flex items-center justify-between border-b border-neutral-200 bg-neutral-50 px-4 py-3 dark:border-neutral-700 dark:bg-neutral-800"
>
<div
data-slot="business-hours-title"
className="flex items-center gap-2 font-medium text-neutral-900 dark:text-white"
>
<ClockIcon className="text-neutral-500" />
{headerText}
</div>
Expand All @@ -521,17 +557,29 @@ export function BusinessHours({
)}

{variant !== 'card' && showHeader && (
<div className="mb-3 flex items-center justify-between">
<div className="flex items-center gap-2 font-medium text-neutral-900 dark:text-white">
<div
data-slot="business-hours-header"
className="mb-3 flex items-center justify-between"
>
<div
data-slot="business-hours-title"
className="flex items-center gap-2 font-medium text-neutral-900 dark:text-white"
>
<ClockIcon className="text-neutral-500" />
{headerText}
</div>
{showStatus && <OpenStatusBadge isOpen={isOpen} />}
</div>
)}

<div className={cn(variant === 'card' && 'p-4')}>
<div className="space-y-1 divide-y divide-neutral-100 dark:divide-neutral-800">
<div
data-slot="business-hours-content"
className={cn(variant === 'card' && 'p-4')}
>
<div
data-slot="business-hours-schedule"
className="space-y-1 divide-y divide-neutral-100 dark:divide-neutral-800"
>
{schedule.officeHours.map((dayHours, idx) => (
<DayScheduleRow
key={idx}
Expand All @@ -545,7 +593,10 @@ export function BusinessHours({
</div>

{schedule.timezone && (
<p className="mt-3 text-xs text-neutral-500 dark:text-neutral-400">
<p
data-slot="business-hours-timezone"
className="mt-3 text-xs text-neutral-500 dark:text-neutral-400"
>
All times are in {schedule.timezone}
</p>
)}
Expand Down Expand Up @@ -579,7 +630,10 @@ export function CompactHours({
const todayHours = getTodayHours(schedule.officeHours, use24Hour);

return (
<div className={cn('flex items-center gap-2 text-sm', className)}>
<div
data-slot="business-hours-compact"
className={cn('flex items-center gap-2 text-sm', className)}
>
<ClockIcon className="h-4 w-4 text-neutral-400" />
<span className="text-neutral-700 dark:text-neutral-300">
{todayHours}
Expand Down Expand Up @@ -620,7 +674,10 @@ export function HoursSummary({
schedule.officeHours && schedule.officeHours.length > 0;

return (
<div className={cn('hours-summary', className)}>
<div
data-slot="business-hours-summary"
className={cn('hours-summary', className)}
>
<button
type="button"
onClick={() => setIsExpanded(!isExpanded)}
Expand Down Expand Up @@ -656,7 +713,10 @@ export function HoursSummary({
</button>

{isExpanded && hasStructuredHours && (
<div className="mt-2 rounded-lg border border-neutral-200 bg-white p-3 dark:border-neutral-700 dark:bg-neutral-900">
<div
data-slot="business-hours-summary-content"
className="mt-2 rounded-lg border border-neutral-200 bg-white p-3 dark:border-neutral-700 dark:bg-neutral-900"
>
<BusinessHours
schedule={schedule}
showHeader={false}
Expand Down
26 changes: 18 additions & 8 deletions src/components/EmployerContactCard/EmployerContactCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export function EmployerContactCard({
}: EmployerContactCardProps) {
if (isLoading) {
return (
<Card className={className}>
<CardHeader>
<Card data-slot="employer-contact-card" className={className}>
<CardHeader data-slot="employer-contact-header">
<CardTitle>{title}</CardTitle>
Comment thread
garrity-miepub marked this conversation as resolved.
</CardHeader>
<CardContent>
Expand All @@ -73,8 +73,11 @@ export function EmployerContactCard({
}

return (
<Card className={className}>
<CardHeader className="flex flex-row items-center justify-between">
<Card data-slot="employer-contact-card" className={className}>
<CardHeader
data-slot="employer-contact-header"
className="flex flex-row items-center justify-between"
>
Comment thread
garrity-miepub marked this conversation as resolved.
<CardTitle>{title}</CardTitle>
{showActions && onAddContact && (
<Button variant="ghost" size="sm" onClick={onAddContact}>
Expand All @@ -97,7 +100,7 @@ export function EmployerContactCard({
</CardHeader>
<CardContent>
{contacts.length === 0 ? (
<div className="py-6 text-center">
<div data-slot="employer-contact-empty" className="py-6 text-center">
<svg
className="mx-auto mb-2 h-10 w-10 text-gray-400 dark:text-gray-600"
fill="none"
Expand Down Expand Up @@ -126,10 +129,11 @@ export function EmployerContactCard({
)}
</div>
) : (
<div className="space-y-3">
<div data-slot="employer-contact-list" className="space-y-3">
{contacts.map((contact) => (
<div
key={contact.id}
data-slot="employer-contact-item"
role={onContactClick ? 'button' : undefined}
tabIndex={onContactClick ? 0 : undefined}
className={`flex items-center gap-3 rounded-lg p-2 ${onContactClick ? 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800' : ''} `}
Expand All @@ -139,7 +143,10 @@ export function EmployerContactCard({
}
Comment thread
garrity-miepub marked this conversation as resolved.
>
<Avatar name={contact.name} size="sm" />
<div className="min-w-0 flex-1">
<div
data-slot="employer-contact-info"
className="min-w-0 flex-1"
>
<div className="flex items-center gap-2">
<p className="truncate font-medium text-gray-900 dark:text-white">
{contact.name}
Expand All @@ -157,7 +164,10 @@ export function EmployerContactCard({
)}
</div>
{showActions && (
<div className="flex items-center gap-1">
<div
data-slot="employer-contact-actions"
className="flex items-center gap-1"
>
{contact.email && onEmail && (
<button
onClick={(e) => {
Expand Down
37 changes: 27 additions & 10 deletions src/components/EmployerList/EmployerList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export function EmployerList({

if (isLoading) {
return (
<div className={`space-y-4 ${className}`}>
<div data-slot="employer-list" className={`space-y-4 ${className}`}>
{showSearch && (
<div className="h-10 animate-pulse rounded bg-gray-200 dark:bg-gray-700" />
)}
Expand All @@ -103,11 +103,11 @@ export function EmployerList({
}

return (
<div className={`space-y-4 ${className}`}>
<div data-slot="employer-list" className={`space-y-4 ${className}`}>
{/* Header with search and add button */}
<div className="flex items-center gap-3">
<div data-slot="employer-list-header" className="flex items-center gap-3">
{showSearch && (
<div className="relative flex-1">
<div data-slot="employer-list-search" className="relative flex-1">
<svg
className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-400"
fill="none"
Expand Down Expand Up @@ -152,7 +152,10 @@ export function EmployerList({

{/* List */}
{filteredEmployers.length === 0 ? (
<div className="rounded-lg border border-dashed border-gray-300 py-12 text-center dark:border-gray-700">
<div
data-slot="employer-list-empty"
className="rounded-lg border border-dashed border-gray-300 py-12 text-center dark:border-gray-700"
>
<svg
className="mx-auto mb-3 h-12 w-12 text-gray-400 dark:text-gray-600"
fill="none"
Expand All @@ -176,10 +179,11 @@ export function EmployerList({
)}
</div>
) : (
<div className="space-y-2">
<div data-slot="employer-list-items" className="space-y-2">
{filteredEmployers.map((employer) => (
<div
key={employer.id}
data-slot="employer-list-item"
role={onEmployerClick ? 'button' : undefined}
tabIndex={onEmployerClick ? 0 : undefined}
onClick={() => onEmployerClick?.(employer)}
Expand All @@ -188,24 +192,34 @@ export function EmployerList({
}
className={`rounded-lg border border-gray-200 bg-white p-4 dark:border-gray-700 dark:bg-gray-900 ${onEmployerClick ? 'cursor-pointer transition-all hover:border-gray-300 hover:shadow-sm dark:hover:border-gray-600' : ''} `}
>
<div className="flex items-center gap-4">
<div
data-slot="employer-list-item-content"
className="flex items-center gap-4"
>
{/* Logo */}
{employer.logoUrl ? (
<img
src={employer.logoUrl}
alt={employer.name}
data-slot="employer-list-item-logo"
className="h-10 w-10 rounded bg-gray-50 object-contain dark:bg-gray-800"
/>
) : (
<div className="flex h-10 w-10 items-center justify-center rounded bg-blue-100 dark:bg-blue-900/30">
<div
data-slot="employer-list-item-logo"
className="flex h-10 w-10 items-center justify-center rounded bg-blue-100 dark:bg-blue-900/30"
>
<span className="text-lg font-bold text-blue-600 dark:text-blue-400">
{employer.name.charAt(0)}
</span>
</div>
)}

{/* Info */}
<div className="min-w-0 flex-1">
<div
data-slot="employer-list-item-info"
className="min-w-0 flex-1"
>
<div className="flex items-center gap-2">
<h3 className="truncate font-medium text-gray-900 dark:text-white">
{employer.name}
Expand All @@ -229,7 +243,10 @@ export function EmployerList({
</div>

{/* Stats */}
<div className="hidden items-center gap-4 text-center sm:flex">
<div
data-slot="employer-list-item-stats"
className="hidden items-center gap-4 text-center sm:flex"
>
{employer.activeEmployees !== undefined && (
<div>
<p className="text-lg font-bold text-gray-900 dark:text-white">
Expand Down
Loading
Loading