mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-10 07:19:02 +08:00
feat: enhance Prettier configuration and update store components
- Added Tailwind CSS support to Prettier configuration with new settings for styles and functions. - Updated package.json to include the prettier-plugin-tailwindcss dependency. - Refactored various store components for improved layout and organization, including adjustments to error handling and component structure. - Enhanced CSS styles for better responsiveness and visual consistency across components.
This commit is contained in:
parent
c799f15fcc
commit
ef16558947
@ -4,5 +4,8 @@
|
|||||||
"printWidth": 120,
|
"printWidth": 120,
|
||||||
"trailingComma": "none",
|
"trailingComma": "none",
|
||||||
"endOfLine": "lf",
|
"endOfLine": "lf",
|
||||||
"bracketSameLine": true
|
"bracketSameLine": true,
|
||||||
|
"tailwindStylesheet": "./src/renderer/src/assets/styles/tailwind.css",
|
||||||
|
"tailwindFunctions": ["clsx"],
|
||||||
|
"plugins": ["prettier-plugin-tailwindcss"],
|
||||||
}
|
}
|
||||||
|
|||||||
@ -191,6 +191,7 @@
|
|||||||
"openai": "patch:openai@npm%3A4.96.0#~/.yarn/patches/openai-npm-4.96.0-0665b05cb9.patch",
|
"openai": "patch:openai@npm%3A4.96.0#~/.yarn/patches/openai-npm-4.96.0-0665b05cb9.patch",
|
||||||
"p-queue": "^8.1.0",
|
"p-queue": "^8.1.0",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
"rc-virtual-list": "^3.18.5",
|
"rc-virtual-list": "^3.18.5",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
@import 'tailwindcss';
|
@import 'tailwindcss' source('../../../src');
|
||||||
@import 'tw-animate-css';
|
@import 'tw-animate-css';
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
|
/* 如需自定义:
|
||||||
|
1. 清晰地组织自定义 CSS 到相应的层中。
|
||||||
|
2. 基础样式(如全局重置、链接样式)放入 base 层;
|
||||||
|
3. 可复用的组件样式(如果仍使用 @apply 或原生 CSS 嵌套创建)放入 components 层;
|
||||||
|
4. 新的自定义工具类放入 utilities 层。
|
||||||
|
*/
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--radius: 0.625rem;
|
--radius: 0.625rem;
|
||||||
--background: oklch(1 0 0);
|
--background: oklch(1 0 0);
|
||||||
@ -112,19 +119,19 @@
|
|||||||
--animate-marquee: marquee var(--duration) infinite linear;
|
--animate-marquee: marquee var(--duration) infinite linear;
|
||||||
--animate-marquee-vertical: marquee-vertical var(--duration) linear infinite;
|
--animate-marquee-vertical: marquee-vertical var(--duration) linear infinite;
|
||||||
@keyframes marquee {
|
@keyframes marquee {
|
||||||
from {
|
from {
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
transform: translateX(calc(-100% - var(--gap)));
|
transform: translateX(calc(-100% - var(--gap)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@keyframes marquee-vertical {
|
@keyframes marquee-vertical {
|
||||||
from {
|
from {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
transform: translateY(calc(-100% - var(--gap)));
|
transform: translateY(calc(-100% - var(--gap)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,4 +143,4 @@
|
|||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,9 +20,9 @@ export function GridView({ items }: { items: CherryStoreItem[] }) {
|
|||||||
<>
|
<>
|
||||||
<div className="columns-4 gap-4">
|
<div className="columns-4 gap-4">
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<BlurFade key={item.id} delay={0.2} inView className="mb-4 cursor-pointer ">
|
<BlurFade key={item.id} delay={0.2} inView className="mb-4 cursor-pointer">
|
||||||
<Card
|
<Card
|
||||||
className="overflow-hidden hover:scale-105 transition-transform"
|
className="overflow-hidden transition-transform hover:scale-105"
|
||||||
onClick={() => handleCardClick(item)}>
|
onClick={() => handleCardClick(item)}>
|
||||||
<CardHeader className="p-0">
|
<CardHeader className="p-0">
|
||||||
{item.icon ? (
|
{item.icon ? (
|
||||||
|
|||||||
@ -46,10 +46,10 @@ export function ItemDetailDialog({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
||||||
<DialogContent className="max-h-[90vh] sm:max-w-4xl overflow-y-auto">
|
<DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-4xl">
|
||||||
<DialogHeader className="flex flex-row items-start justify-between">
|
<DialogHeader className="flex flex-row items-start justify-between">
|
||||||
<div>
|
<div>
|
||||||
<DialogTitle className="flex items-center text-xl space-x-1">
|
<DialogTitle className="flex items-center space-x-1 text-xl">
|
||||||
{item.title}
|
{item.title}
|
||||||
<Badge variant="outline" className="ml-2">
|
<Badge variant="outline" className="ml-2">
|
||||||
{item.type}
|
{item.type}
|
||||||
@ -62,7 +62,7 @@ export function ItemDetailDialog({
|
|||||||
|
|
||||||
<div className="mt-4 grid grid-cols-1 gap-6 md:grid-cols-3">
|
<div className="mt-4 grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
<div className="rounded-lg border bg-card p-6 text-card-foreground shadow-sm mt-4">
|
<div className="mt-4 rounded-lg border bg-card p-6 text-card-foreground shadow-sm">
|
||||||
<ReactMarkdown>{item.prompt}</ReactMarkdown>
|
<ReactMarkdown>{item.prompt}</ReactMarkdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ export function ItemDetailDialog({
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="overflow-hidden">
|
<div className="overflow-hidden">
|
||||||
{item.image && (
|
{item.image && (
|
||||||
<div className="aspect-square w-full rounded-lg border overflow-hidden bg-muted">
|
<div className="aspect-square w-full overflow-hidden rounded-lg border bg-muted">
|
||||||
<img src={item.image || '/placeholder.svg'} alt={item.title} className="h-full w-full object-cover" />
|
<img src={item.image || '/placeholder.svg'} alt={item.title} className="h-full w-full object-cover" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -125,7 +125,7 @@ export function ItemDetailDialog({
|
|||||||
{/* )} */}
|
{/* )} */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="rounded-lg border bg-card p-4 text-card-foreground shadow-sm space-y-2">
|
<div className="space-y-2 rounded-lg border bg-card p-4 text-card-foreground shadow-sm">
|
||||||
<h3 className="mb-2 text-sm font-medium">标签</h3>
|
<h3 className="mb-2 text-sm font-medium">标签</h3>
|
||||||
<div className="flex flex-wrap gap-1">
|
<div className="flex flex-wrap gap-1">
|
||||||
{item.tags.map((tag: string) => (
|
{item.tags.map((tag: string) => (
|
||||||
|
|||||||
@ -20,10 +20,10 @@ export function ListView({ items }: { items: CherryStoreItem[] }) {
|
|||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<Card
|
<Card
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="p-0 cursor-pointer hover:shadow-lg transition-shadow"
|
className="cursor-pointer p-0 transition-shadow hover:shadow-lg"
|
||||||
onClick={() => handleCardClick(item)}>
|
onClick={() => handleCardClick(item)}>
|
||||||
<div className="flex flex-col sm:flex-row">
|
<div className="flex flex-col sm:flex-row">
|
||||||
<div className="h-24 w-24 shrink-0 overflow-hidden rounded-l-lg bg-muted sm:h-auto flex items-center justify-center">
|
<div className="flex h-24 w-24 shrink-0 items-center justify-center overflow-hidden rounded-l-lg bg-muted sm:h-auto">
|
||||||
{item.icon ? (
|
{item.icon ? (
|
||||||
<div
|
<div
|
||||||
className="flex h-full w-full items-center justify-center text-3xl"
|
className="flex h-full w-full items-center justify-center text-3xl"
|
||||||
|
|||||||
@ -26,14 +26,14 @@ export function StoreContent({
|
|||||||
onViewModeChange
|
onViewModeChange
|
||||||
}: StoreContentProps) {
|
}: StoreContentProps) {
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 overflow-auto w-full">
|
<div className="w-full flex-1 overflow-auto">
|
||||||
{/* Sticky Header for Search, Filter, View Mode, and Category Tabs */}
|
{/* Sticky Header for Search, Filter, View Mode, and Category Tabs */}
|
||||||
<div className="sticky top-0 z-10 border-b bg-background p-4">
|
<div className="sticky top-0 z-10 border-b bg-background p-4">
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
{/* Top row: Search, Filter, View buttons */}
|
{/* Top row: Search, Filter, View buttons */}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="relative flex-1">
|
<div className="relative flex-1">
|
||||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
<Search className="absolute top-2.5 left-2.5 h-4 w-4 text-muted-foreground" />
|
||||||
<Input
|
<Input
|
||||||
type="search"
|
type="search"
|
||||||
placeholder="Search store..."
|
placeholder="Search store..."
|
||||||
@ -84,7 +84,7 @@ export function StoreContent({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Main Content Area: Grid or List View */}
|
{/* Main Content Area: Grid or List View */}
|
||||||
<div className="p-4 w-full">
|
<div className="w-full p-4">
|
||||||
{items.length === 0 ? (
|
{items.length === 0 ? (
|
||||||
<div className="flex h-[400px] items-center justify-center">
|
<div className="flex h-[400px] items-center justify-center">
|
||||||
<p className="text-center text-muted-foreground">No items found matching your criteria.</p>
|
<p className="text-center text-muted-foreground">No items found matching your criteria.</p>
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export function StoreSidebar({
|
|||||||
}: StoreSidebarProps) {
|
}: StoreSidebarProps) {
|
||||||
if (!categories || categories.length === 0) {
|
if (!categories || categories.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Sidebar className="absolute left-0 top-0 h-full border-r">
|
<Sidebar className="absolute top-0 left-0 h-full border-r">
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<p className="p-4 text-sm text-gray-500">No categories loaded.</p>
|
<p className="p-4 text-sm text-gray-500">No categories loaded.</p>
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
@ -27,7 +27,7 @@ export function StoreSidebar({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar className="absolute left-0 top-0 h-full border-r">
|
<Sidebar className="absolute top-0 left-0 h-full border-r">
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<SidebarMenu className="gap-0">
|
<SidebarMenu className="gap-0">
|
||||||
{categories.map((category, index) => (
|
{categories.map((category, index) => (
|
||||||
@ -41,7 +41,7 @@ export function StoreSidebar({
|
|||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
<CollapsibleContent className="overflow-hidden text-sm transition-all data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down">
|
<CollapsibleContent className="overflow-hidden text-sm transition-all data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down">
|
||||||
<SidebarMenu className="py-1 pl-4 pr-1">
|
<SidebarMenu className="py-1 pr-1 pl-4">
|
||||||
{category.items.map((subItem) => (
|
{category.items.map((subItem) => (
|
||||||
<SidebarMenuItem key={subItem.id}>
|
<SidebarMenuItem key={subItem.id}>
|
||||||
<SidebarMenuButton
|
<SidebarMenuButton
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export default function StoreLayout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <div className="p-4 text-red-500 text-center">Error: {error}</div>
|
return <div className="p-4 text-center text-red-500">Error: {error}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -87,7 +87,7 @@ export default function StoreLayout() {
|
|||||||
<NavbarCenter>{t('store.title')}</NavbarCenter>
|
<NavbarCenter>{t('store.title')}</NavbarCenter>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<div id="content-container" className="h-full w-full">
|
<div id="content-container" className="h-full w-full">
|
||||||
<SidebarProvider className="h-full w-full relative min-h-full">
|
<SidebarProvider className="relative h-full min-h-full w-full">
|
||||||
<StoreSidebar
|
<StoreSidebar
|
||||||
categories={categories}
|
categories={categories}
|
||||||
selectedCategory={selectedCategory}
|
selectedCategory={selectedCategory}
|
||||||
|
|||||||
59
yarn.lock
59
yarn.lock
@ -5348,6 +5348,7 @@ __metadata:
|
|||||||
os-proxy-config: "npm:^1.1.2"
|
os-proxy-config: "npm:^1.1.2"
|
||||||
p-queue: "npm:^8.1.0"
|
p-queue: "npm:^8.1.0"
|
||||||
prettier: "npm:^3.5.3"
|
prettier: "npm:^3.5.3"
|
||||||
|
prettier-plugin-tailwindcss: "npm:^0.6.11"
|
||||||
proxy-agent: "npm:^6.5.0"
|
proxy-agent: "npm:^6.5.0"
|
||||||
rc-virtual-list: "npm:^3.18.5"
|
rc-virtual-list: "npm:^3.18.5"
|
||||||
react: "npm:^19.0.0"
|
react: "npm:^19.0.0"
|
||||||
@ -14867,6 +14868,64 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"prettier-plugin-tailwindcss@npm:^0.6.11":
|
||||||
|
version: 0.6.11
|
||||||
|
resolution: "prettier-plugin-tailwindcss@npm:0.6.11"
|
||||||
|
peerDependencies:
|
||||||
|
"@ianvs/prettier-plugin-sort-imports": "*"
|
||||||
|
"@prettier/plugin-pug": "*"
|
||||||
|
"@shopify/prettier-plugin-liquid": "*"
|
||||||
|
"@trivago/prettier-plugin-sort-imports": "*"
|
||||||
|
"@zackad/prettier-plugin-twig": "*"
|
||||||
|
prettier: ^3.0
|
||||||
|
prettier-plugin-astro: "*"
|
||||||
|
prettier-plugin-css-order: "*"
|
||||||
|
prettier-plugin-import-sort: "*"
|
||||||
|
prettier-plugin-jsdoc: "*"
|
||||||
|
prettier-plugin-marko: "*"
|
||||||
|
prettier-plugin-multiline-arrays: "*"
|
||||||
|
prettier-plugin-organize-attributes: "*"
|
||||||
|
prettier-plugin-organize-imports: "*"
|
||||||
|
prettier-plugin-sort-imports: "*"
|
||||||
|
prettier-plugin-style-order: "*"
|
||||||
|
prettier-plugin-svelte: "*"
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@ianvs/prettier-plugin-sort-imports":
|
||||||
|
optional: true
|
||||||
|
"@prettier/plugin-pug":
|
||||||
|
optional: true
|
||||||
|
"@shopify/prettier-plugin-liquid":
|
||||||
|
optional: true
|
||||||
|
"@trivago/prettier-plugin-sort-imports":
|
||||||
|
optional: true
|
||||||
|
"@zackad/prettier-plugin-twig":
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-astro:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-css-order:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-import-sort:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-jsdoc:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-marko:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-multiline-arrays:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-organize-attributes:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-organize-imports:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-sort-imports:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-style-order:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-svelte:
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/e5688a86f457b4eaa682d83a86702826d2d828db4cfc153b8b1f0b8409c94530a4bde8deb3e819497ba8e4bd0eda08ed55468a41a8138f82db43d633cf332121
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"prettier@npm:^3.5.3":
|
"prettier@npm:^3.5.3":
|
||||||
version: 3.5.3
|
version: 3.5.3
|
||||||
resolution: "prettier@npm:3.5.3"
|
resolution: "prettier@npm:3.5.3"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user