nsarrazin HF Staff commited on
Commit
2b97a5c
·
unverified ·
1 Parent(s): c50aaeb

feat(nav): better mobile nav (#1725)

Browse files

* feat: improve mobile settings navigation

* fix: make sure window resizing works & redirects properly

src/routes/settings/(nav)/+layout.svelte CHANGED
@@ -8,10 +8,14 @@
8
  import CarbonArrowUpRight from "~icons/carbon/ArrowUpRight";
9
  import CarbonAdd from "~icons/carbon/add";
10
  import CarbonTextLongParagraph from "~icons/carbon/text-long-paragraph";
 
11
 
12
  import UserIcon from "~icons/carbon/user";
13
  import type { LayoutData } from "../$types";
14
  import { error } from "$lib/stores/errors";
 
 
 
15
 
16
  interface Props {
17
  data: LayoutData;
@@ -22,17 +26,39 @@
22
 
23
  let previousPage: string = $state(base);
24
  let assistantsSection: HTMLHeadingElement | undefined = $state();
 
 
 
 
 
 
 
25
 
26
  onMount(() => {
27
  if (page.params?.assistantId && assistantsSection) {
28
  assistantsSection.scrollIntoView();
29
  }
 
 
 
 
 
 
 
 
 
 
 
30
  });
31
 
32
  afterNavigate(({ from }) => {
33
  if (!from?.url.pathname.includes("settings")) {
34
  previousPage = from?.url.toString() || previousPage;
35
  }
 
 
 
 
36
  });
37
 
38
  const settings = useSettingsStore();
@@ -42,6 +68,18 @@
42
  class="grid h-full w-full grid-cols-1 grid-rows-[auto,1fr] content-start gap-x-4 overflow-hidden p-4 md:grid-cols-3 md:grid-rows-[auto,1fr] md:p-8"
43
  >
44
  <div class="col-span-1 mb-4 flex items-center justify-between md:col-span-3">
 
 
 
 
 
 
 
 
 
 
 
 
45
  <h2 class="text-xl font-bold">Settings</h2>
46
  <button
47
  class="btn rounded-lg"
@@ -54,7 +92,8 @@
54
  </button>
55
  </div>
56
  <div
57
- class="col-span-1 flex flex-col overflow-y-auto whitespace-nowrap max-md:-mx-4 max-md:h-[245px] max-md:border max-md:border-b-2 md:pr-6"
 
58
  >
59
  <h3 class="pb-3 pl-3 pt-2 text-[.8rem] text-gray-800 sm:pl-1">Models</h3>
60
 
@@ -200,16 +239,17 @@
200
 
201
  <div class="my-2 mt-auto w-full border-b border-gray-200"></div>
202
  <a
203
- href="{base}/settings"
204
  class="group flex h-10 flex-none items-center gap-2 pl-3 pr-2 text-sm text-gray-500 hover:bg-gray-100 max-md:order-first md:rounded-xl
205
- {page.url.pathname === `${base}/settings` ? '!bg-gray-100 !text-gray-800' : ''}"
206
  >
207
  <UserIcon class="text-sm" />
208
  Application Settings
209
  </a>
210
  </div>
211
  <div
212
- class="col-span-1 w-full overflow-y-auto overflow-x-clip px-1 max-md:pt-4 md:col-span-2 md:row-span-2"
 
213
  >
214
  {@render children?.()}
215
  </div>
 
8
  import CarbonArrowUpRight from "~icons/carbon/ArrowUpRight";
9
  import CarbonAdd from "~icons/carbon/add";
10
  import CarbonTextLongParagraph from "~icons/carbon/text-long-paragraph";
11
+ import CarbonChevronLeft from "~icons/carbon/chevron-left";
12
 
13
  import UserIcon from "~icons/carbon/user";
14
  import type { LayoutData } from "../$types";
15
  import { error } from "$lib/stores/errors";
16
+ import { browser } from "$app/environment";
17
+ import { isDesktop } from "$lib/utils/isDesktop";
18
+ import { debounce } from "$lib/utils/debounce";
19
 
20
  interface Props {
21
  data: LayoutData;
 
26
 
27
  let previousPage: string = $state(base);
28
  let assistantsSection: HTMLHeadingElement | undefined = $state();
29
+ let showContent: boolean = $state(false);
30
+
31
+ function checkDesktopRedirect() {
32
+ if (browser && isDesktop(window) && page.url.pathname === `${base}/settings`) {
33
+ goto(`${base}/settings/application`);
34
+ }
35
+ }
36
 
37
  onMount(() => {
38
  if (page.params?.assistantId && assistantsSection) {
39
  assistantsSection.scrollIntoView();
40
  }
41
+ // Show content when not on the root settings page
42
+ showContent = page.url.pathname !== `${base}/settings`;
43
+ // Initial desktop redirect check
44
+ checkDesktopRedirect();
45
+
46
+ // Add resize listener for desktop redirect
47
+ if (browser) {
48
+ const debouncedCheck = debounce(checkDesktopRedirect, 100);
49
+ window.addEventListener("resize", debouncedCheck);
50
+ return () => window.removeEventListener("resize", debouncedCheck);
51
+ }
52
  });
53
 
54
  afterNavigate(({ from }) => {
55
  if (!from?.url.pathname.includes("settings")) {
56
  previousPage = from?.url.toString() || previousPage;
57
  }
58
+ // Show content when not on the root settings page
59
+ showContent = page.url.pathname !== `${base}/settings`;
60
+ // Check desktop redirect after navigation
61
+ checkDesktopRedirect();
62
  });
63
 
64
  const settings = useSettingsStore();
 
68
  class="grid h-full w-full grid-cols-1 grid-rows-[auto,1fr] content-start gap-x-4 overflow-hidden p-4 md:grid-cols-3 md:grid-rows-[auto,1fr] md:p-8"
69
  >
70
  <div class="col-span-1 mb-4 flex items-center justify-between md:col-span-3">
71
+ {#if showContent && browser}
72
+ <button
73
+ class="btn rounded-lg md:hidden"
74
+ aria-label="Back to menu"
75
+ onclick={() => {
76
+ showContent = false;
77
+ goto(`${base}/settings`);
78
+ }}
79
+ >
80
+ <CarbonChevronLeft class="text-xl text-gray-900 hover:text-black" />
81
+ </button>
82
+ {/if}
83
  <h2 class="text-xl font-bold">Settings</h2>
84
  <button
85
  class="btn rounded-lg"
 
92
  </button>
93
  </div>
94
  <div
95
+ class="col-span-1 flex flex-col overflow-y-auto whitespace-nowrap max-md:-mx-4 max-md:h-full md:pr-6"
96
+ class:max-md:hidden={showContent && browser}
97
  >
98
  <h3 class="pb-3 pl-3 pt-2 text-[.8rem] text-gray-800 sm:pl-1">Models</h3>
99
 
 
239
 
240
  <div class="my-2 mt-auto w-full border-b border-gray-200"></div>
241
  <a
242
+ href="{base}/settings/application"
243
  class="group flex h-10 flex-none items-center gap-2 pl-3 pr-2 text-sm text-gray-500 hover:bg-gray-100 max-md:order-first md:rounded-xl
244
+ {page.url.pathname === `${base}/settings/application` ? '!bg-gray-100 !text-gray-800' : ''}"
245
  >
246
  <UserIcon class="text-sm" />
247
  Application Settings
248
  </a>
249
  </div>
250
  <div
251
+ class="col-span-1 w-full overflow-y-auto overflow-x-clip px-1 md:col-span-2 md:row-span-2"
252
+ class:max-md:hidden={!showContent && browser}
253
  >
254
  {@render children?.()}
255
  </div>
src/routes/settings/(nav)/+layout.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ export const ssr = false;
src/routes/settings/(nav)/+page.svelte CHANGED
@@ -1,105 +0,0 @@
1
- <script lang="ts">
2
- import CarbonTrashCan from "~icons/carbon/trash-can";
3
- import CarbonArrowUpRight from "~icons/carbon/arrow-up-right";
4
-
5
- import { useSettingsStore } from "$lib/stores/settings";
6
- import Switch from "$lib/components/Switch.svelte";
7
- import { env as envPublic } from "$env/dynamic/public";
8
- import { goto } from "$app/navigation";
9
- import { error } from "$lib/stores/errors";
10
- import { base } from "$app/paths";
11
-
12
- let settings = useSettingsStore();
13
- </script>
14
-
15
- <div class="flex w-full flex-col gap-5">
16
- <div class="flex flex-col items-start justify-between text-xl font-semibold text-gray-800">
17
- <h2>Application Settings</h2>
18
- {#if !!envPublic.PUBLIC_COMMIT_SHA}
19
- <a
20
- href={`https://github.com/huggingface/chat-ui/commit/${envPublic.PUBLIC_COMMIT_SHA}`}
21
- target="_blank"
22
- rel="noreferrer"
23
- class="text-sm font-light text-gray-500"
24
- >
25
- Latest deployment <span class="gap-2 font-mono"
26
- >{envPublic.PUBLIC_COMMIT_SHA.slice(0, 7)}</span
27
- >
28
- </a>
29
- {/if}
30
- </div>
31
- <div class="flex h-full max-w-2xl flex-col gap-2 max-sm:pt-0">
32
- {#if envPublic.PUBLIC_APP_DATA_SHARING === "1"}
33
- <label class="flex items-center">
34
- <Switch
35
- name="shareConversationsWithModelAuthors"
36
- bind:checked={$settings.shareConversationsWithModelAuthors}
37
- />
38
- <div class="inline cursor-pointer select-none items-center gap-2 pl-2">
39
- Share conversations with model authors
40
- </div>
41
- </label>
42
-
43
- <p class="text-sm text-gray-500">
44
- Sharing your data will help improve the training data and make open models better over time.
45
- </p>
46
- {/if}
47
- <label class="mt-6 flex items-center">
48
- <Switch name="hideEmojiOnSidebar" bind:checked={$settings.hideEmojiOnSidebar} />
49
- <div class="inline cursor-pointer select-none items-center gap-2 pl-2 font-semibold">
50
- Hide emoticons in conversation topics
51
- <p class="text-sm font-normal text-gray-500">
52
- Emoticons are shown in the sidebar by default, enable this to hide them.
53
- </p>
54
- </div>
55
- </label>
56
-
57
- <label class="mt-6 flex items-center">
58
- <Switch name="disableStream" bind:checked={$settings.disableStream} />
59
- <div class="inline cursor-pointer select-none items-center gap-2 pl-2 font-semibold">
60
- Disable streaming tokens
61
- </div>
62
- </label>
63
-
64
- <label class="mt-6 flex items-center">
65
- <Switch name="directPaste" bind:checked={$settings.directPaste} />
66
- <div class="inline cursor-pointer select-none items-center gap-2 pl-2 font-semibold">
67
- Paste text directly into chat
68
- <p class="text-sm font-normal text-gray-500">
69
- By default, when pasting long text into the chat, we treat it as a plaintext file. Enable
70
- this to paste directly into the chat instead.
71
- </p>
72
- </div>
73
- </label>
74
-
75
- <div class="mt-12 flex flex-col gap-3">
76
- <a
77
- href="https://huggingface.co/spaces/huggingchat/chat-ui/discussions"
78
- target="_blank"
79
- rel="noreferrer"
80
- class="flex items-center underline decoration-gray-300 underline-offset-2 hover:decoration-gray-700"
81
- ><CarbonArrowUpRight class="mr-1.5 shrink-0 text-sm " /> Share your feedback on HuggingChat</a
82
- >
83
- <button
84
- onclick={async (e) => {
85
- e.preventDefault();
86
-
87
- confirm("Are you sure you want to delete all conversations?") &&
88
- (await fetch(`${base}/api/conversations`, {
89
- method: "DELETE",
90
- })
91
- .then(async () => {
92
- await goto(`${base}/`, { invalidateAll: true });
93
- })
94
- .catch((err) => {
95
- console.error(err);
96
- $error = err.message;
97
- }));
98
- }}
99
- type="submit"
100
- class="flex items-center underline decoration-gray-300 underline-offset-2 hover:decoration-gray-700"
101
- ><CarbonTrashCan class="mr-2 inline text-sm text-red-500" />Delete all conversations</button
102
- >
103
- </div>
104
- </div>
105
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/routes/settings/(nav)/application/+page.svelte ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import CarbonTrashCan from "~icons/carbon/trash-can";
3
+ import CarbonArrowUpRight from "~icons/carbon/arrow-up-right";
4
+
5
+ import { useSettingsStore } from "$lib/stores/settings";
6
+ import Switch from "$lib/components/Switch.svelte";
7
+ import { env as envPublic } from "$env/dynamic/public";
8
+ import { goto } from "$app/navigation";
9
+ import { error } from "$lib/stores/errors";
10
+ import { base } from "$app/paths";
11
+
12
+ let settings = useSettingsStore();
13
+ </script>
14
+
15
+ <div class="flex w-full flex-col gap-5">
16
+ <div class="flex flex-col items-start justify-between text-xl font-semibold text-gray-800">
17
+ <h2>Application Settings</h2>
18
+ {#if !!envPublic.PUBLIC_COMMIT_SHA}
19
+ <a
20
+ href={`https://github.com/huggingface/chat-ui/commit/${envPublic.PUBLIC_COMMIT_SHA}`}
21
+ target="_blank"
22
+ rel="noreferrer"
23
+ class="text-sm font-light text-gray-500"
24
+ >
25
+ Latest deployment <span class="gap-2 font-mono"
26
+ >{envPublic.PUBLIC_COMMIT_SHA.slice(0, 7)}</span
27
+ >
28
+ </a>
29
+ {/if}
30
+ </div>
31
+ <div class="flex h-full max-w-2xl flex-col gap-2 max-sm:pt-0">
32
+ {#if envPublic.PUBLIC_APP_DATA_SHARING === "1"}
33
+ <label class="flex items-center">
34
+ <Switch
35
+ name="shareConversationsWithModelAuthors"
36
+ bind:checked={$settings.shareConversationsWithModelAuthors}
37
+ />
38
+ <div class="inline cursor-pointer select-none items-center gap-2 pl-2">
39
+ Share conversations with model authors
40
+ </div>
41
+ </label>
42
+
43
+ <p class="text-sm text-gray-500">
44
+ Sharing your data will help improve the training data and make open models better over time.
45
+ </p>
46
+ {/if}
47
+ <label class="mt-6 flex items-center">
48
+ <Switch name="hideEmojiOnSidebar" bind:checked={$settings.hideEmojiOnSidebar} />
49
+ <div class="inline cursor-pointer select-none items-center gap-2 pl-2 font-semibold">
50
+ Hide emoticons in conversation topics
51
+ <p class="text-sm font-normal text-gray-500">
52
+ Emoticons are shown in the sidebar by default, enable this to hide them.
53
+ </p>
54
+ </div>
55
+ </label>
56
+
57
+ <label class="mt-6 flex items-center">
58
+ <Switch name="disableStream" bind:checked={$settings.disableStream} />
59
+ <div class="inline cursor-pointer select-none items-center gap-2 pl-2 font-semibold">
60
+ Disable streaming tokens
61
+ </div>
62
+ </label>
63
+
64
+ <label class="mt-6 flex items-center">
65
+ <Switch name="directPaste" bind:checked={$settings.directPaste} />
66
+ <div class="inline cursor-pointer select-none items-center gap-2 pl-2 font-semibold">
67
+ Paste text directly into chat
68
+ <p class="text-sm font-normal text-gray-500">
69
+ By default, when pasting long text into the chat, we treat it as a plaintext file. Enable
70
+ this to paste directly into the chat instead.
71
+ </p>
72
+ </div>
73
+ </label>
74
+
75
+ <div class="mt-12 flex flex-col gap-3">
76
+ <a
77
+ href="https://huggingface.co/spaces/huggingchat/chat-ui/discussions"
78
+ target="_blank"
79
+ rel="noreferrer"
80
+ class="flex items-center underline decoration-gray-300 underline-offset-2 hover:decoration-gray-700"
81
+ ><CarbonArrowUpRight class="mr-1.5 shrink-0 text-sm " /> Share your feedback on HuggingChat</a
82
+ >
83
+ <button
84
+ onclick={async (e) => {
85
+ e.preventDefault();
86
+
87
+ confirm("Are you sure you want to delete all conversations?") &&
88
+ (await fetch(`${base}/api/conversations`, {
89
+ method: "DELETE",
90
+ })
91
+ .then(async () => {
92
+ await goto(`${base}/`, { invalidateAll: true });
93
+ })
94
+ .catch((err) => {
95
+ console.error(err);
96
+ $error = err.message;
97
+ }));
98
+ }}
99
+ type="submit"
100
+ class="flex items-center underline decoration-gray-300 underline-offset-2 hover:decoration-gray-700"
101
+ ><CarbonTrashCan class="mr-2 inline text-sm text-red-500" />Delete all conversations</button
102
+ >
103
+ </div>
104
+ </div>
105
+ </div>