Pronouns labels on Bluesky
1import { createSignal, For, Show, type Component } from "solid-js";
2import { PRONOUNS, METANOUNS, NEOPRONOUNS } from "./constants.js";
3
4const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
5const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 1;
6const basePostUrl =
7 isSafari && isTouchDevice
8 ? "bluesky:///profile/pronouns.adorable.mom/post/"
9 : "https://bsky.app/profile/pronouns.adorable.mom/post/";
10
11const [search, setSearch] = createSignal("");
12
13const PronounsList: Component<{ search: string }> = (props) => {
14 const searchFilter = (arr: string[]) =>
15 arr.filter(
16 (x) =>
17 x.includes(props.search.replaceAll(" ", "/")) ||
18 x.includes(props.search),
19 );
20
21 return (
22 <div class="screen flex flex-col sm:h-[70svh] sm:w-[32rem] sm:flex-row sm:gap-x-4">
23 <div class="w-full overflow-auto sm:flex-none sm:basis-1/3">
24 <For each={searchFilter(Object.keys(PRONOUNS))}>
25 {(pronoun, index) => (
26 <div>
27 <Show when={index() === 0}>
28 <div class="my-1 text-center text-xl">Pronouns</div>
29 </Show>
30 <div
31 classList={{
32 "border-b border-b-zinc-600":
33 index() !== searchFilter(Object.keys(PRONOUNS)).length - 1,
34 }}
35 >
36 <a
37 href={basePostUrl + PRONOUNS[pronoun]}
38 class="block h-full w-full py-3 text-center text-sky-500 hover:bg-zinc-800"
39 >
40 {pronoun}
41 </a>
42 </div>
43 </div>
44 )}
45 </For>
46 </div>
47 <div class="w-full overflow-auto sm:flex-none sm:basis-1/3">
48 <For each={searchFilter(Object.keys(METANOUNS))}>
49 {(pronoun, index) => (
50 <div>
51 <Show when={index() === 0}>
52 <div class="my-1 text-center text-xl">Meta</div>
53 </Show>
54 <div
55 classList={{
56 "border-b border-b-zinc-600":
57 index() !== searchFilter(Object.keys(METANOUNS)).length - 1,
58 }}
59 >
60 <a
61 href={basePostUrl + METANOUNS[pronoun]}
62 class="block h-full w-full py-3 text-center text-sky-500 hover:bg-zinc-800"
63 >
64 {pronoun}
65 </a>
66 </div>
67 </div>
68 )}
69 </For>
70 </div>
71 <div class="w-full overflow-auto sm:flex-none sm:basis-1/3">
72 <For each={searchFilter(Object.keys(NEOPRONOUNS))}>
73 {(pronoun, index) => (
74 <div>
75 <Show when={index() === 0}>
76 <div class="my-1 text-center text-xl">Neopronouns</div>
77 </Show>
78 <div
79 classList={{
80 "border-b border-b-zinc-600":
81 index() !==
82 searchFilter(Object.keys(NEOPRONOUNS)).length - 1,
83 }}
84 >
85 <a
86 href={basePostUrl + NEOPRONOUNS[pronoun]}
87 class="block h-full w-full py-3 text-center text-sky-500 hover:bg-zinc-800"
88 >
89 {pronoun}
90 </a>
91 </div>
92 </div>
93 )}
94 </For>
95 </div>
96 </div>
97 );
98};
99
100const PronounsSearch: Component = () => {
101 return (
102 <div class="m-5 flex flex-col items-center">
103 <div>
104 <input
105 type="text"
106 placeholder="Search pronouns"
107 class="mb-3 rounded-md bg-zinc-700 px-2 py-1 text-zinc-200"
108 onInput={(e) => setSearch(e.currentTarget.value)}
109 />
110 </div>
111 </div>
112 );
113};
114
115const App: Component = () => {
116 return (
117 <div class="flex flex-col items-center text-slate-200">
118 <div class="py-6 text-center text-3xl">Pronouns Labeler Search</div>
119 <div>
120 <a
121 href={basePostUrl + "3kwsqucto3j2a"}
122 class="text-xl text-sky-500 hover:underline"
123 >
124 Post to remove labels
125 </a>
126 </div>
127 <PronounsSearch />
128 <PronounsList search={search()} />
129 </div>
130 );
131};
132
133export default App;