optimize ui
This commit is contained in:
241
src/App.vue
241
src/App.vue
@@ -157,9 +157,6 @@ onMounted(() => {
|
||||
<h1>Browser Assistant</h1>
|
||||
<p>Local Chromium profile manager</p>
|
||||
</div>
|
||||
<button class="refresh-button" type="button" @click="scanBrowsers">
|
||||
{{ loading ? "Scanning..." : "Refresh" }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="browsers.length" class="browser-nav">
|
||||
@@ -182,6 +179,10 @@ onMounted(() => {
|
||||
<div v-else class="sidebar-empty">
|
||||
<p>No supported Chromium browser data was found yet.</p>
|
||||
</div>
|
||||
|
||||
<button class="refresh-button sidebar-refresh" type="button" @click="scanBrowsers">
|
||||
{{ loading ? "Scanning..." : "Refresh" }}
|
||||
</button>
|
||||
</aside>
|
||||
|
||||
<main class="content-panel">
|
||||
@@ -228,130 +229,132 @@ onMounted(() => {
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<section v-if="activeSection === 'profiles'" class="content-section">
|
||||
<div v-if="currentBrowser.profiles.length" class="stack-list">
|
||||
<article
|
||||
v-for="profile in currentBrowser.profiles"
|
||||
:key="profile.id"
|
||||
class="profile-card"
|
||||
>
|
||||
<div class="profile-avatar">
|
||||
<img
|
||||
v-if="profile.avatarDataUrl"
|
||||
:src="profile.avatarDataUrl"
|
||||
:alt="`${profile.name} avatar`"
|
||||
/>
|
||||
<span v-else>{{ profile.avatarLabel }}</span>
|
||||
</div>
|
||||
<div class="profile-body">
|
||||
<div class="profile-topline">
|
||||
<h4>{{ profile.name }}</h4>
|
||||
<span class="badge neutral">{{ profile.id }}</span>
|
||||
<div class="content-scroll-area">
|
||||
<section v-if="activeSection === 'profiles'" class="content-section">
|
||||
<div v-if="currentBrowser.profiles.length" class="stack-list">
|
||||
<article
|
||||
v-for="profile in currentBrowser.profiles"
|
||||
:key="profile.id"
|
||||
class="profile-card"
|
||||
>
|
||||
<div class="profile-avatar">
|
||||
<img
|
||||
v-if="profile.avatarDataUrl"
|
||||
:src="profile.avatarDataUrl"
|
||||
:alt="`${profile.name} avatar`"
|
||||
/>
|
||||
<span v-else>{{ profile.avatarLabel }}</span>
|
||||
</div>
|
||||
<p class="profile-email">{{ profile.email || "No email found" }}</p>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div v-else class="empty-card">
|
||||
<p>No profile directories were found for this browser.</p>
|
||||
</div>
|
||||
</section>
|
||||
<div class="profile-body">
|
||||
<div class="profile-topline">
|
||||
<h4>{{ profile.name }}</h4>
|
||||
<span class="badge neutral">{{ profile.id }}</span>
|
||||
</div>
|
||||
<p class="profile-email">{{ profile.email || "No email found" }}</p>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div v-else class="empty-card">
|
||||
<p>No profile directories were found for this browser.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-else-if="activeSection === 'extensions'" class="content-section">
|
||||
<div v-if="currentBrowser.extensions.length" class="stack-list">
|
||||
<article
|
||||
v-for="extension in currentBrowser.extensions"
|
||||
:key="extension.id"
|
||||
class="extension-card"
|
||||
>
|
||||
<div class="extension-icon">
|
||||
<img
|
||||
v-if="extension.iconDataUrl"
|
||||
:src="extension.iconDataUrl"
|
||||
:alt="`${extension.name} icon`"
|
||||
/>
|
||||
<span v-else>{{ extensionMonogram(extension.name) }}</span>
|
||||
</div>
|
||||
<div class="extension-body">
|
||||
<div class="extension-topline">
|
||||
<h4>{{ extension.name }}</h4>
|
||||
<span v-if="extension.version" class="badge neutral">
|
||||
v{{ extension.version }}
|
||||
</span>
|
||||
<section v-else-if="activeSection === 'extensions'" class="content-section">
|
||||
<div v-if="currentBrowser.extensions.length" class="stack-list">
|
||||
<article
|
||||
v-for="extension in currentBrowser.extensions"
|
||||
:key="extension.id"
|
||||
class="extension-card"
|
||||
>
|
||||
<div class="extension-icon">
|
||||
<img
|
||||
v-if="extension.iconDataUrl"
|
||||
:src="extension.iconDataUrl"
|
||||
:alt="`${extension.name} icon`"
|
||||
/>
|
||||
<span v-else>{{ extensionMonogram(extension.name) }}</span>
|
||||
</div>
|
||||
<p class="meta-line">{{ extension.id }}</p>
|
||||
<div class="source-disclosure">
|
||||
<button
|
||||
class="disclosure-button"
|
||||
type="button"
|
||||
@click="toggleExtensionProfiles(extension.id)"
|
||||
>
|
||||
<span>Profiles</span>
|
||||
<span class="badge neutral">{{ extension.profileIds.length }}</span>
|
||||
</button>
|
||||
<div
|
||||
v-if="extensionProfilesExpanded(extension.id)"
|
||||
class="disclosure-panel"
|
||||
>
|
||||
<span
|
||||
v-for="profileId in extension.profileIds"
|
||||
:key="`${extension.id}-${profileId}`"
|
||||
class="badge"
|
||||
>
|
||||
{{ profileId }}
|
||||
<div class="extension-body">
|
||||
<div class="extension-topline">
|
||||
<h4>{{ extension.name }}</h4>
|
||||
<span v-if="extension.version" class="badge neutral">
|
||||
v{{ extension.version }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div v-else class="empty-card">
|
||||
<p>No extensions were discovered for this browser.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-else class="content-section">
|
||||
<div v-if="currentBrowser.bookmarks.length" class="bookmark-list">
|
||||
<article
|
||||
v-for="bookmark in currentBrowser.bookmarks"
|
||||
:key="bookmark.url"
|
||||
class="bookmark-card"
|
||||
>
|
||||
<div class="bookmark-body">
|
||||
<div class="bookmark-topline">
|
||||
<h4>{{ bookmark.title }}</h4>
|
||||
<span class="badge neutral">{{ domainFromUrl(bookmark.url) }}</span>
|
||||
</div>
|
||||
<p class="bookmark-url" :title="bookmark.url">{{ bookmark.url }}</p>
|
||||
<div class="source-disclosure">
|
||||
<button
|
||||
class="disclosure-button"
|
||||
type="button"
|
||||
@click="toggleBookmarkProfiles(bookmark.url)"
|
||||
>
|
||||
<span>Profiles</span>
|
||||
<span class="badge neutral">{{ bookmark.profileIds.length }}</span>
|
||||
</button>
|
||||
<div
|
||||
v-if="bookmarkProfilesExpanded(bookmark.url)"
|
||||
class="disclosure-panel"
|
||||
>
|
||||
<span
|
||||
v-for="profileId in bookmark.profileIds"
|
||||
:key="`${bookmark.url}-${profileId}`"
|
||||
class="badge"
|
||||
<p class="meta-line">{{ extension.id }}</p>
|
||||
<div class="source-disclosure">
|
||||
<button
|
||||
class="disclosure-button"
|
||||
type="button"
|
||||
@click="toggleExtensionProfiles(extension.id)"
|
||||
>
|
||||
{{ profileId }}
|
||||
</span>
|
||||
<span>Profiles</span>
|
||||
<span class="badge neutral">{{ extension.profileIds.length }}</span>
|
||||
</button>
|
||||
<div
|
||||
v-if="extensionProfilesExpanded(extension.id)"
|
||||
class="disclosure-panel"
|
||||
>
|
||||
<span
|
||||
v-for="profileId in extension.profileIds"
|
||||
:key="`${extension.id}-${profileId}`"
|
||||
class="badge"
|
||||
>
|
||||
{{ profileId }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div v-else class="empty-card">
|
||||
<p>No bookmarks were discovered for this browser.</p>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
<div v-else class="empty-card">
|
||||
<p>No extensions were discovered for this browser.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-else class="content-section">
|
||||
<div v-if="currentBrowser.bookmarks.length" class="bookmark-list">
|
||||
<article
|
||||
v-for="bookmark in currentBrowser.bookmarks"
|
||||
:key="bookmark.url"
|
||||
class="bookmark-card"
|
||||
>
|
||||
<div class="bookmark-body">
|
||||
<div class="bookmark-topline">
|
||||
<h4>{{ bookmark.title }}</h4>
|
||||
<span class="badge neutral">{{ domainFromUrl(bookmark.url) }}</span>
|
||||
</div>
|
||||
<p class="bookmark-url" :title="bookmark.url">{{ bookmark.url }}</p>
|
||||
<div class="source-disclosure">
|
||||
<button
|
||||
class="disclosure-button"
|
||||
type="button"
|
||||
@click="toggleBookmarkProfiles(bookmark.url)"
|
||||
>
|
||||
<span>Profiles</span>
|
||||
<span class="badge neutral">{{ bookmark.profileIds.length }}</span>
|
||||
</button>
|
||||
<div
|
||||
v-if="bookmarkProfilesExpanded(bookmark.url)"
|
||||
class="disclosure-panel"
|
||||
>
|
||||
<span
|
||||
v-for="profileId in bookmark.profileIds"
|
||||
:key="`${bookmark.url}-${profileId}`"
|
||||
class="badge"
|
||||
>
|
||||
{{ profileId }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div v-else class="empty-card">
|
||||
<p>No bookmarks were discovered for this browser.</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<section v-else class="state-panel">
|
||||
|
||||
@@ -60,9 +60,10 @@ button {
|
||||
.app-shell {
|
||||
display: grid;
|
||||
grid-template-columns: 320px minmax(0, 1fr);
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
padding: 14px;
|
||||
gap: 14px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar,
|
||||
@@ -76,6 +77,7 @@ button {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 20px 16px;
|
||||
min-height: 0;
|
||||
border: 1px solid var(--panel-border);
|
||||
border-radius: 22px;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(248, 250, 252, 0.7));
|
||||
@@ -151,6 +153,9 @@ button {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.browser-nav-item {
|
||||
@@ -263,8 +268,12 @@ button {
|
||||
}
|
||||
|
||||
.content-panel {
|
||||
padding: 4px 0 4px 0;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
min-height: 0;
|
||||
padding: 4px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.section-tabs,
|
||||
@@ -277,7 +286,6 @@ button {
|
||||
}
|
||||
|
||||
.content-section {
|
||||
margin-top: 10px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
@@ -286,6 +294,13 @@ button {
|
||||
gap: 10px;
|
||||
margin-top: 0;
|
||||
padding: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.content-scroll-area {
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.section-tab {
|
||||
@@ -472,6 +487,11 @@ button {
|
||||
padding: 28px;
|
||||
}
|
||||
|
||||
.sidebar-refresh {
|
||||
margin-top: auto;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.state-panel.error {
|
||||
background: linear-gradient(180deg, rgba(254, 242, 242, 0.92), rgba(255, 255, 255, 0.86));
|
||||
}
|
||||
@@ -479,11 +499,20 @@ button {
|
||||
@media (max-width: 1180px) {
|
||||
.app-shell {
|
||||
grid-template-columns: 1fr;
|
||||
height: auto;
|
||||
min-height: 100vh;
|
||||
padding: 12px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.content-panel {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.browser-nav,
|
||||
.content-scroll-area {
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user