Skip to content

Commit

Permalink
Added about and support links. First version of the DecentBar. Is it …
Browse files Browse the repository at this point in the history
…decent?
  • Loading branch information
erikh2000 authored and erikh2000 committed Feb 1, 2025
1 parent 3c5d1e1 commit 8702e8d
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 3 deletions.
87 changes: 87 additions & 0 deletions src/components/decentbar/DecentBar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
@value colors: "@/components/commonPalette.module.css";
@value button, button-text, button-highlight, button-text-highlight, button-disabled, button-text-disabled from colors;
@value commonStyles: "@/components/commonStyles.module.css";
@value disableSelect from commonStyles;

/*
Dynamic sizing of app name text.
Why it's hard to do with just CSS - app facet can grow automatically to fit the child elements within it. But as soon as I use that, it breaks the transition
animation. Also, there are elements to the right of the text that are meant to be hidden when non-hovered over app facet.
I fiddled with this for a long time. I think maybe it's a dead-end for pure CSS. But what should work is measuring the text in JS and setting in-line style width
based on the text measurement.
*/
.container {
composes: disableSelect;
display: flex;
grid-area: header;
width: 100%;
height: 5vh;
}

.decentFacet {
background-color: #000;
width: 8.5vh;
clip-path: polygon(0 0, 100% 0, calc(100% - 5vh) 100%, 0% 100%);
margin-right: -5vh;
}

.appFacet {
background: linear-gradient(button, #222222);
clip-path: polygon(5vh 0, 100% 0, calc(100% - 5vh) 100%, 0% 100%);
margin-right: -6.1vh;
display: inline-block;
width: 22vh; /* See comments on dynamic sizing at top. */
color: white;
overflow-x: hidden;
transition: width 0.3s ease-in-out;
position: relative;
}

.appFacet:hover {
width: 40vh;
}

.appName {
padding-left: 5.5vh;
padding-right: 6vh;
width: 22vh; /* See comments on dynamic sizing at top. */
font-size: 4vh;
-webkit-text-fill-color: white;
-webkit-text-stroke-width: .2vh;
-webkit-text-stroke-color: #222222;
font-family: "hobby-of-night";
display: inline-block;
}

.appButtonArea {
display: inline-block;
height: 100%;
margin-left: -4vh;
}

.appFacetSeparator {
background-color: black;
width: 6vh;
margin-right: -5.5vh;
clip-path: polygon(5vh 0, 100% 0, calc(100% - 5vh) 100%, 0% 100%);
}

.contributorFacet {
background: linear-gradient(#dddddd, #222222);
flex: 1;
clip-path: polygon(5vh 0, 100% 0, 100% 100%, 0% 100%);
margin-right: -5vh;
padding-left: 5vh;
position: relative;
color: #555;
font-size: 1vh;
}

.favIcon {
position: relative;
top: .5vh;
left: .5vh;
height: 4vh;
}
65 changes: 65 additions & 0 deletions src/components/decentbar/DecentBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useEffect, useState } from 'react';

import styles from './DecentBar.module.css';
import ContentButton from '@/components/contentButton/ContentButton';

export type Link = {
description:string,
url:string
}

type Props = {
appName:string,
appLinks?:Link[],
contributorText?:string,
onClickLink:(link:Link) => void
}

function _findFavIconLink() {
return document.querySelector<HTMLLinkElement>('link[rel~="icon"][sizes="192x192"]') ||
document.querySelector<HTMLLinkElement>('link[rel~="icon"]');
}

function _appLinksContent(links:Link[], onClickLink:Function) {
if (!links.length) return null;
const linkButtons = links.map((link, buttonNo) => {
return (
<ContentButton key={buttonNo} text={link.description} onClick={() => {onClickLink(link)}}/>
);
});
return <>Links:<br />{linkButtons}</>;
}

function DecentBar({ appName, appLinks, contributorText, onClickLink }: Props) {
const [favIconUrl, setFavIconUrl] = useState<string | null>(null);

useEffect(() => {
const link = _findFavIconLink();
if (!link) return;
setFavIconUrl(link.href);
}, []);

if (!favIconUrl) return null;

const appLinksContent = _appLinksContent(appLinks || [], onClickLink);

return (
<div className={styles.container}>
<div className={styles.decentFacet}>
<img src={favIconUrl} className={styles.favIcon} draggable="false"/>
</div>
<div className={styles.appFacet}>
<div className={styles.appName}>{appName}</div>
<div className={styles.appButtonArea}>
{appLinksContent}
</div>
</div>
<div className={styles.appFacetSeparator} />
<div className={styles.contributorFacet}>
{contributorText}
</div>
</div>
)
}

export default DecentBar;
24 changes: 21 additions & 3 deletions src/homeScreen/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
discardPartialDataAfterCancel
} from "./interactions/execute";
import ExecutionJob from "@/sheets/types/ExecutionJob";
import AboutDialog from "./dialogs/AboutDialog";
import ExecuteDialog from "./dialogs/ExecuteDialog";
import { chooseExportType, exportSheet } from "./interactions/export";
import KeepPartialDataDialog from "./dialogs/KeepPartialDataDialog";
Expand All @@ -32,6 +33,12 @@ import { LOAD_URL } from "@/common/urlUtil";
import { doesSheetHaveWritableColumns } from "@/sheets/sheetUtil";
import HorizontalScroll from "@/components/sheetTable/types/HorizontalScroll";
import ConfirmClearSheetDialog from "./dialogs/ConfirmClearSheetDialog";
import DecentBar, { Link } from "@/components/decentbar/DecentBar";

const appLinks:Link[] = [
{description:'About', url:'about'},
{description:'Support', url:'https://github.com/erikh2000/hone/issues'},
];

function HomeScreen() {
const [sheet, setSheet] = useState<HoneSheet|null>(null);
Expand Down Expand Up @@ -70,11 +77,20 @@ function HomeScreen() {
onExecute={promptTemplate => setUpExecution(job, sheet, promptTemplate, setPromptTemplate, setJob, setModalDialog)}
/>;

function _onClickLink(link:Link) {
const { url } = link;
if (url.startsWith('https://')) {
window.open(link.url, '_blank');
return;
}
if (url === 'about') {
setModalDialog(AboutDialog.name);
}
}

return (
<div className={styles.container}>
<div className={styles.header}>
<h1>Hone</h1>
</div>
<DecentBar appName="Hone" appLinks={appLinks} contributorText="by Erik Hermansen" onClickLink={_onClickLink} />
<SheetPane
sheet={sheet} className={styles.sheetPane} selectedRowNo={selectedRowNo}
horizontalScroll={sheetHorizontalScroll}
Expand Down Expand Up @@ -148,6 +164,8 @@ function HomeScreen() {
onCancel={() => setModalDialog(null)}
/>

<AboutDialog isOpen={modalDialog === AboutDialog.name} onClose={() => setModalDialog(null)} />

<ToastPane/>
</div>
);
Expand Down
18 changes: 18 additions & 0 deletions src/homeScreen/dialogs/AboutDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import OkayDialog from "@/components/modalDialogs/OkayDialog";

type Props = {
onClose: () => void,
isOpen: boolean
}

function AboutDialog({ onClose, isOpen }: Props) {
return (
<OkayDialog title="About Hone"
isOpen={isOpen}
description="There was an AI feature I wanted from Excel that Microsoft wasn't giving me. And it seemed like a really useful feature. So I made Hone. I hope you like it. -Erik"
onOkay={onClose}
/>
);
}

export default AboutDialog;

0 comments on commit 8702e8d

Please sign in to comment.