mobile support improvements

This commit is contained in:
Kohaku-Blueleaf
2025-10-05 00:45:16 +08:00
parent 8d2a22c707
commit 2cee3ce004
11 changed files with 184 additions and 53 deletions

View File

@@ -6,7 +6,8 @@
>
<div class="flex items-center gap-2 min-w-0 flex-1">
<el-tag size="small" type="info">{{ language }}</el-tag>
<span class="text-xs sm:text-sm text-gray-600 dark:text-gray-400 whitespace-nowrap"
<span
class="text-xs sm:text-sm text-gray-600 dark:text-gray-400 whitespace-nowrap"
>{{ lineCount }} lines</span
>
</div>

View File

@@ -4,7 +4,9 @@
class="bg-gray-100 dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 mt-4 transition-colors"
>
<div class="container-main py-8">
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
<div
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8"
>
<div>
<h3 class="font-semibold mb-3">KohakuHub</h3>
<p class="text-sm text-gray-600 dark:text-gray-400">

View File

@@ -1,7 +1,8 @@
<!-- src/components/layout/TheHeader.vue -->
<template>
<header
class="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 sticky top-0 z-50 transition-colors"
class="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 sticky top-0 transition-colors"
style="z-index: 1000"
>
<div class="container-main flex items-center justify-between h-12 md:h-16">
<!-- Logo -->
@@ -109,7 +110,10 @@
</div>
<!-- Mobile Menu Button -->
<div class="flex md:hidden items-center gap-2">
<div
class="flex md:hidden items-center gap-2"
style="position: relative; z-index: 1001"
>
<!-- Dark Mode Toggle - Mobile -->
<el-button
@click="themeStore.toggle()"
@@ -121,13 +125,12 @@
<div v-if="themeStore.isDark" class="i-carbon-moon text-lg" />
<div v-else class="i-carbon-asleep text-lg" />
</el-button>
<!-- Hamburger Menu -->
<el-button
@click="mobileMenuOpen = !mobileMenuOpen"
circle
text
class="!text-gray-700 dark:!text-gray-300"
class="!text-gray-700 dark:!text-gray-300 !min-w-10 !min-h-10"
>
<div class="i-carbon-menu text-2xl" />
</el-button>
@@ -140,10 +143,11 @@
direction="rtl"
size="280px"
:show-close="false"
:z-index="9999"
>
<div class="flex flex-col h-full">
<!-- Navigation Links -->
<nav class="flex flex-col gap-1 mb-6">
<nav class="flex flex-col gap-1 mb-6 px-4 pt-4">
<RouterLink
to="/models"
@click="mobileMenuOpen = false"
@@ -177,17 +181,22 @@
</nav>
<!-- Divider -->
<div class="border-t border-gray-200 dark:border-gray-700 mb-4"></div>
<div
class="border-t border-gray-200 dark:border-gray-700 mb-4 mx-4"
></div>
<!-- User Menu -->
<template v-if="isAuthenticated">
<!-- Create New Options -->
<div class="mb-4">
<div class="mb-4 px-4">
<div class="px-4 text-xs text-gray-500 dark:text-gray-400 mb-2">
CREATE NEW
</div>
<div
@click="createNew('model'); mobileMenuOpen = false"
@click="
createNew('model');
mobileMenuOpen = false;
"
class="px-4 py-3 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer transition-colors"
>
<div class="flex items-center gap-2">
@@ -196,7 +205,10 @@
</div>
</div>
<div
@click="createNew('dataset'); mobileMenuOpen = false"
@click="
createNew('dataset');
mobileMenuOpen = false;
"
class="px-4 py-3 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer transition-colors"
>
<div class="flex items-center gap-2">
@@ -205,7 +217,10 @@
</div>
</div>
<div
@click="createNew('space'); mobileMenuOpen = false"
@click="
createNew('space');
mobileMenuOpen = false;
"
class="px-4 py-3 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer transition-colors"
>
<div class="flex items-center gap-2">
@@ -216,15 +231,20 @@
</div>
<!-- Divider -->
<div class="border-t border-gray-200 dark:border-gray-700 mb-4"></div>
<div
class="border-t border-gray-200 dark:border-gray-700 mb-4 mx-4"
></div>
<!-- User Options -->
<div>
<div class="px-4">
<div class="px-4 text-xs text-gray-500 dark:text-gray-400 mb-2">
{{ username }}
</div>
<div
@click="$router.push(`/${username}`); mobileMenuOpen = false"
@click="
$router.push(`/${username}`);
mobileMenuOpen = false;
"
class="px-4 py-3 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer transition-colors"
>
<div class="flex items-center gap-2">
@@ -233,7 +253,10 @@
</div>
</div>
<div
@click="$router.push('/settings'); mobileMenuOpen = false"
@click="
$router.push('/settings');
mobileMenuOpen = false;
"
class="px-4 py-3 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer transition-colors"
>
<div class="flex items-center gap-2">
@@ -242,7 +265,10 @@
</div>
</div>
<div
@click="handleLogout(); mobileMenuOpen = false"
@click="
handleLogout();
mobileMenuOpen = false;
"
class="px-4 py-3 text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer transition-colors"
>
<div class="flex items-center gap-2">
@@ -255,17 +281,26 @@
<!-- Not authenticated -->
<template v-else>
<div class="flex flex-col gap-2 px-4">
<div class="flex flex-col gap-1 px-4">
<el-button
@click="$router.push('/login'); mobileMenuOpen = false"
text
@click="
$router.push('/login');
mobileMenuOpen = false;
"
size="large"
class="w-full"
>
Login
</el-button>
<div class="w-0 h-0 p-0 m-0"></div>
<!-- Avoid el-button+el-button spacing -->
<el-button
type="primary"
@click="$router.push('/register'); mobileMenuOpen = false"
@click="
$router.push('/register');
mobileMenuOpen = false;
"
size="large"
class="w-full"
>
Sign Up
@@ -306,3 +341,12 @@ async function handleLogout() {
}
}
</script>
<style scoped>
/* Ensure mobile menu buttons have proper touch targets */
@media (max-width: 768px) {
:deep(.el-button) {
min-height: 44px;
}
}
</style>

