Skip to content

Commit eb7f856

Browse files
Make toast copy more consistent (#2504)
* Make toast copy more consistent * Add confirmation for disk deletion * Add highlighting to toast contents * keep str test * Fix tests; a few more ToastContents, but will hold here * Move away from ToastContent * Migrate other addToasts to new approach * Add toast on a couple of onSuccess functions missing them * Fix a few tests * Missed a couple * Formatting * surely saying this was the last test to fix won't jinx it * nope; it was not fully reading the previous CI report * Add expectToast helper * use a lighter weight font * Close toasts at end of expectToast * let addToast take the content directly, fix type errors, change one case * a billion one-liner toasts with the magic of prettier-ignore * eliminate HLs by using CSS instead * actually..... do it in tailwind with group. yowza * undo spurious changes to checksums in package-lock.json --------- Co-authored-by: David Crespo <[email protected]>
1 parent df0dea4 commit eb7f856

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+311
-120
lines changed

.github/workflows/lintBuildTest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
- uses: actions/checkout@v4
1414
- uses: actions/setup-node@v4
1515
with:
16-
node-version: 20
16+
node-version: 22
1717
cache: 'npm'
1818
- name: Cache node_modules
1919
uses: actions/cache@v4

app/components/AttachEphemeralIpModal.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useForm } from 'react-hook-form'
1111

