add README, CC0 license, and button icon alignment fix

- Comprehensive README with full feature docs, settings reference,
  keyboard shortcuts, data storage layout, and build instructions
- CC0 1.0 Universal public domain dedication
- Fix button icon/text vertical alignment (leading-none + svg translate)
- Lock Cargo dependencies
This commit is contained in:
Your Name
2026-02-16 15:40:28 +02:00
parent 414c1f7d68
commit 59aaa688bb
4 changed files with 573 additions and 2 deletions

116
LICENSE Normal file
View File

@@ -0,0 +1,116 @@
CC0 1.0 Universal
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not invalidate
the remainder of the License, and in such case Affirmer hereby affirms that he
or she will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of action
with respect to the Work, in either case contrary to Affirmer's express
Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions or
other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this CC0
or use of the Work.
For more information, please see
<https://creativecommons.org/publicdomain/zero/1.0/>

359
README.md Normal file
View File

@@ -0,0 +1,359 @@
<p align="center">
<img src="src-tauri/icons/128x128.png" alt="OpenPylon" width="96" />
</p>
<h1 align="center">OpenPylon</h1>
<p align="center">
<strong>A local-first Kanban board for people who want to own their work.</strong>
<br />
No accounts. No cloud. No telemetry. No landlords between you and your data.
</p>
<p align="center">
<img src="https://img.shields.io/badge/license-CC0_1.0-blue" alt="License: CC0 1.0" />
<img src="https://img.shields.io/badge/version-0.1.0-green" alt="Version 0.1.0" />
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey" alt="Platforms" />
<img src="https://img.shields.io/badge/built%20with-Tauri%20v2-orange" alt="Built with Tauri v2" />
</p>
---
## 🏴 Why OpenPylon?
Your productivity tools shouldn't phone home. They shouldn't harvest your habits. They shouldn't stop working when a company pivots to AI or gets acqui-hired.
OpenPylon is a desktop Kanban application that keeps everything on your machine. Every board, card, and attachment is a plain JSON file in a folder next to the executable. Copy it to a USB drive. Back it up to a NAS. Share it with your team over a local network. The data is yours — always has been, always will be.
No subscription. No signup. No server between you and your work.
**Built for people, not for platforms.**
---
## ✨ Features
### 📋 Boards
- **Unlimited boards** with custom accent colors and editable titles
- **Three built-in templates** — Blank, Kanban (To Do / In Progress / Done), and Sprint (Backlog / To Do / In Progress / Review / Done)
- **Save any board as a reusable template** — build your own workflows and share them freely
- **Duplicate entire boards** with all cards, labels, and settings preserved
- **Drag-and-drop reordering** in the board list
- **Sort boards** by name, last modified, date created, or manual drag order
- **Import and export** — JSON (full fidelity) and CSV (spreadsheet-compatible); imports from Trello JSON too
### 🏛️ Columns
- **Add, rename, reorder, and delete** columns with drag-and-drop
- **Three column widths** — Narrow, Standard, Wide
- **Column colors** — 10 preset hues or no color
- **WIP limits** — optional per-column capacity limits (3, 5, 7, or 10) with amber/red header warnings when the collective workload exceeds what's sustainable
- **Collapse columns** to a narrow vertical strip showing just the title and card count — keep things tidy without losing context
### 🃏 Cards
- **Drag-and-drop** cards within and between columns
- **Markdown descriptions** — full GitHub Flavored Markdown with tables, strikethrough, task lists, autolinks, and a live preview toggle
- **Checklists** — add items, check them off, reorder by dragging, track progress with a visual bar
- **Labels** — create labels with custom names and colors, toggle them per card
- **Due dates** — custom calendar picker with relative time display ("in 3 days", "overdue by 2 days")
- **Priority levels** — None, Low, Medium, High, Urgent — each with a distinct color indicator visible on card thumbnails
- **Cover colors** — 10 preset hues rendered as a colored header bar on the card detail
- **File attachments** — link to files in place or copy them into the board's data directory; open in your system's default application
- **Comments** — timestamped notes on each card, newest first, with add and delete
- **Card duplication** — copy a card within its column
- **Card aging** — cards that haven't been touched in a while gradually fade, so you can see at a glance where work has stalled
### 🔍 Filtering and Search
- **Filter bar** (press `/`) — narrow down cards by text search, labels, due date status (overdue, today, this week, no date), and priority level
- **Command palette** (`Ctrl+K`) — fuzzy search across cards in the current board, across all boards, and quick access to app actions like creating a new board or toggling dark mode
- **Cross-board search** — find any card by title or description across every board you have
### ⌨️ Keyboard Navigation
Full keyboard-driven workflow. Vim-style or arrow keys — your choice.
| Shortcut | Action |
|---|---|
| `j` / `k` or `↓` / `↑` | Navigate between cards vertically |
| `h` / `l` or `←` / `→` | Navigate between columns |
| `Enter` | Open the focused card |
| `Escape` | Close modal / clear focus / cancel edit |
| `/` | Toggle filter bar |
| `Ctrl+K` | Open command palette |
| `Ctrl+Z` | Undo |
| `Ctrl+Shift+Z` | Redo |
| `?` | Show all keyboard shortcuts |
### 🎨 Appearance
- **Theme** — Light, Dark, or follow your system preference
- **Accent color** — 10 hues (Teal, Blue, Purple, Pink, Red, Orange, Yellow, Lime, Cyan, Slate) applied globally across the interface
- **UI zoom** — 75% to 150% in 5% increments
- **Density** — Compact, Comfortable, or Spacious — adjust how much breathing room the interface gets
- **Board backgrounds** — None, Dots, Grid, or Gradient pattern per board
- **Default column width** — configure what width new columns start at
- **Custom scrollbars** — themed scrollbars throughout, with auto-hide behavior
- **Smooth animations** — staggered entrances, layout transitions, and micro-interactions powered by Framer Motion, with full `prefers-reduced-motion` support
### 🛡️ Data Safety
Your work is protected by multiple layers of redundancy — because tools that lose your data don't deserve your trust.
- **Auto-save** — boards save automatically 500ms after every change
- **Automatic backups** — timestamped snapshots every 5 minutes, last 10 retained per board
- **Version history** — browse and restore previous versions from the board settings menu
- **Rolling backup** — the previous save is always preserved as a `.backup.json` file
- **Portable storage** — all data lives in a `data/` folder next to the executable; no registry entries, no AppData, no hidden folders
- **Schema validation** — all data is validated with Zod on every load, with graceful fallback to defaults if a file is corrupted. Forward-compatible: boards from older versions just work.
### 🖥️ Desktop Integration
- **Custom frameless window** — integrated title bar with minimize, maximize, and close controls, plus a drag region that feels native
- **Window state persistence** — remembers your window position, size, and maximized state between sessions
- **Due date notifications** — OS-level desktop notifications for cards that are due today or overdue, checked hourly
- **Open attachments** directly in your system's default application
- **Right-click context menus** — on boards (duplicate, export, save as template, delete) and on cards (move, duplicate, set priority, delete)
---
## 📥 Installation
### Download
Grab the latest release from the [Releases](https://github.com/nicepylon/openpylon/releases) page.
| Platform | Format | Notes |
|---|---|---|
| Windows | `.exe` (portable) | Just unzip and run. No installer needed. |
| Windows | `.msi` / `.exe` (installer) | Traditional install if you prefer it. |
| macOS | `.dmg` | Drag to Applications. |
| Linux | `.AppImage` / `.deb` | AppImage runs anywhere; .deb for Debian/Ubuntu. |
### Build from Source
Anyone can build this. The source is yours.
**Prerequisites:**
- [Node.js](https://nodejs.org/) 18+
- [Rust](https://rustup.rs/) (latest stable)
- Platform-specific dependencies per the [Tauri v2 docs](https://v2.tauri.app/start/prerequisites/)
```bash
# Clone
git clone https://github.com/nicepylon/openpylon.git
cd openpylon
# Install dependencies
npm install
# Development (hot reload)
npm run tauri dev
# Production build
npm run tauri build
```
The compiled binary lands in `src-tauri/target/release/`. Installers (MSI, NSIS, etc.) appear in `src-tauri/target/release/bundle/`.
---
## 📂 Data Storage
Everything lives next to the executable. No cloud. No hidden directories. Just files you can see, copy, and control.
```
openpylon.exe
data/
├── settings.json # App preferences
├── boards/
│ ├── 01HXR5K9N2...json # Each board is one JSON file
│ └── ...
├── templates/
│ ├── 01HXR7M3P4...json # Saved board templates
│ └── ...
├── backups/
│ └── 01HXR5K9N2.../
│ ├── 01HXR5K9N2.1708123456.json
│ ├── 01HXR5K9N2.1708123756.json
│ └── ... # Timestamped snapshots (last 10 kept)
└── attachments/
└── 01HXR5K9N2.../
├── diagram.png
└── ... # Copied attachments per board
```
### 📄 Board Format
Each board is a self-contained JSON file with a Zod-validated schema. New fields added in future versions receive sensible defaults on load — so older board files never break. You can read, edit, or script against these files with any tool you like. They're just JSON.
### 🔄 Backup and Recovery
If something goes wrong:
1. **Version History** — open board settings (⚙️ icon in the top bar) → "Version History" → pick a snapshot → restore. Your current state is backed up first.
2. **Manual `.backup.json`** — every board has a `.backup.json` sibling in the `boards/` folder. Rename it to replace the current file.
3. **Timestamped snapshots** — find the one you want in `data/backups/<board-id>/` and copy it into `data/boards/`.
---
## 🔄 Import and Export
### Importing
Click the **Import** button on the board list screen and pick a `.json` file. OpenPylon auto-detects the format:
| Format | What Gets Imported |
|---|---|
| **OpenPylon JSON** | Everything — full fidelity round-trip, no data loss |
| **Trello JSON** | Lists → columns, cards, labels (with color mapping), checklists. Archived/closed items are skipped. |
Migrating off Trello? Export your board from Trello (Menu → Share → Export as JSON), then import it here. Your data belongs with you.
### Exporting
Right-click any board card on the board list to export:
| Format | Use Case |
|---|---|
| **JSON** | Full board data. Re-importable into OpenPylon or parseable by any tool. |
| **CSV** | Flat table with board name, column, title, description, labels, due date, checklist progress, and timestamps. Opens in Excel, Sheets, LibreOffice, or anything that reads CSV. |
No lock-in. Take your data wherever you want, whenever you want.
---
## ⚙️ Settings Reference
### Global Settings
| Setting | Options | Default |
|---|---|---|
| 🎨 Theme | Light · Dark · System | System |
| 🎯 Accent Color | Teal · Blue · Purple · Pink · Red · Orange · Yellow · Lime · Cyan · Slate | Teal |
| 🔎 UI Zoom | 75% 150% (5% steps) | 100% |
| 📐 Density | Compact · Comfortable · Spacious | Comfortable |
| 📏 Default Column Width | Narrow · Standard · Wide | Standard |
| 🗂️ Board Sort Order | Manual · Name · Created · Modified | Modified |
### Per-Board Settings
| Setting | Options | Default |
|---|---|---|
| 🖼️ Background | None · Dots · Grid · Gradient | None |
| 📎 Attachment Mode | Link to original · Copy into board | Link |
### Per-Column Settings
| Setting | Options |
|---|---|
| 📏 Width | Narrow · Standard · Wide |
| 🎨 Color | 10 hues or None |
| 🚦 WIP Limit | None · 3 · 5 · 7 · 10 |
| 📌 Collapsed | Toggle on/off |
---
## 🛠️ Tech Stack
| Layer | Technology |
|---|---|
| 🦀 Runtime | [Tauri v2](https://v2.tauri.app/) — lightweight, native, no Electron bloat |
| ⚛️ Frontend | [React 19](https://react.dev/) + [TypeScript 5.8](https://www.typescriptlang.org/) |
| 🎨 Styling | [Tailwind CSS 4](https://tailwindcss.com/) + [Radix UI](https://www.radix-ui.com/) primitives |
| 🧠 State | [Zustand 5](https://zustand.docs.pmnd.rs/) + [Zundo](https://github.com/charkour/zundo) (50-step undo/redo) |
| 🖱️ Drag & Drop | [dnd-kit](https://dndkit.com/) |
| 🎬 Animation | [Framer Motion](https://www.framer.com/motion/) |
| ✅ Validation | [Zod](https://zod.dev/) |
| 🔣 Icons | [Lucide](https://lucide.dev/) |
| 📝 Markdown | [react-markdown](https://github.com/remarkjs/react-markdown) + [remark-gfm](https://github.com/remarkjs/remark-gfm) |
| 📜 Scrollbars | [OverlayScrollbars](https://kingsora.github.io/OverlayScrollbars/) |
| 🔤 Typography | [Epilogue](https://fonts.google.com/specimen/Epilogue) · [Instrument Serif](https://fonts.google.com/specimen/Instrument+Serif) · [Space Mono](https://fonts.google.com/specimen/Space+Mono) |
---
## 📁 Project Structure
```
openpylon/
├── src/ # React frontend
│ ├── components/
│ │ ├── board/ # Board view — columns, cards, filter bar, drag overlays
│ │ ├── boards/ # Board list — grid, new board dialog, board cards
│ │ ├── card-detail/ # Card modal — markdown, checklists, labels, priority,
│ │ │ # due dates, attachments, comments, cover colors
│ │ ├── command-palette/ # Ctrl+K fuzzy search across everything
│ │ ├── import-export/ # Import/export buttons and file handling
│ │ ├── layout/ # Top bar, window controls, frameless chrome
│ │ ├── settings/ # Settings dialog with tabs
│ │ └── ui/ # Shared primitives (button, dialog, tooltip, popover…)
│ ├── hooks/ # Keyboard shortcuts, keyboard card navigation
│ ├── lib/ # Storage, import/export, board factory, motion presets
│ ├── stores/ # Zustand — app store, board store, toast store
│ └── types/ # TypeScript interfaces and type definitions
├── src-tauri/ # Tauri / Rust backend
│ ├── src/
│ │ ├── lib.rs # Plugin registration, portable data dir command
│ │ └── main.rs # Entry point
│ ├── capabilities/ # Tauri security permissions
│ ├── icons/ # App icons (ICO, ICNS, PNG)
│ ├── Cargo.toml # Rust dependencies
│ └── tauri.conf.json # Tauri app configuration
├── docs/plans/ # Design documents and implementation plans
├── package.json
└── README.md # You are here
```
---
## 🧑‍💻 Development
```bash
# Start dev server with hot reload (Vite + Cargo watch)
npm run tauri dev
# Type-check the frontend
npx tsc --noEmit
# Production build (exe + installers)
npm run tauri build
```
The dev server runs on `http://localhost:1420` with Vite HMR. Rust backend changes trigger automatic recompilation through Cargo watch.
### Contributing
OpenPylon is released into the public domain under CC0 1.0. There's no CLA, no copyright assignment, no gatekeeping. If you want to contribute, just open a PR. If you want to fork it and build something entirely different, go ahead — no permission needed.
Good things happen when tools are shared freely.
---
## 📄 License
<p align="center">
<a href="https://creativecommons.org/publicdomain/zero/1.0/">
<img src="https://licensebuttons.net/p/zero/1.0/88x31.png" alt="CC0 1.0" />
</a>
</p>
**CC0 1.0 Universal — Public Domain Dedication**
To the extent possible under law, the authors of OpenPylon have waived all copyright and related rights to this software. This work is published from the United States.
You can copy, modify, distribute, and use this software — even for commercial purposes — without asking permission and without owing anyone anything.
See [LICENSE](LICENSE) or https://creativecommons.org/publicdomain/zero/1.0/ for details.
---
<p align="center">
<sub>
Made with care. Shared without conditions.
<br />
Your tools should serve you — not the other way around.
</sub>
</p>

98
src-tauri/Cargo.lock generated
View File

@@ -1929,6 +1929,18 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "mac-notification-sys"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fd3f75411f4725061682ed91f131946e912859d0044d39c4ec0aac818d7621"
dependencies = [
"cc",
"objc2",
"objc2-foundation",
"time",
]
[[package]]
name = "markup5ever"
version = "0.14.1"
@@ -2065,6 +2077,20 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "notify-rust"
version = "4.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21af20a1b50be5ac5861f74af1a863da53a11c38684d9818d82f1c42f7fdc6c2"
dependencies = [
"futures-lite",
"log",
"mac-notification-sys",
"serde",
"tauri-winrt-notification",
"zbus",
]
[[package]]
name = "num-conv"
version = "0.2.0"
@@ -2342,6 +2368,7 @@ dependencies = [
"tauri-build",
"tauri-plugin-dialog",
"tauri-plugin-fs",
"tauri-plugin-notification",
"tauri-plugin-opener",
"tauri-plugin-shell",
]
@@ -2609,7 +2636,7 @@ checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07"
dependencies = [
"base64 0.22.1",
"indexmap 2.13.0",
"quick-xml",
"quick-xml 0.38.4",
"serde",
"time",
]
@@ -2749,6 +2776,15 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-xml"
version = "0.37.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
dependencies = [
"memchr",
]
[[package]]
name = "quick-xml"
version = "0.38.4"
@@ -2798,6 +2834,16 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.5",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
@@ -2818,6 +2864,16 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.5",
]
[[package]]
name = "rand_core"
version = "0.5.1"
@@ -2836,6 +2892,15 @@ dependencies = [
"getrandom 0.2.17",
]
[[package]]
name = "rand_core"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
dependencies = [
"getrandom 0.3.4",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
@@ -3745,6 +3810,25 @@ dependencies = [
"url",
]
[[package]]
name = "tauri-plugin-notification"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc"
dependencies = [
"log",
"notify-rust",
"rand 0.9.2",
"serde",
"serde_json",
"serde_repr",
"tauri",
"tauri-plugin",
"thiserror 2.0.18",
"time",
"url",
]
[[package]]
name = "tauri-plugin-opener"
version = "2.5.3"
@@ -3889,6 +3973,18 @@ dependencies = [
"toml 0.9.12+spec-1.1.0",
]
[[package]]
name = "tauri-winrt-notification"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b1e66e07de489fe43a46678dd0b8df65e0c973909df1b60ba33874e297ba9b9"
dependencies = [
"quick-xml 0.37.5",
"thiserror 2.0.18",
"windows",
"windows-version",
]
[[package]]
name = "tempfile"
version = "3.25.0"

View File

@@ -5,7 +5,7 @@ import { Slot } from "radix-ui"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium leading-none transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 [&_svg]:-translate-y-px outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{
variants: {
variant: {