mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 19:49:01 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			322 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { ComponentChildren } from 'preact';
 | |
| import Card from '../../components/Card.js';
 | |
| import Section from '../../components/Section.js';
 | |
| import DownloadButton from '../../components/DownloadButton.js';
 | |
| import "./index.css";
 | |
| import { useColorScheme, usePageTitle } from '../../hooks.js';
 | |
| import Button, { Link } from '../../components/Button.js';
 | |
| import gitHubIcon from "../../assets/boxicons/bx-github.svg?raw";
 | |
| import dockerIcon from "../../assets/boxicons/bx-docker.svg?raw";
 | |
| import noteStructureIcon from "../../assets/boxicons/bx-folder.svg?raw";
 | |
| import attributesIcon from "../../assets/boxicons/bx-tag.svg?raw";
 | |
| import hoistingIcon from "../../assets/boxicons/bx-chevrons-up.svg?raw";
 | |
| import revisionsIcon from "../../assets/boxicons/bx-history.svg?raw";
 | |
| import syncIcon from "../../assets/boxicons/bx-refresh-cw.svg?raw";
 | |
| import protectedNotesIcon from "../../assets/boxicons/bx-shield.svg?raw";
 | |
| import jumpToIcon from "../../assets/boxicons/bx-send-alt.svg?raw";
 | |
| import searchIcon from "../../assets/boxicons/bx-search.svg?raw";
 | |
| import webClipperIcon from "../../assets/boxicons/bx-paperclip.svg?raw";
 | |
| import importExportIcon from "../../assets/boxicons/bx-swap-horizontal.svg?raw";
 | |
| import shareIcon from "../../assets/boxicons/bx-globe.svg?raw";
 | |
| import codeIcon from "../../assets/boxicons/bx-code.svg?raw";
 | |
| import restApiIcon from "../../assets/boxicons/bx-extension.svg?raw";
 | |
| import textNoteIcon from "../../assets/boxicons/bx-note.svg?raw";
 | |
| import fileIcon from "../../assets/boxicons/bx-file.svg?raw";
 | |
| import canvasIcon from "../../assets/boxicons/bx-pen.svg?raw";
 | |
| import mermaidIcon from "../../assets/boxicons/bx-vector-square.svg?raw";
 | |
| import mindmapIcon from "../../assets/boxicons/bx-network-chart.svg?raw";
 | |
| import calendarIcon from "../../assets/boxicons/bx-calendar.svg?raw";
 | |
| import tableIcon from "../../assets/boxicons/bx-table.svg?raw";
 | |
| import boardIcon from "../../assets/boxicons/bx-columns-3.svg?raw";
 | |
| import geomapIcon from "../../assets/boxicons/bx-map.svg?raw";
 | |
| import { getPlatform } from '../../download-helper.js';
 | |
| import { useEffect, useState } from 'preact/hooks';
 | |
| import { Trans, useTranslation } from 'react-i18next';
 | |
| 
 | |
| export function Home() {
 | |
|     usePageTitle("");
 | |
| 
 | |
| 	return (
 | |
|         <>
 | |
|             <HeroSection />
 | |
|             <OrganizationBenefitsSection />
 | |
|             <ProductivityBenefitsSection />
 | |
|             <NoteTypesSection />
 | |
|             <ExtensibilityBenefitsSection />
 | |
|             <CollectionsSection />
 | |
|             <FaqSection />
 | |
|             <FinalCta />
 | |
|         </>
 | |
| 	);
 | |
| }
 | |
| 
 | |