1212
import { useApiMutation, useApiQueryClient, usePrefetchedApiQuery } from '~/api'
1313
import { ListboxField } from '~/components/form/fields/ListboxField'
14+
import { HL } from '~/components/HL'
1415
import { useInstanceSelector } from '~/hooks/use-params'
1516
import { addToast } from '~/stores/toast'
1617
import { Modal } from '~/ui/lib/Modal'
@@ -29,9 +30,9 @@ export const AttachEphemeralIpModal = ({ onDismiss }: { onDismiss: () => void })
2930
[siloPools]
3031
)
3132
const instanceEphemeralIpAttach = useApiMutation('instanceEphemeralIpAttach', {
32-
onSuccess() {
33+
onSuccess(ephemeralIp) {
3334
queryClient.invalidateQueries('instanceExternalIpList')
34-
addToast({ content: 'Your ephemeral IP has been attached' })
35+
addToast(<>IP <HL>{ephemeralIp.ip}</HL> attached</>) // prettier-ignore
3536
onDismiss()
3637
},
3738
onError: (err) => {

app/components/AttachFloatingIpModal.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { useForm } from 'react-hook-form'
1010

1111
import { useApiMutation, useApiQueryClient, type FloatingIp, type Instance } from '~/api'
1212
import { ListboxField } from '~/components/form/fields/ListboxField'
13+
import { HL } from '~/components/HL'
1314
import { addToast } from '~/stores/toast'
1415
import { Message } from '~/ui/lib/Message'
1516
import { Modal } from '~/ui/lib/Modal'
@@ -45,10 +46,10 @@ export const AttachFloatingIpModal = ({
4546
}) => {
4647
const queryClient = useApiQueryClient()
4748
const floatingIpAttach = useApiMutation('floatingIpAttach', {
48-
onSuccess() {
49+
onSuccess(floatingIp) {
4950
queryClient.invalidateQueries('floatingIpList')
5051
queryClient.invalidateQueries('instanceExternalIpList')
51-
addToast({ content: 'Your floating IP has been attached' })
52+
addToast(<>IP <HL>{floatingIp.name}</HL> attached</>) // prettier-ignore
5253
onDismiss()
5354
},
5455
onError: (err) => {

app/components/HL.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@
77
*/
88
import { classed } from '~/util/classed'
99

10-
export const HL = classed.span`text-sans-semi-md text-default`
10+
// note parent with secondary text color must have 'group' on it for
11+
// this to work. see Toast for an example
12+
export const HL = classed.span`
13+
text-sans-md text-default
14+
group-[.text-accent-secondary]:text-accent
15+
group-[.text-error-secondary]:text-error
16+
group-[.text-info-secondary]:text-info
17+
`

app/components/ToastStack.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ export function ToastStack() {
2222
})
2323

2424
return (
25-
<div className="pointer-events-auto fixed bottom-4 left-4 z-toast flex flex-col items-end space-y-2">
25+
<div
26+
className="pointer-events-auto fixed bottom-4 left-4 z-toast flex flex-col items-end space-y-2"
27+
data-testid="Toasts"
28+
>
2629
{transition((style, item) => (
2730
<animated.div
2831
style={{

app/forms/disk-create.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { ListboxField } from '~/components/form/fields/ListboxField'
2828
import { NameField } from '~/components/form/fields/NameField'
2929
import { RadioField } from '~/components/form/fields/RadioField'
3030
import { SideModalForm } from '~/components/form/SideModalForm'
31+
import { HL } from '~/components/HL'
3132
import { useProjectSelector } from '~/hooks/use-params'
3233
import { addToast } from '~/stores/toast'
3334
import { FormDivider } from '~/ui/lib/Divider'
@@ -76,7 +77,7 @@ export function CreateDiskSideModalForm({
7677
const createDisk = useApiMutation('diskCreate', {
7778
onSuccess(data) {
7879
queryClient.invalidateQueries('diskList')
79-
addToast({ content: 'Your disk has been created' })
80+
addToast(<>Disk <HL>{data.name}</HL> created</>) // prettier-ignore
8081
onSuccess?.(data)
8182
onDismiss(navigate)
8283
},

app/forms/firewall-rules-create.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
} from '@oxide/api'
1919

2020
import { SideModalForm } from '~/components/form/SideModalForm'
21+
import { HL } from '~/components/HL'
2122
import { getVpcSelector, useVpcSelector } from '~/hooks/use-params'
2223
import { addToast } from '~/stores/toast'
2324
import { ALL_ISH } from '~/util/consts'
@@ -74,9 +75,10 @@ export function CreateFirewallRuleForm() {
7475
const onDismiss = () => navigate(pb.vpcFirewallRules(vpcSelector))
7576

7677
const updateRules = useApiMutation('vpcFirewallRulesUpdate', {
77-
onSuccess() {
78+
onSuccess(updatedRules) {
79+
const newRule = updatedRules.rules[updatedRules.rules.length - 1]
7880
queryClient.invalidateQueries('vpcFirewallRulesView')
79-
addToast({ content: 'Your firewall rule has been created' })
81+
addToast(<>Firewall rule <HL>{newRule.name}</HL> created</>) // prettier-ignore
8082
navigate(pb.vpcFirewallRules(vpcSelector))
8183
},
8284
})

app/forms/firewall-rules-edit.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ import {
1818

1919
import { trigger404 } from '~/components/ErrorBoundary'
2020
import { SideModalForm } from '~/components/form/SideModalForm'
21+
import { HL } from '~/components/HL'
2122
import {
2223
getFirewallRuleSelector,
2324
useFirewallRuleSelector,
2425
useVpcSelector,
2526
} from '~/hooks/use-params'
27+
import { addToast } from '~/stores/toast'
2628
import { ALL_ISH } from '~/util/consts'
2729
import { invariant } from '~/util/invariant'
2830
import { pb } from '~/util/path-builder'
@@ -64,13 +66,15 @@ export function EditFirewallRuleForm() {
6466
const onDismiss = () => navigate(pb.vpcFirewallRules(vpcSelector))
6567

6668
const updateRules = useApiMutation('vpcFirewallRulesUpdate', {
67-
onSuccess() {
69+
onSuccess(updatedRules, { body }) {
6870
// Nav before the invalidate because I once saw the above invariant fail
6971
// briefly after successful edit (error page flashed but then we land
7072
// on the rules list ok) and I think it was a race condition where the
7173
// invalidate managed to complete while the modal was still open.
7274
onDismiss()
7375
queryClient.invalidateQueries('vpcFirewallRulesView')
76+
const updatedRule = body.rules[body.rules.length - 1]
77+
addToast(<>Firewall rule <HL>{updatedRule.name}</HL> updated</>) // prettier-ignore
7478
},
7579
})
7680

app/forms/floating-ip-create.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { toIpPoolItem } from '~/components/form/fields/ip-pool-item'
2323
import { ListboxField } from '~/components/form/fields/ListboxField'
2424
import { NameField } from '~/components/form/fields/NameField'
2525
import { SideModalForm } from '~/components/form/SideModalForm'
26+
import { HL } from '~/components/HL'
2627
import { useProjectSelector } from '~/hooks/use-params'
2728
import { addToast } from '~/stores/toast'
2829
import { Message } from '~/ui/lib/Message'
@@ -45,10 +46,10 @@ export function CreateFloatingIpSideModalForm() {
4546
const navigate = useNavigate()
4647

4748
const createFloatingIp = useApiMutation('floatingIpCreate', {
48-
onSuccess() {
49+
onSuccess(floatingIp) {
4950
queryClient.invalidateQueries('floatingIpList')
5051
queryClient.invalidateQueries('ipPoolUtilizationView')
51-
addToast({ content: 'Your Floating IP has been created' })
52+
addToast(<>Floating IP <HL>{floatingIp.name}</HL> created</>) // prettier-ignore
5253
navigate(pb.floatingIps(projectSelector))
5354
},
5455
})

app/forms/floating-ip-edit.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import { DescriptionField } from '~/components/form/fields/DescriptionField'
1919
import { NameField } from '~/components/form/fields/NameField'
2020
import { SideModalForm } from '~/components/form/SideModalForm'
21+
import { HL } from '~/components/HL'
2122
import { getFloatingIpSelector, useFloatingIpSelector } from '~/hooks/use-params'
2223
import { addToast } from '~/stores/toast'
2324
import { pb } from 'app/util/path-builder'
@@ -47,7 +48,7 @@ export function EditFloatingIpSideModalForm() {
4748
const editFloatingIp = useApiMutation('floatingIpUpdate', {
4849
onSuccess(_floatingIp) {
4950
queryClient.invalidateQueries('floatingIpList')
50-
addToast({ content: 'Your floating IP has been updated' })
51+
addToast(<>Floating IP <HL>{_floatingIp.name}</HL> updated</>) // prettier-ignore
5152
onDismiss()
5253
},
5354
})

0 commit comments

Comments
 (0)