Table
Table
The Table
is the main way to present data in Bubbles. Tables are created with individual components, meaning you'll import TableRow
and TableCell
.
The Table
is made up of an optional TableHeader
, where you can set the headings for rows. And TableRow
, which itself is just an array of TableCell
components.
If you're looking to add filters or pagination at the bottom of your table, you'll want to slot the Table
into a Card
, and add the CardHeader
with filters and CardFooter
with pagination.
Props
padding string
roomy
"roomy" or "compact". Decides how much spacing is between each row.
id string
You can pass in an ID to the component if you need to reference it later. If you do not pass an ID, there will be a unique id added to the component.
overflow boolean
false
Allow for the table contents to overflow the container. The table will become scrollable.
TableHeader
This is the top of the Table
that explains what each of the column are.
Props
cells array<Object>
Cells are an array of Objects that will add text to the top of the table. The number of cells should match the numbers for TableCell
components that are in each TableRow
.
cell[].label string
This is the text the user will see. Leave this blank or pass in null to add a blank cell. Useful if you have an icon or image in one of your TableCell and don't want a header.
cell[].align string
Normally cells are aligned to the left, but if you want to align the header to the right, pass in "right" or "end
cell[].width integer
Set the width to 0
to hide this item
cell[].mobile_width integer
Set to zero to hide this cell on mobile devices
"Select All" Checkbox Props
In some tables, you'll want the user to select multiple items and do an action, like deleting all items. Each TableRow
can have a checkbox component. Adding an option to the header will let you select and deselect all checkboxes in the same column, and adjust to UI of the CardHeader
to display options.
cell[].checkbox boolean
Set this value to true to display the checkbox in the header
cell[].options array<Object>
An array that will contain the options the user can select. These options should be functions that apply to all selected items. To get all of the selected rows, make sure you have provided an id
property to all rows, then import the getSelectedTableRows.
Show Details
option[].label string The text the user sees for the option |
option[].value string The value that will be added for the url query param |
option[].caption string More details to give about the option |
option[].img string An image that will be displayed on the left of the text |
option[].icon string An icon to display on the right. Defaults to an arrow. You can remove this by setting this value to null |
option[].onselect function A function that can be run if this option is selected |
Table Sorting
At some point you'll want to sort the data in your table. There are two ways you can sort the data. First, you can sort the data in place, that means you are not refetching data from an API and the other route is to fetch the data from the API and have the server do the sorting. The sorting props let you do both. Refetching data will add query parameters to the url, which will trigger the load function to run. Make sure that you have destructured the url
property in the load function.
cell[].sort Object
Set this value to sort the table rows for the end user. The result is when the user clicks on the cell to sort, an event gets fired. If you are modifying the query params and refetching data, you don't need to do anything at this point. If you are sorting locally, you'll need to listen for the sort event dispatched to the header, and sort the data yourself. Bubbles has a built in utility function that can sort for you.
Show Details
cell.sort.id string The prop name you want to search for. If the prop is nested, use dot notation like "hello.world" |
cell.sort.order string The default order for the displayed arrow. Defaults to "ascending" but you can change to "descending" |
cell.sort.query boolean Set to true if you want the sort to add query params to refetch the API |
cell.sort.key string The key for the query param. Will default to the ID |
cell.sort.value string The value for the query param, will default to the order |
import { TableHeader, sort } from "bubbles-ui";
$: data = [] //This is the data for your table
<TableHeader
on:sort={(event) => (data = sort(data, event.detail.sort_by, event.detail.order))} //Will sort the data locally without refetching
cells={[
{ label: "Name", sort: { id: "name", query: true, key: "name" } }, //Will add a query param, with custom key
{ label: "Weight", sort: { id: "size.weight" } }, //The sort function will sort by numbers and find the value nested on obj.size.weight
]}
/>;
TableRow
Props
id string
You can set an ID for the row to reference it later. For example, set the id of the TableRow
to each user you're displaying in your table so you can go to that user's details page if the table is clicked on.
href string
The href value for the entire row. This is useful is you are using a Table for a settings menu, where you don't care where the user clicks. If you have a more complex cell, set the href on the cell, not the row.
onclick function
You can run a function when the user clicks on the row. If you just want to take the user to a new page, use href because it will have better performance as the page with be prefetched.
wrap boolean
true
Set to false
if you don't want to wrap the contents of each cell.
mobile_wrap boolean
true
Set to false
fi you don't wan to wrap the contents of each cell mobile only
TableCell
The cell that is inside of the TableRow
.
When a user is viewing your table on a mobile device, we'll need the table to be responsive. You can attempt to make the whole table row overflow but that is a bad user experience. Ideally, on a smaller screen, you'll want to present less information on your table, and let the user navigate to a page with more details.
There are specific mobile properties on for the TableCell
to help you deal with small screen devices.
There are some predefined props for the table for standard layouts. You can of course just add your own custom markup as a slot.
Props
text string
This will add a string of text to the cell
href string
Will cause the text to be an href. This is different than setting the TableRow
as an href, since only this part will be clickable. Best used on complex tables that may have multiple clickable parts.
caption string
This will add a second line of text below in grey below the text
large boolean
false
Make the text in the cell large. Best used for simple tables like settings screens
bold boolean
false
Will make the text in this cell bold. Great for complex table to show the most import piece of information.
align string
left
By default the text in the cell is left aligned, but you can change that to "right"
img.src string
If you pass in an img, Bubbles will assume you want to add an image to the cell, like someone's profile picture. The image will be added and all text properties will be ignored.
img.alt string
If you pass an image, add an alt tag for accessibility.
tag object
ou can add a tag into your cell. See the tag sectionfor more details.
button object
If you add a button property, Bubbles will assume you want to add an IconButton
to that cell. See the props needed for an IconButton here
width number|string
The the width for the cell. Enter a number for the width to be treated as a percentage, or a string with the units you want like "3rem" or "20px"
mobile_width number
Select the width this cell will take up on small screens. If you want to hide the cell on mobile, set the value to 0.
mobile_order number
This is the order
css property. You can change the order or elements by passing in larger integers and move them left in the stack by passing in larger negative integers.
wrap boolean
true
Set to false
if you don't want to wrap the contents of the cell.
mobile_wrap boolean
true
Set to false
fi you don't wan to wrap the contents of mobile only
<script>
import { Table, TableRow, TableCell, pageStore } from "bubbles-ui";
</script>
<Table>
<TableRow href="#table">
<TableCell text="Profile" large={true} bold={true} caption="Edit your profile and update your photo" />
<TableCell button={{ icon: "arrowRight" }} />
</TableRow>
<TableRow href="#table">
<TableCell text="Notifications" large={true} caption="Select how and went we message you" />
<TableCell button={{ icon: "arrowRight" }} />
</TableRow>
<TableRow href="#table">
<TableCell text="Billing" large={true} bold={true} caption="Edit your payment methods and see past transactions" />
<TableCell button={{ icon: "arrowRight" }} />
</TableRow>
</Table>
<script>
import {
Card,
CardHeader,
CardFooter,
Row,
Column as Column100,
Table,
TableHeader,
TableRow,
TableCell,
Pagination,
sort,
} from "bubbles-ui";
import store from "$docs/utils/store";
import { getSelectedTableRows, deselectTableRows } from "$lib/utils/table";
$: pagination = $store?.pagination ? $store.pagination : {};
$: pokemon = $store.pokemon ? $store.pokemon : [];
function typeColor(type) {
switch (type) {
case "normal":
return "gray-light";
case "fire":
return "error";
case "water":
return "info";
case "grass":
return "success";
case "electric":
return "warning";
case "ice":
return "info-light";
case "fighting":
return "error-light";
case "poison":
return "primary";
case "ground":
return "warning-light";
case "flying":
return "primary-light";
case "psychic":
return "secondary-light";
case "bug":
return "success-light";
case "rock":
return "dark-light";
case "ghost":
return "primary-border";
case "dark":
return "dark";
case "dragon":
return "primary-light";
case "steel":
return "gray";
case "fairy":
return "secondary";
default:
return "gray";
}
}
</script>
<Row>
<Column>
<Card>
<CardHeader
title="Complex Table Example"
caption="This example uses an external API for data, which may run slowly especially when using the search."
buttons={[{ icon: "search", color: "gray-lighter", search: true }]}
border={false}
filters={[
{
id: "type",
label: "Type",
value: "",
reset_label: "All",
break_after_reset: true,
options: types.map((type) => {
return {
label: type,
value: type.toLowerCase(),
};
}),
},
]}
/>
<Table id="pokemon-table" padding="roomy">
<TableHeader
on:sort={(event) => (pokemon = sort(pokemon, event.detail.sort_by, event.detail.order))}
cells={[
{
checkbox: true,
options: [
{
label: "Print Selected Rows To Console",
value: "label1",
onselect: (event) => {
console.log(getSelectedTableRows("pokemon-table"));
deselectTableRows("pokemon-table");
},
},
],
},
{ label: null },
{ label: "Name", sort: { id: "name" } },
{ label: "Weight", sort: { id: "weight" }, mobile_width: 0 },
{ label: "Type(s)", mobile_width: 0 },
{ label: "Possible Moves", align: "end", mobile_width: 0 },
{ label: null, align: "end" },
]}
/>
{#each pokemon as poke}
<TableRow id={poke.id}>
<TableCell checkbox={{ value: false }} />
<TableCell img={{ src: poke?.sprites?.front_default, alt: "Sprite" }} mobile_width={10} />
<TableCell
text={poke.name}
href={`/examples/pokedex/${poke.name}`}
captions={[`Pokedex Number: ${poke.id}`, `evolutions: ${poke.evo}`]}
bold={true}
mobile_width={70}
/>
<TableCell text={`${poke.weight} lbs`} mobile_width={0} />
<TableCell mobile_width={0}>
{#if poke?.types[0]}
<Tag
label={poke?.types[0]?.type?.name}
color={typeColor(poke?.types[0]?.type?.name)}
margin="0 0 .25rem 0"
/>
{/if}
{#if poke?.types[1]}
<Tag
label={poke?.types[1]?.type?.name}
color={typeColor(poke?.types[1]?.type?.name)}
margin="0 0 .25rem 0"
/>
{/if}
</TableCell>
<TableCell
tag={{ label: poke.moves.length, color: "primary", min_width: 2.75 }}
align="right"
mobile_width={0}
/>
<TableCell
mobile_width={10}
button={{
icon: "more",
options: [
{
label: "Encounters",
href: poke.location_area_encounters,
caption: "Areas you can find this pokemon",
},
{ break: true },
{
label: "View JSON",
href: poke.species.url,
},
{
label: "Shiny Sprite",
onclick: () => {
showModal("Shiny Sprite", { img: poke.sprites.front_shiny });
},
},
],
}}
/>
</TableRow>
{/each}
</Table>
<CardFooter>
<Pagination {...pagination} />
</CardFooter>
</Card>
</Column>
</Row>
Complex Table Example
This example uses an external API for data, which may run slowly especially when using the search.