View File

@@ -30,7 +30,10 @@
</span>
</div>
<div v-if="repo.tags && repo.tags.length" class="mt-2 flex gap-2 flex-wrap">
<div
v-if="repo.tags && repo.tags.length"
class="mt-2 flex gap-2 flex-wrap"
>
<el-tag
v-for="tag in repo.tags.slice(0, 3)"
:key="tag"

View File

@@ -30,11 +30,20 @@
<main class="min-w-0">
<!-- Repo Header -->
<div class="card mb-6">
<div class="flex flex-col sm:flex-row items-start justify-between gap-4 mb-4">
<div
class="flex flex-col sm:flex-row items-start justify-between gap-4 mb-4"
>
<div class="flex items-start gap-3">
<div :class="getIconClass(repoType)" class="text-3xl sm:text-4xl flex-shrink-0" />
<div
:class="getIconClass(repoType)"
class="text-3xl sm:text-4xl flex-shrink-0"
/>
<div class="min-w-0">
<h1 class="text-xl sm:text-2xl lg:text-3xl font-bold break-words">{{ repoInfo?.id }}</h1>
<h1
class="text-xl sm:text-2xl lg:text-3xl font-bold break-words"
>
{{ repoInfo?.id }}
</h1>
<div class="flex items-center gap-2 mt-1">
<RouterLink
:to="`/${namespace}`"
@@ -99,7 +108,9 @@
<!-- Navigation Tabs -->
<div class="mb-6 -mx-4 sm:mx-0 px-4 sm:px-0 overflow-x-auto">
<div class="flex gap-1 border-b border-gray-200 dark:border-gray-700 min-w-max sm:min-w-0">
<div
class="flex gap-1 border-b border-gray-200 dark:border-gray-700 min-w-max sm:min-w-0"
>
<button
:class="[
'px-4 py-2 font-medium transition-colors',
@@ -181,7 +192,9 @@
</div>
<div v-if="activeTab === 'files'" class="card">
<div class="mb-4 flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3">
<div
class="mb-4 flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3"
>
<div class="flex items-center gap-2">
<el-select
v-model="currentBranch"
@@ -191,13 +204,17 @@
>
<el-option label="main" value="main" />
</el-select>
<span class="text-sm text-gray-600 dark:text-gray-400 whitespace-nowrap">
<span
class="text-sm text-gray-600 dark:text-gray-400 whitespace-nowrap"
>
{{ fileTree.length }}
{{ fileTree.length === 1 ? "file" : "files" }}
</span>
</div>
<div class="flex flex-col sm:flex-row items-stretch sm:items-center gap-2">
<div
class="flex flex-col sm:flex-row items-stretch sm:items-center gap-2"
>
<el-button
v-if="isOwner"
size="small"

View File

@@ -32,12 +32,21 @@
<div v-else>
<!-- File Header -->
<div class="card mb-6">
<div class="flex flex-col sm:flex-row items-start justify-between gap-4">
<div
class="flex flex-col sm:flex-row items-start justify-between gap-4"
>
<div class="flex items-start gap-3 min-w-0 flex-1">
<div :class="getFileIcon(fileName)" class="text-2xl sm:text-3xl flex-shrink-0" />
<div
:class="getFileIcon(fileName)"
class="text-2xl sm:text-3xl flex-shrink-0"
/>
<div class="min-w-0 flex-1">
<h1 class="text-lg sm:text-xl md:text-2xl font-bold break-words">{{ fileName }}</h1>
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400 mt-1">
<h1 class="text-lg sm:text-xl md:text-2xl font-bold break-words">
{{ fileName }}
</h1>
<div
class="text-xs sm:text-sm text-gray-600 dark:text-gray-400 mt-1"
>
{{ formatSize(fileSize) }}
<span v-if="fileSize" class="mx-2"></span>
<span>{{ fileExtension || "No extension" }}</span>
@@ -45,18 +54,34 @@
</div>
</div>
<div class="flex flex-wrap sm:flex-nowrap items-center gap-2 w-full sm:w-auto">
<el-button v-if="canEdit" @click="editFile" size="small" class="flex-1 sm:flex-initial">
<div
class="flex flex-wrap sm:flex-nowrap items-center gap-2 w-full sm:w-auto"
>
<el-button
v-if="canEdit"
@click="editFile"
size="small"
class="flex-1 sm:flex-initial"
>
<div class="i-carbon-edit inline-block mr-1" />
<span class="hidden sm:inline">Edit</span>
<span class="sm:hidden">Edit</span>
</el-button>
<el-button @click="copyFileUrl" size="small" class="flex-1 sm:flex-initial">
<el-button
@click="copyFileUrl"
size="small"
class="flex-1 sm:flex-initial"
>
<div class="i-carbon-link inline-block mr-1" />
<span class="hidden sm:inline">Copy URL</span>
<span class="sm:hidden">Copy</span>
</el-button>
<el-button type="primary" @click="downloadFile" size="small" class="flex-1 sm:flex-initial">
<el-button
type="primary"
@click="downloadFile"
size="small"
class="flex-1 sm:flex-initial"
>
<div class="i-carbon-download inline-block mr-1" />
Download
</el-button>
@@ -145,9 +170,17 @@
<div
class="flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3 mb-4 pb-3 border-b border-gray-200 dark:border-gray-700"
>
<el-radio-group v-model="markdownView" size="small" class="w-full sm:w-auto">
<el-radio-button label="preview" class="flex-1 sm:flex-initial">Preview</el-radio-button>
<el-radio-button label="source" class="flex-1 sm:flex-initial">Source</el-radio-button>
<el-radio-group
v-model="markdownView"
size="small"
class="w-full sm:w-auto"
>
<el-radio-button label="preview" class="flex-1 sm:flex-initial"
>Preview</el-radio-button
>
<el-radio-button label="source" class="flex-1 sm:flex-initial"
>Source</el-radio-button
>
</el-radio-group>
<el-button
v-if="markdownView === 'source'"

View File

@@ -1,10 +1,14 @@
<!-- src/kohaku-hub-ui/src/pages/[type]s/index.vue -->
<template>
<div class="container-main">
<div class="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6">
<div
class="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6"
>
<div>
<h1 class="text-2xl md:text-3xl font-bold mb-2">{{ pageTitle }}</h1>
<p class="text-sm md:text-base text-gray-600 dark:text-gray-400">{{ pageDescription }}</p>
<p class="text-sm md:text-base text-gray-600 dark:text-gray-400">
{{ pageDescription }}
</p>
</div>
<el-button
@@ -21,7 +25,9 @@
<!-- Filters -->
<div class="card mb-6">
<div class="flex flex-col sm:flex-row items-stretch sm:items-center gap-4">
<div
class="flex flex-col sm:flex-row items-stretch sm:items-center gap-4"
>
<el-input
v-model="searchQuery"
:placeholder="`Search ${repoType}s...`"
@@ -33,7 +39,11 @@
</template>
</el-input>
<el-select v-model="sortBy" placeholder="Sort by" class="w-full sm:w-50">
<el-select
v-model="sortBy"
placeholder="Sort by"
class="w-full sm:w-50"
>
<el-option label="Recently Updated" value="updated" />
<el-option label="Recently Created" value="created" />
<el-option label="Most Downloads" value="downloads" />

View File

@@ -188,7 +188,9 @@
class="flex items-center justify-between mb-4 pb-3 border-b-2 border-green-500"
>
<div class="flex items-center gap-2">
<div class="i-carbon-data-table text-green-500 text-xl md:text-2xl" />
<div
class="i-carbon-data-table text-green-500 text-xl md:text-2xl"
/>
<h2 class="text-xl md:text-2xl font-bold">Datasets</h2>
</div>
<el-tag type="success" size="large">{{
@@ -273,7 +275,9 @@
class="flex items-center justify-between mb-4 pb-3 border-b-2 border-purple-500"
>
<div class="flex items-center gap-2">
<div class="i-carbon-application text-purple-500 text-xl md:text-2xl" />
<div
class="i-carbon-application text-purple-500 text-xl md:text-2xl"
/>
<h2 class="text-xl md:text-2xl font-bold">Spaces</h2>
</div>
<el-tag type="warning" size="large">{{ getCount("space") }}</el-tag>

View File

@@ -4,12 +4,14 @@
<!-- Hero Section -->
<div class="bg-gradient-to-r from-blue-500 to-purple-600 text-white">
<div class="container-main py-8 md:py-16 text-center">
<h1 class="text-3xl md:text-4xl lg:text-5xl font-bold mb-4">Welcome to KohakuHub</h1>
<h1 class="text-3xl md:text-4xl lg:text-5xl font-bold mb-4">
Welcome to KohakuHub
</h1>
<p class="text-base md:text-lg lg:text-xl mb-6 md:mb-8 px-4">
Self-hosted HuggingFace Hub alternative for your AI models and
datasets
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center px-4">
<div class="flex flex-col sm:flex-row gap-2 justify-center px-4">
<el-button
size="large"
type="default"
@@ -18,6 +20,7 @@
>
Get Started
</el-button>
<div class="w-0 h-0 p-0 m-0"></div>
<el-button
size="large"
plain
@@ -32,7 +35,9 @@
<!-- Recent Repos - Three Columns -->
<div class="container-main py-8">
<h2 class="text-2xl md:text-3xl font-bold mb-6 md:mb-8">Recently Updated</h2>
<h2 class="text-2xl md:text-3xl font-bold mb-6 md:mb-8">
Recently Updated
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Models Column -->

View File

@@ -3,7 +3,9 @@
<div class="container-main">
<div class="max-w-3xl mx-auto">
<h1 class="text-2xl md:text-3xl font-bold mb-2">Create New Repository</h1>
<p class="text-sm md:text-base text-gray-600 dark:text-gray-400 mb-6 md:mb-8">
<p
class="text-sm md:text-base text-gray-600 dark:text-gray-400 mb-6 md:mb-8"
>
A repository contains all project files, including revision history.
</p>
@@ -18,7 +20,11 @@
<!-- Repository Type -->
<el-form-item label="Repository Type" prop="type">
<div class="w-full">
<el-radio-group v-model="form.type" size="large" class="w-full grid grid-cols-1 sm:grid-cols-3 gap-2">
<el-radio-group
v-model="form.type"
size="large"
class="w-full grid grid-cols-1 sm:grid-cols-3 gap-2"
>
<el-radio-button value="model">
<div class="flex items-center justify-center gap-2 py-2">
<div class="i-carbon-model text-xl" />
@@ -123,7 +129,13 @@
<div
class="flex flex-col-reverse sm:flex-row gap-3 mt-8 pt-6 border-t border-gray-200 dark:border-gray-700"
>
<el-button size="large" @click="$router.back()" class="w-full sm:w-auto"> Cancel </el-button>
<el-button
size="large"
@click="$router.back()"
class="w-full sm:w-auto"
>
Cancel
</el-button>
<el-button
type="primary"
size="large"

View File

@@ -23,7 +23,7 @@ export default defineConfig({
'btn-secondary': 'btn bg-gray-200 text-gray-800 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600',
'card': 'bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4',
'input': 'px-3 py-2 border border-gray-300 dark:border-gray-600 rounded focus:outline-none focus:border-blue-500 dark:bg-gray-700 dark:text-white',
'container-main': 'max-w-7xl mx-auto px-4 py-6'
'container-main': 'max-w-7xl mx-auto px-4 sm:px-6 py-6'
},
theme: {