rustyle_css/components/
tooltip.rs1use super::{ComponentStyle, Variant};
6use crate::css::{Color, Radius, Spacing};
7use crate::tokens::{BorderTokens, ColorTokens, SpacingTokens};
8
9#[derive(Clone, Debug)]
11pub enum TooltipPosition {
12 Top,
13 Bottom,
14 Left,
15 Right,
16}
17
18#[derive(Clone, Debug)]
20pub struct TooltipStyle {
21 pub variant: Variant,
22 pub position: TooltipPosition,
23 pub tokens: Option<TooltipTokens>,
24}
25
26#[derive(Clone, Debug)]
28pub struct TooltipTokens {
29 pub colors: ColorTokens,
30 pub spacing: SpacingTokens,
31 pub borders: BorderTokens,
32}
33
34impl TooltipStyle {
35 pub fn new(variant: Variant, position: TooltipPosition) -> Self {
37 Self {
38 variant,
39 position,
40 tokens: None,
41 }
42 }
43
44 pub fn tokens(mut self, tokens: TooltipTokens) -> Self {
46 self.tokens = Some(tokens);
47 self
48 }
49
50 fn background_color(&self) -> Color {
51 let default_colors = ColorTokens::default();
52 let colors = self
53 .tokens
54 .as_ref()
55 .map(|t| &t.colors)
56 .unwrap_or(&default_colors);
57
58 match &self.variant {
59 Variant::Primary => colors.primary.c600.clone(),
60 Variant::Secondary => colors.secondary.c600.clone(),
61 Variant::Success => colors.semantic.success.clone(),
62 Variant::Error => colors.semantic.error.clone(),
63 Variant::Warning => colors.semantic.warning.clone(),
64 Variant::Info => colors.semantic.info.clone(),
65 }
66 }
67
68 fn text_color(&self) -> Color {
69 Color::named("white")
70 }
71
72 fn padding(&self) -> Spacing {
73 let default_spacing = SpacingTokens::default();
74 let spacing = self
75 .tokens
76 .as_ref()
77 .map(|t| &t.spacing)
78 .unwrap_or(&default_spacing);
79
80 Spacing::vh(spacing.xs.clone(), spacing.sm.clone())
81 }
82
83 fn border_radius(&self) -> Radius {
84 let default_borders = BorderTokens::default();
85 let borders = self
86 .tokens
87 .as_ref()
88 .map(|t| &t.borders)
89 .unwrap_or(&default_borders);
90
91 Radius::all(borders.radius.sm.clone())
92 }
93}
94
95impl ComponentStyle for TooltipStyle {
96 fn to_css(&self) -> String {
97 let mut css = String::new();
98
99 css.push_str(&format!(
100 "background-color: {}; ",
101 self.background_color().to_css()
102 ));
103 css.push_str(&format!("color: {}; ", self.text_color().to_css()));
104 css.push_str(&format!("padding: {}; ", self.padding().to_css()));
105 css.push_str(&format!(
106 "border-radius: {}; ",
107 self.border_radius().to_css()
108 ));
109 css.push_str("position: absolute; ");
110 css.push_str("z-index: 1000; ");
111 css.push_str("pointer-events: none; ");
112 css.push_str("white-space: nowrap; ");
113 css.push_str(
114 "box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); ",
115 );
116
117 match &self.position {
119 TooltipPosition::Top => {
120 css.push_str("bottom: 100%; ");
121 css.push_str("left: 50%; ");
122 css.push_str("transform: translateX(-50%); ");
123 css.push_str("margin-bottom: 5px; ");
124 }
125 TooltipPosition::Bottom => {
126 css.push_str("top: 100%; ");
127 css.push_str("left: 50%; ");
128 css.push_str("transform: translateX(-50%); ");
129 css.push_str("margin-top: 5px; ");
130 }
131 TooltipPosition::Left => {
132 css.push_str("right: 100%; ");
133 css.push_str("top: 50%; ");
134 css.push_str("transform: translateY(-50%); ");
135 css.push_str("margin-right: 5px; ");
136 }
137 TooltipPosition::Right => {
138 css.push_str("left: 100%; ");
139 css.push_str("top: 50%; ");
140 css.push_str("transform: translateY(-50%); ");
141 css.push_str("margin-left: 5px; ");
142 }
143 }
144
145 css
146 }
147
148 fn class_name(&self) -> &str {
149 "rustyle-tooltip"
150 }
151}
152
153impl Default for TooltipStyle {
154 fn default() -> Self {
155 Self::new(Variant::Primary, TooltipPosition::Top)
156 }
157}