Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 781aebb

Browse files
authored
Svelte rollout: add toggles for svelte-enabled pages (#63960)
This is the last bit of work before flipping the switch on dotcom. Implemented based on the behavior @taiyab and I aligned on this morning. Can definitely still use a little sparkle, but I'll let others follow up on that. It adds a toggle button to all pages that we have a svelte version of. The toggle is off when you're in the react webapp and on when you're in the svelte webapp. It also updates the copy of the popover to be more appropriate for the dotcom crowd.
1 parent d33b87c commit 781aebb

File tree

5 files changed

+183
-40
lines changed

5 files changed

+183
-40
lines changed

client/web-sveltekit/src/lib/navigation/GlobalHeader.svelte

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@
1313
</script>
1414

1515
<script lang="ts">
16-
import { browser } from '$app/environment'
1716
import { page } from '$app/stores'
1817
import { onClickOutside } from '$lib/dom'
1918
import Icon from '$lib/Icon.svelte'
2019
import MainNavigationLink from '$lib/navigation/MainNavigationLink.svelte'
2120
import Popover from '$lib/Popover.svelte'
2221
import SourcegraphLogo from '$lib/SourcegraphLogo.svelte'
23-
import { isViewportMediumDown, isViewportMobile } from '$lib/stores'
24-
import { Badge, Button } from '$lib/wildcard'
22+
import { isViewportMediumDown } from '$lib/stores'
23+
import { Button } from '$lib/wildcard'
24+
import Badge from '$lib/wildcard/Badge.svelte'
25+
import Toggle from '$lib/wildcard/Toggle.svelte'
2526
2627
import { GlobalNavigation_User } from './GlobalNavigation.gql'
2728
import { type NavigationEntry, type NavigationMenu, isNavigationMenu, isCurrent } from './mainNavigation'
@@ -31,10 +32,6 @@
3132
export let handleOptOut: (() => Promise<void>) | undefined
3233
export let entries: (NavigationEntry | NavigationMenu)[]
3334
34-
const isDevOrS2 =
35-
(browser && window.location.hostname === 'localhost') ||
36-
window.location.hostname === 'sourcegraph.sourcegraph.com'
37-
3835
let sidebarNavigationOpen: boolean = false
3936
let closeMenuTimer: number = 0
4037
let openedMenu: string = ''
@@ -122,29 +119,31 @@
122119

123120
<div class="global-portal" bind:this={$extensionElement} />
124121

125-
<Popover let:registerTrigger let:toggle showOnHover={!$isViewportMobile} hoverDelay={100} hoverCloseDelay={50}>
126-
<button class="web-next-badge" use:registerTrigger on:click={() => toggle()}>
127-
<Badge variant="warning">Experimental</Badge>
128-
</button>
129-
<div slot="content" class="web-next-content">
130-
<h3>Experimental web app</h3>
131-
<p>
132-
You are using an experimental version of the Sourcegraph web app. This version is under active
133-
development and may contain bugs or incomplete features.
134-
</p>
135-
{#if isDevOrS2}
122+
<div class="web-next-notice">
123+
{#if handleOptOut}
124+
<Toggle on={true} on:click={() => handleOptOut && handleOptOut()} />
125+
{/if}
126+
<Popover let:toggle let:registerTrigger>
127+
<button class="web-next-badge" use:registerTrigger on:click={() => toggle()}>
128+
<Badge variant="warning">Experimental</Badge>
129+
</button>
130+
<div slot="content" class="web-next-content">
131+
<h3>Experimental web app</h3>
132+
<p>
133+
You are using an experimental version of the Sourcegraph web app. This version is under active
134+
development and may contain bugs or incomplete features.
135+
</p>
136136
<p>
137-
If you encounter any issues, please report them in our <a
138-
href="https://sourcegraph.slack.com/archives/C05MHAP318B">Slack channel</a
137+
If you encounter any issues, please report them in our <a href="https://community.sourcegraph.com/"
138+
>community forums</a
139139
>.
140140
</p>
141-
{/if}
142-
{#if handleOptOut}
143-
Or you can <button role="link" class="opt-out" on:click={handleOptOut}>opt out</button> of the Sveltekit
144-
experiment.
145-
{/if}
146-
</div>
147-
</Popover>
141+
{#if handleOptOut}
142+
<p>You can opt out of the new experience with the toggle above.</p>
143+
{/if}
144+
</div>
145+
</Popover>
146+
</div>
148147
<div>
149148
{#if authenticatedUser}
150149
<UserMenu user={authenticatedUser} />
@@ -419,10 +418,17 @@
419418
text-decoration: underline;
420419
}
421420
421+
.web-next-notice {
422+
display: flex;
423+
align-items: center;
424+
gap: 0.5rem;
425+
}
426+
422427
.web-next-badge {
423428
all: unset;
429+
display: flex;
430+
align-items: center;
424431
cursor: pointer;
425-
padding: 0.25rem;
426432
margin-left: auto;
427433
}
428434
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<script lang="ts">
2+
import type { HTMLButtonAttributes } from 'svelte/elements'
3+
4+
type $$Props = {
5+
on: boolean
6+
} & HTMLButtonAttributes
7+
8+
export let on: boolean
9+
</script>
10+
11+
<button type="button" class="toggle" role="switch" aria-checked={on} {...$$restProps} on:click>
12+
<span class="bar" class:bar--on={on} />
13+
<span class="knob" class:knob--on={on} />
14+
</button>
15+
16+
<style lang="scss">
17+
.toggle {
18+
--toggle-width: 2rem;
19+
--toggle-bar-bg: var(--icon-color);
20+
--toggle-bar-bg-on: var(--primary);
21+
--toggle-knob-bg: var(--body-bg);
22+
--toggle-knob-bg-on: var(--body-bg);
23+
--toggle-bar-opacity: 1;
24+
--toggle-bar-focus-opacity: 1;
25+
--toggle-knob-disabled-opacity: 1;
26+
--toggle-bar-focus-box-shadow: 0 0 0 1px var(--body-bg), 0 0 0 0.1875rem var(--primary-2);
27+
28+
background: none;
29+
border: none;
30+
outline: none !important;
31+
padding: 0;
32+
position: relative;
33+
width: var(--toggle-width);
34+
35+
height: 1rem;
36+
display: inline-flex;
37+
align-items: center;
38+
39+
&:focus-visible {
40+
/* Move focus style to the rounded bar */
41+
box-shadow: none;
42+
}
43+
44+
&:disabled {
45+
--toggle-knob-bg: var(--icon-color);
46+
--toggle-knob-bg-on: var(--icon-color);
47+
--toggle-bar-bg: var(--input-disabled-bg);
48+
--toggle-bar-bg-on: var(--input-disabled-bg);
49+
}
50+
51+
&:hover:enabled .bar {
52+
opacity: var(--toggle-bar-focus-opacity);
53+
}
54+
55+
&:disabled .knob {
56+
opacity: var(--toggle-knob-disabled-opacity);
57+
}
58+
59+
&:focus-visible .bar {
60+
box-shadow: var(--toggle-bar-focus-box-shadow);
61+
}
62+
}
63+
64+
.inline-center {
65+
margin-top: 0.125rem;
66+
}
67+
68+
.bar {
69+
border-radius: 1rem;
70+
left: 0;
71+
height: 1rem;
72+
width: 100%;
73+
position: absolute;
74+
75+
opacity: var(--toggle-bar-opacity);
76+
background-color: var(--toggle-bar-bg);
77+
78+
transition: all 0.3s;
79+
transition-property: opacity;
80+
81+
&--on {
82+
background-color: var(--toggle-bar-bg-on);
83+
}
84+
}
85+
86+
.knob {
87+
background-color: var(--toggle-knob-bg);
88+
89+
border-radius: 0.375rem;
90+
display: block;
91+
92+
height: 0.75rem;
93+
width: 0.75rem;
94+
left: 0.125rem;
95+
96+
position: relative;
97+
98+
&--on {
99+
background-color: var(--toggle-knob-bg-on);
100+
transform: translate3d(1rem, 0, 0);
101+
}
102+
}
103+
</style>

client/web-sveltekit/src/routes/layout.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ test('has experimental opt out popover', async ({ sg, page }) => {
1414
sg.signIn({ username: 'test' })
1515

1616
await page.goto('/')
17-
await page.getByText('Experimental').hover()
18-
await expect(page.getByRole('link', { name: 'opt out' })).toBeVisible()
17+
await page.getByText('Experimental').click()
18+
await expect(page.getByText('opt out')).toBeVisible()
1919
})
2020

2121
test('has user menu', async ({ sg, page }) => {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.container {
2+
display: flex;
3+
gap: 0.5rem;
4+
align-items: center;
5+
}
6+
7+
.toggle {
8+
margin: 0;
9+
}
10+
11+
.badge {
12+
all: unset;
13+
}
14+
15+
.popover {
16+
padding: 1rem;
17+
width: 20rem;
18+
19+
p:last-child {
20+
margin-bottom: 0;
21+
}
22+
}
Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
import type { FC } from 'react'
1+
import { FC } from 'react'
22

33
import { useApolloClient } from '@apollo/client'
4-
import { mdiFlaskEmptyOutline } from '@mdi/js'
54
import { useLocation } from 'react-router-dom'
65

7-
import { Button, Icon, Tooltip } from '@sourcegraph/wildcard'
6+
import { Toggle } from '@sourcegraph/branded/src/components/Toggle'
7+
import { Text, H3, Popover, PopoverTrigger, PopoverContent, Badge } from '@sourcegraph/wildcard'
88

99
import { enableSvelteAndReload, canEnableSvelteKit } from './util'
1010

11+
import styles from './SvelteKitNavItem.module.scss'
12+
1113
export const SvelteKitNavItem: FC<{ userID?: string }> = ({ userID }) => {
1214
const location = useLocation()
1315
const client = useApolloClient()
@@ -17,12 +19,22 @@ export const SvelteKitNavItem: FC<{ userID?: string }> = ({ userID }) => {
1719
}
1820

1921
return (
20-
<Tooltip content="Go to experimental web app">
21-
<Button variant="icon" onClick={() => enableSvelteAndReload(client, userID)}>
22-
<span className="text-muted">
23-
<Icon svgPath={mdiFlaskEmptyOutline} aria-hidden={true} inline={false} />
24-
</span>
25-
</Button>
26-
</Tooltip>
22+
<div className={styles.container}>
23+
<Toggle
24+
value={false}
25+
onToggle={() => enableSvelteAndReload(client, userID)}
26+
title="Go to experimental web app"
27+
className={styles.toggle}
28+
/>
29+
<Popover>
30+
<PopoverTrigger className={styles.badge}>
31+
<Badge variant="warning">Try the new experience</Badge>
32+
</PopoverTrigger>
33+
<PopoverContent className={styles.popover}>
34+
<H3>Sourcegraph is getting a refresh!</H3>
35+
<Text>Try it out early with the toggle above.</Text>
36+
</PopoverContent>
37+
</Popover>
38+
</div>
2739
)
2840
}

0 commit comments

Comments
 (0)