Project · Issues and boards: a board, issue cards, a task's panel, labels

KanbanBoard lays columns of cards side by side. A card drags to a
place in any column: it rides raised at the pointer, a slot opens where
it would land, the other cards glide aside on motion::Flip, and the
drop asks the owner through on_move(card, column, index); a drop in its
own place asks nothing. Option with an arrow moves the focused card,
whose focus the board keys by card so it follows it across columns. A
press, Enter or Space opens it. Sprint Board is this board.

IssueCard shows an issue's status, name, assignee, title, priority,
labels and due day. TaskDetailPanel lays a task out in full: its title
edits in place, its status, priority, assignee and due day change where
they stand, and its notes and steps follow; each edit hands the whole
task on, and a blank title is not taken. LabelManager tends a team's
labels: a hue picked from a popover, a name edited in place, a delete,
and a field that makes a new one; names stay unique in any case, and a
refused name says why.

The fill rule changes: min_w_full, taken up in T30d, resolves against
a block's outer width in taffy 0.9, so a field in a padded card ran
past its padding. A component that fills now takes no width on its
root, which blocks and flex columns stretch; FormField and the new
roots do. The chart's hue names move to theme::HUE_NAMES, which the
event editor and the label manager share.
This commit is contained in:
ZacharyZhang-NY committed 2026-09-27 05:12:20 -04:00
1 parent 1633bc9293
commit 8cbd389d72
24 files changed
+1813 -31

No files matched your search

-1
View File
@@ -227,7 +227,6 @@ impl RenderOnce for AvailabilityPicker {
});
div()
.debug_selector(|| "availability".into())
.min_w_full()
.flex()
.flex_col()
.gap_3()
+5 -8
View File
@@ -18,17 +18,12 @@ use crate::{
ColorPalette, DatePicker, DateTimePicker, FormError, FormField, Input, InputEvent, Run,
Switch, TextInput,
},
theme::ActiveTheme,
theme::{ActiveTheme, HUE_NAMES},
typography::format,
};
type OnDraft = Rc<dyn Fn(&EventDraft, &mut Window, &mut App)>;
/// The chart's hues by name, for the color an event wears.
const HUES: [&str; 8] = [
"Blue", "Teal", "Ochre", "Rose", "Violet", "Green", "Rust", "Cyan",
];
/// An event's parts as an editor hands them back.
#[derive(Clone, Debug, PartialEq)]
pub struct EventDraft {
@@ -362,7 +357,6 @@ impl RenderOnce for EventEditor {
};
div()
.debug_selector(|| "event-editor".into())
.min_w_full()
.flex()
.flex_col()
.gap_4()
@@ -402,7 +396,10 @@ impl RenderOnce for EventEditor {
FormField::new((self.id.clone(), "color-field"), "Color").child(
ColorPalette::new(
(self.id.clone(), "color"),
HUES.iter().zip(chart).map(|(name, color)| (*name, color)),
HUE_NAMES
.iter()
.zip(chart)
.map(|(name, color)| (*name, color)),
)
.selected(chart[draft.hue])
.on_change({
+1 -2
View File
@@ -116,7 +116,7 @@ impl RenderOnce for RecurrenceEditor {
.selected(frequency_key(rule.as_ref().map(|rule| rule.frequency)))
.on_change(pick);
let Some(rule) = rule else {
return div().min_w_full().child(frequency);
return div().child(frequency);
};
let unit = match (rule.frequency, rule.interval) {
(Frequency::Daily, 1) => "day",
@@ -259,7 +259,6 @@ impl RenderOnce for RecurrenceEditor {
};
div()
.debug_selector(|| "recurrence".into())
.min_w_full()
.flex()
.flex_col()
.gap_3()
-1
View File
@@ -139,7 +139,6 @@ impl RenderOnce for ReminderPicker {
};
div()
.debug_selector(|| "reminders".into())
.min_w_full()
.flex()
.flex_col()
.gap_2()