cronixui 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -2
- package/packages/go/cronixui/cronixui.go +379 -0
- package/packages/go/cronixui/go.mod +3 -0
- package/packages/go/cronixui/tokens.go +129 -0
- package/packages/python/cronixui/__init__.py +109 -0
- package/packages/python/cronixui/accordion.py +29 -0
- package/packages/python/cronixui/command_palette.py +53 -0
- package/packages/python/cronixui/core.py +48 -0
- package/packages/python/cronixui/dropdown.py +26 -0
- package/packages/python/cronixui/modal.py +22 -0
- package/packages/python/cronixui/nav.py +31 -0
- package/packages/python/cronixui/pagination.py +58 -0
- package/packages/python/cronixui/pyproject.toml +11 -0
- package/packages/python/cronixui/search.py +50 -0
- package/packages/python/cronixui/tabs.py +18 -0
- package/packages/python/cronixui/toast.py +73 -0
- package/packages/python/cronixui/toggle.py +22 -0
- package/packages/python/cronixui/tokens.py +200 -0
- package/packages/rust/cronixui/src/accordion.rs +49 -0
- package/packages/rust/cronixui/src/command_palette.rs +62 -0
- package/packages/rust/cronixui/src/dropdown.rs +31 -0
- package/packages/rust/cronixui/src/lib.rs +81 -0
- package/packages/rust/cronixui/src/modal.rs +27 -0
- package/packages/rust/cronixui/src/pagination.rs +37 -0
- package/packages/rust/cronixui/src/search.rs +49 -0
- package/packages/rust/cronixui/src/tabs.rs +23 -0
- package/packages/rust/cronixui/src/toast.rs +70 -0
- package/packages/rust/cronixui/src/toggle.rs +27 -0
- package/packages/rust/cronixui/src/tokens.rs +137 -0
- package/packages/web/src/index.js +2 -0
- package/packages/web/src/index.mjs +2 -0
- package/packages/web/src/tokens.ts +120 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
pub struct CommandPaletteItem {
|
|
2
|
+
pub title: String,
|
|
3
|
+
pub kbd: Option<String>,
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
impl CommandPaletteItem {
|
|
7
|
+
pub fn new(title: impl Into<String>) -> Self {
|
|
8
|
+
Self {
|
|
9
|
+
title: title.into(),
|
|
10
|
+
kbd: None,
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn kbd(mut self, kbd: impl Into<String>) -> Self {
|
|
15
|
+
self.kbd = Some(kbd.into());
|
|
16
|
+
self
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub struct CommandPalette {
|
|
21
|
+
open: bool,
|
|
22
|
+
items: Vec<CommandPaletteItem>,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
impl CommandPalette {
|
|
26
|
+
pub fn new() -> Self {
|
|
27
|
+
Self {
|
|
28
|
+
open: false,
|
|
29
|
+
items: Vec::new(),
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pub fn open(&mut self) {
|
|
34
|
+
self.open = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
pub fn close(&mut self) {
|
|
38
|
+
self.open = false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
pub fn toggle(&mut self) {
|
|
42
|
+
self.open = !self.open;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
pub fn is_open(&self) -> bool {
|
|
46
|
+
self.open
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pub fn set_items(&mut self, items: Vec<CommandPaletteItem>) {
|
|
50
|
+
self.items = items;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
pub fn items(&self) -> &[CommandPaletteItem] {
|
|
54
|
+
&self.items
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
impl Default for CommandPalette {
|
|
59
|
+
fn default() -> Self {
|
|
60
|
+
Self::new()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
pub struct Dropdown {
|
|
2
|
+
open: bool,
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
impl Dropdown {
|
|
6
|
+
pub fn new() -> Self {
|
|
7
|
+
Self { open: false }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
pub fn open(&mut self) {
|
|
11
|
+
self.open = true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn close(&mut self) {
|
|
15
|
+
self.open = false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn toggle(&mut self) {
|
|
19
|
+
self.open = !self.open;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pub fn is_open(&self) -> bool {
|
|
23
|
+
self.open
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
impl Default for Dropdown {
|
|
28
|
+
fn default() -> Self {
|
|
29
|
+
Self::new()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//! CronixUI - A dark-themed UI toolkit with crimson accents and Outfit typography
|
|
2
|
+
//!
|
|
3
|
+
//! ## Example
|
|
4
|
+
//!
|
|
5
|
+
//! ```rust
|
|
6
|
+
//! use cronixui::{Toast, Toggle, Modal};
|
|
7
|
+
//!
|
|
8
|
+
//! // Create a toast
|
|
9
|
+
//! let toast = Toast::success("Operation completed!");
|
|
10
|
+
//!
|
|
11
|
+
//! // Create a toggle
|
|
12
|
+
//! let mut toggle = Toggle::new();
|
|
13
|
+
//! toggle.toggle();
|
|
14
|
+
//! assert!(toggle.is_on());
|
|
15
|
+
//! ```
|
|
16
|
+
|
|
17
|
+
pub const VERSION: &str = "1.0.4";
|
|
18
|
+
|
|
19
|
+
mod toast;
|
|
20
|
+
mod toggle;
|
|
21
|
+
mod modal;
|
|
22
|
+
mod dropdown;
|
|
23
|
+
mod tabs;
|
|
24
|
+
mod accordion;
|
|
25
|
+
mod pagination;
|
|
26
|
+
mod command_palette;
|
|
27
|
+
mod search;
|
|
28
|
+
mod tokens;
|
|
29
|
+
|
|
30
|
+
pub use toast::{Toast, ToastType};
|
|
31
|
+
pub use toggle::Toggle;
|
|
32
|
+
pub use modal::Modal;
|
|
33
|
+
pub use dropdown::Dropdown;
|
|
34
|
+
pub use tabs::Tabs;
|
|
35
|
+
pub use accordion::Accordion;
|
|
36
|
+
pub use pagination::Pagination;
|
|
37
|
+
pub use command_palette::{CommandPalette, CommandPaletteItem};
|
|
38
|
+
pub use search::{Search, SearchItem};
|
|
39
|
+
pub use tokens::*;
|
|
40
|
+
|
|
41
|
+
/// Initialize CronixUI
|
|
42
|
+
pub fn init() {
|
|
43
|
+
println!("CronixUI {} initialized", VERSION);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#[cfg(test)]
|
|
47
|
+
mod tests {
|
|
48
|
+
use super::*;
|
|
49
|
+
|
|
50
|
+
#[test]
|
|
51
|
+
fn test_toggle() {
|
|
52
|
+
let mut toggle = Toggle::new();
|
|
53
|
+
assert!(!toggle.is_on());
|
|
54
|
+
toggle.toggle();
|
|
55
|
+
assert!(toggle.is_on());
|
|
56
|
+
toggle.set_on(false);
|
|
57
|
+
assert!(!toggle.is_on());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#[test]
|
|
61
|
+
fn test_pagination() {
|
|
62
|
+
let mut pagination = Pagination::new(10, 1);
|
|
63
|
+
assert_eq!(pagination.current(), 1);
|
|
64
|
+
pagination.next();
|
|
65
|
+
assert_eq!(pagination.current(), 2);
|
|
66
|
+
pagination.go_to(5);
|
|
67
|
+
assert_eq!(pagination.current(), 5);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#[test]
|
|
71
|
+
fn test_search() {
|
|
72
|
+
let mut search = Search::new();
|
|
73
|
+
search.set_items(vec![
|
|
74
|
+
SearchItem::new("Apple"),
|
|
75
|
+
SearchItem::new("Banana"),
|
|
76
|
+
SearchItem::new("Apricot"),
|
|
77
|
+
]);
|
|
78
|
+
let results = search.filter("ap");
|
|
79
|
+
assert_eq!(results.len(), 2);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
pub struct Modal {
|
|
2
|
+
open: bool,
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
impl Modal {
|
|
6
|
+
pub fn new() -> Self {
|
|
7
|
+
Self { open: false }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
pub fn open(&mut self) {
|
|
11
|
+
self.open = true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn close(&mut self) {
|
|
15
|
+
self.open = false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn is_open(&self) -> bool {
|
|
19
|
+
self.open
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
impl Default for Modal {
|
|
24
|
+
fn default() -> Self {
|
|
25
|
+
Self::new()
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
pub struct Pagination {
|
|
2
|
+
total: usize,
|
|
3
|
+
current: usize,
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
impl Pagination {
|
|
7
|
+
pub fn new(total: usize, current: usize) -> Self {
|
|
8
|
+
let current = current.clamp(1, total.max(1));
|
|
9
|
+
Self { total, current }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
pub fn go_to(&mut self, page: usize) {
|
|
13
|
+
if page >= 1 && page <= self.total {
|
|
14
|
+
self.current = page;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn current(&self) -> usize {
|
|
19
|
+
self.current
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pub fn total(&self) -> usize {
|
|
23
|
+
self.total
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
pub fn next(&mut self) {
|
|
27
|
+
if self.current < self.total {
|
|
28
|
+
self.current += 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pub fn prev(&mut self) {
|
|
33
|
+
if self.current > 1 {
|
|
34
|
+
self.current -= 1;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
pub struct SearchItem {
|
|
2
|
+
pub title: String,
|
|
3
|
+
pub subtitle: Option<String>,
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
impl SearchItem {
|
|
7
|
+
pub fn new(title: impl Into<String>) -> Self {
|
|
8
|
+
Self {
|
|
9
|
+
title: title.into(),
|
|
10
|
+
subtitle: None,
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn subtitle(mut self, subtitle: impl Into<String>) -> Self {
|
|
15
|
+
self.subtitle = Some(subtitle.into());
|
|
16
|
+
self
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub struct Search {
|
|
21
|
+
items: Vec<SearchItem>,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
impl Search {
|
|
25
|
+
pub fn new() -> Self {
|
|
26
|
+
Self { items: Vec::new() }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
pub fn set_items(&mut self, items: Vec<SearchItem>) {
|
|
30
|
+
self.items = items;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pub fn filter(&self, query: &str) -> Vec<&SearchItem> {
|
|
34
|
+
self.items
|
|
35
|
+
.iter()
|
|
36
|
+
.filter(|item| item.title.to_lowercase().contains(&query.to_lowercase()))
|
|
37
|
+
.collect()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pub fn items(&self) -> &[SearchItem] {
|
|
41
|
+
&self.items
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
impl Default for Search {
|
|
46
|
+
fn default() -> Self {
|
|
47
|
+
Self::new()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
pub struct Tabs {
|
|
2
|
+
active_index: usize,
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
impl Tabs {
|
|
6
|
+
pub fn new() -> Self {
|
|
7
|
+
Self { active_index: 0 }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
pub fn set_active(&mut self, index: usize) {
|
|
11
|
+
self.active_index = index;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn active_index(&self) -> usize {
|
|
15
|
+
self.active_index
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
impl Default for Tabs {
|
|
20
|
+
fn default() -> Self {
|
|
21
|
+
Self::new()
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
use std::fmt;
|
|
2
|
+
|
|
3
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
4
|
+
pub enum ToastType {
|
|
5
|
+
Success,
|
|
6
|
+
Error,
|
|
7
|
+
Warning,
|
|
8
|
+
Info,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
impl fmt::Display for ToastType {
|
|
12
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
13
|
+
match self {
|
|
14
|
+
ToastType::Success => write!(f, "success"),
|
|
15
|
+
ToastType::Error => write!(f, "error"),
|
|
16
|
+
ToastType::Warning => write!(f, "warning"),
|
|
17
|
+
ToastType::Info => write!(f, "info"),
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#[derive(Debug, Clone)]
|
|
23
|
+
pub struct Toast {
|
|
24
|
+
pub title: Option<String>,
|
|
25
|
+
pub message: String,
|
|
26
|
+
pub toast_type: ToastType,
|
|
27
|
+
pub duration: u32,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
impl Toast {
|
|
31
|
+
pub fn show(message: impl Into<String>) -> Self {
|
|
32
|
+
Self {
|
|
33
|
+
title: None,
|
|
34
|
+
message: message.into(),
|
|
35
|
+
toast_type: ToastType::Info,
|
|
36
|
+
duration: 4000,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pub fn title(mut self, title: impl Into<String>) -> Self {
|
|
41
|
+
self.title = Some(title.into());
|
|
42
|
+
self
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
pub fn toast_type(mut self, toast_type: ToastType) -> Self {
|
|
46
|
+
self.toast_type = toast_type;
|
|
47
|
+
self
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
pub fn duration(mut self, duration: u32) -> Self {
|
|
51
|
+
self.duration = duration;
|
|
52
|
+
self
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
pub fn success(message: impl Into<String>) -> Self {
|
|
56
|
+
Self::show(message).toast_type(ToastType::Success)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
pub fn error(message: impl Into<String>) -> Self {
|
|
60
|
+
Self::show(message).toast_type(ToastType::Error)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pub fn warning(message: impl Into<String>) -> Self {
|
|
64
|
+
Self::show(message).toast_type(ToastType::Warning)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
pub fn info(message: impl Into<String>) -> Self {
|
|
68
|
+
Self::show(message).toast_type(ToastType::Info)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
pub struct Toggle {
|
|
2
|
+
on: bool,
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
impl Toggle {
|
|
6
|
+
pub fn new() -> Self {
|
|
7
|
+
Self { on: false }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
pub fn toggle(&mut self) {
|
|
11
|
+
self.on = !self.on;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn is_on(&self) -> bool {
|
|
15
|
+
self.on
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn set_on(&mut self, value: bool) {
|
|
19
|
+
self.on = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
impl Default for Toggle {
|
|
24
|
+
fn default() -> Self {
|
|
25
|
+
Self::new()
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
//! Design tokens for CronixUI
|
|
2
|
+
|
|
3
|
+
use std::fmt;
|
|
4
|
+
|
|
5
|
+
/// Color representation
|
|
6
|
+
#[derive(Debug, Clone, Copy)]
|
|
7
|
+
pub struct Color {
|
|
8
|
+
pub hex: &'static str,
|
|
9
|
+
pub r: u8,
|
|
10
|
+
pub g: u8,
|
|
11
|
+
pub b: u8,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl fmt::Display for Color {
|
|
15
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
16
|
+
write!(f, "{}", self.hex)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Background colors
|
|
21
|
+
pub const BG: Color = Color { hex: "#0a0a0a", r: 10, g: 10, b: 10 };
|
|
22
|
+
pub const SURFACE: Color = Color { hex: "#111111", r: 17, g: 17, b: 17 };
|
|
23
|
+
pub const SURFACE_2: Color = Color { hex: "#1a1a1a", r: 26, g: 26, b: 26 };
|
|
24
|
+
pub const SURFACE_3: Color = Color { hex: "#222222", r: 34, g: 34, b: 34 };
|
|
25
|
+
pub const SURFACE_4: Color = Color { hex: "#2a2a2a", r: 42, g: 42, b: 42 };
|
|
26
|
+
|
|
27
|
+
// Text colors
|
|
28
|
+
pub const TEXT: Color = Color { hex: "#f0ede8", r: 240, g: 237, b: 232 };
|
|
29
|
+
pub const TEXT_MUTED: &str = "rgba(240, 237, 232, 0.5)";
|
|
30
|
+
pub const TEXT_DIM: &str = "rgba(240, 237, 232, 0.25)";
|
|
31
|
+
|
|
32
|
+
// Accent colors (Crimson)
|
|
33
|
+
pub const ACCENT: Color = Color { hex: "#6b2323", r: 107, g: 35, b: 35 };
|
|
34
|
+
pub const ACCENT_HOVER: Color = Color { hex: "#7d2a2a", r: 125, g: 42, b: 42 };
|
|
35
|
+
pub const ACCENT_LIGHT: Color = Color { hex: "#8a3535", r: 138, g: 53, b: 53 };
|
|
36
|
+
pub const ACCENT_GLOW: &str = "rgba(107, 35, 35, 0.3)";
|
|
37
|
+
pub const ACCENT_TEXT: Color = Color { hex: "#c97a7a", r: 201, g: 122, b: 122 };
|
|
38
|
+
|
|
39
|
+
// Semantic colors - Success
|
|
40
|
+
pub const SUCCESS: Color = Color { hex: "#1e5028", r: 30, g: 80, b: 40 };
|
|
41
|
+
pub const SUCCESS_BORDER: &str = "rgba(60, 140, 70, 0.4)";
|
|
42
|
+
pub const SUCCESS_TEXT: Color = Color { hex: "#6bc47a", r: 107, g: 196, b: 122 };
|
|
43
|
+
|
|
44
|
+
// Semantic colors - Warning
|
|
45
|
+
pub const WARNING: Color = Color { hex: "#503c14", r: 80, g: 60, b: 20 };
|
|
46
|
+
pub const WARNING_BORDER: &str = "rgba(150, 110, 30, 0.4)";
|
|
47
|
+
pub const WARNING_TEXT: Color = Color { hex: "#c4a43a", r: 196, g: 164, b: 58 };
|
|
48
|
+
|
|
49
|
+
// Semantic colors - Error
|
|
50
|
+
pub const ERROR: Color = Color { hex: "#501414", r: 80, g: 20, b: 20 };
|
|
51
|
+
pub const ERROR_BORDER: &str = "rgba(180, 60, 60, 0.4)";
|
|
52
|
+
pub const ERROR_TEXT: Color = Color { hex: "#c46b6b", r: 196, g: 107, b: 107 };
|
|
53
|
+
|
|
54
|
+
// Semantic colors - Info
|
|
55
|
+
pub const INFO: Color = Color { hex: "#143550", r: 20, g: 53, b: 80 };
|
|
56
|
+
pub const INFO_BORDER: &str = "rgba(60, 140, 200, 0.4)";
|
|
57
|
+
pub const INFO_TEXT: Color = Color { hex: "#6ba8c4", r: 107, g: 168, b: 196 };
|
|
58
|
+
|
|
59
|
+
// Border colors
|
|
60
|
+
pub const BORDER: &str = "rgba(255, 255, 255, 0.08)";
|
|
61
|
+
pub const BORDER_HOVER: &str = "rgba(255, 255, 255, 0.15)";
|
|
62
|
+
pub const BORDER_FOCUS: &str = "rgba(255, 255, 255, 0.25)";
|
|
63
|
+
|
|
64
|
+
// Typography
|
|
65
|
+
pub const FONT_FAMILY: &str = "'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
|
|
66
|
+
pub const FONT_MONO: &str = "'JetBrains Mono', 'Fira Code', 'Consolas', monospace";
|
|
67
|
+
|
|
68
|
+
pub const FONT_SIZE_XS: u8 = 11;
|
|
69
|
+
pub const FONT_SIZE_SM: u8 = 12;
|
|
70
|
+
pub const FONT_SIZE_BASE: u8 = 13;
|
|
71
|
+
pub const FONT_SIZE_MD: u8 = 14;
|
|
72
|
+
pub const FONT_SIZE_LG: u8 = 16;
|
|
73
|
+
pub const FONT_SIZE_XL: u8 = 20;
|
|
74
|
+
pub const FONT_SIZE_2XL: u8 = 28;
|
|
75
|
+
pub const FONT_SIZE_3XL: u8 = 36;
|
|
76
|
+
|
|
77
|
+
// Spacing
|
|
78
|
+
pub const SPACE_1: u8 = 4;
|
|
79
|
+
pub const SPACE_2: u8 = 8;
|
|
80
|
+
pub const SPACE_3: u8 = 12;
|
|
81
|
+
pub const SPACE_4: u8 = 16;
|
|
82
|
+
pub const SPACE_5: u8 = 20;
|
|
83
|
+
pub const SPACE_6: u8 = 24;
|
|
84
|
+
pub const SPACE_8: u8 = 32;
|
|
85
|
+
pub const SPACE_10: u8 = 40;
|
|
86
|
+
pub const SPACE_12: u8 = 48;
|
|
87
|
+
|
|
88
|
+
// Border radius
|
|
89
|
+
pub const RADIUS_SM: u8 = 6;
|
|
90
|
+
pub const RADIUS: u8 = 10;
|
|
91
|
+
pub const RADIUS_LG: u8 = 14;
|
|
92
|
+
pub const RADIUS_XL: u8 = 20;
|
|
93
|
+
pub const RADIUS_FULL: u16 = 9999;
|
|
94
|
+
|
|
95
|
+
// Shadows
|
|
96
|
+
pub const SHADOW_SM: &str = "0 1px 2px rgba(0, 0, 0, 0.3)";
|
|
97
|
+
pub const SHADOW: &str = "0 4px 12px rgba(0, 0, 0, 0.4)";
|
|
98
|
+
pub const SHADOW_LG: &str = "0 8px 24px rgba(0, 0, 0, 0.5)";
|
|
99
|
+
pub const SHADOW_GLOW: &str = "0 0 20px rgba(107, 35, 35, 0.3)";
|
|
100
|
+
|
|
101
|
+
// Transitions
|
|
102
|
+
pub const TRANSITION_FAST: &str = "0.1s ease";
|
|
103
|
+
pub const TRANSITION_DEFAULT: &str = "0.15s ease";
|
|
104
|
+
pub const TRANSITION_SLOW: &str = "0.25s ease";
|
|
105
|
+
|
|
106
|
+
// Z-index
|
|
107
|
+
pub const Z_INDEX_DROPDOWN: u16 = 100;
|
|
108
|
+
pub const Z_INDEX_STICKY: u16 = 200;
|
|
109
|
+
pub const Z_INDEX_FIXED: u16 = 300;
|
|
110
|
+
pub const Z_INDEX_MODAL_BACKDROP: u16 = 400;
|
|
111
|
+
pub const Z_INDEX_MODAL: u16 = 500;
|
|
112
|
+
pub const Z_INDEX_POPOVER: u16 = 600;
|
|
113
|
+
pub const Z_INDEX_TOOLTIP: u16 = 700;
|
|
114
|
+
pub const Z_INDEX_TOAST: u16 = 800;
|
|
115
|
+
|
|
116
|
+
// Layout
|
|
117
|
+
pub const CONTAINER_MAX: u16 = 1200;
|
|
118
|
+
pub const SIDEBAR_WIDTH: u16 = 260;
|
|
119
|
+
|
|
120
|
+
#[cfg(test)]
|
|
121
|
+
mod tests {
|
|
122
|
+
use super::*;
|
|
123
|
+
|
|
124
|
+
#[test]
|
|
125
|
+
fn test_colors() {
|
|
126
|
+
assert_eq!(BG.hex, "#0a0a0a");
|
|
127
|
+
assert_eq!(ACCENT.hex, "#6b2323");
|
|
128
|
+
assert_eq!(TEXT.r, 240);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#[test]
|
|
132
|
+
fn test_spacing() {
|
|
133
|
+
assert_eq!(SPACE_1, 4);
|
|
134
|
+
assert_eq!(SPACE_4, 16);
|
|
135
|
+
assert_eq!(SPACE_12, 48);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
export interface ColorToken {
|
|
2
|
+
hex: string;
|
|
3
|
+
r: number;
|
|
4
|
+
g: number;
|
|
5
|
+
b: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Background colors
|
|
9
|
+
export const BG: ColorToken = { hex: '#0a0a0a', r: 10, g: 10, b: 10 };
|
|
10
|
+
export const SURFACE: ColorToken = { hex: '#111111', r: 17, g: 17, b: 17 };
|
|
11
|
+
export const SURFACE_2: ColorToken = { hex: '#1a1a1a', r: 26, g: 26, b: 26 };
|
|
12
|
+
export const SURFACE_3: ColorToken = { hex: '#222222', r: 34, g: 34, b: 34 };
|
|
13
|
+
export const SURFACE_4: ColorToken = { hex: '#2a2a2a', r: 42, g: 42, b: 42 };
|
|
14
|
+
|
|
15
|
+
// Text colors
|
|
16
|
+
export const TEXT: ColorToken = { hex: '#f0ede8', r: 240, g: 237, b: 232 };
|
|
17
|
+
export const TEXT_MUTED = 'rgba(240, 237, 232, 0.5)' as const;
|
|
18
|
+
export const TEXT_DIM = 'rgba(240, 237, 232, 0.25)' as const;
|
|
19
|
+
|
|
20
|
+
// Accent colors (Crimson)
|
|
21
|
+
export const ACCENT: ColorToken = { hex: '#6b2323', r: 107, g: 35, b: 35 };
|
|
22
|
+
export const ACCENT_HOVER: ColorToken = { hex: '#7d2a2a', r: 125, g: 42, b: 42 };
|
|
23
|
+
export const ACCENT_LIGHT: ColorToken = { hex: '#8a3535', r: 138, g: 53, b: 53 };
|
|
24
|
+
export const ACCENT_GLOW = 'rgba(107, 35, 35, 0.3)' as const;
|
|
25
|
+
export const ACCENT_TEXT: ColorToken = { hex: '#c97a7a', r: 201, g: 122, b: 122 };
|
|
26
|
+
|
|
27
|
+
// Semantic colors - Success
|
|
28
|
+
export const SUCCESS: ColorToken = { hex: '#1e5028', r: 30, g: 80, b: 40 };
|
|
29
|
+
export const SUCCESS_BORDER = 'rgba(60, 140, 70, 0.4)' as const;
|
|
30
|
+
export const SUCCESS_TEXT: ColorToken = { hex: '#6bc47a', r: 107, g: 196, b: 122 };
|
|
31
|
+
|
|
32
|
+
// Semantic colors - Warning
|
|
33
|
+
export const WARNING: ColorToken = { hex: '#503c14', r: 80, g: 60, b: 20 };
|
|
34
|
+
export const WARNING_BORDER = 'rgba(150, 110, 30, 0.4)' as const;
|
|
35
|
+
export const WARNING_TEXT: ColorToken = { hex: '#c4a43a', r: 196, g: 164, b: 58 };
|
|
36
|
+
|
|
37
|
+
// Semantic colors - Error
|
|
38
|
+
export const ERROR: ColorToken = { hex: '#501414', r: 80, g: 20, b: 20 };
|
|
39
|
+
export const ERROR_BORDER = 'rgba(180, 60, 60, 0.4)' as const;
|
|
40
|
+
export const ERROR_TEXT: ColorToken = { hex: '#c46b6b', r: 196, g: 107, b: 107 };
|
|
41
|
+
|
|
42
|
+
// Semantic colors - Info
|
|
43
|
+
export const INFO: ColorToken = { hex: '#143550', r: 20, g: 53, b: 80 };
|
|
44
|
+
export const INFO_BORDER = 'rgba(60, 140, 200, 0.4)' as const;
|
|
45
|
+
export const INFO_TEXT: ColorToken = { hex: '#6ba8c4', r: 107, g: 168, b: 196 };
|
|
46
|
+
|
|
47
|
+
// Border colors
|
|
48
|
+
export const BORDER = 'rgba(255, 255, 255, 0.08)' as const;
|
|
49
|
+
export const BORDER_HOVER = 'rgba(255, 255, 255, 0.15)' as const;
|
|
50
|
+
export const BORDER_FOCUS = 'rgba(255, 255, 255, 0.25)' as const;
|
|
51
|
+
|
|
52
|
+
// Typography
|
|
53
|
+
export const FONT_FAMILY = "'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" as const;
|
|
54
|
+
export const FONT_MONO = "'JetBrains Mono', 'Fira Code', 'Consolas', monospace" as const;
|
|
55
|
+
|
|
56
|
+
export const FONT_SIZE = {
|
|
57
|
+
xs: 11,
|
|
58
|
+
sm: 12,
|
|
59
|
+
base: 13,
|
|
60
|
+
md: 14,
|
|
61
|
+
lg: 16,
|
|
62
|
+
xl: 20,
|
|
63
|
+
'2xl': 28,
|
|
64
|
+
'3xl': 36,
|
|
65
|
+
} as const;
|
|
66
|
+
|
|
67
|
+
// Spacing
|
|
68
|
+
export const SPACE = {
|
|
69
|
+
1: 4,
|
|
70
|
+
2: 8,
|
|
71
|
+
3: 12,
|
|
72
|
+
4: 16,
|
|
73
|
+
5: 20,
|
|
74
|
+
6: 24,
|
|
75
|
+
8: 32,
|
|
76
|
+
10: 40,
|
|
77
|
+
12: 48,
|
|
78
|
+
} as const;
|
|
79
|
+
|
|
80
|
+
// Border radius
|
|
81
|
+
export const RADIUS = {
|
|
82
|
+
sm: 6,
|
|
83
|
+
default: 10,
|
|
84
|
+
lg: 14,
|
|
85
|
+
xl: 20,
|
|
86
|
+
full: 9999,
|
|
87
|
+
} as const;
|
|
88
|
+
|
|
89
|
+
// Shadows
|
|
90
|
+
export const SHADOW = {
|
|
91
|
+
sm: '0 1px 2px rgba(0, 0, 0, 0.3)',
|
|
92
|
+
default: '0 4px 12px rgba(0, 0, 0, 0.4)',
|
|
93
|
+
lg: '0 8px 24px rgba(0, 0, 0, 0.5)',
|
|
94
|
+
glow: '0 0 20px rgba(107, 35, 35, 0.3)',
|
|
95
|
+
} as const;
|
|
96
|
+
|
|
97
|
+
// Transitions
|
|
98
|
+
export const TRANSITION = {
|
|
99
|
+
fast: '0.1s ease',
|
|
100
|
+
default: '0.15s ease',
|
|
101
|
+
slow: '0.25s ease',
|
|
102
|
+
} as const;
|
|
103
|
+
|
|
104
|
+
// Z-index
|
|
105
|
+
export const Z_INDEX = {
|
|
106
|
+
dropdown: 100,
|
|
107
|
+
sticky: 200,
|
|
108
|
+
fixed: 300,
|
|
109
|
+
modalBackdrop: 400,
|
|
110
|
+
modal: 500,
|
|
111
|
+
popover: 600,
|
|
112
|
+
tooltip: 700,
|
|
113
|
+
toast: 800,
|
|
114
|
+
} as const;
|
|
115
|
+
|
|
116
|
+
// Layout
|
|
117
|
+
export const LAYOUT = {
|
|
118
|
+
containerMax: 1200,
|
|
119
|
+
sidebarWidth: 260,
|
|
120
|
+
} as const;
|