mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 22:09:22 -05:00
feat: improved Tooltip component
This commit is contained in:
parent
5aac76c558
commit
e4593a2bf3
7 changed files with 194 additions and 63 deletions
|
@ -14,29 +14,21 @@
|
|||
}
|
||||
|
||||
.demo-demo__toolbar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0.4rem;
|
||||
height: 26px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
border-top: 1px dashed var(--demo-border-color);
|
||||
border-bottom: 1px dashed var(--demo-border-color);
|
||||
}
|
||||
|
||||
.demo-demo__toolbar > .thaw-tooltip {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.demo-demo__toolbar--code {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.demo-demo__toolbar-btn {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
color: var(--demo-color);
|
||||
transition: color .3s;
|
||||
}
|
||||
|
||||
.demo-demo__toolbar-btn:hover {
|
||||
color: var(--demo-color-hover);
|
||||
}
|
||||
|
||||
.demo-demo__code {
|
||||
font-weight: 400;
|
||||
font-size: 0.875em;
|
||||
|
|
|
@ -17,13 +17,9 @@ pub fn Demo(demo_code: DemoCode, #[prop(optional)] children: Option<Children>) -
|
|||
let mut css_vars = String::new();
|
||||
theme.with(|theme| {
|
||||
if theme.color.color_scheme == "dark" {
|
||||
css_vars.push_str("--demo-color: #ffffff60;");
|
||||
css_vars.push_str("--demo-color-hover: #ffffffe0;");
|
||||
css_vars.push_str("--demo-border-color: #383f52;");
|
||||
css_vars.push_str("--demo-background-color: #242832;");
|
||||
} else {
|
||||
css_vars.push_str("--demo-color: #00000060;");
|
||||
css_vars.push_str("--demo-color-hover: #000000e0;");
|
||||
css_vars.push_str(&format!("--demo-border-color: var(--colorNeutralStroke2);",));
|
||||
css_vars.push_str("--demo-background-color: #f9fafb;");
|
||||
}
|
||||
|
@ -52,31 +48,24 @@ pub fn Demo(demo_code: DemoCode, #[prop(optional)] children: Option<Children>) -
|
|||
view! {
|
||||
<div class="demo-demo__view">{children()}</div>
|
||||
<div class="demo-demo__toolbar" class=("demo-demo__toolbar--code", move || !is_show_code.get())>
|
||||
<Popover appearance=PopoverAppearance::Inverted>
|
||||
<PopoverTrigger slot>
|
||||
<span on:click=move |_| is_show_code.update(|show| *show = !*show) class="demo-demo__toolbar-btn">
|
||||
{
|
||||
move || if is_show_code.get() {
|
||||
view! {
|
||||
<Icon icon=icondata::LuCode2/>
|
||||
}
|
||||
} else {
|
||||
view! {
|
||||
<Icon icon=icondata::LuCode/>
|
||||
}
|
||||
}
|
||||
}
|
||||
</span>
|
||||
</PopoverTrigger>
|
||||
{
|
||||
move || if is_show_code.get() {
|
||||
"Hide code"
|
||||
<Tooltip
|
||||
content=MaybeSignal::derive(move || if is_show_code.get() {
|
||||
"Hide code".to_string()
|
||||
} else {
|
||||
"Show code".to_string()
|
||||
})
|
||||
appearance=TooltipAppearance::Inverted
|
||||
>
|
||||
<Button icon=MaybeProp::derive(move || if is_show_code.get() {
|
||||
Some(icondata::LuCode2)
|
||||
} else {
|
||||
"Show code"
|
||||
}
|
||||
}
|
||||
</Popover>
|
||||
|
||||
Some(icondata::LuCode)
|
||||
})
|
||||
on:click=move |_| is_show_code.update(|show| *show = !*show)
|
||||
appearance=ButtonAppearance::Transparent
|
||||
size=ButtonSize::Small
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
}.into()
|
||||
} else {
|
||||
|
|
|
@ -44,6 +44,9 @@ pub struct ColorTheme {
|
|||
pub color_neutral_stroke_accessible_hover: String,
|
||||
pub color_neutral_stroke_accessible_pressed: String,
|
||||
|
||||
pub color_neutral_shadow_ambient: String,
|
||||
pub color_neutral_shadow_key: String,
|
||||
|
||||
pub color_neutral_stencil_1: String,
|
||||
pub color_neutral_stencil_2: String,
|
||||
|
||||
|
@ -160,6 +163,9 @@ impl ColorTheme {
|
|||
color_neutral_stroke_accessible_hover: "#575757".into(),
|
||||
color_neutral_stroke_accessible_pressed: "#4d4d4d".into(),
|
||||
|
||||
color_neutral_shadow_ambient: "rgba(0,0,0,0.12)".into(),
|
||||
color_neutral_shadow_key: "rgba(0,0,0,0.14)".into(),
|
||||
|
||||
color_neutral_stencil_1: "#e6e6e6".into(),
|
||||
color_neutral_stencil_2: "#fafafa".into(),
|
||||
|
||||
|
@ -277,6 +283,9 @@ impl ColorTheme {
|
|||
color_neutral_stroke_accessible_hover: "#bdbdbd".into(),
|
||||
color_neutral_stroke_accessible_pressed: "#b3b3b3".into(),
|
||||
|
||||
color_neutral_shadow_ambient: "rgba(0,0,0,0.24)".into(),
|
||||
color_neutral_shadow_key: "rgba(0,0,0,0.28)".into(),
|
||||
|
||||
color_neutral_stencil_1: "#575757".into(),
|
||||
color_neutral_stencil_2: "#333333".into(),
|
||||
|
||||
|
|
|
@ -9,3 +9,25 @@ view! {
|
|||
</Tooltip>
|
||||
}
|
||||
```
|
||||
|
||||
### Appearance: inverted
|
||||
|
||||
```rust demo
|
||||
view! {
|
||||
<Tooltip content="Example tooltip" appearance=TooltipAppearance::Inverted>
|
||||
<Button>
|
||||
"Example"
|
||||
</Button>
|
||||
</Tooltip>
|
||||
}
|
||||
```
|
||||
|
||||
### Textarea Props
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| ---------- | -------------------------------- | ------------------------- | -------------------------------------- |
|
||||
| class | `MaybeProp<String>` | `Default::default()` | |
|
||||
| content | `Option<MaybeSignal<String>>` | `None` | The text of the tooltip. |
|
||||
| position | `TooltipPosition` | `TooltipPosition::Top` | Configure the position of the tooltip. |
|
||||
| appearance | `MaybeSignal<TooltipAppearance>` | `TooltipAppearance::None` | The tooltip's visual appearance. |
|
||||
| children | `Children` | | |
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
div.thaw-tooltip-content {
|
||||
position: relative;
|
||||
transform-origin: inherit;
|
||||
|
||||
padding: 4px 11px 6px;
|
||||
border-radius: var(--borderRadiusMedium);
|
||||
border: 1px solid var(--colorTransparentStroke);
|
||||
line-height: var(--lineHeightBase200);
|
||||
font-size: var(--fontSizeBase200);
|
||||
font-family: var(--fontFamilyBase);
|
||||
max-width: 240px;
|
||||
overflow-wrap: break-word;
|
||||
box-sizing: border-box;
|
||||
filter: drop-shadow(0 0 2px var(--colorNeutralShadowAmbient))
|
||||
drop-shadow(0 4px 8px var(--colorNeutralShadowKey));
|
||||
}
|
||||
|
||||
div.thaw-tooltip-content--normal {
|
||||
background-color: var(--colorNeutralBackground1);
|
||||
color: var(--colorNeutralForeground1);
|
||||
}
|
||||
|
||||
div.thaw-tooltip-content--inverted {
|
||||
background-color: var(--colorNeutralBackgroundStatic);
|
||||
color: var(--colorNeutralForegroundStaticInverted);
|
||||
}
|
||||
|
||||
.thaw-tooltip-content__angle {
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.thaw-tooltip {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
[data-thaw-placement="top-start"] > .thaw-tooltip-content,
|
||||
[data-thaw-placement="top-end"] > .thaw-tooltip-content,
|
||||
[data-thaw-placement="top"] > .thaw-tooltip-content {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
[data-thaw-placement="top-start"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="top-end"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="top"] .thaw-tooltip-content__angle {
|
||||
transform: rotate(45deg) translateX(-7px);
|
||||
bottom: -10px;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
[data-thaw-placement="bottom-start"] > .thaw-tooltip-content,
|
||||
[data-thaw-placement="bottom-end"] > .thaw-tooltip-content,
|
||||
[data-thaw-placement="bottom"] > .thaw-tooltip-content {
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
[data-thaw-placement="bottom-start"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="bottom-end"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="bottom"] .thaw-tooltip-content__angle {
|
||||
transform: rotate(45deg) translateY(7px);
|
||||
top: -10px;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
[data-thaw-placement="left-start"] > .thaw-tooltip-content,
|
||||
[data-thaw-placement="left-end"] > .thaw-tooltip-content,
|
||||
[data-thaw-placement="left"] > .thaw-tooltip-content {
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
[data-thaw-placement="left-start"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="left-end"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="left"] .thaw-tooltip-content__angle {
|
||||
transform: rotate(45deg) translateX(-7px);
|
||||
top: 50%;
|
||||
right: -10px;
|
||||
}
|
||||
|
||||
[data-thaw-placement="right-start"] > .thaw-tooltip-content,
|
||||
[data-thaw-placement="right-end"] > .thaw-tooltip-content,
|
||||
[data-thaw-placement="right"] > .thaw-tooltip-content {
|
||||
margin-left: 7px;
|
||||
}
|
||||
|
||||
[data-thaw-placement="right-start"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="right-end"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="right"] .thaw-tooltip-content__angle {
|
||||
transform: rotate(45deg) translateY(-7px);
|
||||
top: 50%;
|
||||
left: -10px;
|
||||
}
|
||||
|
||||
[data-thaw-placement="bottom-start"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="top-start"] .thaw-tooltip-content__angle {
|
||||
left: 16px;
|
||||
}
|
||||
[data-thaw-placement="bottom-end"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="top-end"] .thaw-tooltip-content__angle {
|
||||
left: initial;
|
||||
right: 7px;
|
||||
}
|
||||
[data-thaw-placement="right-start"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="left-start"] .thaw-tooltip-content__angle {
|
||||
top: 16px;
|
||||
}
|
||||
[data-thaw-placement="right-end"] .thaw-tooltip-content__angle,
|
||||
[data-thaw-placement="left-end"] .thaw-tooltip-content__angle {
|
||||
top: initial;
|
||||
bottom: 7px;
|
||||
}
|
||||
|
||||
.thaw-tooltip-content.tooltip-transition-enter-from,
|
||||
.thaw-tooltip-content.tooltip-transition-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.85);
|
||||
}
|
||||
|
||||
.thaw-tooltip-content.tooltip-transition-enter-to,
|
||||
.thaw-tooltip-content.tooltip-transition-leave-from {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.thaw-tooltip-content.tooltip-transition-leave-active,
|
||||
.thaw-tooltip-content.tooltip-transition-enter-active {
|
||||
transition: opacity var(--durationNormal) var(--curveDecelerateMid),
|
||||
transform var(--durationNormal) var(--curveDecelerateMid);
|
||||
}
|
|
@ -4,26 +4,18 @@ use std::time::Duration;
|
|||
use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement};
|
||||
use thaw_utils::{class_list, mount_style};
|
||||
|
||||
#[slot]
|
||||
pub struct TooltipContent {
|
||||
#[prop(optional, into)]
|
||||
class: MaybeProp<String>,
|
||||
children: Children,
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Tooltip(
|
||||
#[prop(optional, into)] class: MaybeProp<String>,
|
||||
#[prop(optional)] tooltip_content: Option<TooltipContent>,
|
||||
/// The text of the tooltip.
|
||||
#[prop(optional, into)]
|
||||
content: MaybeProp<String>,
|
||||
/// Configure the positioning of the tooltip
|
||||
content: Option<MaybeSignal<String>>,
|
||||
/// Configure the position of the tooltip.
|
||||
#[prop(optional)]
|
||||
position: TooltipPosition,
|
||||
/// The tooltip's visual appearance.
|
||||
#[prop(optional, into)]
|
||||
appearance: MaybeProp<TooltipAppearance>,
|
||||
appearance: MaybeSignal<TooltipAppearance>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
mount_style("tooltip", include_str!("./tooltip.css"));
|
||||
|
@ -86,7 +78,7 @@ pub fn Tooltip(
|
|||
<div
|
||||
class=class_list![
|
||||
"thaw-config-provider thaw-tooltip-content",
|
||||
move || appearance.get().map(|a| format!("thaw-tooltip-content--{}", a.as_str()))
|
||||
move || format!("thaw-tooltip-content--{}", appearance.get().as_str())
|
||||
]
|
||||
data-thaw-id=config_provider.id().clone()
|
||||
style=move || display.get().unwrap_or_default()
|
||||
|
@ -95,11 +87,7 @@ pub fn Tooltip(
|
|||
on:mouseenter=on_mouse_enter
|
||||
on:mouseleave=on_mouse_leave
|
||||
>
|
||||
{
|
||||
move || {
|
||||
content.get()
|
||||
}
|
||||
}
|
||||
{move || { content.as_ref().map(|c| c.get()).unwrap_or_default() }}
|
||||
<div class="thaw-tooltip-content__angle"></div>
|
||||
</div>
|
||||
</CSSTransition>
|
||||
|
@ -108,8 +96,9 @@ pub fn Tooltip(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub enum TooltipAppearance {
|
||||
#[default]
|
||||
Normal,
|
||||
Inverted,
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue