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