1#![allow(clippy::too_many_lines)]
6
7use std::collections::BTreeMap;
8use std::error::Error;
9
10use tangible::color::{ColorDef, ColorSpace, GradientDef, GradientStop, InterpolationMode};
11use tangible::spec::{
12 Borders, Elevation, Fonts, Glow, Gradient, InkConfig, Scales, SemanticValue, Shadows,
13 TextShadowElevation,
14};
15use tangible::{Renderer, Spec};
16
17fn main() -> Result<(), Box<dyn Error>> {
18 let mut colors = BTreeMap::new();
19 colors.insert(
20 "neutral".into(),
21 ColorDef::Explicit(vec!["#f5f5f5".into(), "#888888".into(), "#1a1a1a".into()]),
22 );
23 colors.insert(
24 "primary".into(),
25 ColorDef::Gradient(GradientDef {
26 stops: vec![
27 GradientStop::Color("#b3f0e6".into()),
28 GradientStop::Color("#00c9a7".into()),
29 GradientStop::Color("#061e1c".into()),
30 ],
31 mode: InterpolationMode::Linear,
32 blend: ColorSpace::Oklab,
33 }),
34 );
35
36 let mut semantic = BTreeMap::new();
37 semantic.insert(
38 "bg".into(),
39 SemanticValue::PaletteRef("neutral".into(), 900),
40 );
41 semantic.insert(
42 "text".into(),
43 SemanticValue::PaletteRef("neutral".into(), 100),
44 );
45 semantic.insert(
46 "interactive".into(),
47 SemanticValue::PaletteRef("primary".into(), 500),
48 );
49
50 let mut shadow_elevations = BTreeMap::new();
51 shadow_elevations.insert(
52 "low".into(),
53 Elevation {
54 layers: 1,
55 offsets: vec![(0.0, 1.0)],
56 opacity: 0.1,
57 },
58 );
59
60 let mut shadow_colors = BTreeMap::new();
61 shadow_colors.insert("neutral".into(), "220 10% 10%".into());
62
63 let mut text_shadows = BTreeMap::new();
64 text_shadows.insert(
65 "medium".into(),
66 TextShadowElevation {
67 blur: vec![2, 4],
68 opacity: 0.4,
69 },
70 );
71
72 let mut glows = BTreeMap::new();
73 glows.insert(
74 "primary".into(),
75 Glow {
76 color: "hsla(170, 100%, 40%, {a})".into(),
77 radii: vec![4, 8, 16],
78 },
79 );
80
81 let mut transitions = BTreeMap::new();
82 transitions.insert("default".into(), "150ms ease".into());
83
84 let mut z = BTreeMap::new();
85 z.insert("base".into(), serde_json::json!(0));
86
87 let mut opacity = BTreeMap::new();
88 opacity.insert("disabled".into(), 0.4);
89
90 let mut letter_spacing = BTreeMap::new();
91 letter_spacing.insert("tight".into(), "-0.01em".into());
92
93 let mut families = BTreeMap::new();
94 families.insert("sans".into(), vec!["Inter".into(), "sans-serif".into()]);
95
96 let mut radius = BTreeMap::new();
97 radius.insert("sm".into(), "4px".into());
98 radius.insert("md".into(), "8px".into());
99 radius.insert("lg".into(), "16px".into());
100
101 let spec = Spec {
102 scales: Scales {
103 shades: vec![100, 500, 900],
104 sizes: vec!["sm".into(), "md".into(), "lg".into()],
105 elevations: vec!["low".into(), "medium".into(), "high".into()],
106 },
107 colors,
108 semantic,
109 fonts: Fonts {
110 families,
111 sizes: vec!["0.75rem".into(), "1rem".into(), "1.25rem".into()],
112 weights: vec![400, 700],
113 line_heights: vec![1.4, 1.5, 1.6],
114 letter_spacing,
115 },
116 space: vec!["0.5rem".into(), "1rem".into(), "2rem".into()],
117 dimensions: vec!["16rem".into(), "32rem".into(), "64rem".into()],
118 borders: Borders {
119 radius,
120 widths: vec!["1px".into(), "2px".into(), "4px".into()],
121 },
122 shadows: Shadows {
123 colors: shadow_colors,
124 elevations: shadow_elevations,
125 },
126 text_shadows,
127 ink: InkConfig {
128 light: ("neutral".into(), 100),
129 dark: ("neutral".into(), 900),
130 },
131 glows,
132 gradients: vec![Gradient {
133 name: "sweep".into(),
134 gradient_type: "linear".into(),
135 angle: 135,
136 stops: vec![("primary".into(), 100), ("primary".into(), 900)],
137 blend: Some(ColorSpace::Oklab),
138 mode: Some(InterpolationMode::Linear),
139 samples: 5,
140 }],
141 transitions,
142 z,
143 opacity,
144 overlay: BTreeMap::new(),
145 };
146
147 let manifest = Renderer::new().render(&spec)?;
148 print!("{manifest}");
149 Ok(())
150}