diff --git a/src/components/Common/DataView/DataTable/DataTable.test.tsx b/src/components/Common/DataView/DataTable/DataTable.test.tsx index cfce1cc4bd..e25c05a71d 100644 --- a/src/components/Common/DataView/DataTable/DataTable.test.tsx +++ b/src/components/Common/DataView/DataTable/DataTable.test.tsx @@ -221,6 +221,26 @@ describe('DataTable Component', () => { expect(screen.getByText('Name').closest('div')?.className).toMatch(/cellEnd/) expect(screen.getByText('Alice').closest('div')?.className).toMatch(/cellEnd/) }) + + test('does not wrap content when justify is unset — even for the last column', () => { + // Alignment is now driven solely by column.justify; there is no implicit + // "last column right-aligns" behavior, so an unset column must not be wrapped. + renderTable({ + columns: [{ key: 'name', title: 'Name', render: item => item.name }], + }) + + expect(screen.getByText('Name').closest('div')?.className ?? '').not.toMatch(/cellEnd/) + expect(screen.getByText('Alice').closest('div')?.className ?? '').not.toMatch(/cellEnd/) + }) + + test('end-aligns the injected actions column so the row menu stays flush-right', () => { + renderTable({ + columns: [{ key: 'name', title: 'Name', render: item => item.name }], + itemMenu: item => , + }) + + expect(screen.getByText('Menu for Alice').closest('div')?.className).toMatch(/cellEnd/) + }) }) describe('accessibility', () => { diff --git a/src/components/Common/DataView/DataTable/DataTable.tsx b/src/components/Common/DataView/DataTable/DataTable.tsx index 37d7df6668..00e59e654c 100644 --- a/src/components/Common/DataView/DataTable/DataTable.tsx +++ b/src/components/Common/DataView/DataTable/DataTable.tsx @@ -116,7 +116,10 @@ export const DataTable = ({ ? [ { key: 'actions-header', - content: {t('table.actionsColumnHeader')}, + content: withJustify( + {t('table.actionsColumnHeader')}, + 'end', + ), }, ] : []), @@ -176,7 +179,7 @@ export const DataTable = ({ ? [ { key: `menu-${rowIndex}`, - content: itemMenu(item), + content: withJustify(itemMenu(item), 'end'), }, ] : []), diff --git a/src/components/Common/DataView/DataView.stories.tsx b/src/components/Common/DataView/DataView.stories.tsx index 35650cd9c7..4aebadaded 100644 --- a/src/components/Common/DataView/DataView.stories.tsx +++ b/src/components/Common/DataView/DataView.stories.tsx @@ -373,3 +373,22 @@ export const DataViewWithFooter = () => { return } + +// Alignment is driven entirely by column.justify: the numeric "Amount" column +// right-aligns (header, body, and footer), while text columns stay left. The +// injected row-menu column is always flush-right. +export const DataViewWithJustifiedColumns = () => { + const justifiedColumns: useDataViewProp['columns'] = [ + { key: 'jobTitle', title: 'Job Title' }, + { key: 'payType', title: 'Pay Type' }, + { key: 'amount', title: 'Amount', justify: 'end' }, + { key: 'payTimePeriod', title: 'Pay Time Period' }, + ] + const dataProps = useDataView({ + data: compensationData, + columns: justifiedColumns, + itemMenu: renderItemMenu, + footer: () => ({ jobTitle: 'Total', amount: '$1,050.15' }), + }) + return +} diff --git a/src/components/Common/UI/Table/Table.module.scss b/src/components/Common/UI/Table/Table.module.scss index b1993314d7..6c9bc554d8 100644 --- a/src/components/Common/UI/Table/Table.module.scss +++ b/src/components/Common/UI/Table/Table.module.scss @@ -106,13 +106,6 @@ outline: var(--g-focusRingWidth) solid var(--g-focusRingColor); outline-offset: -2px; } - &:last-child { - text-align: right; - - :global(.react-aria-Button) { - display: inline-flex; - } - } // Empty state row styling :global(.react-aria-Row[data-empty-state='true']) & { diff --git a/src/components/Company/StateTaxes/TaxRateManagement/TaxRateHistorySection.tsx b/src/components/Company/StateTaxes/TaxRateManagement/TaxRateHistorySection.tsx index f6f3f36c98..1e47f08ed2 100644 --- a/src/components/Company/StateTaxes/TaxRateManagement/TaxRateHistorySection.tsx +++ b/src/components/Company/StateTaxes/TaxRateManagement/TaxRateHistorySection.tsx @@ -68,6 +68,7 @@ export function TaxRateHistorySection({ group, showHeader = true }: TaxRateHisto ...requirementColumns.map(column => ({ key: column.key, title: column.label ?? column.key, + justify: 'end' as const, render: (row: HistoryRow) => row.values[column.key] ?? '', })), ], diff --git a/src/components/Contractor/Payments/PaymentStatement/PaymentStatementPresentation.tsx b/src/components/Contractor/Payments/PaymentStatement/PaymentStatementPresentation.tsx index df3cb4198a..ed6a6d8dd7 100644 --- a/src/components/Contractor/Payments/PaymentStatement/PaymentStatementPresentation.tsx +++ b/src/components/Contractor/Payments/PaymentStatement/PaymentStatementPresentation.tsx @@ -190,6 +190,7 @@ export const PaymentStatementPresentation = ({ }, { title: t('amountColumn'), + justify: 'end', render: ({ amount }) => amount || '', }, ]} diff --git a/src/components/Employee/Compensation/onboarding/JobsList/JobsListPresentation.tsx b/src/components/Employee/Compensation/onboarding/JobsList/JobsListPresentation.tsx index 2cd6fd3730..2dfee1602f 100644 --- a/src/components/Employee/Compensation/onboarding/JobsList/JobsListPresentation.tsx +++ b/src/components/Employee/Compensation/onboarding/JobsList/JobsListPresentation.tsx @@ -66,6 +66,7 @@ export function JobsListPresentation({ { key: 'rate', title: t('allCompensations.amountColumn'), + justify: 'end', render: (job: Job) => job.rate?.toString() || '', }, { diff --git a/src/components/Employee/Deductions/management/DeductionsCard/DeductionsCard.tsx b/src/components/Employee/Deductions/management/DeductionsCard/DeductionsCard.tsx index 634309cc10..85766f20cb 100644 --- a/src/components/Employee/Deductions/management/DeductionsCard/DeductionsCard.tsx +++ b/src/components/Employee/Deductions/management/DeductionsCard/DeductionsCard.tsx @@ -113,6 +113,7 @@ function DeductionsCardContent({ employeeId, onEvent, LoaderComponent }: Deducti { key: 'amount', title: t('columns.withhold'), + justify: 'end' as const, render: (garnishment: Garnishment) => formatDeductionAmount(garnishment, { formatCurrency, diff --git a/src/components/Employee/Deductions/onboarding/DeductionsList/DeductionsList.tsx b/src/components/Employee/Deductions/onboarding/DeductionsList/DeductionsList.tsx index d38d9210dd..3065bde654 100644 --- a/src/components/Employee/Deductions/onboarding/DeductionsList/DeductionsList.tsx +++ b/src/components/Employee/Deductions/onboarding/DeductionsList/DeductionsList.tsx @@ -60,6 +60,7 @@ export function DeductionsList({ { key: 'amount', title: t('withheldColumn'), + justify: 'end', render: deduction => formatDeductionAmount(deduction, { formatCurrency, diff --git a/src/components/Employee/PaymentMethod/onboarding/ListView.tsx b/src/components/Employee/PaymentMethod/onboarding/ListView.tsx index 59ddea2965..6fbce40915 100644 --- a/src/components/Employee/PaymentMethod/onboarding/ListView.tsx +++ b/src/components/Employee/PaymentMethod/onboarding/ListView.tsx @@ -110,6 +110,7 @@ function ListViewReady({ { key: 'splitAmount', title: t('allocationColumn'), + justify: 'end', render: bankAccount => { const splitAmount = paymentMethod.splits?.find(split => split.uuid === bankAccount.uuid)?.splitAmount ?? 0 diff --git a/src/components/Employee/Paystubs/management/PaystubsCard/PaystubsCard.tsx b/src/components/Employee/Paystubs/management/PaystubsCard/PaystubsCard.tsx index 72288c4034..1be9849100 100644 --- a/src/components/Employee/Paystubs/management/PaystubsCard/PaystubsCard.tsx +++ b/src/components/Employee/Paystubs/management/PaystubsCard/PaystubsCard.tsx @@ -199,6 +199,7 @@ function PaystubsCardReady({ { key: 'checkAmount', title: t('checkAmount'), + justify: 'end' as const, render: (payStub: EmployeePayStub) => { if (!payStub.netPay) return '-' const amount = parseFloat(payStub.netPay) @@ -208,6 +209,7 @@ function PaystubsCardReady({ { key: 'grossPay', title: t('grossPay'), + justify: 'end' as const, render: (payStub: EmployeePayStub) => { if (!payStub.grossPay) return '-' const amount = parseFloat(payStub.grossPay) diff --git a/src/components/Payroll/OffCycleTaxWithholdingTable/OffCycleTaxWithholdingTable.module.scss b/src/components/Payroll/OffCycleTaxWithholdingTable/OffCycleTaxWithholdingTable.module.scss index 32280b229f..35a54a8f0f 100644 --- a/src/components/Payroll/OffCycleTaxWithholdingTable/OffCycleTaxWithholdingTable.module.scss +++ b/src/components/Payroll/OffCycleTaxWithholdingTable/OffCycleTaxWithholdingTable.module.scss @@ -32,10 +32,6 @@ :global(.react-aria-Cell) { width: 50%; text-align: left; - - &:last-child { - text-align: left; - } } } } diff --git a/src/components/Payroll/PayrollConfiguration/PayrollConfigurationPresentation.tsx b/src/components/Payroll/PayrollConfiguration/PayrollConfigurationPresentation.tsx index e66383f03e..1660fa34c5 100644 --- a/src/components/Payroll/PayrollConfiguration/PayrollConfigurationPresentation.tsx +++ b/src/components/Payroll/PayrollConfiguration/PayrollConfigurationPresentation.tsx @@ -216,6 +216,7 @@ export const PayrollConfigurationPresentation = ({ }, { title: t('tableColumns.hours'), + justify: 'end', render: (item: PayrollEmployeeCompensationsType) => { const hours = getRegularHours(item) const overtimeHours = getOvertimeHours(item) @@ -224,6 +225,7 @@ export const PayrollConfigurationPresentation = ({ }, { title: t('tableColumns.timeOff'), + justify: 'end', render: (item: PayrollEmployeeCompensationsType) => { const ptoHours = getTotalPtoHours(item) return formatHoursDisplay(ptoHours) @@ -231,6 +233,7 @@ export const PayrollConfigurationPresentation = ({ }, { title: t('tableColumns.additionalEarnings'), + justify: 'end', render: (item: PayrollEmployeeCompensationsType) => { const earnings = getAdditionalEarnings(item) return formatNumberAsCurrency(earnings) @@ -240,6 +243,7 @@ export const PayrollConfigurationPresentation = ({ ? [ { title: t('tableColumns.reimbursements'), + justify: 'end' as const, render: (item: PayrollEmployeeCompensationsType) => { const reimbursements = getReimbursements(item) return formatNumberAsCurrency(reimbursements) @@ -249,6 +253,7 @@ export const PayrollConfigurationPresentation = ({ : []), { title: t('tableColumns.totalPay'), + justify: 'end', render: (item: PayrollEmployeeCompensationsType) => { const employee = employeeMap.get(item.employeeUuid || '') const calculatedGrossPay = employee diff --git a/src/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.tsx b/src/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.tsx index 064101b4df..8d156ec5a9 100644 --- a/src/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.tsx +++ b/src/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.tsx @@ -450,6 +450,7 @@ export const PayrollEditEmployeePresentation = ({ { key: 'amount', title: t('reimbursementAmountColumn'), + justify: 'end', render: row => formatNumberAsCurrency(parseFloat(row.amount || '0')), }, { diff --git a/src/components/Payroll/PayrollHistory/PayrollHistoryPresentation.tsx b/src/components/Payroll/PayrollHistory/PayrollHistoryPresentation.tsx index 7444fa13bd..5e6cdb7e5f 100644 --- a/src/components/Payroll/PayrollHistory/PayrollHistoryPresentation.tsx +++ b/src/components/Payroll/PayrollHistory/PayrollHistoryPresentation.tsx @@ -187,6 +187,7 @@ export const PayrollHistoryPresentation = ({ }, { title: t('columns.totalPayroll'), + justify: 'end', render: (item: Payroll) => formatNumberAsCurrency(calculateTotalPayroll(item)), }, ]} diff --git a/src/components/Payroll/PayrollOverview/PayrollOverviewPresentation.tsx b/src/components/Payroll/PayrollOverview/PayrollOverviewPresentation.tsx index 94c2880c97..d6d20401b3 100644 --- a/src/components/Payroll/PayrollOverview/PayrollOverviewPresentation.tsx +++ b/src/components/Payroll/PayrollOverview/PayrollOverviewPresentation.tsx @@ -218,6 +218,7 @@ export const PayrollOverviewPresentation = ({ const companyPaysColumns: Array<{ key: string title: string + justify?: 'start' | 'end' render: (item: EmployeeCompensations) => React.ReactNode }> = [ { @@ -236,6 +237,7 @@ export const PayrollOverviewPresentation = ({ { key: 'grossPay', title: t('tableHeaders.grossPay'), + justify: 'end', render: (employeeCompensations: EmployeeCompensations) => formatCurrency(Number(employeeCompensations.grossPay!)), }, @@ -244,6 +246,7 @@ export const PayrollOverviewPresentation = ({ { key: 'reimbursements', title: t('tableHeaders.reimbursements'), + justify: 'end' as const, render: (employeeCompensation: EmployeeCompensations) => formatCurrency(getReimbursements(employeeCompensation)), }, @@ -252,18 +255,21 @@ export const PayrollOverviewPresentation = ({ { key: 'companyTaxes', title: t('tableHeaders.companyTaxes'), + justify: 'end', render: (employeeCompensation: EmployeeCompensations) => formatCurrency(getCompanyTaxes(employeeCompensation)), }, { key: 'companyBenefits', title: t('tableHeaders.companyBenefits'), + justify: 'end', render: (employeeCompensation: EmployeeCompensations) => formatCurrency(getCompanyBenefits(employeeCompensation)), }, { key: 'companyPays', title: t('tableHeaders.companyPays'), + justify: 'end', render: (employeeCompensation: EmployeeCompensations) => formatCurrency(getCompanyCost(employeeCompensation)), }, diff --git a/src/components/Payroll/PayrollReceipts/PayrollReceiptsPresentation.tsx b/src/components/Payroll/PayrollReceipts/PayrollReceiptsPresentation.tsx index 3a460edf56..78e7286074 100644 --- a/src/components/Payroll/PayrollReceipts/PayrollReceiptsPresentation.tsx +++ b/src/components/Payroll/PayrollReceipts/PayrollReceiptsPresentation.tsx @@ -180,6 +180,7 @@ export const PayrollReceiptsPresentation = ({ }, { title: t('breakdown.amount'), + justify: 'end', render: (item: { label: string; amount: number }) => formatNumberAsCurrency(item.amount), }, @@ -204,6 +205,7 @@ export const PayrollReceiptsPresentation = ({ }, { title: t('tax.amount'), + justify: 'end', render: (tax: TaxBreakdownItem) => formatNumberAsCurrency(parseFloat(tax.amount || '0')), }, @@ -259,6 +261,7 @@ export const PayrollReceiptsPresentation = ({ }, { title: t('employee.childSupport'), + justify: 'end', render: (employee: EmployeeBreakdownItem) => formatNumberAsCurrency(parseFloat(employee.childSupportGarnishment || '0')), }, @@ -266,6 +269,7 @@ export const PayrollReceiptsPresentation = ({ ? [ { title: t('employee.reimbursement'), + justify: 'end' as const, render: (employee: EmployeeBreakdownItem) => formatNumberAsCurrency(parseFloat(employee.totalReimbursement || '0')), }, @@ -273,11 +277,13 @@ export const PayrollReceiptsPresentation = ({ : []), { title: t('employee.totalTaxes'), + justify: 'end', render: (employee: EmployeeBreakdownItem) => formatNumberAsCurrency(parseFloat(employee.totalTax || '0')), }, { title: t('employee.netPay'), + justify: 'end', render: (employee: EmployeeBreakdownItem) => formatNumberAsCurrency(parseFloat(employee.netPay || '0')), }, diff --git a/src/components/Payroll/RecoveryCases/RecoveryCasesList/RecoveryCasesList.tsx b/src/components/Payroll/RecoveryCases/RecoveryCasesList/RecoveryCasesList.tsx index b1352d7368..e88ebac8b7 100644 --- a/src/components/Payroll/RecoveryCases/RecoveryCasesList/RecoveryCasesList.tsx +++ b/src/components/Payroll/RecoveryCases/RecoveryCasesList/RecoveryCasesList.tsx @@ -132,6 +132,7 @@ function Root({ companyId, dictionary, onEvent }: RecoveryCasesListProps) { { key: 'totalAmount', title: t('columns.totalAmount'), + justify: 'end', render: recoveryCase => ( {recoveryCase.eventTotalAmount @@ -143,6 +144,7 @@ function Root({ companyId, dictionary, onEvent }: RecoveryCasesListProps) { { key: 'amountOutstanding', title: t('columns.amountOutstanding'), + justify: 'end', render: recoveryCase => ( {recoveryCase.amountOutstanding diff --git a/src/components/TimeOff/shared/EmployeeTable/EmployeeTable.module.scss b/src/components/TimeOff/shared/EmployeeTable/EmployeeTable.module.scss index c3425c61a6..9b2d5d1ab4 100644 --- a/src/components/TimeOff/shared/EmployeeTable/EmployeeTable.module.scss +++ b/src/components/TimeOff/shared/EmployeeTable/EmployeeTable.module.scss @@ -3,15 +3,6 @@ display: flex; flex-direction: column; gap: toRem(16); - - &:not([data-has-menu]) { - :global(.react-aria-Cell), - :global(.react-aria-Column) { - &:last-child { - text-align: left; - } - } - } } .searchContainer { diff --git a/src/components/TimeOff/shared/EmployeeTable/EmployeeTable.tsx b/src/components/TimeOff/shared/EmployeeTable/EmployeeTable.tsx index 871b6b8b6b..03a771606c 100644 --- a/src/components/TimeOff/shared/EmployeeTable/EmployeeTable.tsx +++ b/src/components/TimeOff/shared/EmployeeTable/EmployeeTable.tsx @@ -100,7 +100,7 @@ export function EmployeeTable({ } as useDataViewProp) return ( -
+
{!hideSearch && (