@lotics/ui 5.10.0 → 5.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -1
- package/examples/tpl_tasks.tsx +31 -15
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -690,7 +690,11 @@ recipe for a screen JOB; copy and adapt). Pick by the job:
|
|
|
690
690
|
rows). For thousands+ you BROWSE, that's `tpl_dossier`'s paginated register, not this.** Both build
|
|
691
691
|
on the `DataGrid` primitive (the grid shape, extracted once these two uses confirmed it); each owns
|
|
692
692
|
only its data, toolbar, columns and per-group add. There is NO Task component — a task ROW varies
|
|
693
|
-
too much to bake into one, so rows compose `CheckCircle` + `InlineTextInput` + inline-editor cells
|
|
693
|
+
too much to bake into one, so rows compose `CheckCircle` + `InlineTextInput` + inline-editor cells
|
|
694
|
+
as **sibling** controls in a plain `View`. NEVER wrap the whole row in a `Pressable accessibilityRole="button"`
|
|
695
|
+
(for tap-to-expand) with those controls nested inside: RNW renders the row AND each control as a `<button>`,
|
|
696
|
+
so you get `<button>`s inside a `<button>` — invalid DOM + the inner controls drop out of the keyboard tab
|
|
697
|
+
order. Give "expand" its own affordance (a trailing `Pressable` over the meta/chevron), as `tpl_tasks` does.
|
|
694
698
|
- **Data capture** — `tpl_intake` (multi-fieldset form + attachments) · `tpl_order` (the
|
|
695
699
|
transactional form: find-or-create + line items + attachment CRUD + 2-col grid) · `tpl_billing`
|
|
696
700
|
(charges→invoice→collect: the invoice DOCUMENT is the unit — editable charge lines + method,
|
package/examples/tpl_tasks.tsx
CHANGED
|
@@ -285,25 +285,38 @@ export function TplTasks() {
|
|
|
285
285
|
const d = dueInfo(t.due);
|
|
286
286
|
return (
|
|
287
287
|
<View key={t.id}>
|
|
288
|
-
|
|
288
|
+
{/* A row is NOT a single button: the ring, the title, and the expand
|
|
289
|
+
affordance are SIBLING controls in a plain View. Wrapping the row in a
|
|
290
|
+
Pressable accessibilityRole="button" while nesting CheckCircle +
|
|
291
|
+
InlineTextInput (each renders a <button> on web) would put <button>s
|
|
292
|
+
inside a <button> — invalid DOM + the inner controls drop out of the
|
|
293
|
+
keyboard tab order. So the expand affordance is its own Pressable. */}
|
|
294
|
+
<View style={styles.row}>
|
|
289
295
|
<CheckCircle checked={done} onChange={(on) => patch(t.id, { status: on ? "done" : "todo" })} accessibilityLabel={t.title} />
|
|
290
296
|
<View style={{ flex: 1 }}>
|
|
291
297
|
<InlineTextInput value={t.title} onSave={(v) => patch(t.id, { title: v })} struck={done} accessibilityLabel="Title" />
|
|
292
298
|
</View>
|
|
293
|
-
<
|
|
294
|
-
{t.
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
299
|
+
<Pressable
|
|
300
|
+
onPress={() => toggleExpand(t.id, !open)}
|
|
301
|
+
accessibilityRole="button"
|
|
302
|
+
accessibilityLabel={open ? `Collapse ${t.title}` : `Expand ${t.title}`}
|
|
303
|
+
style={({ hovered }: { hovered?: boolean }) => [styles.expand, hovered ? styles.rowHover : null]}
|
|
304
|
+
>
|
|
305
|
+
<View style={styles.meta}>
|
|
306
|
+
{t.files.length > 0 ? (
|
|
307
|
+
<View style={styles.clip}>
|
|
308
|
+
<Icon name="paperclip" size={13} color={colors.zinc[400]} />
|
|
309
|
+
<Text size="xs" color="muted" tabular>{t.files.length}</Text>
|
|
310
|
+
</View>
|
|
311
|
+
) : null}
|
|
312
|
+
{t.tags.length > 0 ? (
|
|
313
|
+
<View style={styles.dots}>{t.tags.map((tag) => <View key={tag.value} style={[styles.dot, { backgroundColor: tagColor(tag) }]} />)}</View>
|
|
314
|
+
) : null}
|
|
315
|
+
{d ? <Text size="xs" weight="medium" color={d.overdue && !done ? "danger" : "muted"}>{d.label}</Text> : null}
|
|
316
|
+
</View>
|
|
317
|
+
<Icon name={open ? "chevron-up" : "chevron-down"} size={16} color={colors.zinc[300]} />
|
|
318
|
+
</Pressable>
|
|
319
|
+
</View>
|
|
307
320
|
{open ? (
|
|
308
321
|
<View style={styles.detail}>
|
|
309
322
|
<Field label="Due">
|
|
@@ -414,6 +427,9 @@ const styles = StyleSheet.create({
|
|
|
414
427
|
borderRadius: 10,
|
|
415
428
|
},
|
|
416
429
|
rowHover: { backgroundColor: colors.zinc[50] },
|
|
430
|
+
// The expand affordance — its own button (meta + chevron), sibling to the ring
|
|
431
|
+
// and title so no interactive control nests inside another.
|
|
432
|
+
expand: { flexDirection: "row", alignItems: "center", gap: 10, minHeight: 36, paddingHorizontal: 8, borderRadius: 8 },
|
|
417
433
|
capture: {
|
|
418
434
|
borderBottomWidth: 1,
|
|
419
435
|
borderBottomColor: colors.zinc[100],
|