sidebar part 2: hit dice block

This commit is contained in:
YK 2025-09-13 11:53:59 +03:00
parent 5fa38ad67d
commit 1c0c0a2b5f
2 changed files with 110 additions and 1 deletions

View File

@ -26,13 +26,14 @@ pub fn Sidebar () -> impl IntoView {
let image = player.image(); let image = player.image();
let hit_dice = player.hit_dice();
let adjust_level = move |adjustment: i8| level.update(|l| { let adjust_level = move |adjustment: i8| level.update(|l| {
if let Some(new) = l.checked_add_signed(adjustment) { if let Some(new) = l.checked_add_signed(adjustment) {
*l = new; *l = new;
} }
}); });
let adjust_xp = move |ev: Targeted<Event, HtmlInputElement>| { let adjust_xp = move |ev: Targeted<Event, HtmlInputElement>| {
utils::adjust_checked(ev, xp); utils::adjust_checked(ev, xp);
}; };
@ -54,6 +55,17 @@ pub fn Sidebar () -> impl IntoView {
format!("width: {}%", utils::filled_pc(a, b).min(100.)) format!("width: {}%", utils::filled_pc(a, b).min(100.))
}; };
let process_die_click = move |slot_id: u8| {
hit_dice.update(|d| {
if slot_id < d.used {
d.used = slot_id;
} else {
d.used = slot_id + 1;
}
})
};
view! { view! {
<aside> <aside>
<Show when=move || !image.get().is_empty() > <Show when=move || !image.get().is_empty() >
@ -104,6 +116,43 @@ pub fn Sidebar () -> impl IntoView {
</div> </div>
</div> </div>
</div> </div>
<h6>hit dice/кости хитов:</h6>
<div class="hit-dice">
<div class="die-selector">
<select
id="die-kind"
on:change:target=move |ev| {
let val = ev.target().value();
if let Ok(v) = val.parse() {
hit_dice.update(|d| d.kind = v);
}
}
prop:value=move || hit_dice.get().kind
>
<option value=4>4</option>
<option value=6>6</option>
<option value=8>8</option>
<option value=10>10</option>
<option value=12>12</option>
<option value=20>20</option>
</select>
</div>
<For
each=move || (0..level.get())
key=|slot| slot.clone()
let (slot)
>
<div
class=move || {
let d = hit_dice.get();
format!("die-{} die {}", d.kind, if slot < d.used { "spent" } else { "" })
}
on:click=move |_| process_die_click(slot)
>
{move || hit_dice.get().kind}
</div>
</For>
</div>
</aside> </aside>
} }
} }

View File

@ -89,6 +89,8 @@ aside {
> h6 { > h6 {
font-size: 0.7em; font-size: 0.7em;
text-align: right; text-align: right;
margin-top: 10px;
margin-bottom: 6px;
padding: 5px; padding: 5px;
color: #666; color: #666;
font-family: "Galderglynn Titling"; font-family: "Galderglynn Titling";
@ -142,6 +144,64 @@ aside {
} }
} }
.hit-dice {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-evenly;
margin: 5px 8px;
.die-selector {
width: 100%;
display: flex;
justify-content: flex-end;
margin-right: 6px;
align-items: center;
margin-bottom: 10px;
select {
color: white;
background: crimson;
padding: 3px 12px;
border-left: solid 3px red;
}
}
.die {
width: 30px;
height: 30px;
margin: 3px;
display: flex;
justify-content: center;
align-items: center;
font-size: 0.75em;
&.spent {
filter: contrast(20%);
}
&:hover {
cursor: cell;
}
@for $i from 1 through 20 {
&.die-#{$i} {
background: hsl((60 + ($i * 87)) * 1deg, 100%, 40%);
}
}
@include mixins.heading;
}
.die:has(~ .die:hover), .die:hover {
filter: contrast(20%);
}
.die.spent:hover, .die.spent:hover ~ .die.spent {
filter: contrast(70%);
}
}
input { input {
max-width: 100%; max-width: 100%;
width: fit-content; width: fit-content;