mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
cuter scrollbars, better focus, small design improvements
This commit is contained in:
@@ -10,14 +10,18 @@ export default function UserInfo() {
|
||||
const userinfo = useFiefUserinfo();
|
||||
|
||||
return !isAuthenticated ? (
|
||||
<span className="hover:underline underline-offset-2 decoration-[.5px] font-light px-2">
|
||||
<Link href="/login">Log in or create account</Link>
|
||||
<span className="hover:underline focus-within:underline underline-offset-2 decoration-[.5px] font-light px-2">
|
||||
<Link href="/login" className="outline-none">
|
||||
Log in or create account
|
||||
</Link>
|
||||
</span>
|
||||
) : (
|
||||
<span className="font-light px-2">
|
||||
{userinfo?.email} (
|
||||
<span className="hover:underline underline-offset-2 decoration-[.5px]">
|
||||
<Link href="/logout">Log out</Link>
|
||||
<span className="hover:underline focus-within:underline underline-offset-2 decoration-[.5px]">
|
||||
<Link href="/logout" className="outline-none">
|
||||
Log out
|
||||
</Link>
|
||||
</span>
|
||||
)
|
||||
</span>
|
||||
|
||||
@@ -18,16 +18,16 @@ const ErrorMessage: React.FC = () => {
|
||||
if (!isVisible || !error) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
<button
|
||||
onClick={() => {
|
||||
setIsVisible(false);
|
||||
setError(null);
|
||||
}}
|
||||
className="max-w-xs z-50 fixed bottom-5 right-5 md:bottom-10 md:right-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded transition-opacity duration-300 ease-out opacity-100 hover:opacity-80 cursor-pointer transform hover:scale-105"
|
||||
className="max-w-xs z-50 fixed bottom-5 right-5 md:bottom-10 md:right-10 border-solid bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded transition-opacity duration-300 ease-out opacity-100 hover:opacity-80 focus-visible:opacity-80 cursor-pointer transform hover:scale-105 focus-visible:scale-105"
|
||||
role="alert"
|
||||
>
|
||||
<span className="block sm:inline">{error?.message}</span>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -67,15 +67,18 @@ export default function RootLayout({ children }) {
|
||||
>
|
||||
<header className="flex justify-between items-center w-full">
|
||||
{/* Logo on the left */}
|
||||
<Link href="/" className="flex">
|
||||
<Link
|
||||
href="/"
|
||||
className="flex outline-blue-300 md:outline-none focus-visible:underline underline-offset-2 decoration-[.5px] decoration-gray-500"
|
||||
>
|
||||
<Image
|
||||
src="/reach.png"
|
||||
width={16}
|
||||
height={16}
|
||||
className="h-10 w-auto mr-2"
|
||||
className="h-10 w-auto"
|
||||
alt="Reflector"
|
||||
/>
|
||||
<div className="hidden flex-col md:flex">
|
||||
<div className="hidden flex-col ml-2 md:block">
|
||||
<h1 className="text-4xl font-bold">Reflector</h1>
|
||||
<p className="text-gray-500">
|
||||
Capture The Signal, Not The Noise
|
||||
|
||||
@@ -6,7 +6,6 @@ button {
|
||||
background-color: transparent;
|
||||
font-family: inherit;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
/* Visual */
|
||||
border-radius: 8px;
|
||||
/* Size */
|
||||
@@ -23,6 +22,10 @@ button {
|
||||
transition: 220ms all ease-in-out;
|
||||
}
|
||||
|
||||
button:focus-visible {
|
||||
outline-style: none;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
input[type="button"],
|
||||
button {
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
body {
|
||||
background: white;
|
||||
scrollbar-color: rgb(96 165 250) transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.Dropdown-placeholder {
|
||||
@@ -22,3 +24,14 @@ body {
|
||||
.Dropdown-control.Dropdown-disabled {
|
||||
background-color: lightgray;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
visibility: visible;
|
||||
width: 5px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background-color: rgb(96 165 250);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,7 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
{transcript?.loading === true ||
|
||||
waveform?.loading == true ||
|
||||
topics?.loading == true ? (
|
||||
<Modal
|
||||
title="Loading"
|
||||
text={"Loading transcript..." + transcript.loading}
|
||||
/>
|
||||
<Modal title="Loading" text={"Loading transcript..."} />
|
||||
) : (
|
||||
<>
|
||||
<Recorder
|
||||
@@ -57,7 +54,7 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
useActiveTopic={useActiveTopic}
|
||||
/>
|
||||
<section className="relative w-full h-auto max-h-full bg-blue-400/20 rounded-lg md:rounded-xl px-2 md:px-4 flex flex-col justify-center align-center">
|
||||
<div className="py-2 h-auto">
|
||||
<div className="py-2 h-full">
|
||||
{transcript?.response?.longSummary && (
|
||||
<FinalSummary text={transcript?.response?.longSummary} />
|
||||
)}
|
||||
|
||||
@@ -6,7 +6,7 @@ type ModalProps = {
|
||||
export default function Modal(props: ModalProps) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col items-center justify-center w-fit bg-white px-6 py-8 mt-8 rounded-xl">
|
||||
<div className="w-full flex flex-col items-center justify-center bg-white px-6 py-8 mt-8 rounded-xl">
|
||||
<h1 className="text-2xl font-bold text-blue-500">{props.title}</h1>
|
||||
<p className="text-gray-500 text-center mt-5">{props.text}</p>
|
||||
</div>
|
||||
|
||||
@@ -58,7 +58,7 @@ const TranscriptCreate = () => {
|
||||
audioDevices={audioDevices}
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 grid-rows-2 lg:grid-rows-1 gap-2 lg:gap-4 h-full">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 grid-rows-mobile-inner lg:grid-rows-1 gap-2 lg:gap-4 h-full">
|
||||
<TopicList
|
||||
topics={webSockets.topics}
|
||||
useActiveTopic={useActiveTopic}
|
||||
@@ -109,7 +109,7 @@ const TranscriptCreate = () => {
|
||||
: "Please grant permission to continue."}
|
||||
</p>
|
||||
<button
|
||||
className="mt-4 bg-blue-400 hover:bg-blue-500 text-white font-bold py-2 px-4 rounded m-auto"
|
||||
className="mt-4 bg-blue-400 hover:bg-blue-500 focus-visible:bg-blue-500 text-white font-bold py-2 px-4 rounded m-auto"
|
||||
onClick={requestPermission}
|
||||
disabled={permissionDenied}
|
||||
>
|
||||
|
||||
@@ -243,8 +243,8 @@ export default function Recorder(props: RecorderProps) {
|
||||
<button
|
||||
className={`${
|
||||
isPlaying
|
||||
? "bg-orange-400 hover:bg-orange-500"
|
||||
: "bg-green-400 hover:bg-green-500"
|
||||
? "bg-orange-400 hover:bg-orange-500 focus-visible:bg-orange-500"
|
||||
: "bg-green-400 hover:bg-green-500 focus-visible:bg-green-500"
|
||||
} text-white ml-2 md:ml:4 md:h-[78px] md:min-w-[100px] text-lg`}
|
||||
id="play-btn"
|
||||
onClick={handlePlayClick}
|
||||
@@ -256,7 +256,7 @@ export default function Recorder(props: RecorderProps) {
|
||||
{props.transcriptId && (
|
||||
<a
|
||||
title="Download recording"
|
||||
className="text-center cursor-pointer text-blue-400 hover:text-blue-700 ml-2 md:ml:4 p-2"
|
||||
className="text-center cursor-pointer text-blue-400 hover:text-blue-700 ml-2 md:ml:4 p-2 rounded-lg outline-blue-400"
|
||||
href={`${process.env.NEXT_PUBLIC_API_URL}/v1/transcripts/${props.transcriptId}/audio/mp3`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faDownload} className="h-5 w-auto" />
|
||||
@@ -267,7 +267,7 @@ export default function Recorder(props: RecorderProps) {
|
||||
<a
|
||||
id="download-recording"
|
||||
title="Download recording"
|
||||
className="invisible text-center cursor-pointer text-blue-400 hover:text-blue-700 ml-2 md:ml:4 p-2"
|
||||
className="invisible text-center text-blue-400 hover:text-blue-700 ml-2 md:ml:4 p-2 rounded-lg outline-blue-400"
|
||||
>
|
||||
<FontAwesomeIcon icon={faDownload} className="h-5 w-auto" />
|
||||
</a>
|
||||
@@ -279,8 +279,8 @@ export default function Recorder(props: RecorderProps) {
|
||||
<button
|
||||
className={`${
|
||||
isRecording
|
||||
? "bg-red-400 hover:bg-red-500"
|
||||
: "bg-blue-400 hover:bg-blue-500"
|
||||
? "bg-red-400 hover:bg-red-500 focus-visible:bg-red-500"
|
||||
: "bg-blue-400 hover:bg-blue-500 focus-visible:bg-blue-500"
|
||||
} text-white ml-2 md:ml:4 md:h-[78px] md:min-w-[100px] text-lg`}
|
||||
onClick={handleRecClick}
|
||||
disabled={isPlaying}
|
||||
@@ -290,7 +290,7 @@ export default function Recorder(props: RecorderProps) {
|
||||
{props.audioDevices && props.audioDevices?.length > 0 && (
|
||||
<>
|
||||
<button
|
||||
className="text-center cursor-pointer text-blue-400 hover:text-blue-700 ml-2 md:ml:4 p-2"
|
||||
className="text-center text-blue-400 hover:text-blue-700 ml-2 md:ml:4 p-2 rounded-lg focus-visible:outline outline-blue-400"
|
||||
onClick={() => setShowDevices((prev) => !prev)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faMicrophone} className="h-5 w-auto" />
|
||||
|
||||
@@ -57,36 +57,34 @@ export function TopicList({ topics, useActiveTopic }: TopicListProps) {
|
||||
className="overflow-y-auto py-2 h-full"
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
{topics.map((item, index) => (
|
||||
<div
|
||||
{topics.map((topic, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className="border-b border-blue-300 last:border-none p-2 hover:bg-blue-400/20"
|
||||
role="button"
|
||||
className="rounded-none border-solid border-0 border-b-blue-300 border-b last:border-none p-2 hover:bg-blue-400/20 focus-visible:bg-blue-400/20 text-left block w-full"
|
||||
onClick={() =>
|
||||
setActiveTopic(activeTopic?.id == item.id ? null : item)
|
||||
setActiveTopic(activeTopic?.id == topic.id ? null : topic)
|
||||
}
|
||||
>
|
||||
<div className="flex justify-between items-center rounded-lg md:rounded-xl text-lg md:text-xl font-bold">
|
||||
<div className="w-full flex justify-between items-center rounded-lg md:rounded-xl text-lg md:text-xl font-bold leading-tight">
|
||||
<p>
|
||||
<span className="font-light font-mono text-slate-500 pr-1 text-base md:text-lg">
|
||||
[{formatTime(item.timestamp)}]
|
||||
<span className="font-light font-mono text-slate-500 text-base md:text-lg">
|
||||
[{formatTime(topic.timestamp)}]
|
||||
</span>
|
||||
|
||||
<span className="pr-1">{item.title}</span>
|
||||
<span>{topic.title}</span>
|
||||
</p>
|
||||
<FontAwesomeIcon
|
||||
className="transform transition-transform duration-200 ml-2"
|
||||
icon={
|
||||
activeTopic?.id == item.id
|
||||
activeTopic?.id == topic.id
|
||||
? faChevronDown
|
||||
: faChevronRight
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{activeTopic?.id == item.id && (
|
||||
<div className="px-2">{item.transcript}</div>
|
||||
{activeTopic?.id == topic.id && (
|
||||
<div className="p-2">{topic.transcript}</div>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -10,6 +10,7 @@ module.exports = {
|
||||
extend: {
|
||||
gridTemplateRows: {
|
||||
layout: "auto auto minmax(0, 1fr)",
|
||||
"mobile-inner": "minmax(0, 2fr) minmax(0, 1fr)",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user