2 Commits

Author SHA1 Message Date
Marcos Paulo 22544b6d61 feat(ui): Catppuccin palettes (Latte, Frappé, Macchiato, Mocha)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 23:34:39 -03:00
Marcos Paulo a8c928ae82 chore: debrand ArtCraft references
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 23:31:11 -03:00
8 changed files with 191 additions and 2 deletions
+5
View File
@@ -0,0 +1,5 @@
# Strip upstream (ArtCraft / Discord) branding. Run: tools/craft-skills/skills/debrand/debrand.pl (--check in CI)
keep ^(LICENSE-(MIT|APACHE)|\.debrand)$
sub ; ArtCraft trademarks remain outside such a library\. => ; trademarks remain outside such a library.
forbid (?i)artcraft(?! Team and the [\w-]+ contributors)
forbid (?i)discord
+3
View File
@@ -0,0 +1,3 @@
[submodule "tools/craft-skills"]
path = tools/craft-skills
url = https://git.marcospaulo.dev.br/storytold/craft-skills.git
+3 -1
View File
@@ -4,4 +4,6 @@ Third-party assets bundled in this repository (fonts, icons, images, test data),
author, source and license. Library code and original assets are under the repository license
(MIT OR Apache-2.0, see [NOTICE](NOTICE)).
None yet.
| Path | Title | Author | Source | License |
| --- | --- | --- | --- | --- |
| `crates/ui/src/theme/catppuccin.rs` | Catppuccin Latte, Frappé, Macchiato and Mocha palettes | Catppuccin | https://catppuccin.com/palette | MIT (`crates/ui/LICENSE-catppuccin.txt`) |
+28
View File
@@ -0,0 +1,28 @@
Catppuccin
https://catppuccin.com/palette
https://github.com/catppuccin/catppuccin
The Catppuccin Latte, Frappé, Macchiato and Mocha themes' colour palettes in `catppuccin.rs`
are the Catppuccin project's palettes, used under the MIT License below.
MIT License
Copyright (c) 2021 Catppuccin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+148
View File
@@ -0,0 +1,148 @@
//! The Catppuccin colour palettes (Latte, Frappé, Macchiato, Mocha).
//!
//! Colours only: how they map onto an application's tokens stays with the application.
//! Palette: <https://catppuccin.com/palette> (MIT, see `LICENSE-catppuccin.txt`).
use egui::Color32;
/// The 26 named colours of one Catppuccin flavour.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Palette {
pub rosewater: Color32,
pub flamingo: Color32,
pub pink: Color32,
pub mauve: Color32,
pub red: Color32,
pub maroon: Color32,
pub peach: Color32,
pub yellow: Color32,
pub green: Color32,
pub teal: Color32,
pub sky: Color32,
pub sapphire: Color32,
pub blue: Color32,
pub lavender: Color32,
pub text: Color32,
pub subtext1: Color32,
pub subtext0: Color32,
pub overlay2: Color32,
pub overlay1: Color32,
pub overlay0: Color32,
pub surface2: Color32,
pub surface1: Color32,
pub surface0: Color32,
pub base: Color32,
pub mantle: Color32,
pub crust: Color32,
}
const fn rgb(hex: u32) -> Color32 {
Color32::from_rgb((hex >> 16) as u8, (hex >> 8) as u8, hex as u8)
}
impl Palette {
/// `h` in the field order above, as 0xRRGGBB.
const fn new(h: [u32; 26]) -> Self {
Self {
rosewater: rgb(h[0]),
flamingo: rgb(h[1]),
pink: rgb(h[2]),
mauve: rgb(h[3]),
red: rgb(h[4]),
maroon: rgb(h[5]),
peach: rgb(h[6]),
yellow: rgb(h[7]),
green: rgb(h[8]),
teal: rgb(h[9]),
sky: rgb(h[10]),
sapphire: rgb(h[11]),
blue: rgb(h[12]),
lavender: rgb(h[13]),
text: rgb(h[14]),
subtext1: rgb(h[15]),
subtext0: rgb(h[16]),
overlay2: rgb(h[17]),
overlay1: rgb(h[18]),
overlay0: rgb(h[19]),
surface2: rgb(h[20]),
surface1: rgb(h[21]),
surface0: rgb(h[22]),
base: rgb(h[23]),
mantle: rgb(h[24]),
crust: rgb(h[25]),
}
}
}
pub const LATTE: Palette = Palette::new([
0xdc8a78, 0xdd7878, 0xea76cb, 0x8839ef, 0xd20f39, 0xe64553, 0xfe640b, 0xdf8e1d, 0x40a02b, 0x179299, 0x04a5e5, 0x209fb5, 0x1e66f5, 0x7287fd,
0x4c4f69, 0x5c5f77, 0x6c6f85, 0x7c7f93, 0x8c8fa1, 0x9ca0b0, 0xacb0be, 0xbcc0cc, 0xccd0da, 0xeff1f5, 0xe6e9ef, 0xdce0e8,
]);
pub const FRAPPE: Palette = Palette::new([
0xf2d5cf, 0xeebebe, 0xf4b8e4, 0xca9ee6, 0xe78284, 0xea999c, 0xef9f76, 0xe5c890, 0xa6d189, 0x81c8be, 0x99d1db, 0x85c1dc, 0x8caaee, 0xbabbf1,
0xc6d0f5, 0xb5bfe2, 0xa5adce, 0x949cbb, 0x838ba7, 0x737994, 0x626880, 0x51576d, 0x414559, 0x303446, 0x292c3c, 0x232634,
]);
pub const MACCHIATO: Palette = Palette::new([
0xf4dbd6, 0xf0c6c6, 0xf5bde6, 0xc6a0f6, 0xed8796, 0xee99a0, 0xf5a97f, 0xeed49f, 0xa6da95, 0x8bd5ca, 0x91d7e3, 0x7dc4e4, 0x8aadf4, 0xb7bdf8,
0xcad3f5, 0xb8c0e0, 0xa5adcb, 0x939ab7, 0x8087a2, 0x6e738d, 0x5b6078, 0x494d64, 0x363a4f, 0x24273a, 0x1e2030, 0x181926,
]);
pub const MOCHA: Palette = Palette::new([
0xf5e0dc, 0xf2cdcd, 0xf5c2e7, 0xcba6f7, 0xf38ba8, 0xeba0ac, 0xfab387, 0xf9e2af, 0xa6e3a1, 0x94e2d5, 0x89dceb, 0x74c7ec, 0x89b4fa, 0xb4befe,
0xcdd6f4, 0xbac2de, 0xa6adc8, 0x9399b2, 0x7f849c, 0x6c7086, 0x585b70, 0x45475a, 0x313244, 0x1e1e2e, 0x181825, 0x11111b,
]);
/// The four Catppuccin flavours.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Flavor {
Latte,
Frappe,
Macchiato,
Mocha,
}
impl Flavor {
pub const ALL: [Flavor; 4] = [Flavor::Latte, Flavor::Frappe, Flavor::Macchiato, Flavor::Mocha];
pub const fn palette(self) -> &'static Palette {
match self {
Flavor::Latte => &LATTE,
Flavor::Frappe => &FRAPPE,
Flavor::Macchiato => &MACCHIATO,
Flavor::Mocha => &MOCHA,
}
}
/// Latte is the only light flavour.
pub const fn is_dark(self) -> bool {
!matches!(self, Flavor::Latte)
}
pub const fn name(self) -> &'static str {
match self {
Flavor::Latte => "Latte",
Flavor::Frappe => "Frappé",
Flavor::Macchiato => "Macchiato",
Flavor::Mocha => "Mocha",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_values_and_brightness() {
assert_eq!(Flavor::Mocha.palette().base, Color32::from_rgb(0x1e, 0x1e, 0x2e));
assert_eq!(Flavor::Latte.palette().mauve, Color32::from_rgb(0x88, 0x39, 0xef));
assert_eq!(Flavor::Frappe.palette().crust, Color32::from_rgb(0x23, 0x26, 0x34));
assert_eq!(Flavor::Macchiato.palette().text, Color32::from_rgb(0xca, 0xd3, 0xf5));
assert_eq!(Flavor::ALL.iter().filter(|f| !f.is_dark()).count(), 1);
for f in Flavor::ALL {
let p = f.palette();
// Text must contrast with the base surface in the right direction.
assert_eq!(p.text.r() > p.base.r(), f.is_dark(), "{}", f.name());
}
}
}
+2
View File
@@ -3,6 +3,8 @@
//! This module does not install fonts, store a theme, or change global visuals. Applications
//! decide their colors, borders, typography, spacing and saved preferences independently.
pub mod catppuccin;
use egui::{Color32, CornerRadius, Stroke, style::Widgets};
/// Background colors for egui's five widget interaction states.
+1 -1
View File
@@ -66,7 +66,7 @@ The SVG substitution is deliberately narrow: it preserves the existing literal r
PdfCraft resolves the fallback name before requesting a source, preserving its existing URI policy. This replaces its indexed fallback lookup with the shared non-panicking lookup; the shared absent-fallback test covers a catalog without that entry. No icon assets move.
Most other Rust apps draw icons with egui's painter. Converting them all to SVG would be a separate visual change with different cost and fidelity questions. Common icon assets are a future candidate after checking file hashes, ownership and each app's asset manifest; ArtCraft trademarks remain outside such a library.
Most other Rust apps draw icons with egui's painter. Converting them all to SVG would be a separate visual change with different cost and fidelity questions. Common icon assets are a future candidate after checking file hashes, ownership and each app's asset manifest; trademarks remain outside such a library.
## Themes and common controls
Submodule tools/craft-skills added at 26c1c201a7