Skip to content

Commit

Permalink
docs(examples): add advanced table example (#393)
Browse files Browse the repository at this point in the history
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
  • Loading branch information
Haythamasalama and benjamincanac authored Jul 30, 2023
1 parent 8e1aa2f commit a9300db
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 0 deletions.
245 changes: 245 additions & 0 deletions docs/components/content/examples/TableExampleAdvanced.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
<script lang="ts" setup>
// Columns
const columns = [{
key: 'id',
label: '#',
sortable: true
}, {
key: 'title',
label: 'Title',
sortable: true
}, {
key: 'completed',
label: 'Status',
sortable: true
}, {
key: 'actions',
label: 'Actions',
sortable: false
}]
const selectedColumns = ref(columns)
const columnsTable = computed(() => columns.filter((column) => selectedColumns.value.includes(column)))
// Selected Rows
const selectedRows = ref([])
function select (row) {
const index = selectedRows.value.findIndex((item) => item.id === row.id)
if (index === -1) {
selectedRows.value.push(row)
} else {
selectedRows.value.splice(index, 1)
}
}
// Actions
const actions = [
[{
key: 'completed',
label: 'Completed',
icon: 'i-heroicons-check'
}], [{
key: 'uncompleted',
label: 'In Progress',
icon: 'i-heroicons-arrow-path'
}]
]
// Filters
const todoStatus = [{
key: 'uncompleted',
label: 'In Progress',
value: false
}, {
key: 'completed',
label: 'Completed',
value: true
}]
const search = ref('')
const selectedStatus = ref([])
const searchStatus = computed(() => {
if (selectedStatus.value?.length === 0) {
return ''
}
if (selectedStatus?.value?.length > 1) {
return `?completed=${selectedStatus.value[0].value}&completed=${selectedStatus.value[1].value}`
}
return `?completed=${selectedStatus.value[0].value}`
})
const resetFilters = () => {
search.value = ''
selectedStatus.value = []
}
// Pagination
const page = ref(1)
const pageCount = ref(10)
const pageTotal = ref(200) // This value should be dynamic coming from the API
const pageFrom = computed(() => (page.value - 1) * pageCount.value + 1)
const pageTo = computed(() => Math.min(page.value * pageCount.value, pageTotal.value))
// Data
const { data: todos, pending } = await useLazyAsyncData('todos', () => $fetch<{
id: number
title: string
completed: string
}[]>(`https://jsonplaceholder.typicode.com/todos${searchStatus.value}`, {
query: {
q: search.value,
'_page': page.value,
'_limit': pageCount.value
}
}), {
default: () => [],
watch: [page, search, searchStatus, pageCount]
})
</script>

<template>
<UCard
class="w-full"
:ui="{
base: '',
ring: '',
divide: 'divide-y divide-gray-200 dark:divide-gray-700',
header: { padding: 'px-4 py-5' },
body: { padding: '', base: 'divide-y divide-gray-200 dark:divide-gray-700' },
footer: { padding: 'p-4' }
}"
>
<template #header>
<h2 class="font-semibold text-xl text-gray-900 dark:text-white leading-tight">
Todos
</h2>
</template>

<!-- Filters -->
<div class="flex items-center justify-between gap-3 px-4 py-3">
<UInput v-model="search" icon="i-heroicons-magnifying-glass-20-solid" placeholder="Search..." />

<USelectMenu v-model="selectedStatus" :options="todoStatus" multiple placeholder="Status" class="w-40" />
</div>

<!-- Header and Action buttons -->
<div class="flex justify-between items-center w-full px-4 py-3">
<div class="flex items-center gap-1.5">
<span class="text-sm leading-5">Rows per page:</span>

<USelect
v-model="pageCount"
:options="[3, 5, 10, 20, 30, 40]"
class="me-2 w-20"
size="xs"
/>
</div>

<div class="flex gap-1.5 items-center">
<UDropdown v-if="selectedRows.length > 1" :items="actions" :ui="{ width: 'w-36' }">
<UButton
icon="i-heroicons-chevron-down"
trailing
variant="soft"
size="xs"
>
Mark as
</UButton>
</UDropdown>

<USelectMenu v-model="selectedColumns" :options="columns" multiple>
<UButton
icon="i-heroicons-view-columns"
variant="soft"
size="xs"
>
Columns
</UButton>
</USelectMenu>

<UButton
icon="i-heroicons-funnel"
variant="soft"
color="red"
size="xs"
:disabled="search === '' && selectedStatus.length === 0"
@click="resetFilters"
>
Reset
</UButton>
</div>
</div>

<!-- Table -->
<UTable
v-model="selectedRows"
:rows="todos"
:columns="columnsTable"
:loading="pending"
sort-asc-icon="i-heroicons-arrow-up"
sort-desc-icon="i-heroicons-arrow-down"
@select="select"
>
<template #completed-data="{ row }">
<UBadge size="xs" :label="row.completed ? 'Completed' : 'In Progress'" :color="row.completed ? 'emerald' : 'orange'" variant="subtle" />
</template>

<template #actions-data="{ row }">
<UButton
v-if="!row.completed"
icon="i-heroicons-check"
size="2xs"
color="emerald"
variant="outline"
:ui="{ rounded: 'rounded-full' }"
square
/>

<UButton
v-else
icon="i-heroicons-arrow-path"
size="2xs"
color="orange"
variant="outline"
:ui="{ rounded: 'rounded-full' }"
square
/>
</template>
</UTable>

<!-- Number of rows & Pagination -->
<template #footer>
<div class="flex justify-between items-center">
<div>
<span class="text-sm leading-5">
Showing
<span class="font-medium">{{ pageFrom }}</span>
to
<span class="font-medium">{{ pageTo }}</span>
of
<span class="font-medium">{{ pageTotal }}</span>
results
</span>
</div>

<UPagination
v-model="page"
:page-count="pageCount"
:total="pageTotal"
:ui="{
wrapper: 'flex items-center gap-1',
rounded: 'rounded-full min-w-[32px] justify-center',
default: {
activeButton: {
variant: 'outline'
}
}
}"
/>
</div>
</template>
</UCard>
</template>
17 changes: 17 additions & 0 deletions docs/content/1.getting-started/5.examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,23 @@ const label = computed(() => date.value.toLocaleDateString('en-us', { weekday: '
```
::

### Table

Here is an example of a Table component with all its features implemented.

::component-example
---
padding: false
---

#default
:table-example-advanced
::

::callout{icon="i-simple-icons-github" to="https://github.com/nuxtlabs/ui/blob/dev/docs/components/content/examples/TableExampleAdvanced.vue"}
Take a look at the component!
::

## Theming

Our theming system provides a lot of flexibility to customize the components.
Expand Down

1 comment on commit a9300db

@vercel
Copy link

@vercel vercel bot commented on a9300db Jul 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ui – ./

ui-nuxtlabs.vercel.app
ui-git-dev-nuxtlabs.vercel.app
ui.nuxtlabs.com

Please sign in to comment.