feat: add semantic-release for automated versioning and help dialog

- Set up semantic-release with zero-touch CI pipeline on push to main
- Add version sync script to keep all package.json files and APP_VERSION
  constant in sync automatically
- Consolidate Docker publishing into single tag-triggered workflow that
  pushes to both Docker Hub and ghcr.io with semver tags
- Add help dialog with keyboard shortcuts, getting started guide, and
  resource links
- Sync all versions to 0.2.1 to match Docker Hub latest
This commit is contained in:
Siddharth Kumar Sah
2026-03-22 21:25:14 +08:00
parent fb1d366d5f
commit 4807bd2726
22 changed files with 2359 additions and 82 deletions
+13 -1
View File
@@ -13,6 +13,7 @@ import { ToolPanel } from "./tool-panel";
import { Footer } from "./footer";
import { Dropzone } from "../common/dropzone";
import { SettingsDialog } from "../settings/settings-dialog";
import { HelpDialog } from "../help/help-dialog";
import { useMobile } from "@/hooks/use-mobile";
import { cn } from "@/lib/utils";
@@ -24,6 +25,7 @@ interface AppLayoutProps {
export function AppLayout({ children, showToolPanel = true, onFiles }: AppLayoutProps) {
const [settingsOpen, setSettingsOpen] = useState(false);
const [helpOpen, setHelpOpen] = useState(false);
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
const isMobile = useMobile();
@@ -31,7 +33,7 @@ export function AppLayout({ children, showToolPanel = true, onFiles }: AppLayout
<div className="flex h-screen bg-background text-foreground overflow-hidden">
{/* Desktop sidebar */}
{!isMobile && (
<Sidebar onSettingsClick={() => setSettingsOpen(true)} />
<Sidebar onSettingsClick={() => setSettingsOpen(true)} onHelpClick={() => setHelpOpen(true)} />
)}
{/* Mobile sidebar overlay */}
@@ -59,6 +61,10 @@ export function AppLayout({ children, showToolPanel = true, onFiles }: AppLayout
setMobileSidebarOpen(false);
setSettingsOpen(true);
}}
onHelpClick={() => {
setMobileSidebarOpen(false);
setHelpOpen(true);
}}
expanded
/>
</div>
@@ -122,6 +128,12 @@ export function AppLayout({ children, showToolPanel = true, onFiles }: AppLayout
open={settingsOpen}
onClose={() => setSettingsOpen(false)}
/>
{/* Help dialog */}
<HelpDialog
open={helpOpen}
onClose={() => setHelpOpen(false)}
/>
</div>
);
}
+10 -2
View File
@@ -25,17 +25,18 @@ const topItems: SidebarItem[] = [
];
const bottomItems: SidebarItem[] = [
{ icon: HelpCircle, label: "Help", href: "/help" },
{ icon: HelpCircle, label: "Help" },
{ icon: Settings, label: "Settings" },
];
interface SidebarProps {
onSettingsClick: () => void;
onHelpClick: () => void;
/** When true, renders in expanded mode (for mobile overlay). */
expanded?: boolean;
}
export function Sidebar({ onSettingsClick, expanded = false }: SidebarProps) {
export function Sidebar({ onSettingsClick, onHelpClick, expanded = false }: SidebarProps) {
const location = useLocation();
const renderItem = (item: SidebarItem, isActive: boolean) => {
@@ -72,6 +73,13 @@ export function Sidebar({ onSettingsClick, expanded = false }: SidebarProps) {
</button>
);
}
if (item.label === "Help") {
return (
<button key={item.label} onClick={onHelpClick} className="w-full">
{content}
</button>
);
}
return (
<Link key={item.label} to={item.href || "/"}>
{content}