Skip to content

Commit e763b78

Browse files
committed
feat: add mobileCard prop to table
1 parent 67dbdcf commit e763b78

File tree

3 files changed

+155
-140
lines changed

3 files changed

+155
-140
lines changed

helper/classes.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
"is-fullwidth": [],
5353
"has-icons-left": [],
5454
"has-icons-right": [],
55-
"is-current": []
55+
"is-current": [],
56+
"has-mobile-cards": ["mobileCards"]
5657
},
5758
"VSelect": {
5859
"is-fullwidth": ["expanded"]

helper/mappings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,14 +417,16 @@
417417
"sticky-row",
418418
"table",
419419
"table-container",
420+
"table-wrapper",
420421
"tag",
421422
"tbody",
422423
"td",
423424
"text",
424425
"th",
425426
"thead",
426427
"tr",
427-
"v-checkbox"
428+
"v-checkbox",
429+
"v-table"
428430
],
429431
"optional": [
430432
"is-active",
@@ -453,6 +455,7 @@
453455
"has-ellipsis",
454456
"has-icons-left",
455457
"has-icons-right",
458+
"has-mobile-cards",
456459
"is-current",
457460
"is-delete",
458461
"is-fullwidth",

src/components/compounds/Table/Table.vue

Lines changed: 149 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script>
2-
import { computed, reactive, ref, watch, watchEffect } from 'vue'
2+
import { computed, reactive, ref, watch } from 'vue'
33
import VTag from '../../primitives/Tag/Tag.vue'
44
import VButton from '../../primitives/Button/Button.vue'
55
import VCheckbox from '../../primitives/Checkbox/Checkbox.vue'
@@ -40,6 +40,7 @@ export default {
4040
editable: Boolean,
4141
groupBy: String,
4242
sticky: Boolean,
43+
mobileCards: Boolean,
4344
},
4445
4546
setup(props, { slots }) {
@@ -159,158 +160,168 @@ export default {
159160

160161
<template>
161162
<!-- eslint-disable @pathscale/vue3/v-directive -->
162-
<div class="table-container" :class="{ 'sticky-table': sticky }">
163-
<div class="tableHeader" v-if="hasHeader">
164-
<slot name="header">
165-
<v-button
166-
@click="data.resetFilters()"
167-
v-if="hasResetBtn"
168-
type="is-light has-text-black"
169-
class="my-2">
170-
&#x21bb;
171-
</v-button>
172-
</slot>
173-
</div>
174-
<table
175-
class="table"
176-
:class="[
177-
{
178-
'is-bordered': bordered,
179-
'is-striped': striped,
180-
'is-narrow': narrow,
181-
'is-hoverable': hoverable,
182-
'is-fullwidth': fullwidth,
183-
},
184-
]"
185-
style="position: relative">
186-
<thead class="thead">
187-
<tr class="tr">
188-
<td class="td" v-if="checkable" />
189-
<td v-if="expandable" />
190-
<th
191-
class="th"
192-
v-for="(column, idx) in data.getColumns()"
193-
:key="idx"
194-
:class="columnClasses(column)"
195-
@click="handleSort(column)"
196-
:draggable="draggableColumns"
197-
@dragstart="data.onDragStartColumn($event, row, idx)"
198-
@drop="data.onDropColumn($event, column, idx)"
199-
@dragover="data.onDragOverColumn($event, column, idx)"
200-
@dragleave="data.onDragLeaveColumn($event, column, idx)">
201-
{{ column.caption }}
202-
<span v-if="sortable">
203-
{{ column.ascendant ? '&darr;' : '\t&uarr;' }}
204-
</span>
205-
</th>
206-
</tr>
207-
</thead>
208-
<tbody class="tbody">
209-
<tr v-if="searchable">
210-
<td v-if="checkable" />
211-
<td v-if="expandable" />
212-
<td v-for="column in data.getColumns()" :key="column.name" :class="column.style">
213-
<v-input
214-
name="search"
215-
type="text"
216-
v-model="search[column.name]"
217-
@input="data.searchColumn(column.name, search[column.name])"
218-
placeholder="Search" />
219-
</td>
220-
</tr>
221-
<template v-if="!groupBy">
222-
<template v-for="(row, idx) in data.rows" :key="idx">
223-
<tr
224-
:draggable="draggableRows"
225-
@dragstart="data.onDragStartRow($event, row, idx)"
226-
@drop="data.onDropRow($event, row, idx)"
227-
@dragover="data.onDragOverRow($event, row, idx)"
228-
@dragleave="data.onDragLeaveRow($event, row, idx)"
229-
:class="selectedClasses(row)">
230-
<td v-if="checkable">
231-
<v-checkbox @change="data.toggleCheck($event, row)" />
232-
</td>
233-
<td v-if="expandable">
234-
<a @click="toggleExpanded(row.id)" class="is-primary">{{
235-
expandedRows.has(row.id) ? '&uarr;' : '&darr;'
236-
}}</a>
237-
</td>
238-
<td
239-
v-for="column in data.getColumns()"
240-
:key="column.name"
241-
:class="cellClasses(column)"
242-
:contenteditable="props.editable"
243-
@blur="data.editCell(row, column, $event.target.textContent)">
244-
<slot :name="column.name" :row="row">
245-
{{ row[column.name] }}
246-
</slot>
247-
</td>
248-
</tr>
249-
<tr class="expansion" v-if="expandedRows.has(row.id)">
250-
<td :colspan="countColumns">
251-
<slot name="expanded" :row="row" />
252-
</td>
253-
</tr>
254-
</template>
255-
</template>
256-
257-
<template v-if="groupBy">
258-
<template v-for="(group, idx) in data.groups(groupBy)" :key="idx">
259-
<tr>
260-
<td :colspan="countColumns" class="is-aligned-center">
261-
<a @click="toggleExpandedGroup(group)" class="mr-4">{{
262-
expandedGroups.has(group) ? '&darr;' : '&rarr;'
263-
}}</a>
264-
{{ groupBy }}:
265-
<v-tag type="is-primary" class="mx-4">
266-
{{ group }}
267-
</v-tag>
268-
</td>
269-
</tr>
270-
<template v-if="expandedGroups.has(group)">
271-
<tr v-for="(row, rowIdx) in data.filterRows(groupBy, group)" :key="rowIdx">
163+
<div class="v-table">
164+
<div
165+
class="table-wrapper table-container"
166+
:class="{ 'sticky-table': sticky, 'has-mobile-cards': mobileCards }">
167+
<div class="tableHeader" v-if="hasHeader">
168+
<slot name="header">
169+
<v-button
170+
@click="data.resetFilters()"
171+
v-if="hasResetBtn"
172+
type="is-light has-text-black"
173+
class="my-2">
174+
&#x21bb;
175+
</v-button>
176+
</slot>
177+
</div>
178+
<table
179+
class="table"
180+
:class="[
181+
{
182+
'is-bordered': bordered,
183+
'is-striped': striped,
184+
'is-narrow': narrow,
185+
'is-hoverable': hoverable,
186+
'is-fullwidth': fullwidth,
187+
},
188+
]"
189+
style="position: relative;">
190+
<thead class="thead">
191+
<tr class="tr">
192+
<td class="td" v-if="checkable" />
193+
<td v-if="expandable" />
194+
<th
195+
class="th"
196+
v-for="(column, idx) in data.getColumns()"
197+
:key="idx"
198+
:class="columnClasses(column)"
199+
@click="handleSort(column)"
200+
:draggable="draggableColumns"
201+
@dragstart="data.onDragStartColumn($event, row, idx)"
202+
@drop="data.onDropColumn($event, column, idx)"
203+
@dragover="data.onDragOverColumn($event, column, idx)"
204+
@dragleave="data.onDragLeaveColumn($event, column, idx)">
205+
{{ column.caption }}
206+
<span v-if="sortable">
207+
{{ column.ascendant ? '&darr;' : '\t&uarr;' }}
208+
</span>
209+
</th>
210+
</tr>
211+
</thead>
212+
<tbody class="tbody">
213+
<tr v-if="searchable">
214+
<td v-if="checkable" />
215+
<td v-if="expandable" />
216+
<td
217+
v-for="column in data.getColumns()"
218+
:data-label="column.caption"
219+
:key="column.name"
220+
:class="column.style">
221+
<v-input
222+
name="search"
223+
type="text"
224+
v-model="search[column.name]"
225+
@input="data.searchColumn(column.name, search[column.name])"
226+
placeholder="Search" />
227+
</td>
228+
</tr>
229+
<template v-if="!groupBy">
230+
<template v-for="(row, idx) in data.rows" :key="idx">
231+
<tr
232+
:draggable="draggableRows"
233+
@dragstart="data.onDragStartRow($event, row, idx)"
234+
@drop="data.onDropRow($event, row, idx)"
235+
@dragover="data.onDragOverRow($event, row, idx)"
236+
@dragleave="data.onDragLeaveRow($event, row, idx)"
237+
:class="selectedClasses(row)">
238+
<td v-if="checkable">
239+
<v-checkbox @change="data.toggleCheck($event, row)" />
240+
</td>
241+
<td v-if="expandable">
242+
<a @click="toggleExpanded(row.id)" class="is-primary">{{
243+
expandedRows.has(row.id) ? '&uarr;' : '&darr;'
244+
}}</a>
245+
</td>
272246
<td
273247
v-for="column in data.getColumns()"
248+
:data-label="column.caption"
274249
:key="column.name"
275-
:class="column.style"
250+
:class="cellClasses(column)"
276251
:contenteditable="props.editable"
277252
@blur="data.editCell(row, column, $event.target.textContent)">
278253
<slot :name="column.name" :row="row">
279254
{{ row[column.name] }}
280255
</slot>
281256
</td>
282257
</tr>
258+
<tr class="expansion" v-if="expandedRows.has(row.id)">
259+
<td :colspan="countColumns">
260+
<slot name="expanded" :row="row" />
261+
</td>
262+
</tr>
283263
</template>
284264
</template>
285-
</template>
286-
</tbody>
287-
</table>
288265

289-
<div v-if="pagination" class="pagination-container px-1">
290-
<v-select v-model="computedRowsPerPage">
291-
>
292-
<option v-for="value in rowsPerPageOptions" :key="value" :value="value">
293-
{{ value }}
294-
</option>
295-
</v-select>
266+
<template v-if="groupBy">
267+
<template v-for="(group, idx) in data.groups(groupBy)" :key="idx">
268+
<tr>
269+
<td :colspan="countColumns" class="is-aligned-center">
270+
<a @click="toggleExpandedGroup(group)" class="mr-4">{{
271+
expandedGroups.has(group) ? '&darr;' : '&rarr;'
272+
}}</a>
273+
{{ groupBy }}:
274+
<v-tag type="is-primary" class="mx-4">
275+
{{ group }}
276+
</v-tag>
277+
</td>
278+
</tr>
279+
<template v-if="expandedGroups.has(group)">
280+
<tr v-for="(row, rowIdx) in data.filterRows(groupBy, group)" :key="rowIdx">
281+
<td
282+
v-for="column in data.getColumns()"
283+
:data-label="column.caption"
284+
:key="column.name"
285+
:class="column.style"
286+
:contenteditable="props.editable"
287+
@blur="data.editCell(row, column, $event.target.textContent)">
288+
<slot :name="column.name" :row="row">
289+
{{ row[column.name] }}
290+
</slot>
291+
</td>
292+
</tr>
293+
</template>
294+
</template>
295+
</template>
296+
</tbody>
297+
</table>
296298

297-
<v-pagination
298-
class="px-1"
299-
:total="total"
300-
:current="currentPage + 1"
301-
@update:current="handlePageChange"
302-
:range-before="1"
303-
:range-after="1"
304-
order="is-centered"
305-
:per-page="computedRowsPerPage"
306-
aria-next-label="Next page"
307-
aria-previous-label="Previous page"
308-
aria-page-label="Page"
309-
aria-current-label="Current page" />
310-
</div>
299+
<div v-if="pagination" class="pagination-container px-1">
300+
<v-select v-model="computedRowsPerPage">
301+
>
302+
<option v-for="value in rowsPerPageOptions" :key="value" :value="value">
303+
{{ value }}
304+
</option>
305+
</v-select>
306+
307+
<v-pagination
308+
class="px-1"
309+
:total="total"
310+
:current="currentPage + 1"
311+
@update:current="handlePageChange"
312+
:range-before="1"
313+
:range-after="1"
314+
order="is-centered"
315+
:per-page="computedRowsPerPage"
316+
aria-next-label="Next page"
317+
aria-previous-label="Previous page"
318+
aria-page-label="Page"
319+
aria-current-label="Current page" />
320+
</div>
311321

312-
<div class="tableFooter" v-if="slots.footer">
313-
<slot name="footer" />
322+
<div class="tableFooter" v-if="slots.footer">
323+
<slot name="footer" />
324+
</div>
314325
</div>
315326
</div>
316327
</template>

0 commit comments

Comments
 (0)