| function HeroSection() {
 | |
|     const { t } = useTranslation();
 | |
|     const platform = getPlatform();
 | |
|     const colorScheme = useColorScheme();
 | |
|     const [ screenshotUrl, setScreenshotUrl ] = useState<string>();
 | |
| 
 | |
|     useEffect(() => {
 | |
|         switch (platform) {
 | |
|             case "macos":
 | |
|                 setScreenshotUrl(`/screenshot_desktop_mac_${colorScheme}.webp`);
 | |
|                 break;
 | |
|             case "linux":
 | |
|                 setScreenshotUrl(`/screenshot_desktop_linux_${colorScheme}.webp`);
 | |
|                 break;
 | |
|             case "windows":
 | |
|             default:
 | |
|                 setScreenshotUrl(`/screenshot_desktop_win_${colorScheme}.webp`);
 | |
|                 break;
 | |
|         }
 | |
|     }, [ colorScheme ]);
 | |
| 
 | |
|     return (
 | |
|         <Section className="hero-section">
 | |
|             <div class="title-section">
 | |
|                 <h1>{t("hero_section.title")}</h1>
 | |
|                 <p>{t("hero_section.subtitle")}</p>
 | |
| 
 | |
|                 <div className="download-wrapper">
 | |
|                     <DownloadButton big />
 | |
|                     <Button href="./get-started/" className="mobile-only" text={t("hero_section.get_started")} />
 | |
|                     <div className="additional-options">
 | |
|                         <Button iconSvg={gitHubIcon} outline text={t("hero_section.github")} href="https://github.com/TriliumNext/Trilium/" openExternally />
 | |
|                         <Button iconSvg={dockerIcon} outline text={t("hero_section.dockerhub")} href="https://hub.docker.com/r/triliumnext/trilium" openExternally />
 | |
|                     </div>
 | |
|                 </div>
 | |
| 
 | |
|             </div>
 | |
| 
 | |
|             <div className="screenshot-container">
 | |
|                 {screenshotUrl && <img class="screenshot" src={screenshotUrl} alt={t("hero_section.screenshot_alt")} />}
 | |
|             </div>
 | |
|         </Section>
 | |
|     )
 | |
| }
 | |
| 
 | |
| function OrganizationBenefitsSection() {
 | |
|     const { t } = useTranslation();
 | |
|     return (
 | |
|         <>
 | |
|             <Section className="benefits" title={t("organization_benefits.title")}>
 | |
|                 <div className="benefits-container grid-3-cols">
 | |
|                     <Card iconSvg={noteStructureIcon} title={t("organization_benefits.note_structure_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes/index.html">{t("organization_benefits.note_structure_description")}</Card>
 | |
|                     <Card iconSvg={attributesIcon} title={t("organization_benefits.attributes_title")} moreInfoUrl="https://docs.triliumnotes.org/User Guide/User Guide/Advanced Usage/Attributes/index.html">{t("organization_benefits.attributes_description")}</Card>
 | |
|                     <Card iconSvg={hoistingIcon} title={t("organization_benefits.hoisting_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Navigation/Note%20Hoisting.html">{t("organization_benefits.hoisting_description")}</Card>
 | |
|                 </div>
 | |
|             </Section>
 | |
|         </>
 | |
|     );
 | |
| }
 | |
| 
 | |
| function ProductivityBenefitsSection() {
 | |
|     const { t } = useTranslation();
 | |
|     return (
 | |
|         <>
 | |
|             <Section className="benefits accented" title={t("productivity_benefits.title")}>
 | |
|                 <div className="benefits-container grid-3-cols">
 | |
|                     <Card iconSvg={revisionsIcon} title={t("productivity_benefits.revisions_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes/Note%20Revisions.html">{t("productivity_benefits.revisions_content")}</Card>
 | |
|                     <Card iconSvg={syncIcon} title={t("productivity_benefits.sync_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Installation%20%26%20Setup/Synchronization.html">{t("productivity_benefits.sync_content")}</Card>
 | |
|                     <Card iconSvg={protectedNotesIcon} title={t("productivity_benefits.protected_notes_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes/Protected%20Notes.html">{t("productivity_benefits.protected_notes_content")}</Card>
 | |
|                     <Card iconSvg={jumpToIcon} title={t("productivity_benefits.jump_to_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Navigation/Jump%20to.html">{t("productivity_benefits.jump_to_content")}</Card>
 | |
|                     <Card iconSvg={searchIcon} title={t("productivity_benefits.search_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Navigation/Search.html">{t("productivity_benefits.search_content")}</Card>
 | |
|                     <Card iconSvg={webClipperIcon} title={t("productivity_benefits.web_clipper_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Installation%20%26%20Setup/Web%20Clipper.html">{t("productivity_benefits.web_clipper_content")}</Card>
 | |
|                 </div>
 | |
|             </Section>
 | |
|         </>
 | |
|     );
 | |
| }
 | |
| 
 | |
| function NoteTypesSection() {
 | |
|     const { t } = useTranslation();
 | |
|     return (
 | |
|         <Section className="note-types" title={t("note_types.title")}>
 | |
|             <ListWithScreenshot horizontal items={[
 | |
|                 {
 | |
|                     title: t("note_types.text_title"),
 | |
|                     imageUrl: "/type_text.webp",
 | |
|                     iconSvg: textNoteIcon,
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Text/index.html",
 | |
|                     description: t("note_types.text_description")
 | |
|                 },
 | |
|                 {
 | |
|                     title: t("note_types.code_title"),
 | |
|                     imageUrl: "/type_code.webp",
 | |
|                     iconSvg: codeIcon,
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Code.html",
 | |
|                     description: t("note_types.code_description")
 | |
|                 },
 | |
|                 {
 | |
|                     title: t("note_types.file_title"),
 | |
|                     imageUrl: "/type_file.webp",
 | |
|                     iconSvg: fileIcon,
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/File.html",
 | |
|                     description: t("note_types.file_description")
 | |
|                 },
 | |
|                 {
 | |
|                     title: t("note_types.canvas_title"),
 | |
|                     imageUrl: "/type_canvas.webp",
 | |
|                     iconSvg: canvasIcon,
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Canvas.html",
 | |
|                     description: t("note_types.canvas_description")
 | |
|                 },
 | |
|                 {
 | |
|                     title: t("note_types.mermaid_title"),
 | |
|                     imageUrl: "/type_mermaid.webp",
 | |
|                     iconSvg: mermaidIcon,
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Mermaid%20Diagrams/index.html",
 | |
|                     description: t("note_types.mermaid_description")
 | |
|                 },
 | |
|                 {
 | |
|                     title: t("note_types.mindmap_title"),
 | |
|                     imageUrl: "/type_mindmap.webp",
 | |
|                     iconSvg: mindmapIcon,
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Mind%20Map.html",
 | |
|                     description: t("note_types.mindmap_description")
 | |
|                 }
 | |
|             ]} />
 | |
|             <p>
 | |
|                 <Trans
 | |
|                     i18nKey="note_types.others_list"
 | |
|                     components={[
 | |
|                         <Link href="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Note%20Map.html" openExternally />,
 | |
|                         <Link href="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Relation%20Map.html" openExternally />,
 | |
|                         <Link href="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Saved%20Search.html" openExternally />,
 | |
|                         <Link href="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Render%20Note.html" openExternally />,
 | |
|                         <Link href="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Web%20View.html" openExternally />
 | |
|                     ]}
 | |
|                 />
 | |
|             </p>
 | |
|         </Section>
 | |
|     );
 | |
| }
 | |
| 
 | |
| function ExtensibilityBenefitsSection() {
 | |
|     const { t } = useTranslation();
 | |
|     return (
 | |
|         <>
 | |
|             <Section className="benefits accented" title={t("extensibility_benefits.title")}>
 | |
|                 <div className="benefits-container grid-4-cols">
 | |
|                     <Card iconSvg={importExportIcon} title={t("extensibility_benefits.import_export_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Import%20%26%20Export/Markdown/index.html">{t("extensibility_benefits.import_export_description")}</Card>
 | |
|                     <Card iconSvg={shareIcon} title={t("extensibility_benefits.share_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Advanced%20Usage/Sharing/Serving%20directly%20the%20content%20o.html">{t("extensibility_benefits.share_description")}</Card>
 | |
|                     <Card iconSvg={codeIcon} title={t("extensibility_benefits.scripting_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Scripting/Custom%20Widgets/index.html">{t("extensibility_benefits.scripting_description")}</Card>
 | |
|                     <Card iconSvg={restApiIcon} title={t("extensibility_benefits.api_title")} moreInfoUrl="https://docs.triliumnotes.org/User%20Guide/User%20Guide/Advanced%20Usage/ETAPI%20%28REST%20API%29/index.html">{t("extensibility_benefits.api_description")}</Card>
 | |
|                 </div>
 | |
|             </Section>
 | |
|         </>
 | |
|     );
 | |
| }
 | |
| 
 | |
| function CollectionsSection() {
 | |
|     const { t } = useTranslation();
 | |
|     return (
 | |
|         <Section className="collections" title={t("collections.title")}>
 | |
|             <ListWithScreenshot items={[
 | |
|                 {
 | |
|                     title: t("collections.calendar_title"),
 | |
|                     imageUrl: "/collection_calendar.webp",
 | |
|                     iconSvg: calendarIcon,
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Collections/Calendar%20View.html",
 | |
|                     description: t("collections.calendar_description")
 | |
|                 },
 | |
|                 {
 | |
|                     title: t("collections.table_title"),
 | |
|                     iconSvg: tableIcon,
 | |
|                     imageUrl: "/collection_table.webp",
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Collections/Table%20View.html",
 | |
|                     description: t("collections.table_description")
 | |
|                 },
 | |
|                 {
 | |
|                     title: t("collections.board_title"),
 | |
|                     iconSvg: boardIcon,
 | |
|                     imageUrl: "/collection_board.webp",
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Collections/Board%20View.html",
 | |
|                     description: t("collections.board_description")
 | |
|                 },
 | |
|                 {
 | |
|                     title: t("collections.geomap_title"),
 | |
|                     iconSvg: geomapIcon,
 | |
|                     imageUrl: "/collection_geomap.webp",
 | |
|                     moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Collections/Geo%20Map%20View.html",
 | |
|                     description: t("collections.geomap_description")
 | |
|                 }
 | |
|             ]} />
 | |
|         </Section>
 | |
|     );
 | |
| }
 | |
| 
 | |
| function ListWithScreenshot({ items, horizontal, cardExtra }: {
 | |
|     items: { title: string, imageUrl: string, description: string, moreInfo: string, iconSvg?: string }[];
 | |
|     horizontal?: boolean;
 | |
|     cardExtra?: ComponentChildren;
 | |
| }) {
 | |
|     const [ selectedItem, setSelectedItem ] = useState(items[0]);
 | |
|     const { t } = useTranslation();
 | |
| 
 | |
|     return (
 | |
|         <div className={`list-with-screenshot ${horizontal ? "horizontal" : ""}`}>
 | |
|             <ul>
 | |
|                 {items.map(item => (
 | |
|                     <li className={`${item === selectedItem ? "selected" : ""}`}>
 | |
|                         <Card
 | |
|                             title={item.title}
 | |
|                             onMouseEnter={() => setSelectedItem(item)}
 | |
|                             onClick={() => setSelectedItem(item)}
 | |
|                             moreInfoUrl={item.moreInfo}
 | |
|                             iconSvg={item.iconSvg}
 | |
|                         >
 | |
|                             {item.description}
 | |
|                         </Card>
 | |
|                     </li>
 | |
|                 ))}
 | |
|             </ul>
 | |
| 
 | |
|             <div className="details">
 | |
|                 {selectedItem && (
 | |
|                     <>
 | |
|                         <img src={selectedItem.imageUrl} alt={t("components.list_with_screenshot_alt")} loading="lazy" />
 | |
|                     </>
 | |
|                 )}
 | |
|             </div>
 | |
|         </div>
 | |
|     )
 | |
| }
 | |
| 
 | |
| function FaqSection() {
 | |
|     const { t } = useTranslation();
 | |
|     return (
 | |
|         <Section className="faq" title={t("faq.title")}>
 | |
|             <div class="grid-2-cols">
 | |
|                 <FaqItem question={t("faq.mobile_question")}>{t("faq.mobile_answer")}</FaqItem>
 | |
|                 <FaqItem question={t("faq.database_question")}>{t("faq.database_answer")}</FaqItem>
 | |
|                 <FaqItem question={t("faq.server_question")}>{t("faq.server_answer")}</FaqItem>
 | |
|                 <FaqItem question={t("faq.scaling_question")}>{t("faq.scaling_answer")}</FaqItem>
 | |
|                 <FaqItem question={t("faq.network_share_question")}>{t("faq.network_share_answer")}</FaqItem>
 | |
|                 <FaqItem question={t("faq.security_question")}>{t("faq.security_answer")}</FaqItem>
 | |
|             </div>
 | |
|         </Section>
 | |
|     );
 | |
| }
 | |
| 
 | |
| function FaqItem({ question, children }: { question: string; children: ComponentChildren }) {
 | |
|     return (
 | |
|         <Card title={question}>
 | |
|             {children}
 | |
|         </Card>
 | |
|     )
 | |
| }
 | |
| 
 | |
| function FinalCta() {
 | |
|     const { t } = useTranslation();
 | |
|     return (
 | |
|         <Section className="final-cta accented" title={t("final_cta.title")}>
 | |
|             <p>{t("final_cta.description")}</p>
 | |
| 
 | |
|             <div class="buttons">
 | |
|                 <Button href="./get-started/" text={t("final_cta.get_started")} />
 | |
|             </div>
 | |
|         </Section>
 | |
|     )
 | |
| }
 | 
