Small UX improvements and basic mobile UI
- cards have full width on mobile - input has full width on mobile - copy-on-click for the feed URLs
This commit is contained in:
parent
2c74cdab3f
commit
84ac24e173
|
|
@ -1,12 +0,0 @@
|
||||||
import { JSX } from "preact";
|
|
||||||
import { IS_BROWSER } from "$fresh/runtime.ts";
|
|
||||||
|
|
||||||
export function Button(props: JSX.HTMLAttributes<HTMLButtonElement>) {
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
{...props}
|
|
||||||
disabled={!IS_BROWSER || props.disabled}
|
|
||||||
class="px-2 py-1 border(gray-100 2) hover:bg-gray-200"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
export default function Search(props: {defaultValue: string}) {
|
export default function Search(props: { defaultValue: string }) {
|
||||||
return (
|
return (
|
||||||
<form className="flex flex-col w-1/2 mx-auto my-4">
|
<form className="flex flex-col w-full lg:w-2/3 mx-auto my-4">
|
||||||
<label className="sr-only" htmlFor="query">Program</label>
|
<label className="sr-only" htmlFor="query">Program</label>
|
||||||
<input placeholder="NRK-podcast" className="border-2" name="query" id="query" defaultValue={props.defaultValue} />
|
<input placeholder="NRK-podcast" className="border-2 rounded-md px-2" name="query" id="query" defaultValue={props.defaultValue} />
|
||||||
<button type="submit" className="my-2 bg-gray-100">Søk</button>
|
<button type="submit" className="my-2 bg-gray-100 rounded-md">Søk</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,21 @@
|
||||||
import { Serie } from "../lib/nrk.ts"
|
import { Serie } from "../lib/nrk.ts"
|
||||||
|
import CopyButton from "../islands/CopyButton.tsx";
|
||||||
|
|
||||||
export function SerieCard(props: { serie: Serie, origin: string }) {
|
export function SerieCard(props: { serie: Serie, origin: string }) {
|
||||||
const feedUrl = new URL(`/api/feeds/${props.serie.seriesId}`, props.origin);
|
const feedUrl = new URL(`/api/feeds/${props.serie.seriesId}`, props.origin);
|
||||||
|
|
||||||
|
console.log(feedUrl.toString())
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border-2 my-2 mx-4">
|
<div className="border-2 my-2 p-2">
|
||||||
<h2 className="text-4xl">{props.serie.title}</h2>
|
<div className="mx-auto h-full w-full">
|
||||||
<p className="text-2xl">{props.serie.description}</p>
|
<h2 className="text-xl">{props.serie.title}</h2>
|
||||||
<img src={props.serie.images[0].uri} />
|
<p className="text-md">{props.serie.description}</p>
|
||||||
<p>Feed: {feedUrl.toString()}</p>
|
<img src={props.serie.images[0].uri} />
|
||||||
</div>
|
<CopyButton text={feedUrl.toString()}>
|
||||||
|
Kopier URL
|
||||||
|
</CopyButton>
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import config from "./deno.json" assert { type: "json" };
|
||||||
import * as $0 from "./routes/api/feeds/[seriesId].ts";
|
import * as $0 from "./routes/api/feeds/[seriesId].ts";
|
||||||
import * as $1 from "./routes/api/search.ts";
|
import * as $1 from "./routes/api/search.ts";
|
||||||
import * as $2 from "./routes/index.tsx";
|
import * as $2 from "./routes/index.tsx";
|
||||||
|
import * as $$0 from "./islands/CopyButton.tsx";
|
||||||
|
|
||||||
const manifest = {
|
const manifest = {
|
||||||
routes: {
|
routes: {
|
||||||
|
|
@ -13,7 +14,9 @@ const manifest = {
|
||||||
"./routes/api/search.ts": $1,
|
"./routes/api/search.ts": $1,
|
||||||
"./routes/index.tsx": $2,
|
"./routes/index.tsx": $2,
|
||||||
},
|
},
|
||||||
islands: {},
|
islands: {
|
||||||
|
"./islands/CopyButton.tsx": $$0,
|
||||||
|
},
|
||||||
baseUrl: import.meta.url,
|
baseUrl: import.meta.url,
|
||||||
config,
|
config,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import Preact from "preact";
|
||||||
|
import { useState } from "preact/hooks"
|
||||||
|
import { IS_BROWSER } from "$fresh/runtime.ts";
|
||||||
|
|
||||||
|
export default function CopyButton(props: { textBefore: string, textAfter: string } & Preact.PropsWithChildren) {
|
||||||
|
|
||||||
|
const [clicked, setClicked] = useState(false);
|
||||||
|
|
||||||
|
const startReset = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
setClicked(false);
|
||||||
|
}, 2_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(props.text.toString());
|
||||||
|
setClicked(true);
|
||||||
|
startReset();
|
||||||
|
}}
|
||||||
|
disabled={!IS_BROWSER || props.disabled}
|
||||||
|
class="px-2 py-1 border(gray-100 2) hover:bg-gray-200 mx-auto"
|
||||||
|
>
|
||||||
|
{clicked ? "Kopiert!" : props.children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ export const handler: Handlers<HandlerData> = {
|
||||||
}
|
}
|
||||||
return ctx.render({ query: query || "", result, origin: url.origin });
|
return ctx.render({ query: query || "", result, origin: url.origin });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Home({ data }: PageProps<HandlerData>) {
|
export default function Home({ data }: PageProps<HandlerData>) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -29,10 +29,13 @@ export default function Home({ data }: PageProps<HandlerData>) {
|
||||||
<title>NRSS</title>
|
<title>NRSS</title>
|
||||||
</Head>
|
</Head>
|
||||||
<div className="p-4 mx-auto max-w-screen-md bg-blue-400">
|
<div className="p-4 mx-auto max-w-screen-md bg-blue-400">
|
||||||
<h1 className="text-4xl text-center">NRSS - NRK-podcast som RSS</h1>
|
<div className="text-center">
|
||||||
|
<h1 className="text-2xl lg:text-3xl">NRSS</h1>
|
||||||
|
<h2 className="lg:text-xl">NRK-podcast som RSS</h2>
|
||||||
|
</div>
|
||||||
<Search defaultValue={data.query} />
|
<Search defaultValue={data.query} />
|
||||||
{data.result ? (
|
{data.result ? (
|
||||||
<div className="w-1/2 mx-auto my-4">
|
<div className="w-full mx-auto my-4">
|
||||||
{data.result.map(result => <SerieCard serie={result} origin={data.origin} />)}
|
{data.result.map(result => <SerieCard serie={result} origin={data.origin} />)}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue