[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: improve color contrast of comparison table via badge styling (#790)

Co-authored-by: Cassidy Williams <cassidoo@users.noreply.github.com>
Co-authored-by: Philippe Serhal <philippe.serhal@gmail.com>
Co-authored-by: Daniel Roe <daniel@roe.dev>

+45 -16
+37 -8
app/components/Compare/FacetRow.vue
··· 38 38 return (value.raw / maxValue.value) * 100 39 39 } 40 40 41 - function getStatusClass(status?: FacetValue['status']): string { 41 + function getStatusClass(status?: FacetValue['status'], hasBar = false): string { 42 + // When there's a bar, only apply text color, not background 43 + if (hasBar) { 44 + switch (status) { 45 + case 'muted': 46 + return 'text-fg-subtle' 47 + default: 48 + return 'text-fg' 49 + } 50 + } 51 + 52 + // Original behavior when no bar 42 53 switch (status) { 43 54 case 'good': 44 - return 'text-emerald-400' 55 + return 'bg-emerald-400/20 px-3 py-0.5 rounded-xl' 45 56 case 'info': 46 - return 'text-blue-400' 57 + return 'bg-blue-400/20 px-3 py-0.5 rounded-xl' 47 58 case 'warning': 48 - return 'text-amber-400' 59 + return 'bg-amber-400/20 px-3 py-0.5 rounded-xl' 49 60 case 'bad': 50 - return 'text-red-400' 61 + return 'bg-red-400/20 px-3 py-0.5 rounded-xl' 51 62 case 'muted': 52 63 return 'text-fg-subtle' 53 64 default: ··· 55 66 } 56 67 } 57 68 69 + function getStatusBarClass(status?: FacetValue['status']): string { 70 + switch (status) { 71 + case 'good': 72 + return 'bg-emerald-500/20' 73 + case 'info': 74 + return 'bg-blue-500/20' 75 + case 'warning': 76 + return 'bg-amber-500/20' 77 + case 'bad': 78 + return 'bg-red-500/20' 79 + default: 80 + return 'bg-fg/5' 81 + } 82 + } 83 + 58 84 // Check if a specific cell is loading 59 85 function isCellLoading(index: number): boolean { 60 86 return props.facetLoading || (props.columnLoading?.[index] ?? false) ··· 80 106 <!-- Background bar for numeric values --> 81 107 <div 82 108 v-if="showBar && value && getBarWidth(value) > 0" 83 - class="absolute inset-y-1 inset-is-1 bg-fg/5 rounded-sm transition-all duration-300" 109 + class="absolute inset-y-1 inset-is-1 rounded-sm transition-all duration-300" 110 + :class="getStatusBarClass(value.status)" 84 111 :style="{ width: `calc(${getBarWidth(value)}% - 8px)` }" 85 112 aria-hidden="true" 86 113 /> ··· 103 130 <TooltipApp v-if="value.tooltip" :text="value.tooltip" position="top"> 104 131 <span 105 132 class="relative font-mono text-sm text-center tabular-nums cursor-help" 106 - :class="getStatusClass(value.status)" 133 + :class="getStatusClass(value.status, showBar && getBarWidth(value) > 0)" 134 + :data-status="value.status" 107 135 > 108 136 <!-- Date values use DateTime component for i18n and user settings --> 109 137 <DateTime v-if="value.type === 'date'" :datetime="value.display" date-style="medium" /> ··· 113 141 <span 114 142 v-else 115 143 class="relative font-mono text-sm text-center tabular-nums" 116 - :class="getStatusClass(value.status)" 144 + :class="getStatusClass(value.status, showBar && getBarWidth(value) > 0)" 145 + :data-status="value.status" 117 146 > 118 147 <!-- Date values use DateTime component for i18n and user settings --> 119 148 <DateTime v-if="value.type === 'date'" :datetime="value.display" date-style="medium" />
+8 -8
test/nuxt/components/compare/FacetRow.spec.ts
··· 98 98 }) 99 99 100 100 describe('status styling', () => { 101 - it('applies good status class', async () => { 101 + it('applies good status', async () => { 102 102 const component = await mountSuspended(FacetRow, { 103 103 props: { 104 104 ...baseProps, 105 105 values: [{ raw: 0, display: 'None', status: 'good' }], 106 106 }, 107 107 }) 108 - expect(component.find('.text-emerald-400').exists()).toBe(true) 108 + expect(component.find('[data-status="good"]').exists()).toBe(true) 109 109 }) 110 110 111 - it('applies warning status class', async () => { 111 + it('applies warning status', async () => { 112 112 const component = await mountSuspended(FacetRow, { 113 113 props: { 114 114 ...baseProps, 115 115 values: [{ raw: 100, display: '100 MB', status: 'warning' }], 116 116 }, 117 117 }) 118 - expect(component.find('.text-amber-400').exists()).toBe(true) 118 + expect(component.find('[data-status="warning"]').exists()).toBe(true) 119 119 }) 120 120 121 - it('applies bad status class', async () => { 121 + it('applies bad status', async () => { 122 122 const component = await mountSuspended(FacetRow, { 123 123 props: { 124 124 ...baseProps, 125 125 values: [{ raw: 5, display: '5 critical', status: 'bad' }], 126 126 }, 127 127 }) 128 - expect(component.find('.text-red-400').exists()).toBe(true) 128 + expect(component.find('[data-status="bad"]').exists()).toBe(true) 129 129 }) 130 130 131 - it('applies info status class', async () => { 131 + it('applies info status', async () => { 132 132 const component = await mountSuspended(FacetRow, { 133 133 props: { 134 134 ...baseProps, 135 135 values: [{ raw: '@types', display: '@types', status: 'info' }], 136 136 }, 137 137 }) 138 - expect(component.find('.text-blue-400').exists()).toBe(true) 138 + expect(component.find('[data-status="info"]').exists()).toBe(true) 139 139 }) 140 140 }) 141 141