Skip to content
Merged
57 changes: 49 additions & 8 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ h3 {
}

.dash-grid-2 {
@apply grid grid-cols-2 gap-8;
@apply mt-2 grid grid-cols-2;
}

.dash-tile-rect {
Expand All @@ -70,7 +70,7 @@ h3 {
}

.dash-tile-square {
@apply card border-primary bg-base-100 my-1 rounded-lg border p-6 transition-shadow hover:shadow-md;
@apply card border-primary bg-base-100 mx-10 my-1 rounded-lg border p-3 transition-shadow hover:shadow-md;
@apply flex flex-col items-center justify-center text-center;
@apply cursor-pointer;
/* Height constraints relative to .list-item */
Expand All @@ -87,8 +87,8 @@ h3 {
}

.footer {
@apply bg-primary text-primary-content h-20;
padding-bottom: env(safe-area-inset-bottom);
@apply bg-primary text-primary-content h-16;
/* padding-bottom: env(safe-area-inset-bottom); */
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
Expand All @@ -106,29 +106,30 @@ h3 {
}

.header-container-logo {
@apply rounded-xl bg-white p-2 shadow-sm;
@apply flex-shrink-0 rounded-xl bg-white p-2 shadow-sm;
}

.header-content {
@apply flex h-20 w-full flex-row items-center justify-between px-2 sm:px-6 lg:px-8;
@apply flex h-20 w-full flex-row items-center justify-between px-5;
}

.header-left {
@apply flex items-center space-x-4 px-2;
@apply flex items-center space-x-4;
}

.view {
@apply flex h-full w-full flex-col overflow-hidden;
}

.view-header {
@apply bg-accent max-w-full p-3;
@apply bg-accent h-14 max-w-full px-5;
/* height: 4.5rem; */
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
}


.view-layout {
/* DASH */
@apply max-w-full justify-around space-y-4 px-2;
Expand Down Expand Up @@ -243,6 +244,46 @@ h3 {
@apply mx-1 mb-2 w-full;
}

.help-section {
border-bottom: 1px solid hsl(var(--bc) / 0.1);
}

.help-section:last-child {
border-bottom: none;
padding-bottom: 0;
}

.screenshot-container {
display: flex;
flex-direction: column;
align-items: center;
}

.breadcrumb {
font-size: 1.25rem;
font-weight: 700;
}

.breadcrumb-list {
@apply flex items-center space-x-2 m-0 p-0 list-none;
}

.breadcrumb-item {
@apply flex items-center;
}

.breadcrumb-link {
@apply text-accent-content hover:text-white transition-colors underline bg-transparent border-none cursor-pointer p-0 font-normal;
}

.breadcrumb-current {
@apply text-accent-content font-bold;
}

.breadcrumb-separator {
@apply text-accent-content/70 mx-2 font-normal;
}

@media (max-width: 375px) {
.dash-grid {
@apply grid-cols-1;
Expand Down
8 changes: 4 additions & 4 deletions src/lib/components/layouts/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
<div id="header-content" class="header-content">
<div id="header-left" class="header-left">
<div id="brand-logo" class="header-container-logo">
<img alt="LIFT logo" src="/logo/LIFT_logo_gradient_clean.svg" class="h-8 w-auto sm:h-10" />
<img alt="LIFT logo" src="/logo/LIFT_logo_gradient_clean.svg" class="h-10 w-20" />
</div>

<div id="app-name" class="header-container-name flex flex-row items-end gap-2">
<h1>Workwise</h1>
<p class="text-sm">{version}</p>
<!-- <p class="text-sm">{version}</p> -->
</div>
</div>

Expand All @@ -57,12 +57,12 @@
<button
id="email-button"
onclick={onEmailClick}
class="btn-nav"
class="w-8 h-8 rounded-full border-2 border-white bg-transparent flex items-center justify-center hover:bg-white hover:bg-opacity-20 transition-colors disabled:opacity-50"
type="button"
aria-label="Send Email to Line Manager"
disabled={isInEmailView}
>
<Icon src={Envelope} solid class="h-6 w-6" />
<Icon src={Envelope} solid class="h-4 w-4 text-white" />
</button>
</Tooltip>
{/if}
Expand Down
14 changes: 10 additions & 4 deletions src/lib/components/layouts/ViewHeader.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<script lang="ts">
import HelpButton from '../ui/HelpButton.svelte';
import Breadcrumb from '../ui/Breadcrumb.svelte';

interface Props {
title: string;
onclick?: () => void;
Expand All @@ -8,9 +11,12 @@
</script>

<div id="{title}-header" class="view-header">
<h2 class="text-accent-content flex items-center">{title}</h2>
<Breadcrumb />

{#if onclick}
<button {onclick} class="btn-nav border-primary"> Back </button>
{/if}
<div class="flex items-center gap-3">
{#if onclick}
<button {onclick} class="btn-nav border-primary"> Back </button>
{/if}
<HelpButton />
</div>
</div>
141 changes: 141 additions & 0 deletions src/lib/components/ui/Breadcrumb.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<script lang="ts">
import { getContext } from 'svelte';
import type { AppState, ViewName, List } from '$lib/types/appState';

const getApp = getContext<() => AppState>('getApp');
const setViewName = getContext<(view: ViewName) => void>('setViewName');
const setList = getContext<(list: List) => void>('setList');

const app = $derived(getApp());

interface BreadcrumbItem {
label: string;
clickable: boolean;
action?: () => void;
}

// Generate breadcrumb items based on current app state
const breadcrumbItems = $derived(() => {
const viewName = app.view.name;
const listTable = app.list.table;
const detailTable = app.detail.table;
const categoryFormat = app.list.category?.format;

const items: BreadcrumbItem[] = [];

// Always start with Dashboard
items.push({
label: 'Dashboard',
clickable: true,
action: () => setViewName('dash')
});

// Add intermediate levels based on current view
if (viewName === 'list') {
if (listTable === 'questions' && categoryFormat) {
items.push({
label: categoryFormat,
clickable: false
});
} else if (listTable === 'actions') {
items.push({
label: 'Actions',
clickable: false
});
} else if (listTable === 'resources') {
items.push({
label: 'Resources',
clickable: false
});
} else if (listTable === 'responses') {
items.push({
label: 'Responses',
clickable: false
});
}
} else if (viewName === 'detail') {
// Add the list level first
if (detailTable === 'responses') {
if (categoryFormat) {
items.push({
label: categoryFormat,
clickable: true,
action: () => {
const category = app.list.category || { raw: null, format: null };
setList({ table: 'questions', category });
setViewName('list');
}
});
}
items.push({
label: 'Response',
clickable: false
});
} else if (detailTable === 'actions') {
items.push({
label: 'Actions',
clickable: true,
action: () => {
setList({ table: 'actions', category: { raw: null, format: null } });
setViewName('list');
}
});
items.push({
label: 'Action',
clickable: false
});
} else if (detailTable === 'resources') {
items.push({
label: 'Resources',
clickable: true,
action: () => {
setList({ table: 'resources', category: { raw: null, format: null } });
setViewName('list');
}
});
items.push({
label: 'Resource',
clickable: false
});
}
} else if (viewName === 'email') {
items.push({
label: 'Email Preview',
clickable: false
});
}

return items;
});

// Cache the breadcrumb items to avoid multiple function calls
const items = $derived(breadcrumbItems());

// Always show breadcrumbs (at minimum shows current page)
const showBreadcrumbs = $derived(items.length > 0);
</script>

{#if showBreadcrumbs}
<nav class="breadcrumb" aria-label="Breadcrumb navigation">
<ol class="breadcrumb-list">
{#each items as item, index (item.label)}
<li class="breadcrumb-item">
{#if item.clickable && item.action}
<button
class="breadcrumb-link"
onclick={item.action}
type="button"
>
{item.label}
</button>
{:else}
<span class="breadcrumb-current">{item.label}</span>
{/if}
{#if index < items.length - 1}
<span class="breadcrumb-separator" aria-hidden="true">→</span>
{/if}
</li>
{/each}
</ol>
</nav>
{/if}
Loading