@lotics/ui 12.1.1 → 12.1.2

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/docs/catalog.md CHANGED
@@ -934,9 +934,11 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
934
934
  `ChangeRecord` (THE item card: registers like a Change; tone wash + localized op word;
935
935
  verb level follows the decision level) · `ChangeBand` (the raw ± band) ·
936
936
  `ChangeValueInput` (the diff-at-rest editor); the `changeReview` locale slice.
937
- - **`clarify`** — `Clarify`: the agent asks back, via `ChoiceList`.
938
- - **`choice_list`** — `ChoiceList` + `ChoiceOption`: selectable answer options, the agent's
939
- quick-reply surface.
937
+ - **`clarify`** — `Clarify`: the agent asks back a borderless block (question + a
938
+ `ChoiceList`), no card wrapper.
939
+ - **`choice_list`** — `ChoiceList` + `ChoiceOption`: selectable answer options as
940
+ divider-separated rows (no bordered cards) with a per-row focus ring + hover wash; the
941
+ agent's quick-reply surface.
940
942
  - **`sources`** — `Sources` + `SourceRef`/`SourceKind` (record | document | table | web |
941
943
  knowledge): provenance chips, per-kind glyphs.
942
944
  - **`finding`** — `Finding` + `FindingComparison` + `FindingSeverity`/`FindingLabels`: one
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/ui",
3
- "version": "12.1.1",
3
+ "version": "12.1.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./vite": {
@@ -1,8 +1,10 @@
1
- import { StyleSheet, View } from "react-native";
1
+ import { Pressable, View } from "react-native";
2
2
  import { colors } from "./colors";
3
3
  import { Text } from "./text";
4
4
  import { Icon } from "./icon";
5
- import { CardSelectItem } from "./card_select_item";
5
+ import { Divider } from "./divider";
6
+ import { useFocusRing } from "./use_focus_ring";
7
+ import { FOCUS_RING } from "./control_surface";
6
8
 
7
9
  export interface ChoiceOption {
8
10
  label: string;
@@ -18,46 +20,55 @@ export interface ChoiceListProps {
18
20
  onSelect: (value: string) => void;
19
21
  }
20
22
 
23
+ /** One selectable option — a role-less-free `Pressable` (its own accessible name
24
+ * + selected state), hover wash + focus ring, no border. */
25
+ function ChoiceRow({ option, selected, onSelect }: { option: ChoiceOption; selected: boolean; onSelect: (value: string) => void }) {
26
+ const { focusVisible, focusProps } = useFocusRing();
27
+ return (
28
+ <Pressable
29
+ accessibilityRole="button"
30
+ accessibilityLabel={option.label}
31
+ accessibilityState={{ selected }}
32
+ onPress={() => onSelect(option.value)}
33
+ {...focusProps}
34
+ style={({ hovered, pressed }) => [
35
+ { flexDirection: "row", alignItems: "center", gap: 12, paddingVertical: 14, paddingHorizontal: 6, borderRadius: 8 },
36
+ hovered || pressed ? { backgroundColor: colors.zinc[50] } : null,
37
+ focusVisible ? { boxShadow: FOCUS_RING } : null,
38
+ ]}
39
+ >
40
+ <View style={{ flex: 1, gap: 3, minWidth: 0 }}>
41
+ <Text size="sm" weight={selected ? "semibold" : "medium"}>
42
+ {option.label}
43
+ </Text>
44
+ {option.description ? (
45
+ <Text size="xs" color="muted">
46
+ {option.description}
47
+ </Text>
48
+ ) : null}
49
+ </View>
50
+ {selected ? <Icon name="check" size={17} color={colors.zinc[900]} /> : null}
51
+ </Pressable>
52
+ );
53
+ }
54
+
21
55
  /**
22
- * A vertical set of selectable answer options — bordered cards with the global
23
- * focus/hover/selected ring (`CardSelectItem`), single-select and freely
24
- * switchable (pick a different option any time). The chosen card shows a check.
25
- * The agent's quick-reply surface (`Clarify` uses it) and any "pick one"
56
+ * A vertical set of selectable answer options — divider-separated rows (no
57
+ * bordered cards), each with its own focus ring + hover wash, single-select and
58
+ * freely switchable (pick a different option any time). The chosen row shows a
59
+ * check. The agent's quick-reply surface (`Clarify` uses it) and any "pick one"
26
60
  * question.
27
61
  */
28
62
  export function ChoiceList(props: ChoiceListProps) {
29
63
  const { options, value, onSelect } = props;
30
64
  return (
31
- <View style={{ gap: 8 }}>
32
- {options.map((o) => {
33
- const selected = value === o.value;
34
- return (
35
- <CardSelectItem
36
- key={o.value}
37
- selected={selected}
38
- onPress={() => onSelect(o.value)}
39
- accessibilityLabel={o.label}
40
- style={styles.item}
41
- >
42
- <View style={styles.text}>
43
- <Text size="sm" weight="medium">
44
- {o.label}
45
- </Text>
46
- {o.description ? (
47
- <Text size="xs" color="muted">
48
- {o.description}
49
- </Text>
50
- ) : null}
51
- </View>
52
- {selected ? <Icon name="check" size={16} color={colors.zinc[900]} /> : null}
53
- </CardSelectItem>
54
- );
55
- })}
65
+ <View>
66
+ {options.map((o, i) => (
67
+ <View key={o.value}>
68
+ {i > 0 ? <Divider /> : null}
69
+ <ChoiceRow option={o} selected={value === o.value} onSelect={onSelect} />
70
+ </View>
71
+ ))}
56
72
  </View>
57
73
  );
58
74
  }
59
-
60
- const styles = StyleSheet.create({
61
- item: { flexDirection: "row", alignItems: "center", gap: 10, paddingVertical: 11, paddingHorizontal: 14 },
62
- text: { flex: 1, gap: 2 },
63
- });
package/src/clarify.tsx CHANGED
@@ -1,5 +1,4 @@
1
- import { StyleSheet, View } from "react-native";
2
- import { colors } from "./colors";
1
+ import { View } from "react-native";
3
2
  import { Text } from "./text";
4
3
  import { ChoiceList, type ChoiceOption } from "./choice_list";
5
4
 
@@ -16,33 +15,24 @@ export interface ClarifyProps {
16
15
  }
17
16
 
18
17
  /**
19
- * The agent asks BACK — a question with selectable answer options (`ChoiceList`)
20
- * the human picks before the run continues, freely switchable until committed.
18
+ * The agent asks BACK — a question with selectable answer options the human picks
19
+ * before the run continues, freely switchable until committed. A borderless block
20
+ * (no card): the question, then divider-separated option rows (`ChoiceList`).
21
21
  * Human-in-the-loop input: when the agent is unsure, it clarifies instead of
22
- * guessing wrong. The run pauses on this and `onAnswer` resumes it. Pair with
23
- * `AgentRun` / `AgentProgress`.
22
+ * guessing wrong. Pair with `AgentRun` / `AgentProgress`.
24
23
  */
25
24
  export function Clarify(props: ClarifyProps) {
26
25
  return (
27
- <View style={styles.card}>
28
- <Text size="xs" color="muted" weight="medium">
29
- Question
30
- </Text>
31
- <Text size="sm" weight="medium">
32
- {props.question}
33
- </Text>
26
+ <View style={{ gap: 14 }}>
27
+ <View style={{ gap: 4 }}>
28
+ <Text size="xs" color="muted" weight="medium">
29
+ Question
30
+ </Text>
31
+ <Text size="sm" weight="medium">
32
+ {props.question}
33
+ </Text>
34
+ </View>
34
35
  <ChoiceList options={props.options} value={props.answer} onSelect={props.onAnswer} />
35
36
  </View>
36
37
  );
37
38
  }
38
-
39
- const styles = StyleSheet.create({
40
- card: {
41
- borderWidth: 1,
42
- borderColor: colors.border,
43
- backgroundColor: colors.white,
44
- borderRadius: 12,
45
- padding: 16,
46
- gap: 12,
47
- },
48
- });