change ui
This commit is contained in:
48
src/App.vue
48
src/App.vue
@@ -49,6 +49,7 @@ const loading = ref(true);
|
|||||||
const error = ref("");
|
const error = ref("");
|
||||||
const response = ref<ScanResponse>({ browsers: [] });
|
const response = ref<ScanResponse>({ browsers: [] });
|
||||||
const selectedBrowserId = ref("");
|
const selectedBrowserId = ref("");
|
||||||
|
const activeSection = ref<"profiles" | "extensions" | "bookmarks">("profiles");
|
||||||
|
|
||||||
const browsers = computed(() => response.value.browsers);
|
const browsers = computed(() => response.value.browsers);
|
||||||
const currentBrowser = computed(() =>
|
const currentBrowser = computed(() =>
|
||||||
@@ -109,6 +110,13 @@ function domainFromUrl(url: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sectionCount(section: "profiles" | "extensions" | "bookmarks") {
|
||||||
|
if (!currentBrowser.value) return 0;
|
||||||
|
if (section === "profiles") return currentBrowser.value.profiles.length;
|
||||||
|
if (section === "extensions") return currentBrowser.value.extensions.length;
|
||||||
|
return currentBrowser.value.bookmarks.length;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
void scanBrowsers();
|
void scanBrowsers();
|
||||||
});
|
});
|
||||||
@@ -193,7 +201,37 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="content-section">
|
<section class="section-tabs">
|
||||||
|
<button
|
||||||
|
class="section-tab"
|
||||||
|
:class="{ active: activeSection === 'profiles' }"
|
||||||
|
type="button"
|
||||||
|
@click="activeSection = 'profiles'"
|
||||||
|
>
|
||||||
|
<span>Profiles</span>
|
||||||
|
<span class="count-pill">{{ sectionCount("profiles") }}</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="section-tab"
|
||||||
|
:class="{ active: activeSection === 'extensions' }"
|
||||||
|
type="button"
|
||||||
|
@click="activeSection = 'extensions'"
|
||||||
|
>
|
||||||
|
<span>Extensions</span>
|
||||||
|
<span class="count-pill">{{ sectionCount("extensions") }}</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="section-tab"
|
||||||
|
:class="{ active: activeSection === 'bookmarks' }"
|
||||||
|
type="button"
|
||||||
|
@click="activeSection = 'bookmarks'"
|
||||||
|
>
|
||||||
|
<span>Bookmarks</span>
|
||||||
|
<span class="count-pill">{{ sectionCount("bookmarks") }}</span>
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section v-if="activeSection === 'profiles'" class="content-section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Profiles</p>
|
<p class="eyebrow">Profiles</p>
|
||||||
@@ -202,7 +240,7 @@ onMounted(() => {
|
|||||||
<span class="count-pill">{{ currentBrowser.profiles.length }}</span>
|
<span class="count-pill">{{ currentBrowser.profiles.length }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="currentBrowser.profiles.length" class="profile-grid">
|
<div v-if="currentBrowser.profiles.length" class="stack-list">
|
||||||
<article
|
<article
|
||||||
v-for="profile in currentBrowser.profiles"
|
v-for="profile in currentBrowser.profiles"
|
||||||
:key="profile.id"
|
:key="profile.id"
|
||||||
@@ -231,7 +269,7 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="content-section">
|
<section v-else-if="activeSection === 'extensions'" class="content-section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Extensions</p>
|
<p class="eyebrow">Extensions</p>
|
||||||
@@ -240,7 +278,7 @@ onMounted(() => {
|
|||||||
<span class="count-pill">{{ currentBrowser.extensions.length }}</span>
|
<span class="count-pill">{{ currentBrowser.extensions.length }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="currentBrowser.extensions.length" class="extension-grid">
|
<div v-if="currentBrowser.extensions.length" class="stack-list">
|
||||||
<article
|
<article
|
||||||
v-for="extension in currentBrowser.extensions"
|
v-for="extension in currentBrowser.extensions"
|
||||||
:key="extension.id"
|
:key="extension.id"
|
||||||
@@ -279,7 +317,7 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="content-section">
|
<section v-else class="content-section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Bookmarks</p>
|
<p class="eyebrow">Bookmarks</p>
|
||||||
|
|||||||
@@ -258,6 +258,7 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hero-card,
|
.hero-card,
|
||||||
|
.section-tabs,
|
||||||
.content-section,
|
.content-section,
|
||||||
.state-panel {
|
.state-panel {
|
||||||
border: 1px solid var(--panel-border);
|
border: 1px solid var(--panel-border);
|
||||||
@@ -312,6 +313,42 @@ button {
|
|||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section-tabs {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-tab {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1;
|
||||||
|
padding: 14px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
color: var(--muted);
|
||||||
|
background: rgba(255, 255, 255, 0.58);
|
||||||
|
cursor: pointer;
|
||||||
|
transition:
|
||||||
|
background 160ms ease,
|
||||||
|
color 160ms ease,
|
||||||
|
transform 160ms ease,
|
||||||
|
box-shadow 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-tab:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-tab.active {
|
||||||
|
color: var(--text);
|
||||||
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.96), rgba(232, 240, 255, 0.92));
|
||||||
|
box-shadow: 0 12px 24px rgba(15, 23, 42, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
.section-heading {
|
.section-heading {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -346,11 +383,11 @@ button {
|
|||||||
color: var(--badge-text);
|
color: var(--badge-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-grid,
|
.stack-list,
|
||||||
.extension-grid {
|
.bookmark-list {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
flex-direction: column;
|
||||||
gap: 16px;
|
gap: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-card,
|
.profile-card,
|
||||||
@@ -437,12 +474,6 @@ button {
|
|||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmark-list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-panel,
|
.state-panel,
|
||||||
.empty-card {
|
.empty-card {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -484,11 +515,6 @@ button {
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-grid,
|
|
||||||
.extension-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-card,
|
.profile-card,
|
||||||
.extension-card,
|
.extension-card,
|
||||||
.bookmark-card {
|
.bookmark-card {
|
||||||
|
|||||||
Reference in New Issue
Block a user