Skip to content

Commit 6d71c57

Browse files
committedMar 14, 2025
baseline
1 parent 8252aaf commit 6d71c57

File tree

5 files changed

+88
-61
lines changed

5 files changed

+88
-61
lines changed
 

‎apps/frontend/ui/src/navigation/partials/OptionTrace/func.tsx

+43-49
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,66 @@
11
import { useState } from "react";
22
import type { JSX } from "react";
33

4-
import { useComboboxFilter, useId } from "@lib-hooks";
5-
import { Combobox, Field } from "@lib-components";
4+
import { useId } from "@lib-hooks";
5+
import { Combobox, Field, Option, Spinner } from "@lib-components";
66
import type { TComboboxProps } from "@lib-components";
77

88
import { OptionLayoutTemplate } from "../../templates";
99
import useClasses from "./styles";
1010

11-
const options = [
12-
// { children: "Alligator", value: "Alligator" },
13-
// { children: "Bee", value: "Bee" },
14-
// { children: "Bird", value: "Bird" },
15-
// { children: "Dog", value: "Dog" },
16-
// { children: "Dolphin", value: "Dolphin" },
17-
// { children: "Ferret", value: "Ferret" },
18-
// { children: "Firefly", value: "Firefly" },
19-
// { children: "Fish", value: "Fish" },
20-
// { children: "Goat", value: "Goat" },
21-
// { children: "Horse", value: "Horse" },
22-
// { children: "Lion", value: "Lion" },
23-
];
11+
type TProps = {
12+
results: string[];
13+
isBouncing: boolean;
14+
isFetching: boolean;
15+
onChange: TComboboxProps["onChange"];
16+
onOptionSelect: () => void;
17+
};
2418

25-
type TProps = {};
26-
27-
export default function OptionTrace({}: TProps): JSX.Element {
19+
export default function OptionTrace({
20+
results,
21+
isBouncing,
22+
isFetching,
23+
onChange,
24+
onOptionSelect,
25+
}: TProps): JSX.Element {
2826
const classes = useClasses();
29-
const comboId = useId();
30-
const [query, setQuery] = useState<string>("");
31-
const currentQueryHasExactMatch = options.some(
32-
(option) => option.children === query,
33-
);
34-
35-
const children = useComboboxFilter(query, options, {
36-
noOptionsMessage: "No animals match your search.",
37-
});
38-
const onOptionSelect: TComboboxProps["onOptionSelect"] = (_, data) => {
39-
setQuery(data.optionText ?? "");
40-
};
27+
const comboId = useId("combobox");
4128

4229
return (
4330
<OptionLayoutTemplate
4431
header="Trace a Word"
4532
subtitle="Use a word as a anchor and find words that are related to it."
46-
onClick={() => {}}
4733
isLoading={false}
48-
disableClick={false}
49-
buttonLabel="Construct trace tree"
34+
withoutButton
5035
>
51-
<Field
52-
label="Search"
53-
validationState={currentQueryHasExactMatch ? "success" : "error"}
54-
validationMessage={
55-
currentQueryHasExactMatch
56-
? "This word is known."
57-
: "This word is not known."
58-
}
59-
>
36+
<Field id={comboId} label="Select a known word">
6037
<Combobox
61-
onOptionSelect={onOptionSelect}
6238
aria-labelledby={comboId}
63-
placeholder="Select a known word from the dictionary"
64-
onChange={(ev) => {
65-
setQuery(ev.target.value);
66-
}}
67-
value={query}
39+
placeholder="Start typing for suggestions"
40+
onChange={onChange}
6841
>
69-
{children}
42+
{isFetching ? (
43+
<Option text="" disabled className={classes.loading}>
44+
<Spinner size="extra-small" label="Searching, hold on..." />
45+
</Option>
46+
) : (
47+
results.map((word) => (
48+
<Option
49+
key={word}
50+
text={word}
51+
disabled={isBouncing}
52+
onClick={onOptionSelect}
53+
>
54+
{word}
55+
</Option>
56+
))
57+
)}
58+
59+
{results.length === 0 && (
60+
<Option text="" disabled className={classes.optionReadOnly}>
61+
No matching words found...
62+
</Option>
63+
)}
7064
</Combobox>
7165
</Field>
7266
</OptionLayoutTemplate>

‎apps/frontend/ui/src/navigation/partials/OptionTrace/stories.tsx

+19-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,22 @@ export default meta;
1111

1212
type Story = StoryObj<typeof OptionTrace>;
1313

14-
export const Index: Story = {};
14+
export const Index: Story = {
15+
args: {
16+
// results: [],
17+
results: [
18+
"apple",
19+
"banana",
20+
"cherry",
21+
"date",
22+
"elderberry",
23+
"fig",
24+
"grape",
25+
"honeydew",
26+
"kiwi",
27+
],
28+
isBouncing: false,
29+
isFetching: false,
30+
onChange: () => {},
31+
},
32+
};
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
import { makeStyles } from "@lib-theme";
1+
import { makeStyles, tokens } from "@lib-theme";
22

33
const useClasses = makeStyles({
44
root: {},
5+
optionReadOnly: {
6+
color: tokens.colorNeutralForeground1,
7+
},
8+
loading: {
9+
display: "flex",
10+
justifyContent: "center",
11+
alignItems: "center",
12+
marginLeft: "-12px",
13+
},
514
});
615

716
export default useClasses;

‎apps/frontend/ui/src/navigation/templates/OptionLayout/func.tsx

+15-10
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,43 @@ import useOptionLayoutClasses from "@app-ui/navigation/templates/OptionLayout/st
77

88
type TProps = {
99
header: string;
10-
onClick: () => void;
10+
onClick?: () => void;
1111
disableClick?: boolean;
1212
buttonLabel?: string;
1313
isLoading?: boolean;
1414
subtitle?: string;
1515
children?: ReactNode;
16+
withoutButton?: boolean;
1617
};
1718

1819
export default function OptionLayout({
1920
header,
20-
onClick,
2121
buttonLabel = "Search",
22+
onClick = () => {},
2223
subtitle = undefined,
2324
children = undefined,
2425
disableClick = false,
2526
isLoading = false,
27+
withoutButton = false,
2628
}: TProps): JSX.Element {
2729
const classes = useOptionLayoutClasses();
2830
return (
29-
<Flex className={classes.root} direction="column" padding={["M"]} gap="M">
31+
<Flex className={classes.root} direction="column" padding={["M"]} gap="L">
3032
<Flex direction="column" gap="XS">
3133
<Subtitle2>{header}</Subtitle2>
3234
{subtitle && <Caption2>{subtitle}</Caption2>}
3335
</Flex>
3436
{children}
35-
<Button appearance="primary" disabled={disableClick} onClick={onClick}>
36-
{isLoading ? (
37-
<Spinner size="tiny" appearance="inverted" />
38-
) : (
39-
buttonLabel
40-
)}
41-
</Button>
37+
38+
{!withoutButton && (
39+
<Button appearance="primary" disabled={disableClick} onClick={onClick}>
40+
{isLoading ? (
41+
<Spinner size="tiny" appearance="inverted" />
42+
) : (
43+
buttonLabel
44+
)}
45+
</Button>
46+
)}
4247
</Flex>
4348
);
4449
}

‎libs/components/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export { MenuList } from "@fluentui/react-components";
66
export { MenuItemRadio } from "@fluentui/react-components";
77
export { Spinner } from "@fluentui/react-components";
88
export { Field } from "@fluentui/react-components";
9+
export { Option } from "@fluentui/react-components";
910

1011
export { Collapse } from "@fluentui/react-motion-components-preview";
1112

0 commit comments

Comments
 (0)
Please sign in to comment.