UI: restyle task detail onto the new tokens
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,11 +4,11 @@ import { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
|
|||||||
import DateField from "../../components/DateField";
|
import DateField from "../../components/DateField";
|
||||||
import EstimateChips from "../../components/EstimateChips";
|
import EstimateChips from "../../components/EstimateChips";
|
||||||
import PriorityChips from "../../components/PriorityChips";
|
import PriorityChips from "../../components/PriorityChips";
|
||||||
import { Button, Chips, Field } from "../../components/ui";
|
import { Button, Chips, Empty, Field } from "../../components/ui";
|
||||||
import { haptic } from "../../lib/haptics";
|
import { haptic } from "../../lib/haptics";
|
||||||
import { REPEAT_LABEL, REPEATS } from "../../lib/repeat";
|
import { REPEAT_LABEL, REPEATS } from "../../lib/repeat";
|
||||||
import { activeProjects, knownContexts, trashTask, updateTask } from "../../lib/store";
|
import { activeProjects, knownContexts, trashTask, updateTask } from "../../lib/store";
|
||||||
import { C } from "../../lib/theme";
|
import { C, radius, space, type } from "../../lib/theme";
|
||||||
import { useStore } from "../../lib/useStore";
|
import { useStore } from "../../lib/useStore";
|
||||||
import type { Repeat, Task, TaskStatus } from "../../lib/types";
|
import type { Repeat, Task, TaskStatus } from "../../lib/types";
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ export default function TaskDetail() {
|
|||||||
// Draft is local to the screen; nothing is written until Save.
|
// Draft is local to the screen; nothing is written until Save.
|
||||||
const [draft, setDraft] = useState<Task | null>(original ?? null);
|
const [draft, setDraft] = useState<Task | null>(original ?? null);
|
||||||
|
|
||||||
if (!draft) return <Text style={{ color: C.muted, margin: 16 }}>Task not found.</Text>;
|
if (!draft) return <Empty>Task not found.</Empty>;
|
||||||
|
|
||||||
const set = (patch: Partial<Task>) => setDraft({ ...draft, ...patch });
|
const set = (patch: Partial<Task>) => setDraft({ ...draft, ...patch });
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ export default function TaskDetail() {
|
|||||||
|
|
||||||
if (draft.status === "trashed") {
|
if (draft.status === "trashed") {
|
||||||
return (
|
return (
|
||||||
<ScrollView style={{ flex: 1, backgroundColor: C.bg }} contentContainerStyle={{ padding: 16 }}>
|
<ScrollView style={{ flex: 1, backgroundColor: C.bg }} contentContainerStyle={s.content}>
|
||||||
<Text style={s.trashedTitle}>{draft.title}</Text>
|
<Text style={s.trashedTitle}>{draft.title}</Text>
|
||||||
<Text style={s.trashedMeta}>In the trash.</Text>
|
<Text style={s.trashedMeta}>In the trash.</Text>
|
||||||
<Button
|
<Button
|
||||||
@@ -66,7 +66,12 @@ export default function TaskDetail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView style={{ flex: 1, backgroundColor: C.bg }} contentContainerStyle={{ padding: 16 }}>
|
<ScrollView
|
||||||
|
style={{ flex: 1, backgroundColor: C.bg }}
|
||||||
|
contentContainerStyle={s.content}
|
||||||
|
keyboardShouldPersistTaps="handled"
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
>
|
||||||
<Field label="Title" value={draft.title} onChangeText={(v) => set({ title: v })} />
|
<Field label="Title" value={draft.title} onChangeText={(v) => set({ title: v })} />
|
||||||
<PriorityChips value={draft.priority} onChange={(priority) => set({ priority })} />
|
<PriorityChips value={draft.priority} onChange={(priority) => set({ priority })} />
|
||||||
<EstimateChips value={draft.estimate_min} onChange={(estimate_min) => set({ estimate_min })} />
|
<EstimateChips value={draft.estimate_min} onChange={(estimate_min) => set({ estimate_min })} />
|
||||||
@@ -87,18 +92,25 @@ export default function TaskDetail() {
|
|||||||
/>
|
/>
|
||||||
{contexts.length > 0 && (
|
{contexts.length > 0 && (
|
||||||
<View style={s.contextRow}>
|
<View style={s.contextRow}>
|
||||||
{contexts.map((c) => (
|
{contexts.map((c) => {
|
||||||
|
const active = draft.context === c;
|
||||||
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
key={c}
|
key={c}
|
||||||
style={[s.contextChip, draft.context === c && s.contextChipActive]}
|
style={({ pressed }) => [
|
||||||
|
s.contextChip,
|
||||||
|
active && s.contextChipActive,
|
||||||
|
pressed && !active && { backgroundColor: C.surface2 },
|
||||||
|
]}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
haptic.select();
|
haptic.select();
|
||||||
set({ context: draft.context === c ? null : c });
|
set({ context: active ? null : c });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={[s.contextText, draft.context === c && { color: C.text }]}>{c}</Text>
|
<Text style={[s.contextText, active && s.contextTextActive]}>{c}</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{draft.status === "waiting" && (
|
{draft.status === "waiting" && (
|
||||||
@@ -126,7 +138,7 @@ export default function TaskDetail() {
|
|||||||
value={draft.notes}
|
value={draft.notes}
|
||||||
onChangeText={(v) => set({ notes: v })}
|
onChangeText={(v) => set({ notes: v })}
|
||||||
multiline
|
multiline
|
||||||
style={{ minHeight: 80, textAlignVertical: "top" }}
|
style={{ minHeight: 96, textAlignVertical: "top" }}
|
||||||
/>
|
/>
|
||||||
<Button title="Save" onPress={save} />
|
<Button title="Save" onPress={save} />
|
||||||
<Button
|
<Button
|
||||||
@@ -142,18 +154,26 @@ export default function TaskDetail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const s = StyleSheet.create({
|
const s = StyleSheet.create({
|
||||||
trashedTitle: { color: C.text, fontSize: 18, marginBottom: 6 },
|
content: { padding: space.lg, paddingBottom: space.xxl },
|
||||||
trashedMeta: { color: C.muted, fontSize: 14, marginBottom: 18 },
|
trashedTitle: { ...type.title, fontSize: 22, color: C.text, marginBottom: space.xs },
|
||||||
contextRow: { flexDirection: "row", flexWrap: "wrap", gap: 8, marginTop: -6, marginBottom: 14 },
|
trashedMeta: { ...type.body, color: C.muted, marginBottom: space.xl },
|
||||||
|
contextRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
gap: space.sm,
|
||||||
|
marginTop: -space.sm,
|
||||||
|
marginBottom: space.lg,
|
||||||
|
},
|
||||||
contextChip: {
|
contextChip: {
|
||||||
paddingVertical: 6,
|
paddingVertical: 7,
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: space.md + 1,
|
||||||
borderRadius: 16,
|
borderRadius: radius.pill,
|
||||||
backgroundColor: C.surface,
|
backgroundColor: C.surface,
|
||||||
borderWidth: 1,
|
borderWidth: StyleSheet.hairlineWidth,
|
||||||
borderColor: C.border,
|
borderColor: C.border,
|
||||||
},
|
},
|
||||||
contextChipActive: { backgroundColor: C.surface2, borderColor: C.accent },
|
contextChipActive: { backgroundColor: C.accentSoft, borderColor: C.accent },
|
||||||
contextText: { color: C.muted, fontSize: 13 },
|
contextText: { ...type.meta, color: C.textSecondary },
|
||||||
deferHint: { color: C.muted, fontSize: 13, marginTop: -8, marginBottom: 12 },
|
contextTextActive: { color: C.accent, fontWeight: "600" },
|
||||||
|
deferHint: { ...type.meta, color: C.muted, marginTop: -space.sm, marginBottom: space.md },
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user