mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-05-19 07:59:34 +00:00
Replace the raw Collabora setup log with a simple Office setup progress state, redesign the Office dashboard around document cards with lightweight previews, and keep backend WOPI sessions aligned with visible Office tabs. Also preserve the restored Office canvas surface across window refreshes and add regression coverage for the new behavior.
992 lines
32 KiB
HTML
992 lines
32 KiB
HTML
<html>
|
|
<head>
|
|
<script type="module">
|
|
import { store } from "/plugins/_office/webui/office-store.js";
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div class="office-panel" x-data x-create="$store.office.onMount($el, xAttrs($el) || {})" x-destroy="$store.office.cleanup()">
|
|
<template x-if="$store.office">
|
|
<div class="office-shell">
|
|
<div class="office-toolbar">
|
|
<button type="button" class="office-button" title="Open" @click="$store.office.openPrompt()">
|
|
<span class="material-symbols-outlined">folder_open</span>
|
|
<span>Open</span>
|
|
</button>
|
|
<button type="button" class="office-button" title="New document" @click="$store.office.create('document')">
|
|
<span class="material-symbols-outlined">note_add</span>
|
|
<span>Doc</span>
|
|
</button>
|
|
<button type="button" class="office-button" title="New spreadsheet" @click="$store.office.create('spreadsheet')">
|
|
<span class="material-symbols-outlined">table</span>
|
|
<span>Sheet</span>
|
|
</button>
|
|
<button type="button" class="office-button" title="New presentation" @click="$store.office.create('presentation')">
|
|
<span class="material-symbols-outlined">slideshow</span>
|
|
<span>Presentation</span>
|
|
</button>
|
|
<span class="office-toolbar-spacer"></span>
|
|
<span
|
|
class="office-health-pill"
|
|
:class="`is-${$store.office.status?.state || 'unknown'}`"
|
|
:title="$store.office.healthTitle()"
|
|
:aria-label="$store.office.healthTitle()"
|
|
>
|
|
<span class="office-health-dot"></span>
|
|
<span x-show="$store.office.status?.state !== 'healthy'" x-text="$store.office.healthText()"></span>
|
|
</span>
|
|
<button type="button" class="office-icon-button" title="Save" @click="$store.office.save()" :disabled="!$store.office.session">
|
|
<span class="material-symbols-outlined">save</span>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="office-icon-button"
|
|
title="Close file"
|
|
aria-label="Close file"
|
|
:disabled="!$store.office.session"
|
|
@click="$confirmClick($event, () => $store.office.closeFile())"
|
|
>
|
|
<span class="material-symbols-outlined">close</span>
|
|
</button>
|
|
<button type="button" class="office-icon-button" title="Refresh status" @click="$store.office.refresh()">
|
|
<span class="material-symbols-outlined">refresh</span>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="office-tabs" x-show="$store.office.tabs.length" role="tablist" aria-label="Open Office files" style="display: none;">
|
|
<template x-for="tab in $store.office.tabs" :key="tab.tab_id">
|
|
<div class="office-tab-shell" :class="{ 'is-active': $store.office.isActiveTab(tab) }">
|
|
<button
|
|
type="button"
|
|
class="office-tab"
|
|
role="tab"
|
|
:aria-selected="$store.office.isActiveTab(tab).toString()"
|
|
:title="$store.office.tabLabel(tab)"
|
|
@click="$store.office.selectTab(tab.tab_id)"
|
|
>
|
|
<span class="material-symbols-outlined office-tab-icon" aria-hidden="true" x-text="$store.office.tabIcon(tab)"></span>
|
|
<span class="office-tab-title" x-text="$store.office.tabTitle(tab)"></span>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="office-tab-close"
|
|
:title="'Close ' + $store.office.tabLabel(tab)"
|
|
:aria-label="'Close ' + $store.office.tabLabel(tab)"
|
|
:disabled="$store.office.loading"
|
|
@click.stop="$confirmClick($event, () => $store.office.closeTab(tab.tab_id))"
|
|
>
|
|
<span class="material-symbols-outlined">close</span>
|
|
</button>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<div class="office-status-line" x-show="$store.office.message || $store.office.error || $store.office.loading" style="display: none;">
|
|
<span class="material-symbols-outlined" :class="{ spinning: $store.office.loading }" x-text="$store.office.loading ? 'progress_activity' : ($store.office.error ? 'error' : 'check_circle')"></span>
|
|
<span x-text="$store.office.error || $store.office.message || 'Working...'"></span>
|
|
</div>
|
|
|
|
<div class="office-body">
|
|
<div class="office-bootstrap" x-show="!$store.office.session && (!$store.office.status || !$store.office.status.healthy)" style="display: none;">
|
|
<div class="office-setup-mark" :class="{ 'is-busy': $store.office.isSetupBusy(), 'is-alert': $store.office.isSetupBlocked() }">
|
|
<span class="material-symbols-outlined" :class="{ spinning: $store.office.isSetupBusy() }" x-text="$store.office.setupIcon()"></span>
|
|
</div>
|
|
<div class="office-setup-copy">
|
|
<span>Agent Zero Office</span>
|
|
<strong x-text="$store.office.setupTitle()"></strong>
|
|
<p x-text="$store.office.setupMessage()"></p>
|
|
</div>
|
|
<div class="office-setup-progress" :class="{ 'is-paused': !$store.office.isSetupBusy() }" aria-hidden="true">
|
|
<span></span>
|
|
</div>
|
|
<div class="office-bootstrap-actions" x-show="$store.office.showSetupActions()" style="display: none;">
|
|
<button type="button" class="office-button" @click="$store.office.retry()" x-show="$store.office.isSetupBlocked()" style="display: none;">
|
|
<span class="material-symbols-outlined">restart_alt</span>
|
|
<span>Retry</span>
|
|
</button>
|
|
<button type="button" class="office-button" @click="$store.office.refresh()">
|
|
<span class="material-symbols-outlined">sync</span>
|
|
<span>Refresh</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="office-start" x-show="!$store.office.session && $store.office.status?.healthy" style="display: none;">
|
|
<section class="office-dashboard-section" aria-label="Create Office file">
|
|
<div class="office-dashboard-heading">Create</div>
|
|
<div class="office-template-grid">
|
|
<button type="button" class="office-create-tile" @click="$store.office.create('document')">
|
|
<span class="material-symbols-outlined">article</span>
|
|
<span>Document</span>
|
|
</button>
|
|
<button type="button" class="office-create-tile" @click="$store.office.create('spreadsheet')">
|
|
<span class="material-symbols-outlined">table_chart</span>
|
|
<span>Spreadsheet</span>
|
|
</button>
|
|
<button type="button" class="office-create-tile" @click="$store.office.create('presentation')">
|
|
<span class="material-symbols-outlined">co_present</span>
|
|
<span>Presentation</span>
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="office-dashboard-section" x-show="$store.office.openCards().length" aria-label="Open Office files" style="display: none;">
|
|
<div class="office-dashboard-heading">Open files</div>
|
|
<div class="office-card-grid">
|
|
<template x-for="doc in $store.office.openCards()" :key="doc.tab_id">
|
|
<button type="button" class="office-document-card is-open" :title="doc.path" @click="$store.office.selectTab(doc.tab_id)">
|
|
<span class="office-card-badge">Open</span>
|
|
<div class="office-card-preview" :class="`is-${$store.office.previewKind(doc)}`">
|
|
<template x-if="$store.office.previewKind(doc) === 'spreadsheet' && $store.office.hasPreview(doc)">
|
|
<div class="office-sheet-preview">
|
|
<template x-for="(row, rowIndex) in $store.office.previewRows(doc)" :key="rowIndex">
|
|
<div class="office-sheet-row">
|
|
<template x-for="(cell, cellIndex) in row" :key="cellIndex">
|
|
<span x-text="cell"></span>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<template x-if="$store.office.previewKind(doc) === 'presentation' && $store.office.hasPreview(doc)">
|
|
<div class="office-slide-preview">
|
|
<template x-for="(slide, index) in $store.office.previewSlides(doc)" :key="index">
|
|
<div class="office-slide-line">
|
|
<strong x-text="slide.title"></strong>
|
|
<span x-text="(slide.lines || []).join(' / ')"></span>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<template x-if="$store.office.previewKind(doc) === 'document' && $store.office.hasPreview(doc)">
|
|
<div class="office-page-preview">
|
|
<template x-for="(line, index) in $store.office.previewLines(doc)" :key="index">
|
|
<span x-text="line"></span>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<template x-if="!$store.office.hasPreview(doc)">
|
|
<div class="office-preview-fallback">
|
|
<span class="material-symbols-outlined" x-text="$store.office.tabIcon(doc)"></span>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<span class="office-card-title" x-text="$store.office.dashboardTitle(doc)"></span>
|
|
<small x-text="$store.office.dashboardMeta(doc)"></small>
|
|
</button>
|
|
</template>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="office-dashboard-section" x-show="$store.office.recentCards().length" aria-label="Recent Office files" style="display: none;">
|
|
<div class="office-dashboard-heading">Recent files</div>
|
|
<div class="office-card-grid">
|
|
<template x-for="doc in $store.office.recentCards()" :key="doc.file_id">
|
|
<button type="button" class="office-document-card" :title="doc.path" @click="$store.office.openPath(doc.path)">
|
|
<div class="office-card-preview" :class="`is-${$store.office.previewKind(doc)}`">
|
|
<template x-if="$store.office.previewKind(doc) === 'spreadsheet' && $store.office.hasPreview(doc)">
|
|
<div class="office-sheet-preview">
|
|
<template x-for="(row, rowIndex) in $store.office.previewRows(doc)" :key="rowIndex">
|
|
<div class="office-sheet-row">
|
|
<template x-for="(cell, cellIndex) in row" :key="cellIndex">
|
|
<span x-text="cell"></span>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<template x-if="$store.office.previewKind(doc) === 'presentation' && $store.office.hasPreview(doc)">
|
|
<div class="office-slide-preview">
|
|
<template x-for="(slide, index) in $store.office.previewSlides(doc)" :key="index">
|
|
<div class="office-slide-line">
|
|
<strong x-text="slide.title"></strong>
|
|
<span x-text="(slide.lines || []).join(' / ')"></span>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<template x-if="$store.office.previewKind(doc) === 'document' && $store.office.hasPreview(doc)">
|
|
<div class="office-page-preview">
|
|
<template x-for="(line, index) in $store.office.previewLines(doc)" :key="index">
|
|
<span x-text="line"></span>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<template x-if="!$store.office.hasPreview(doc)">
|
|
<div class="office-preview-fallback">
|
|
<span class="material-symbols-outlined" x-text="$store.office.tabIcon(doc)"></span>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<span class="office-card-title" x-text="$store.office.dashboardTitle(doc)"></span>
|
|
<small x-text="$store.office.dashboardMeta(doc)"></small>
|
|
</button>
|
|
</template>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="office-frame-wrap" x-show="$store.office.session" style="display: none;">
|
|
<iframe
|
|
data-office-frame
|
|
allow="clipboard-read *; clipboard-write *; fullscreen *"
|
|
allowfullscreen
|
|
></iframe>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<style>
|
|
.office-panel,
|
|
.office-shell {
|
|
display: flex;
|
|
flex: 1 1 auto;
|
|
flex-direction: column;
|
|
width: 100%;
|
|
height: 100%;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
background: var(--color-background);
|
|
}
|
|
|
|
.office-panel {
|
|
container-type: inline-size;
|
|
}
|
|
|
|
.modal-inner.office-modal {
|
|
box-sizing: border-box;
|
|
container-type: inline-size;
|
|
width: min(82vw, 1180px);
|
|
height: min(88vh, 900px);
|
|
min-width: min(340px, calc(100vw - 16px));
|
|
min-height: min(500px, calc(100vh - 16px));
|
|
max-width: calc(100vw - 16px);
|
|
max-height: calc(100vh - 16px);
|
|
resize: both;
|
|
border: 1px solid color-mix(in srgb, var(--color-border) 75%, transparent);
|
|
border-radius: 7px;
|
|
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.32);
|
|
background: color-mix(in srgb, var(--color-background) 94%, #000 6%);
|
|
}
|
|
|
|
.modal.modal-floating {
|
|
pointer-events: none;
|
|
}
|
|
|
|
.modal.modal-floating .modal-inner {
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.modal-inner.office-modal .modal-header {
|
|
min-height: 34px;
|
|
padding: 0.35rem 0.75rem 0.35rem 1rem;
|
|
cursor: move;
|
|
user-select: none;
|
|
background: color-mix(in srgb, var(--color-background) 92%, #000 8%);
|
|
border-bottom: 1px solid color-mix(in srgb, var(--color-border) 70%, transparent);
|
|
}
|
|
|
|
.modal-inner.office-modal .modal-close {
|
|
font-size: 1.35rem;
|
|
line-height: 1;
|
|
}
|
|
|
|
.modal-inner.office-modal .modal-scroll {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
padding: 0;
|
|
}
|
|
|
|
.modal-inner.office-modal .modal-bd.office-modal-body {
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1 1 auto;
|
|
width: 100%;
|
|
height: 100%;
|
|
min-height: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.modal-inner.office-modal .modal-bd.office-modal-body > x-component,
|
|
.modal-inner.office-modal .modal-bd.office-modal-body > div[x-data] {
|
|
display: flex;
|
|
flex: 1 1 auto;
|
|
width: 100%;
|
|
height: 100%;
|
|
min-height: 0;
|
|
}
|
|
|
|
.modal-inner.office-modal .modal-bd.office-modal-body > x-component > .office-panel {
|
|
flex: 1 1 auto;
|
|
height: 100%;
|
|
min-height: 0;
|
|
}
|
|
|
|
.office-toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
min-height: 44px;
|
|
padding: 7px 9px;
|
|
border-bottom: 1px solid color-mix(in srgb, var(--color-border) 66%, transparent);
|
|
background: color-mix(in srgb, var(--color-background) 92%, #000 8%);
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.office-tabs {
|
|
--office-tab-height: 34px;
|
|
--office-tab-close-size: 27px;
|
|
display: flex;
|
|
align-items: end;
|
|
gap: 4px;
|
|
min-height: 39px;
|
|
min-width: 0;
|
|
padding: 5px 9px 0;
|
|
border-bottom: 1px solid color-mix(in srgb, var(--color-border) 58%, transparent);
|
|
background: color-mix(in srgb, var(--color-background) 92%, #000 8%);
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
scrollbar-width: thin;
|
|
}
|
|
|
|
.office-tabs::-webkit-scrollbar {
|
|
height: 4px;
|
|
}
|
|
|
|
.office-tabs::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.office-tabs::-webkit-scrollbar-thumb {
|
|
background: color-mix(in srgb, var(--color-border) 76%, transparent);
|
|
border-radius: 999px;
|
|
}
|
|
|
|
.office-tab-shell {
|
|
flex: 0 1 220px;
|
|
position: relative;
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) var(--office-tab-close-size);
|
|
align-items: center;
|
|
gap: 3px;
|
|
min-width: 132px;
|
|
max-width: 260px;
|
|
height: var(--office-tab-height);
|
|
padding: 0 6px 0 10px;
|
|
border: 1px solid transparent;
|
|
border-radius: 7px 7px 0 0;
|
|
opacity: 0.72;
|
|
transition: border-color 0.16s ease, opacity 0.16s ease, background-color 0.16s ease;
|
|
}
|
|
|
|
.office-tab-shell:hover,
|
|
.office-tab-shell:focus-within {
|
|
opacity: 0.94;
|
|
border-color: color-mix(in srgb, var(--color-border) 78%, transparent);
|
|
}
|
|
|
|
.office-tab-shell.is-active {
|
|
z-index: 2;
|
|
margin-bottom: -1px;
|
|
opacity: 1;
|
|
border-color: color-mix(in srgb, var(--color-border) 68%, transparent);
|
|
background: color-mix(in srgb, var(--color-panel) 72%, transparent);
|
|
}
|
|
|
|
.office-tab,
|
|
.office-tab-close {
|
|
appearance: none;
|
|
border: 0;
|
|
background: transparent;
|
|
color: inherit;
|
|
font: inherit;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.office-tab {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: flex-start;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
padding: 0;
|
|
text-align: left;
|
|
}
|
|
|
|
.office-tab-icon {
|
|
flex: 0 0 auto;
|
|
color: color-mix(in srgb, var(--color-text) 72%, var(--color-primary) 28%);
|
|
font-size: 18px;
|
|
line-height: 1;
|
|
}
|
|
|
|
.office-tab-title {
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
font-size: 0.84rem;
|
|
font-weight: 650;
|
|
}
|
|
|
|
.office-tab-close {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: var(--office-tab-close-size);
|
|
min-width: var(--office-tab-close-size);
|
|
height: var(--office-tab-close-size);
|
|
min-height: var(--office-tab-close-size);
|
|
padding: 0;
|
|
border-radius: 6px;
|
|
color: color-mix(in srgb, var(--color-text) 52%, var(--color-primary) 48%);
|
|
opacity: 0.74;
|
|
}
|
|
|
|
.office-tab-close:hover,
|
|
.office-tab-close.confirming {
|
|
opacity: 1;
|
|
background: color-mix(in srgb, var(--color-background-hover) 70%, transparent);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
.office-tab-close:focus-visible,
|
|
.office-tab:focus-visible {
|
|
outline: 1px solid color-mix(in srgb, var(--color-primary) 70%, transparent);
|
|
outline-offset: 1px;
|
|
}
|
|
|
|
.office-tab-close .material-symbols-outlined {
|
|
font-size: 15px;
|
|
line-height: 1;
|
|
}
|
|
|
|
.office-toolbar-spacer {
|
|
flex: 1 1 auto;
|
|
min-width: 8px;
|
|
}
|
|
|
|
.office-button,
|
|
.office-icon-button,
|
|
.office-health-pill,
|
|
.office-create-tile,
|
|
.office-document-card {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 7px;
|
|
border: 1px solid color-mix(in srgb, var(--color-border) 64%, transparent);
|
|
border-radius: 7px;
|
|
background: color-mix(in srgb, var(--color-panel) 80%, transparent);
|
|
color: var(--color-text);
|
|
font: inherit;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.office-button {
|
|
min-height: 32px;
|
|
padding: 5px 9px;
|
|
font-size: 0.8rem;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.office-icon-button {
|
|
width: 32px;
|
|
height: 32px;
|
|
min-width: 32px;
|
|
padding: 0;
|
|
}
|
|
|
|
.office-health-pill {
|
|
min-height: 28px;
|
|
padding: 4px 8px;
|
|
cursor: default;
|
|
font-size: 0.75rem;
|
|
text-transform: capitalize;
|
|
white-space: nowrap;
|
|
color: var(--color-text-muted);
|
|
background: color-mix(in srgb, var(--color-panel) 64%, transparent);
|
|
}
|
|
|
|
.office-health-pill.is-healthy {
|
|
width: 28px;
|
|
min-width: 28px;
|
|
padding: 0;
|
|
gap: 0;
|
|
}
|
|
|
|
.office-health-dot {
|
|
width: 7px;
|
|
height: 7px;
|
|
border-radius: 999px;
|
|
background: color-mix(in srgb, var(--color-text-muted) 70%, transparent);
|
|
}
|
|
|
|
.office-health-pill.is-healthy .office-health-dot {
|
|
background: #31c48d;
|
|
}
|
|
|
|
.office-health-pill.is-installing .office-health-dot {
|
|
background: #f6ad55;
|
|
}
|
|
|
|
.office-health-pill.is-degraded .office-health-dot,
|
|
.office-health-pill.is-failed .office-health-dot {
|
|
background: #f05252;
|
|
}
|
|
|
|
.office-button:hover:not(:disabled),
|
|
.office-icon-button:hover:not(:disabled),
|
|
.office-create-tile:hover,
|
|
.office-document-card:hover {
|
|
background: color-mix(in srgb, var(--color-background-hover) 70%, transparent);
|
|
border-color: color-mix(in srgb, var(--color-primary) 28%, var(--color-border));
|
|
}
|
|
|
|
.office-button:disabled,
|
|
.office-icon-button:disabled {
|
|
cursor: not-allowed;
|
|
opacity: 0.42;
|
|
}
|
|
|
|
.office-button .material-symbols-outlined,
|
|
.office-icon-button .material-symbols-outlined {
|
|
font-size: 18px;
|
|
}
|
|
|
|
.office-status-line {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
min-height: 32px;
|
|
padding: 5px 10px;
|
|
border-bottom: 1px solid color-mix(in srgb, var(--color-border) 44%, transparent);
|
|
font-size: 0.82rem;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
.office-body {
|
|
position: relative;
|
|
display: flex;
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.office-start {
|
|
display: flex;
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
flex-direction: column;
|
|
gap: 22px;
|
|
padding: 18px;
|
|
overflow: auto;
|
|
}
|
|
|
|
.office-bootstrap {
|
|
display: flex;
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 16px;
|
|
padding: clamp(24px, 7cqi, 56px);
|
|
overflow: auto;
|
|
text-align: center;
|
|
}
|
|
|
|
.office-setup-mark {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 58px;
|
|
height: 58px;
|
|
border: 1px solid color-mix(in srgb, var(--color-primary) 28%, var(--color-border));
|
|
border-radius: 7px;
|
|
color: color-mix(in srgb, var(--color-primary) 70%, var(--color-text));
|
|
background: color-mix(in srgb, var(--color-panel) 78%, transparent);
|
|
}
|
|
|
|
.office-setup-mark.is-busy {
|
|
border-color: color-mix(in srgb, var(--color-primary) 42%, var(--color-border));
|
|
}
|
|
|
|
.office-setup-mark.is-alert {
|
|
border-color: color-mix(in srgb, #f05252 48%, var(--color-border));
|
|
color: #f05252;
|
|
}
|
|
|
|
.office-setup-mark .material-symbols-outlined {
|
|
font-size: 30px;
|
|
line-height: 1;
|
|
}
|
|
|
|
.office-setup-copy {
|
|
display: flex;
|
|
align-items: center;
|
|
min-width: 0;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
max-width: 460px;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
.office-setup-copy > span {
|
|
color: var(--color-text-muted);
|
|
font-size: 0.74rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.office-setup-copy > strong {
|
|
color: var(--color-text);
|
|
font-size: clamp(1.05rem, 4cqi, 1.35rem);
|
|
font-weight: 760;
|
|
}
|
|
|
|
.office-setup-copy > p {
|
|
margin: 0;
|
|
color: var(--color-text-muted);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.office-setup-progress {
|
|
position: relative;
|
|
width: min(260px, 72cqi);
|
|
height: 5px;
|
|
overflow: hidden;
|
|
border-radius: 999px;
|
|
background: color-mix(in srgb, var(--color-border) 45%, transparent);
|
|
}
|
|
|
|
.office-setup-progress > span {
|
|
position: absolute;
|
|
inset: 0 auto 0 0;
|
|
width: 42%;
|
|
border-radius: inherit;
|
|
background: color-mix(in srgb, var(--color-primary) 72%, var(--color-text) 28%);
|
|
animation: office-setup-progress 1.45s ease-in-out infinite;
|
|
}
|
|
|
|
.office-setup-progress.is-paused > span {
|
|
width: 100%;
|
|
opacity: 0.42;
|
|
animation: none;
|
|
}
|
|
|
|
.office-bootstrap-actions,
|
|
.office-template-grid {
|
|
display: flex;
|
|
justify-content: center;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
}
|
|
|
|
.office-dashboard-section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
width: 100%;
|
|
max-width: 1180px;
|
|
}
|
|
|
|
.office-dashboard-heading {
|
|
color: var(--color-text-muted);
|
|
font-size: 0.76rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.office-template-grid {
|
|
justify-content: flex-start;
|
|
}
|
|
|
|
.office-card-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), 1fr));
|
|
gap: 10px;
|
|
width: 100%;
|
|
}
|
|
|
|
.office-create-tile {
|
|
min-width: 132px;
|
|
min-height: 88px;
|
|
flex-direction: column;
|
|
padding: 12px;
|
|
font-weight: 650;
|
|
}
|
|
|
|
.office-create-tile .material-symbols-outlined {
|
|
font-size: 28px;
|
|
}
|
|
|
|
.office-document-card {
|
|
position: relative;
|
|
display: grid;
|
|
grid-template-rows: auto auto auto;
|
|
align-content: start;
|
|
justify-content: stretch;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
min-height: 196px;
|
|
padding: 10px;
|
|
text-align: left;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.office-document-card.is-open {
|
|
border-color: color-mix(in srgb, var(--color-primary) 36%, var(--color-border));
|
|
}
|
|
|
|
.office-card-badge {
|
|
position: absolute;
|
|
top: 8px;
|
|
right: 8px;
|
|
z-index: 2;
|
|
max-width: calc(100% - 16px);
|
|
overflow: hidden;
|
|
padding: 2px 6px;
|
|
border: 1px solid color-mix(in srgb, var(--color-primary) 42%, transparent);
|
|
border-radius: 999px;
|
|
background: color-mix(in srgb, var(--color-background) 82%, transparent);
|
|
color: var(--color-text);
|
|
font-size: 0.68rem;
|
|
font-weight: 700;
|
|
line-height: 1.2;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.office-card-preview {
|
|
position: relative;
|
|
display: grid;
|
|
align-items: stretch;
|
|
width: 100%;
|
|
aspect-ratio: 16 / 10;
|
|
min-height: 112px;
|
|
overflow: hidden;
|
|
border: 1px solid color-mix(in srgb, var(--color-border) 58%, transparent);
|
|
border-radius: 6px;
|
|
background: color-mix(in srgb, var(--color-background) 76%, #fff 4%);
|
|
}
|
|
|
|
.office-page-preview,
|
|
.office-sheet-preview,
|
|
.office-slide-preview,
|
|
.office-preview-fallback {
|
|
min-width: 0;
|
|
min-height: 0;
|
|
}
|
|
|
|
.office-page-preview {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 5px;
|
|
padding: 12px 13px;
|
|
background:
|
|
linear-gradient(to bottom, transparent 0, transparent 21px, color-mix(in srgb, var(--color-border) 30%, transparent) 22px),
|
|
color-mix(in srgb, var(--color-panel) 72%, transparent);
|
|
background-size: 100% 22px;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
.office-page-preview span,
|
|
.office-slide-line span,
|
|
.office-slide-line strong,
|
|
.office-sheet-row span {
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.office-page-preview span {
|
|
font-size: 0.7rem;
|
|
line-height: 1.25;
|
|
}
|
|
|
|
.office-sheet-preview {
|
|
min-width: 0;
|
|
padding: 8px;
|
|
background: color-mix(in srgb, var(--color-panel) 74%, transparent);
|
|
}
|
|
|
|
.office-sheet-row {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
min-height: 20px;
|
|
}
|
|
|
|
.office-sheet-row + .office-sheet-row {
|
|
border-top: 1px solid color-mix(in srgb, var(--color-border) 34%, transparent);
|
|
}
|
|
|
|
.office-sheet-row span {
|
|
padding: 4px 5px;
|
|
border-right: 1px solid color-mix(in srgb, var(--color-border) 34%, transparent);
|
|
color: var(--color-text-muted);
|
|
font-size: 0.66rem;
|
|
line-height: 1.1;
|
|
}
|
|
|
|
.office-sheet-row span:last-child {
|
|
border-right: 0;
|
|
}
|
|
|
|
.office-slide-preview {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
padding: 14px;
|
|
background:
|
|
linear-gradient(135deg, color-mix(in srgb, var(--color-panel) 80%, transparent), color-mix(in srgb, var(--color-background) 84%, var(--color-primary) 10%));
|
|
}
|
|
|
|
.office-slide-line {
|
|
display: flex;
|
|
min-width: 0;
|
|
flex-direction: column;
|
|
gap: 3px;
|
|
}
|
|
|
|
.office-slide-line strong {
|
|
color: var(--color-text);
|
|
font-size: 0.78rem;
|
|
font-weight: 760;
|
|
line-height: 1.15;
|
|
}
|
|
|
|
.office-slide-line span {
|
|
color: var(--color-text-muted);
|
|
font-size: 0.68rem;
|
|
line-height: 1.15;
|
|
}
|
|
|
|
.office-preview-fallback {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: color-mix(in srgb, var(--color-primary) 64%, var(--color-text));
|
|
background: color-mix(in srgb, var(--color-panel) 76%, transparent);
|
|
}
|
|
|
|
.office-preview-fallback .material-symbols-outlined {
|
|
font-size: 36px;
|
|
}
|
|
|
|
.office-card-title {
|
|
display: block;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
color: var(--color-text);
|
|
font-size: 0.86rem;
|
|
font-weight: 720;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.office-document-card small {
|
|
display: block;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
color: var(--color-text-muted);
|
|
font-size: 0.7rem;
|
|
line-height: 1.2;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.office-frame-wrap {
|
|
display: flex;
|
|
position: absolute;
|
|
inset: 0;
|
|
flex: 1 1 auto;
|
|
width: 100%;
|
|
height: 100%;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
background: #fff;
|
|
}
|
|
|
|
.office-frame-wrap iframe {
|
|
flex: 1 1 auto;
|
|
width: 100%;
|
|
height: 100%;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
border: 0;
|
|
background: #fff;
|
|
}
|
|
|
|
.office-panel .spinning {
|
|
display: inline-block;
|
|
animation: office-spin 0.8s linear infinite;
|
|
}
|
|
|
|
@keyframes office-spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
@keyframes office-setup-progress {
|
|
0% { transform: translateX(-110%); }
|
|
55% { transform: translateX(85%); }
|
|
100% { transform: translateX(250%); }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.office-panel .spinning,
|
|
.office-setup-progress > span {
|
|
animation: none;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 520px) {
|
|
.office-button span:last-child {
|
|
display: none;
|
|
}
|
|
.office-health-pill span:last-child {
|
|
display: none;
|
|
}
|
|
.office-tab-shell {
|
|
flex-basis: 152px;
|
|
min-width: 116px;
|
|
}
|
|
.office-create-tile {
|
|
min-width: 104px;
|
|
}
|
|
}
|
|
|
|
@container (max-width: 560px) {
|
|
.office-button span:last-child {
|
|
display: none;
|
|
}
|
|
.office-health-pill span:last-child {
|
|
display: none;
|
|
}
|
|
.office-tab-shell {
|
|
flex-basis: 152px;
|
|
min-width: 116px;
|
|
}
|
|
.office-create-tile {
|
|
min-width: 104px;
|
|
}
|
|
}
|
|
</style>
|
|
</body>
|
|
</html>
|