Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"permissions": [
"core:default",
"opener:default",
"opener:allow-open-path",
"opener:allow-reveal-item-in-dir",
"store:default",
"window-state:default",
"dialog:default"
Expand Down
4 changes: 2 additions & 2 deletions src/home/sections/ContinueCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { openPath } from "@tauri-apps/plugin-opener";
import { revealItemInDir } from "@tauri-apps/plugin-opener";

import { IconChevronRight } from "../icons";
import { openProject } from "../../projects/actions";
Expand Down Expand Up @@ -40,7 +40,7 @@ export function ContinueCard({ project }: Props) {
<button
type="button"
className="home-btn home-btn--ghost"
onClick={() => void openPath(project.path)}
onClick={() => void revealItemInDir(project.path)}
>
Ouvrir le dossier
</button>
Expand Down
24 changes: 1 addition & 23 deletions src/home/sections/HomeSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
import { useRef } from "react";

import { shortcutLabel } from "../../palette/formatShortcut";
import { usePaletteStore } from "../../palette/paletteStore";
import { IconSearch } from "../icons";

export function HomeSearch() {
const openPalette = usePaletteStore((s) => s.openPalette);
const paletteOpen = usePaletteStore((s) => s.open);
const barRef = useRef<HTMLDivElement>(null);

const handleClick = () => {
// Measure where the search bar sits so the palette can animate from
// that exact position — the FLIP technique. Custom properties are set
// on <html> and consumed by @keyframes palette-enter in global.css.
const rect = barRef.current?.getBoundingClientRect();
if (rect) {
const root = document.documentElement;
const paletteTop = 88; // palette resting position (CSS `top: 88px`)
const paletteCenterX = window.innerWidth / 2;
const paletteWidth = Math.min(720, window.innerWidth - 48);

root.style.setProperty("--palette-dy", `${rect.top - paletteTop}px`);
root.style.setProperty("--palette-dx", `${rect.left + rect.width / 2 - paletteCenterX}px`);
root.style.setProperty("--palette-sx", `${rect.width / paletteWidth}`);
}
openPalette();
};

return (
<div
ref={barRef}
className="home-search"
role="search"
onClick={handleClick}
onClick={openPalette}
style={paletteOpen ? { visibility: "hidden" } : undefined}
>
<IconSearch />
Expand Down
4 changes: 2 additions & 2 deletions src/home/sections/ProjectCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { openPath } from "@tauri-apps/plugin-opener";
import { revealItemInDir } from "@tauri-apps/plugin-opener";
import { useState } from "react";

import { ContextMenu } from "../../ide/tree/ContextMenu";
Expand Down Expand Up @@ -61,7 +61,7 @@ export function ProjectCard({ project, index = 0 }: Props) {
{ label: "Ouvrir", onSelect: () => void openProject(project.id) },
{
label: "Ouvrir le dossier",
onSelect: () => void openPath(project.path),
onSelect: () => void revealItemInDir(project.path),
},
{ label: "Renommer", onSelect: () => openRename({ id: project.id }) },
{
Expand Down
20 changes: 7 additions & 13 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,10 @@ button.brand {
.context-menu__item:hover {
background: var(--bg-3);
}
.context-menu__item:focus-visible {
outline: none;
background: var(--bg-3);
}
.context-menu__item--destructive {
color: var(--err);
}
Expand Down Expand Up @@ -2144,33 +2148,23 @@ button.brand {
}
}

/* FLIP animation: HomeSearch measures its own rect on click and writes
--palette-dy / --palette-dx / --palette-sx as CSS custom properties on
<html>. The keyframe starts at those offsets (the search bar's position
and width) and settles at the palette's resting center. All transforms
→ GPU-composited, zero layout thrash. */
.palette-root {
position: fixed;
top: 88px;
left: 50%;
transform: translateX(-50%);
width: min(720px, calc(100vw - 48px));
width: min(800px, calc(100vw - 48px));
z-index: var(--z-modal);
display: flex;
flex-direction: column;
font-family: var(--font-ui);
animation: palette-enter 0.28s cubic-bezier(0.16, 1, 0.3, 1);
transform-origin: top center;
animation: palette-enter 0.18s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes palette-enter {
from {
opacity: 0;
transform: translateX(calc(-50% + var(--palette-dx, 0px))) translateY(var(--palette-dy, 0px))
scaleX(var(--palette-sx, 1));
}
15% {
opacity: 1;
transform: translateX(-50%) scale(0.96) translateY(-8px);
}
}

Expand Down