|
1 | 1 | <script>
|
| 2 | + import Button from "$lib/components/ui/Button.svelte"; |
| 3 | +
|
2 | 4 | let {
|
3 | 5 | componentNameProp = undefined,
|
4 | 6 | data = undefined,
|
5 | 7 | metaData = undefined,
|
| 8 | + caption = undefined, |
| 9 | + colourScale = undefined, |
6 | 10 | } = $props();
|
7 | 11 |
|
8 | 12 | let localCopyOfData = $state([...data]);
|
|
87 | 91 | {/snippet}
|
88 | 92 |
|
89 | 93 | <div class="p-4">
|
90 |
| - <h4>{componentNameProp} component</h4> |
91 |
| - |
92 |
| - <div class="legend"> |
93 |
| - <div>Colour key:</div> |
94 |
| - {#each colorKey as key} |
95 |
| - <div class="good" style="background-color: {normToColor(key[1])}"> |
96 |
| - {key[0]} |
97 |
| - </div> |
98 |
| - {/each} |
99 |
| - </div> |
| 94 | + {#if colourScale === "On"} |
| 95 | + <div class="legend"> |
| 96 | + <div>Colour key:</div> |
| 97 | + {#each colorKey as key} |
| 98 | + <div class="color-keys" style="background-color: {normToColor(key[1])}"> |
| 99 | + {key[0]} |
| 100 | + </div> |
| 101 | + {/each} |
| 102 | + </div> |
| 103 | + {/if} |
100 | 104 |
|
101 | 105 | <div class="table-container">
|
102 |
| - <table class="my-table"> |
103 |
| - <caption></caption> |
104 |
| - <thead |
105 |
| - ><tr> |
106 |
| - <th class="col-one-header">Area</th> |
| 106 | + <table class="govuk-table" data-module="moj-sortable-table"> |
| 107 | + <caption class="govuk-table__caption">{caption}</caption> |
| 108 | + <thead class="govuk-table__head" |
| 109 | + ><tr class="govuk-table__row"> |
| 110 | + <th scope="col" class="govuk-table__header" aria-sort="ascending" |
| 111 | + >Area</th |
| 112 | + > |
107 | 113 | {#each metrics as metric}
|
108 |
| - <th title={metaData[metric].explainer}> |
| 114 | + <th |
| 115 | + scope="col" |
| 116 | + class="govuk-table__header govuk-table__header--numeric" |
| 117 | + title={metaData[metric].explainer} |
| 118 | + aria-sort="none" |
| 119 | + > |
109 | 120 | <div class="header">
|
110 |
| - <div class="header-top"> |
111 |
| - <div class="metric">{metaData[metric].label}</div> |
112 |
| - <div class="sorting-button"> |
113 |
| - <button |
114 |
| - onclick={() => { |
115 |
| - updateSortState(metric, "ascending"); |
116 |
| - sortFunction(); |
117 |
| - }}>▲</button |
118 |
| - > |
119 |
| - <button |
120 |
| - onclick={() => { |
121 |
| - updateSortState(metric, "descending"); |
122 |
| - sortFunction(); |
123 |
| - }}>▼</button |
124 |
| - > |
125 |
| - </div> |
126 |
| - </div> |
127 |
| - <div class="metric-explainer"> |
128 |
| - {metaData[metric].explainer} |
129 |
| - </div> |
130 |
| - </div> |
131 |
| - </th> |
| 121 | + <Button |
| 122 | + textContent={metaData[metric].shortLabel} |
| 123 | + buttonType={"table header"} |
| 124 | + onClickFunction={() => { |
| 125 | + const newDirection = |
| 126 | + sortState.column === metric && |
| 127 | + sortState.order === "ascending" |
| 128 | + ? "descending" |
| 129 | + : "ascending"; |
| 130 | + |
| 131 | + updateSortState(metric, newDirection); |
| 132 | + sortFunction(); |
| 133 | + }} |
| 134 | + ></Button> |
| 135 | + </div></th |
| 136 | + > |
132 | 137 | {/each}
|
133 | 138 | </tr></thead
|
134 | 139 | >
|
135 |
| - <tbody> |
| 140 | + <tbody class="govuk-table__body"> |
136 | 141 | {#each localCopyOfData as row}
|
137 |
| - <tr> |
138 |
| - <td class="areas">{row["areaName"]}</td> |
| 142 | + <tr class="govuk-table__row"> |
| 143 | + <td class="govuk-table__cell">{row["areaName"]}</td> |
139 | 144 | {#each metrics as metric}
|
140 |
| - {#if metaData[metric].direction === "Higher is better"} |
141 |
| - <td |
142 |
| - style="background-color: {normToColor( |
143 |
| - row[metric + '__normalised'], |
144 |
| - )}">{row[metric]}</td |
145 |
| - > |
| 145 | + {#if colourScale === "On"} |
| 146 | + {#if metaData[metric].direction === "Higher is better"} |
| 147 | + <td |
| 148 | + class="govuk-table__cell govuk-table__cell--numeric" |
| 149 | + style="background-color: {normToColor( |
| 150 | + row[metric + '__normalised'], |
| 151 | + )}" |
| 152 | + data-sort-value="42">{row[metric]}</td |
| 153 | + > |
| 154 | + {:else} |
| 155 | + <td |
| 156 | + class="govuk-table__cell govuk-table__cell--numeric" |
| 157 | + style="background-color: {normToColorReverse( |
| 158 | + row[metric + '__normalised'], |
| 159 | + )}" |
| 160 | + data-sort-value="42">{row[metric]}</td |
| 161 | + > |
| 162 | + {/if} |
146 | 163 | {:else}
|
147 | 164 | <td
|
148 |
| - style="background-color: {normToColorReverse( |
149 |
| - row[metric + '__normalised'], |
150 |
| - )}">{row[metric]}</td |
| 165 | + class="govuk-table__cell govuk-table__cell--numeric" |
| 166 | + data-sort-value="42">{row[metric]}</td |
151 | 167 | >
|
152 | 168 | {/if}
|
153 | 169 | {/each}
|
|
159 | 175 | </div>
|
160 | 176 |
|
161 | 177 | <style>
|
162 |
| - * { |
163 |
| - margin: 0px; |
164 |
| - padding: 0px; |
165 |
| - } |
166 |
| -
|
167 | 178 | .table-container {
|
168 |
| - max-height: 85vh; |
| 179 | + max-height: 80vh; |
169 | 180 | overflow-y: auto;
|
170 |
| - border: 1px solid black; |
171 |
| - border-radius: 1%; |
172 | 181 | }
|
173 | 182 |
|
174 |
| - .ascending { |
175 |
| - background-color: #ff7f7f; |
176 |
| - } |
177 |
| - .descending { |
178 |
| - background-color: #add8e6; |
179 |
| - } |
180 |
| - .buttons-container { |
181 |
| - display: flex; |
182 |
| - gap: 20px; |
| 183 | + th { |
| 184 | + position: sticky; |
| 185 | + top: 0; |
| 186 | + z-index: 1; |
| 187 | + background-color: white; |
183 | 188 | }
|
184 | 189 |
|
185 |
| - .metric-explainer { |
186 |
| - font-size: 13px; |
187 |
| - font-style: italic; |
188 |
| - font-weight: 400; |
189 |
| - } |
190 | 190 | .legend {
|
191 | 191 | display: flex;
|
192 | 192 | justify-content: center;
|
193 | 193 | gap: 20px;
|
194 | 194 | margin: 10px;
|
195 | 195 | }
|
196 |
| -
|
197 |
| - .legend > * { |
| 196 | + .color-keys { |
198 | 197 | border-radius: 10%;
|
199 | 198 | padding: 6px;
|
200 | 199 | }
|
201 |
| -
|
202 |
| - td { |
203 |
| - padding: 0.5rem 0.5rem; |
204 |
| - } |
205 |
| -
|
206 |
| - th { |
207 |
| - text-align: left; |
208 |
| - font-size: medium; |
209 |
| - vertical-align: top; |
210 |
| - } |
211 |
| -
|
212 |
| - td { |
213 |
| - text-align: right; |
214 |
| - } |
215 |
| - .areas { |
216 |
| - font-size: medium; |
217 |
| - } |
218 |
| - .my-table { |
219 |
| - table-layout: fixed; |
220 |
| - width: 100%; |
221 |
| - } |
222 |
| -
|
223 |
| - .my-table th:first-child, |
224 |
| - .my-table td:first-child { |
225 |
| - width: 25%; |
226 |
| - } |
227 |
| -
|
228 |
| - .my-table th:nth-child(n + 2), |
229 |
| - .my-table td:nth-child(n + 2) { |
230 |
| - width: 25%; |
231 |
| - } |
232 |
| -
|
233 |
| - .header { |
234 |
| - display: flex; |
235 |
| - flex-direction: column; |
236 |
| - padding: 5px; |
237 |
| - justify-content: flex-start; |
238 |
| - } |
239 |
| -
|
240 |
| - .header-top { |
241 |
| - display: flex; |
242 |
| - gap: 0px; |
243 |
| - } |
244 |
| -
|
245 |
| - .sorting-button { |
246 |
| - display: flex; |
247 |
| - flex-direction: column; |
248 |
| - font-size: 0.8em; |
249 |
| - line-height: 1; /* removes extra space between lines */ |
250 |
| - gap: 3px; |
251 |
| - justify-content: center; |
252 |
| - background-color: lightgray; |
253 |
| - border-radius: 20%; |
254 |
| - } |
255 |
| - .col-one-header { |
256 |
| - text-align: right; |
257 |
| - padding: 5px; |
258 |
| - } |
259 | 200 | </style>
|
0 commit comments