Skip to content

Commit 05d4f92

Browse files
committed
ui(commons): Minor responsiveness changes
- Use UTabs over custom tabs component in model view pages - Change layout of tabs to fit on mobile phones - Swap positions of the actions/stats in the model view action bar to match conventional UX - Hide the orientation selector for model lists on mobile, since it is basically a no-op. - Copy changes to reduce text - Hide like button text on mobile - Other minor changes, mostly only visible on phones
1 parent a56b55e commit 05d4f92

24 files changed

Lines changed: 165 additions & 124 deletions

apps/modeling-commons-frontend/app/app.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ export default defineAppConfig({
262262
tabs: {
263263
slots: {
264264
content: "pt-4",
265+
trigger: "grow flex-col lg:flex-row gap-1 py-2",
266+
label: "text-[10px]/3 lg:text-sm",
265267
},
266268
},
267269

apps/modeling-commons-frontend/app/components/auth/ReclaimAccount.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
variant="subtle"
44
icon="i-lucide-alert-triangle"
55
color="warning"
6-
title="Do you have an old account?"
6+
title="Got an old account?"
77
class="text-left"
88
:actions="[
99
{

apps/modeling-commons-frontend/app/components/layout/ClientNavbar.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Navbar
33
id="main-navbar"
44
ref="navbar"
5-
class="bg-background! py-4! lg:px-[2.5vw]! shadow-none! max-w-500 mx-auto flex-1 w-full"
5+
class="bg-background! py-4! lg:px-[2.5vw]! shadow-none! mx-auto flex-1 w-full"
66
:brand="brand"
77
brand-href="/"
88
:brand-attrs="brandAttrs"
@@ -205,7 +205,7 @@ const isMobileScreen = ref(false);
205205
const navbarRef = useTemplateRef<InstanceType<typeof _Navbar>>("navbar");
206206
207207
const brand = computed(() => WebsiteLogo);
208-
const brandAttrs = computed(() => ({ class: "w-50! lg:w-60! lg:ml-0 lg:[&>svg]:w-full!" }));
208+
const brandAttrs = computed(() => ({ class: "w-40! lg:w-60! lg:ml-0 lg:[&>svg]:w-full!" }));
209209
210210
const handleMediaQueryChange = (): void => {
211211
if (import.meta.client) {
Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
<template>
2-
<UButton
3-
:variant="active ? 'solid' : 'outline'"
4-
:color="active ? 'primary' : 'neutral'"
5-
size="sm"
6-
icon="i-lucide-thumbs-up"
7-
:disabled="busy"
8-
@click="$emit('toggle')"
9-
>
10-
{{ active ? "Liked" : "Like" }}
11-
</UButton>
2+
<div class="contents">
3+
<UButton v-bind="buttonProps" data-show-from="sm" @click="$emit('toggle')">
4+
<span>{{ buttonText }}</span>
5+
</UButton>
6+
<UButton v-bind="buttonProps" data-hide-from="sm" @click="$emit('toggle')" />
7+
</div>
128
</template>
139

1410
<script setup lang="ts">
15-
defineProps<{
11+
import type { ButtonProps } from "#ui/types";
12+
13+
const props = defineProps<{
1614
active: boolean;
1715
busy?: boolean;
1816
}>();
1917
2018
defineEmits<{
2119
toggle: [];
2220
}>();
21+
22+
const buttonText = computed(() => (props.active ? "Liked" : "Like"));
23+
const buttonProps = computed<ButtonProps>(() => ({
24+
variant: props.active ? "solid" : "outline",
25+
color: props.active ? "primary" : "neutral",
26+
size: "sm",
27+
icon: "i-lucide-thumbs-up",
28+
disabled: props.busy,
29+
title: buttonText.value,
30+
}));
2331
</script>

apps/modeling-commons-frontend/app/components/model/detail/ModelBottomBar.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<template>
22
<section class="flex items-center justify-between flex-wrap gap-4">
3-
<ModelStats :likes="likes" :downloads="downloads" :views="views" :runs="runs" />
4-
53
<div class="flex items-center gap-3">
64
<ModelLike :active="likedByMe" :busy="busy" @toggle="$emit('toggleLike')" />
75
<UButton variant="outline" size="sm" icon="i-lucide-share-2" square @click="$emit('share')" />
86
</div>
7+
8+
<ModelStats :likes="likes" :downloads="downloads" :views="views" :runs="runs" />
99
</section>
1010
</template>
1111

apps/modeling-commons-frontend/app/components/model/detail/ModelDetail.vue

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -71,45 +71,38 @@
7171
@share="handleShare"
7272
/>
7373

74-
<section class="rounded-xl border border-default overflow-hidden">
75-
<div class="flex border-b border-default">
76-
<button
77-
v-for="tab in tabs"
78-
:key="tab.key"
79-
class="flex-1 py-3 text-sm font-medium text-center transition-colors border-b-2 -mb-px"
80-
:class="
81-
activeTab === tab.key
82-
? 'border-primary-600 text-highlighted'
83-
: 'border-transparent text-muted hover:text-toned'
84-
"
85-
@click="onTabChange(tab.key)"
86-
>
87-
{{ tab.label }}
88-
</button>
89-
</div>
90-
<ModelDiscussionTab v-if="activeTab === 'discussion'" />
91-
92-
<ModelFilesTab
93-
v-else-if="activeTab === 'files'"
94-
:files="attachedFiles"
95-
:status="filesStatus"
96-
:viewed-version-number="card.latestVersion?.versionNumber"
97-
@download="handleFileDownload"
98-
/>
99-
100-
<ModelVersionsTab
101-
v-else-if="activeTab === 'versions'"
102-
:model-id="card.model.id"
103-
:versions="versions ?? []"
104-
:pending="versionsStatus === 'pending'"
105-
/>
106-
107-
<ModelFamilyTab
108-
v-else-if="activeTab === 'family'"
109-
:parent="family?.parent ?? null"
110-
:children="family?.children ?? []"
111-
/>
112-
</section>
74+
<UTabs
75+
v-model="activeTab"
76+
:items="tabs"
77+
color="primary"
78+
:ui="{ root: 'w-full' }"
79+
@update:model-value="idx => onTabChange(idx)"
80+
>
81+
<template #discussion>
82+
<ModelDiscussionTab />
83+
</template>
84+
<template #files>
85+
<ModelFilesTab
86+
:files="attachedFiles"
87+
:status="filesStatus"
88+
:viewed-version-number="card.latestVersion?.versionNumber"
89+
@download="handleFileDownload"
90+
/>
91+
</template>
92+
<template #versions>
93+
<ModelVersionsTab
94+
:model-id="card.model.id"
95+
:versions="versions ?? []"
96+
:pending="versionsStatus === 'pending'"
97+
/>
98+
</template>
99+
<template #family>
100+
<ModelFamilyTab
101+
:parent="family?.parent ?? null"
102+
:children="family?.children ?? []"
103+
/>
104+
</template>
105+
</UTabs>
113106
</UCard>
114107
</template>
115108

@@ -120,7 +113,7 @@ const props = defineProps<{ card: ModelCard; permissions: UserModelPermissions }
120113
121114
type TabKey = "discussion" | "files" | "versions" | "family";
122115
123-
const activeTab = ref<TabKey>("discussion");
116+
const activeTab = ref<string>('0');
124117
125118
const user = useUser();
126119
const modelId = computed(() => props.card?.model.id ?? "");
@@ -165,11 +158,16 @@ const attachedFiles = computed<AttachedFile[]>(() => {
165158
});
166159
});
167160
168-
const tabs = computed(() => [
169-
{ key: "discussion" as const, label: "Discussion" },
170-
{ key: "files" as const, label: "Files" },
171-
{ key: "versions" as const, label: `Versions (${props.card?.counts.versions ?? 0})` },
172-
{ key: "family" as const, label: "Family" },
161+
162+
const versionTabLabel = computed(() => {
163+
const count = props.card.model.latestVersionNumber ?? 0;
164+
return count > 1 ? `Versions (${count})` : "Versions";
165+
});
166+
const tabs = computed<Array<({ label: string; icon: string; slot: TabKey })>>(() => [
167+
{ label: "Discussion", icon: "i-lucide-message-square", slot: "discussion" },
168+
{ label: "Files", icon: "i-lucide-file-text", slot: "files" },
169+
{ label: versionTabLabel.value, icon: "lucide:git-branch", slot: "versions" },
170+
{ label: "Family", icon: "i-lucide-users", slot: "family" },
173171
]);
174172
175173
const downloadUrl = computed(() => {
@@ -186,8 +184,8 @@ const previewImageUrl = computed(() => {
186184
return appendWindowProtocol(props.card.previewImageUrl);
187185
});
188186
189-
function onTabChange(key: TabKey) {
190-
activeTab.value = key;
187+
function onTabChange(idx: string | number) {
188+
const key = tabs.value[Number(idx)]?.slot;
191189
if (key === "family" && familyStatus.value === "idle") {
192190
void loadFamily();
193191
}

apps/modeling-commons-frontend/app/components/model/detail/ModelDiscussionTab.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ describe("ModelDiscussionTab", () => {
1616

1717
it("renders a filter selector", async () => {
1818
const wrapper = await mountSuspended(ModelDiscussionTab);
19-
expect(wrapper.text()).toContain("Filter Comments By");
19+
expect(wrapper.text()).toContain("Filter by");
2020
});
2121
});

apps/modeling-commons-frontend/app/components/model/detail/ModelDiscussionTab.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
<template>
2-
<div class="p-6">
2+
<div class="p-2 lg:p-6">
33
<div class="flex items-center justify-between mb-6">
44
<h3 class="text-lg font-semibold text-highlighted">Discussion</h3>
55
<div class="flex items-center gap-2 text-sm">
6-
<span class="text-muted">Filter Comments By</span>
7-
<USelectMenu :items="filterOptions" :model-value="filterOptions[0]" class="w-32" />
6+
<span class="text-muted">Filter by</span>
7+
<USelectMenu :items="filterOptions" :model-value="filterOptions[0]" class="lg:w-32" size="sm" />
88
</div>
99
</div>
1010

1111
<div class="flex flex-col items-center justify-center py-12 text-dimmed">
1212
<UIcon name="i-lucide-message-circle" class="size-12 mb-3" />
1313
<p class="text-sm font-medium">Discussions are coming soon!</p>
14-
<p class="text-xs mt-1">In the meantime, if you have any questions or feedback about this model, please reach out to the author.</p>
14+
<p class="text-xs mt-1 text-center text-pretty">In the meantime, if you have any questions or feedback about this model, please reach out to the author.</p>
1515
</div>
1616
</div>
1717
</template>

apps/modeling-commons-frontend/app/components/model/detail/ModelFamilyTab.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="p-6">
2+
<div class="p-2 lg:p-6">
33
<div class="mb-4">
44
<h3 class="text-lg font-semibold text-highlighted">Model Family</h3>
55
<p class="text-xs text-dimmed mt-1">

apps/modeling-commons-frontend/app/components/model/detail/ModelFilesTab.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="p-6">
2+
<div class="p-2 lg:p-6">
33
<div class="flex items-center justify-between mb-2">
44
<h3 class="text-lg font-semibold text-highlighted">Attached Files</h3>
55
<UButton v-if="editable" variant="outline" icon="i-lucide-plus" size="sm">

0 commit comments

Comments
 (0)