{bucket.label}
diff --git a/apps/desktop/src/components/main/sidebar/timeline/item.tsx b/apps/desktop/src/components/main/sidebar/timeline/item.tsx
index 121da8814f..97c6223efb 100644
--- a/apps/desktop/src/components/main/sidebar/timeline/item.tsx
+++ b/apps/desktop/src/components/main/sidebar/timeline/item.tsx
@@ -111,7 +111,7 @@ function ItemBase({
"cursor-pointer w-full text-left px-3 py-2 rounded-lg",
multiSelected && "bg-neutral-200",
!multiSelected && selected && "bg-neutral-200",
- !multiSelected && !selected && "hover:bg-neutral-100",
+ !multiSelected && !selected && "hover:bg-neutral-200/50",
ignored && "opacity-40",
])}
>
diff --git a/apps/desktop/src/routes/app/main/_layout.index.tsx b/apps/desktop/src/routes/app/main/_layout.index.tsx
index 9354ea5d91..9b2d321655 100644
--- a/apps/desktop/src/routes/app/main/_layout.index.tsx
+++ b/apps/desktop/src/routes/app/main/_layout.index.tsx
@@ -67,7 +67,7 @@ function Component() {
return (
{leftsidebar.expanded && !isOnboarding && }
diff --git a/apps/desktop/src/store/zustand/tabs/basic.ts b/apps/desktop/src/store/zustand/tabs/basic.ts
index b383866089..5052a4aa0a 100644
--- a/apps/desktop/src/store/zustand/tabs/basic.ts
+++ b/apps/desktop/src/store/zustand/tabs/basic.ts
@@ -21,7 +21,7 @@ export type BasicState = {
export type BasicActions = {
openCurrent: (tab: TabInput) => void;
- openNew: (tab: TabInput) => void;
+ openNew: (tab: TabInput, options?: { insertFirst?: boolean }) => void;
select: (tab: Tab) => void;
selectNext: () => void;
selectPrev: () => void;
@@ -71,9 +71,9 @@ export const createBasicSlice = <
view: tab.type,
});
},
- openNew: (tab) => {
+ openNew: (tab, options) => {
const { tabs, history, addRecentlyOpened } = get();
- set(openTab(tabs, tab, history, true));
+ set(openTab(tabs, tab, history, true, options?.insertFirst));
if (tab.type === "sessions") {
addRecentlyOpened(tab.id);
@@ -270,6 +270,7 @@ const openTab = (
newTab: TabInput,
history: Map,
forceNewTab: boolean,
+ insertFirst?: boolean,
): Partial => {
const tabWithDefaults: Tab = {
...getDefaultState(newTab),
@@ -316,7 +317,17 @@ const openTab = (
} else {
activeTab = { ...tabWithDefaults, active: true, slotId: id() };
const deactivated = deactivateAll(tabs);
- nextTabs = [...deactivated, activeTab];
+
+ if (insertFirst) {
+ const pinnedCount = deactivated.filter((t) => t.pinned).length;
+ nextTabs = [
+ ...deactivated.slice(0, pinnedCount),
+ activeTab,
+ ...deactivated.slice(pinnedCount),
+ ];
+ } else {
+ nextTabs = [...deactivated, activeTab];
+ }
return updateWithHistory(nextTabs, activeTab, history);
}
diff --git a/package.json b/package.json
index 16fecf09d6..a6d8d0497e 100644
--- a/package.json
+++ b/package.json
@@ -11,14 +11,22 @@
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
"dprint": "^0.51.1",
"eslint": "^9.39.2",
+ "lint-staged": "^16.3.1",
"oxfmt": "^0.18.0",
"oxlint": "^1.46.0",
"oxlint-tsgolint": "^0.12.2",
"prettier": "^3.8.1",
+ "simple-git-hooks": "^2.13.1",
"supabase": "^2.76.8",
"turbo": "2.8.3",
"typescript-eslint": "^8.55.0"
},
+ "simple-git-hooks": {
+ "pre-commit": "pnpm exec lint-staged"
+ },
+ "lint-staged": {
+ "*": "dprint fmt --"
+ },
"packageManager": "pnpm@10.30.0",
"engines": {
"node": ">=22"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6cc5a48239..55f5b834e1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -26,6 +26,9 @@ importers:
eslint:
specifier: ^9.39.2
version: 9.39.2(jiti@2.6.1)
+ lint-staged:
+ specifier: ^16.3.1
+ version: 16.3.1
oxfmt:
specifier: ^0.18.0
version: 0.18.0
@@ -38,6 +41,9 @@ importers:
prettier:
specifier: ^3.8.1
version: 3.8.1
+ simple-git-hooks:
+ specifier: ^2.13.1
+ version: 2.13.1
supabase:
specifier: ^2.76.8
version: 2.76.10
@@ -321,6 +327,9 @@ importers:
'@t3-oss/env-core':
specifier: ^0.13.10
version: 0.13.10(typescript@5.8.3)(zod@4.3.6)
+ '@tailwindcss/postcss':
+ specifier: ^4.1.18
+ version: 4.1.18
'@tanstack/react-form':
specifier: ^1.28.0
version: 1.28.0(@tanstack/react-start@1.159.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vite@7.3.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -9462,6 +9471,10 @@ packages:
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
engines: {node: '>=6'}
+ cli-truncate@5.2.0:
+ resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==}
+ engines: {node: '>=20'}
+
cli-width@3.0.0:
resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
engines: {node: '>= 10'}
@@ -11110,6 +11123,10 @@ packages:
resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
engines: {node: '>=18'}
+ get-east-asian-width@1.5.0:
+ resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==}
+ engines: {node: '>=18'}
+
get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
@@ -12289,10 +12306,19 @@ packages:
linkifyjs@4.3.2:
resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==}
+ lint-staged@16.3.1:
+ resolution: {integrity: sha512-bqvvquXzFBAlSbluugR4KXAe4XnO/QZcKVszpkBtqLWa2KEiVy8n6Xp38OeUbv/gOJOX4Vo9u5pFt/ADvbm42Q==}
+ engines: {node: '>=20.17'}
+ hasBin: true
+
listhen@1.9.0:
resolution: {integrity: sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg==}
hasBin: true
+ listr2@9.0.5:
+ resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
+ engines: {node: '>=20.0.0'}
+
lit-element@4.2.2:
resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==}
@@ -14986,6 +15012,10 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
+ simple-git-hooks@2.13.1:
+ resolution: {integrity: sha512-WszCLXwT4h2k1ufIXAgsbiTOazqqevFCIncOuUBZJ91DdvWcC5+OFkluWRQPrcuSYd8fjq+o2y1QfWqYMoAToQ==}
+ hasBin: true
+
simple-wcswidth@1.1.2:
resolution: {integrity: sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==}
@@ -15012,6 +15042,10 @@ packages:
resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
engines: {node: '>=18'}
+ slice-ansi@8.0.0:
+ resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==}
+ engines: {node: '>=20'}
+
smart-buffer@4.2.0:
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
@@ -15185,6 +15219,10 @@ packages:
strict-event-emitter@0.5.1:
resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==}
+ string-argv@0.3.2:
+ resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
+ engines: {node: '>=0.6.19'}
+
string-convert@0.2.1:
resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==}
@@ -15203,6 +15241,10 @@ packages:
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
engines: {node: '>=18'}
+ string-width@8.2.0:
+ resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==}
+ engines: {node: '>=20'}
+
string_decoder@1.1.1:
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
@@ -25608,6 +25650,11 @@ snapshots:
cli-spinners@2.9.2: {}
+ cli-truncate@5.2.0:
+ dependencies:
+ slice-ansi: 8.0.0
+ string-width: 8.2.0
+
cli-width@3.0.0: {}
cli-width@4.1.0: {}
@@ -27371,6 +27418,8 @@ snapshots:
get-east-asian-width@1.4.0: {}
+ get-east-asian-width@1.5.0: {}
+
get-intrinsic@1.3.0:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -28776,6 +28825,15 @@ snapshots:
linkifyjs@4.3.2: {}
+ lint-staged@16.3.1:
+ dependencies:
+ commander: 14.0.3
+ listr2: 9.0.5
+ micromatch: 4.0.8
+ string-argv: 0.3.2
+ tinyexec: 1.0.2
+ yaml: 2.8.2
+
listhen@1.9.0:
dependencies:
'@parcel/watcher': 2.5.6
@@ -28797,6 +28855,15 @@ snapshots:
untun: 0.1.3
uqr: 0.1.2
+ listr2@9.0.5:
+ dependencies:
+ cli-truncate: 5.2.0
+ colorette: 2.0.20
+ eventemitter3: 5.0.4
+ log-update: 6.1.0
+ rfdc: 1.4.1
+ wrap-ansi: 9.0.2
+
lit-element@4.2.2:
dependencies:
'@lit-labs/ssr-dom-shim': 1.5.1
@@ -32598,6 +32665,8 @@ snapshots:
signal-exit@4.1.0: {}
+ simple-git-hooks@2.13.1: {}
+
simple-wcswidth@1.1.2: {}
sisteransi@1.0.5: {}
@@ -32620,6 +32689,11 @@ snapshots:
ansi-styles: 6.2.3
is-fullwidth-code-point: 5.1.0
+ slice-ansi@8.0.0:
+ dependencies:
+ ansi-styles: 6.2.3
+ is-fullwidth-code-point: 5.1.0
+
smart-buffer@4.2.0: {}
smee-client@2.0.4:
@@ -32791,6 +32865,8 @@ snapshots:
strict-event-emitter@0.5.1: {}
+ string-argv@0.3.2: {}
+
string-convert@0.2.1: {}
string-hash@1.1.3: {}
@@ -32813,6 +32889,11 @@ snapshots:
get-east-asian-width: 1.4.0
strip-ansi: 7.1.2
+ string-width@8.2.0:
+ dependencies:
+ get-east-asian-width: 1.5.0
+ strip-ansi: 7.1.2
+
string_decoder@1.1.1:
dependencies:
safe-buffer: 5.1.2