Update home screen UI to work better on mobile and make spacing more consistent
This commit is contained in:
parent
841feac5fa
commit
69a8376d17
|
@ -63,6 +63,9 @@
|
||||||
.gap-L {
|
.gap-L {
|
||||||
grid-gap: var(--spectrum-alias-grid-gutter-medium);
|
grid-gap: var(--spectrum-alias-grid-gutter-medium);
|
||||||
}
|
}
|
||||||
|
.gap-XL {
|
||||||
|
grid-gap: var(--spectrum-alias-grid-gutter-large);
|
||||||
|
}
|
||||||
.horizontal.gap-S :global(*) + :global(*) {
|
.horizontal.gap-S :global(*) + :global(*) {
|
||||||
margin-left: var(--spectrum-alias-grid-gutter-xsmall);
|
margin-left: var(--spectrum-alias-grid-gutter-xsmall);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,3 +13,9 @@
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
p {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -62,12 +62,8 @@
|
||||||
</StatusLight>
|
</StatusLight>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button disabled={app.lockedOther} on:click={() => editApp(app)} secondary
|
||||||
disabled={app.lockedOther}
|
>Open</Button
|
||||||
on:click={() => editApp(app)}
|
|
||||||
size="S"
|
|
||||||
quiet
|
|
||||||
secondary>Open</Button
|
|
||||||
>
|
>
|
||||||
<ActionMenu align="right">
|
<ActionMenu align="right">
|
||||||
<Icon hoverable slot="control" name="More" />
|
<Icon hoverable slot="control" name="More" />
|
||||||
|
@ -91,7 +87,7 @@
|
||||||
<MenuItem on:click={() => updateApp(app)} icon="Edit">Edit</MenuItem>
|
<MenuItem on:click={() => updateApp(app)} icon="Edit">Edit</MenuItem>
|
||||||
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
|
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
|
||||||
{/if}
|
{/if}
|
||||||
<MenuItem on:click={() => editIcon(app)} icon="Brush">Edit Icon</MenuItem>
|
<MenuItem on:click={() => editIcon(app)} icon="Brush">Edit icon</MenuItem>
|
||||||
</ActionMenu>
|
</ActionMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,11 @@
|
||||||
|
|
||||||
export let app
|
export let app
|
||||||
let modal
|
let modal
|
||||||
$: selectedIcon = app?.icon?.name
|
$: selectedIcon = app?.icon?.name || "Apps"
|
||||||
$: selectedColor = app?.icon?.color
|
$: selectedColor = app?.icon?.color
|
||||||
|
|
||||||
let iconsList = [
|
let iconsList = [
|
||||||
|
"Apps",
|
||||||
"Actions",
|
"Actions",
|
||||||
"ConversionFunnel",
|
"ConversionFunnel",
|
||||||
"App",
|
"App",
|
||||||
|
@ -31,7 +32,6 @@
|
||||||
"GraphDonut",
|
"GraphDonut",
|
||||||
"GraphBarHorizontal",
|
"GraphBarHorizontal",
|
||||||
"Demographic",
|
"Demographic",
|
||||||
"Apps",
|
|
||||||
]
|
]
|
||||||
export const show = () => {
|
export const show = () => {
|
||||||
modal.show()
|
modal.show()
|
||||||
|
@ -68,13 +68,13 @@
|
||||||
>
|
>
|
||||||
<div class="scrollable-icons">
|
<div class="scrollable-icons">
|
||||||
<div class="title-spacing">
|
<div class="title-spacing">
|
||||||
<Label>Select an Icon</Label>
|
<Label>Select an icon</Label>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
{#each iconsList as item}
|
{#each iconsList as item}
|
||||||
<div
|
<div
|
||||||
class="icon-item"
|
class="icon-item"
|
||||||
style="color: {item === selectedIcon ? selectedColor : ''}"
|
class:selected={item === selectedIcon}
|
||||||
on:click={() => (selectedIcon = item)}
|
on:click={() => (selectedIcon = item)}
|
||||||
>
|
>
|
||||||
<Icon name={item} />
|
<Icon name={item} />
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="color-selection">
|
<div class="color-selection">
|
||||||
<div>
|
<div>
|
||||||
<Label>Select a Color</Label>
|
<Label>Select a color</Label>
|
||||||
</div>
|
</div>
|
||||||
<div class="color-selection-item">
|
<div class="color-selection-item">
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
|
@ -124,4 +124,7 @@
|
||||||
.icon-item {
|
.icon-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.icon-item.selected {
|
||||||
|
color: var(--spectrum-global-color-blue-600);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
let cloud = $admin.cloud
|
let cloud = $admin.cloud
|
||||||
let appName = ""
|
let appName = ""
|
||||||
let creatingFromTemplate = false
|
let creatingFromTemplate = false
|
||||||
|
|
||||||
$: enrichedApps = enrichApps($apps, $auth.user, sortBy)
|
$: enrichedApps = enrichApps($apps, $auth.user, sortBy)
|
||||||
$: filteredApps = enrichedApps.filter(app =>
|
$: filteredApps = enrichedApps.filter(app =>
|
||||||
app?.name?.toLowerCase().includes(searchTerm.toLowerCase())
|
app?.name?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
|
@ -280,99 +281,104 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Page wide>
|
<Page wide>
|
||||||
<Layout noPadding>
|
<Layout noPadding gap="XL">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Heading size="S">Welcome to Budibase</Heading>
|
<Layout noPadding gap="XS">
|
||||||
|
<Heading size="M">Welcome to Budibase</Heading>
|
||||||
|
<Body size="S">
|
||||||
|
Manage your apps and get a head start with templates
|
||||||
|
</Body>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
<ButtonGroup>
|
<div class="buttons">
|
||||||
{#if cloud}
|
<!--{#if cloud}-->
|
||||||
<Button secondary on:click={initiateAppsExport}>Export apps</Button>
|
<Button icon="Export" quiet secondary on:click={initiateAppsExport}>
|
||||||
{/if}
|
Export apps
|
||||||
<Button icon="Import" quiet secondary on:click={initiateAppImport}
|
</Button>
|
||||||
>Import app</Button
|
<!--{/if}-->
|
||||||
>
|
<Button icon="Import" quiet secondary on:click={initiateAppImport}>
|
||||||
<Button icon="Add" cta on:click={initiateAppCreation}>Create app</Button
|
Import app
|
||||||
>
|
</Button>
|
||||||
</ButtonGroup>
|
<Button icon="Add" cta on:click={initiateAppCreation}>
|
||||||
|
Create app
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="title-text">
|
<Layout noPadding gap="S">
|
||||||
<Body size="S">Manage your apps and get a head start with templates</Body>
|
<Detail size="L">Quick start templates</Detail>
|
||||||
</div>
|
<div class="grid">
|
||||||
<Detail>Quick Start Templates</Detail>
|
{#each $templates as item}
|
||||||
<div class="grid">
|
<div
|
||||||
{#each $templates as item}
|
on:click={() => {
|
||||||
<div
|
template = item
|
||||||
on:click={() => {
|
creationModal.show()
|
||||||
template = item
|
creatingApp = true
|
||||||
creationModal.show()
|
}}
|
||||||
creatingApp = true
|
class="template-card"
|
||||||
}}
|
>
|
||||||
class="template-card"
|
<div class="card-body">
|
||||||
>
|
<div style="color: {item.background}" class="iconAlign">
|
||||||
<div class="card-body">
|
<svg
|
||||||
<div style="color: {item.background}" class="iconAlign">
|
width="26px"
|
||||||
<svg
|
height="26px"
|
||||||
width="26px"
|
class="spectrum-Icon"
|
||||||
height="26px"
|
style="color:{item.background};"
|
||||||
class="spectrum-Icon"
|
focusable="false"
|
||||||
style="color:{item.background};"
|
>
|
||||||
focusable="false"
|
<use xlink:href="#spectrum-icon-18-{item.icon}" />
|
||||||
>
|
</svg>
|
||||||
<use xlink:href="#spectrum-icon-18-{item.icon}" />
|
</div>
|
||||||
</svg>
|
<div class="iconAlign">
|
||||||
</div>
|
<Body weight="900" size="S">{item.name}</Body>
|
||||||
<div class="iconAlign">
|
<div style="font-size: 10px;">
|
||||||
<Body weight="900" size="S">{item.name}</Body>
|
<Body size="S">{item.category.toUpperCase()}</Body>
|
||||||
<div style="font-size: 10px;">
|
</div>
|
||||||
<Body size="S">{item.category.toUpperCase()}</Body>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
{#if loaded && enrichedApps.length}
|
|
||||||
<div class="title">
|
|
||||||
<Detail>My Apps</Detail>
|
|
||||||
</div>
|
|
||||||
<div class="filter">
|
|
||||||
<div class="select">
|
|
||||||
<Select
|
|
||||||
quiet
|
|
||||||
autoWidth
|
|
||||||
bind:value={sortBy}
|
|
||||||
placeholder={null}
|
|
||||||
options={[
|
|
||||||
{ label: "Sort by name", value: "name" },
|
|
||||||
{ label: "Sort by recently updated", value: "updated" },
|
|
||||||
{ label: "Sort by status", value: "status" },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<div class="desktop-search">
|
|
||||||
<Search quiet placeholder="Search" bind:value={searchTerm} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mobile-search">
|
|
||||||
<Search placeholder="Search" bind:value={searchTerm} />
|
|
||||||
</div>
|
|
||||||
<div class="appTable">
|
|
||||||
{#each filteredApps as app (app.appId)}
|
|
||||||
<AppRow
|
|
||||||
{releaseLock}
|
|
||||||
{editIcon}
|
|
||||||
{app}
|
|
||||||
{unpublishApp}
|
|
||||||
{viewApp}
|
|
||||||
{editApp}
|
|
||||||
{exportApp}
|
|
||||||
{deleteApp}
|
|
||||||
{updateApp}
|
|
||||||
/>
|
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
{#if loaded && enrichedApps.length}
|
||||||
|
<Layout noPadding gap="S">
|
||||||
|
<div class="title">
|
||||||
|
<Detail size="L">My apps</Detail>
|
||||||
|
<div class="filter">
|
||||||
|
<Select
|
||||||
|
quiet
|
||||||
|
autoWidth
|
||||||
|
bind:value={sortBy}
|
||||||
|
placeholder={null}
|
||||||
|
options={[
|
||||||
|
{ label: "Sort by name", value: "name" },
|
||||||
|
{ label: "Sort by recently updated", value: "updated" },
|
||||||
|
{ label: "Sort by status", value: "status" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Search placeholder="Search" bind:value={searchTerm} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="appTable">
|
||||||
|
{#each filteredApps as app (app.appId)}
|
||||||
|
<AppRow
|
||||||
|
{releaseLock}
|
||||||
|
{editIcon}
|
||||||
|
{app}
|
||||||
|
{unpublishApp}
|
||||||
|
{viewApp}
|
||||||
|
{editApp}
|
||||||
|
{exportApp}
|
||||||
|
{deleteApp}
|
||||||
|
{updateApp}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if !enrichedApps.length && !creatingApp && loaded}
|
{#if !enrichedApps.length && !creatingApp && loaded}
|
||||||
<div class="empty-wrapper">
|
<div class="empty-wrapper">
|
||||||
<Modal inline>
|
<Modal inline>
|
||||||
|
@ -380,6 +386,7 @@
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if creatingFromTemplate}
|
{#if creatingFromTemplate}
|
||||||
<div class="empty-wrapper">
|
<div class="empty-wrapper">
|
||||||
<p>Creating your Budibase app from your selected template...</p>
|
<p>Creating your Budibase app from your selected template...</p>
|
||||||
|
@ -427,68 +434,61 @@
|
||||||
<ChooseIconModal app={selectedApp} bind:this={iconModal} />
|
<ChooseIconModal app={selectedApp} bind:this={iconModal} />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.title,
|
.title {
|
||||||
.filter {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 5px;
|
gap: var(--spacing-xl);
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
.buttons {
|
||||||
@media only screen and (max-width: 560px) {
|
display: flex;
|
||||||
.title {
|
flex-direction: row;
|
||||||
flex-direction: column;
|
justify-content: flex-start;
|
||||||
align-items: flex-start;
|
align-items: center;
|
||||||
}
|
gap: var(--spacing-xl);
|
||||||
.grid {
|
flex-wrap: wrap;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
}
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.buttons {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconAlign {
|
.filter {
|
||||||
padding: 0 0 0 var(--spacing-m);
|
display: flex;
|
||||||
display: inline-block;
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: var(--spacing-xl);
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
|
||||||
}
|
}
|
||||||
.template-card {
|
.template-card {
|
||||||
height: 80px;
|
height: 80px;
|
||||||
width: 270px;
|
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
margin-bottom: var(--spacing-m);
|
|
||||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-text {
|
.template-card:hover {
|
||||||
margin-top: calc(var(--spacing-xl) * -1);
|
background: var(--spectrum-alias-background-color-tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-body {
|
.card-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
.iconAlign {
|
||||||
.grid {
|
padding: 0 0 0 var(--spacing-m);
|
||||||
display: grid;
|
display: inline-block;
|
||||||
grid-gap: 5px;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 200px) {
|
|
||||||
}
|
|
||||||
|
|
||||||
.select {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto auto;
|
|
||||||
grid-gap: 30px;
|
|
||||||
}
|
|
||||||
.filter :global(.spectrum-ActionGroup) {
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
}
|
|
||||||
.mobile-search {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.appTable {
|
.appTable {
|
||||||
|
@ -511,6 +511,12 @@
|
||||||
.appTable :global(> div) {
|
.appTable :global(> div) {
|
||||||
border-bottom: var(--border-light);
|
border-bottom: var(--border-light);
|
||||||
}
|
}
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.appTable {
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.empty-wrapper {
|
.empty-wrapper {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -519,20 +525,4 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.appTable {
|
|
||||||
grid-template-columns: 1fr auto;
|
|
||||||
}
|
|
||||||
.desktop-search {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.mobile-search {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.template-card:hover {
|
|
||||||
background: var(--spectrum-alias-background-color-tertiary);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue