This commit is contained in:
Suphonchai Phoonsawat 2026-08-18 12:52:40 +07:00
commit 41573b3c4f
54 changed files with 32839 additions and 0 deletions

View file

@ -0,0 +1,47 @@
import * as React from "react";
import Header from "./Header";
import HeroList, { HeroListItem } from "./HeroList";
import TextInsertion from "./TextInsertion";
import { makeStyles } from "@fluentui/react-components";
import { Ribbon24Regular, LockOpen24Regular, DesignIdeas24Regular } from "@fluentui/react-icons";
import { insertText } from "../taskpane";
interface AppProps {
title: string;
}
const useStyles = makeStyles({
root: {
minHeight: "100vh",
},
});
const App: React.FC<AppProps> = (props: AppProps) => {
const styles = useStyles();
// The list items are static and won't change at runtime,
// so this should be an ordinary const, not a part of state.
const listItems: HeroListItem[] = [
{
icon: <Ribbon24Regular />,
primaryText: "Achieve more with Office integration",
},
{
icon: <LockOpen24Regular />,
primaryText: "Unlock features and functionality",
},
{
icon: <DesignIdeas24Regular />,
primaryText: "Create and visualize like a pro",
},
];
return (
<div className={styles.root}>
<Header logo="assets/logo-filled.png" title={props.title} message="Welcome" />
<HeroList message="Discover what this add-in can do for you today!" items={listItems} />
<TextInsertion insertText={insertText} />
</div>
);
};
export default App;

View file

@ -0,0 +1,38 @@
import * as React from "react";
import { Image, tokens, makeStyles } from "@fluentui/react-components";
export interface HeaderProps {
title: string;
logo: string;
message: string;
}
const useStyles = makeStyles({
welcome__header: {
display: "flex",
flexDirection: "column",
alignItems: "center",
paddingBottom: "30px",
paddingTop: "100px",
backgroundColor: tokens.colorNeutralBackground3,
},
message: {
fontSize: tokens.fontSizeHero900,
fontWeight: tokens.fontWeightRegular,
fontColor: tokens.colorNeutralBackgroundStatic,
},
});
const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
const { title, logo, message } = props;
const styles = useStyles();
return (
<section className={styles.welcome__header}>
<Image width="90" height="90" src={logo} alt={title} />
<h1 className={styles.message}>{message}</h1>
</section>
);
};
export default Header;

View file

@ -0,0 +1,62 @@
import * as React from "react";
import { tokens, makeStyles } from "@fluentui/react-components";
export interface HeroListItem {
icon: React.JSX.Element;
primaryText: string;
}
export interface HeroListProps {
message: string;
items: HeroListItem[];
}
const useStyles = makeStyles({
list: {
marginTop: "20px",
},
listItem: {
paddingBottom: "20px",
display: "flex",
},
icon: {
marginRight: "10px",
},
itemText: {
fontSize: tokens.fontSizeBase300,
fontColor: tokens.colorNeutralBackgroundStatic,
},
welcome__main: {
width: "100%",
display: "flex",
flexDirection: "column",
alignItems: "center",
},
message: {
fontSize: tokens.fontSizeBase500,
fontColor: tokens.colorNeutralBackgroundStatic,
fontWeight: tokens.fontWeightRegular,
paddingLeft: "10px",
paddingRight: "10px",
},
});
const HeroList: React.FC<HeroListProps> = (props: HeroListProps) => {
const { items, message } = props;
const styles = useStyles();
const listItems = items.map((item, index) => (
<li className={styles.listItem} key={index}>
<i className={styles.icon}>{item.icon}</i>
<span className={styles.itemText}>{item.primaryText}</span>
</li>
));
return (
<div className={styles.welcome__main}>
<h2 className={styles.message}>{message}</h2>
<ul className={styles.list}>{listItems}</ul>
</div>
);
};
export default HeroList;

View file

@ -0,0 +1,57 @@
import * as React from "react";
import { useState } from "react";
import { Button, Field, Textarea, tokens, makeStyles } from "@fluentui/react-components";
/* global HTMLTextAreaElement */
interface TextInsertionProps {
insertText: (text: string) => void;
}
const useStyles = makeStyles({
instructions: {
fontWeight: tokens.fontWeightSemibold,
marginTop: "20px",
marginBottom: "10px",
},
textPromptAndInsertion: {
display: "flex",
flexDirection: "column",
alignItems: "center",
},
textAreaField: {
marginLeft: "20px",
marginTop: "30px",
marginBottom: "20px",
marginRight: "20px",
maxWidth: "50%",
},
});
const TextInsertion: React.FC<TextInsertionProps> = (props: TextInsertionProps) => {
const [text, setText] = useState<string>("Some text.");
const handleTextInsertion = async () => {
await props.insertText(text);
};
const handleTextChange = async (event: React.ChangeEvent<HTMLTextAreaElement>) => {
setText(event.target.value);
};
const styles = useStyles();
return (
<div className={styles.textPromptAndInsertion}>
<Field className={styles.textAreaField} size="large" label="Enter text to be inserted into the document.">
<Textarea size="large" value={text} onChange={handleTextChange} />
</Field>
<Field className={styles.instructions}>Click the button to insert text.</Field>
<Button appearance="primary" disabled={false} size="large" onClick={handleTextInsertion}>
Insert text
</Button>
</div>
);
};
export default TextInsertion;