@@ -36,8 +36,10 @@ import { useVpcSelector } from '~/hooks/use-params'
36
36
import { Badge } from '~/ui/lib/Badge'
37
37
import { toComboboxItems , type ComboboxItem } from '~/ui/lib/Combobox'
38
38
import { FormDivider } from '~/ui/lib/Divider'
39
+ import { FieldLabel } from '~/ui/lib/FieldLabel'
39
40
import { Message } from '~/ui/lib/Message'
40
41
import * as MiniTable from '~/ui/lib/MiniTable'
42
+ import { SideModal } from '~/ui/lib/SideModal'
41
43
import { TextInputHint } from '~/ui/lib/TextInput'
42
44
import { KEYS } from '~/ui/util/keys'
43
45
import { ALL_ISH } from '~/util/consts'
@@ -415,46 +417,50 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
415
417
416
418
{ /* Really this should be its own <form>, but you can't have a form inside a form,
417
419
so we just stick the submit handler in a button onClick */ }
418
- < div className = "flex flex-col gap-3" >
419
- < h3 className = "mb-4 text-sans-2xl" > Targets</ h3 >
420
- < Message
421
- variant = "info"
422
- content = {
423
- < >
420
+ < SideModal . Heading > Targets</ SideModal . Heading >
421
+
422
+ < Message
423
+ variant = "info"
424
+ content = {
425
+ < >
426
+ < p >
424
427
Targets determine the instances to which this rule applies. You can target
425
- instances directly by name, or specify a VPC, VPC subnet, IP, or IP subnet,
426
- which will apply the rule to traffic going to all matching instances. Targets
427
- are additive: the rule applies to instances matching{ ' ' }
428
+ instances directly or specify a VPC, VPC subnet, IP, or IP subnet, which will
429
+ apply the rule to traffic going to all matching instances.
430
+ </ p >
431
+ < p className = "mt-2" >
432
+ Targets are additive: the rule applies to instances matching{ ' ' }
428
433
< span className = "underline" > any</ span > target.
429
- </ >
430
- }
431
- />
432
- < DynamicTypeAndValueFields
433
- sectionType = "target"
434
- control = { targetForm . control }
435
- valueType = { targetType }
436
- items = { toComboboxItems ( targetItems [ targetType ] ) }
437
- // HACK: reset the whole subform, keeping type (because we just set
438
- // it). most importantly, this resets isSubmitted so the form can go
439
- // back to validating on submit instead of change
440
- onTypeChange = { ( ) =>
441
- targetForm . reset ( { type : targetForm . getValues ( 'type' ) , value : '' } )
442
- }
443
- onInputChange = { ( value ) => targetForm . setValue ( 'value' , value ) }
444
- onSubmitTextField = { submitTarget }
445
- />
446
- < MiniTable . ClearAndAddButtons
447
- addButtonCopy = "Add target"
448
- disableClear = { ! targetValue }
449
- onClear = { ( ) => targetForm . reset ( ) }
450
- onSubmit = { submitTarget }
451
- />
452
- </ div >
434
+ </ p >
435
+ </ >
436
+ }
437
+ />
438
+
439
+ < DynamicTypeAndValueFields
440
+ sectionType = "target"
441
+ control = { targetForm . control }
442
+ valueType = { targetType }
443
+ items = { toComboboxItems ( targetItems [ targetType ] ) }
444
+ // HACK: reset the whole subform, keeping type (because we just set
445
+ // it). most importantly, this resets isSubmitted so the form can go
446
+ // back to validating on submit instead of change
447
+ onTypeChange = { ( ) =>
448
+ targetForm . reset ( { type : targetForm . getValues ( 'type' ) , value : '' } )
449
+ }
450
+ onInputChange = { ( value ) => targetForm . setValue ( 'value' , value ) }
451
+ onSubmitTextField = { submitTarget }
452
+ />
453
+ < MiniTable . ClearAndAddButtons
454
+ addButtonCopy = "Add target"
455
+ disableClear = { ! targetValue }
456
+ onClear = { ( ) => targetForm . reset ( ) }
457
+ onSubmit = { submitTarget }
458
+ />
453
459
{ ! ! targets . value . length && < TypeAndValueTable sectionType = "target" items = { targets } /> }
454
460
455
461
< FormDivider />
456
462
457
- < h3 className = "mb-4 text-sans-2xl" > Filters</ h3 >
463
+ < SideModal . Heading > Filters</ SideModal . Heading >
458
464
< Message
459
465
variant = "info"
460
466
content = {
@@ -468,12 +474,12 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
468
474
/>
469
475
470
476
< div className = "flex flex-col gap-3" >
471
- { /* We have to blow this up instead of using TextField to get better
477
+ { /* We have to blow this up instead of using TextField to get better
472
478
text styling on the label */ }
473
479
< div className = "mt-2" >
474
- < label id = "portRange-label" htmlFor = "portRange" className = "text-sans-lg ">
480
+ < FieldLabel id = "portRange-label" htmlFor = "portRange" >
475
481
Port filters
476
- </ label >
482
+ </ FieldLabel >
477
483
< TextInputHint id = "portRange-help-text" className = "mb-2" >
478
484
A single destination port (1234) or a range (1234–2345)
479
485
</ TextInputHint >
@@ -523,45 +529,47 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
523
529
) }
524
530
525
531
< fieldset className = "space-y-0.5" >
526
- < legend className = "mb-2 mt-4 text-sans-lg" > Protocol filters</ legend >
532
+ { /* todo: abstract this label and checkbox pattern */ }
533
+ < FieldLabel id = "portRange-label" htmlFor = "portRange" className = "mb-2" >
534
+ Protocol filters
535
+ </ FieldLabel >
527
536
< ProtocolField control = { control } protocol = "TCP" />
528
537
< ProtocolField control = { control } protocol = "UDP" />
529
538
< ProtocolField control = { control } protocol = "ICMP" />
530
539
</ fieldset >
531
540
532
- < div className = "flex flex-col gap-3" >
533
- < h3 className = "mt-4 text-sans-lg" > Host filters</ h3 >
534
- < Message
535
- variant = "info"
536
- content = {
537
- < >
538
- Host filters match the “other end” of traffic from the
539
- target’s perspective: for an inbound rule, they match the source of
540
- traffic. For an outbound rule, they match the destination.
541
- </ >
542
- }
543
- />
544
- < DynamicTypeAndValueFields
545
- sectionType = "host"
546
- control = { hostForm . control }
547
- valueType = { hostType }
548
- items = { toComboboxItems ( hostFilterItems [ hostType ] ) }
549
- // HACK: reset the whole subform, keeping type (because we just set
550
- // it). most importantly, this resets isSubmitted so the form can go
551
- // back to validating on submit instead of change
552
- onTypeChange = { ( ) =>
553
- hostForm . reset ( { type : hostForm . getValues ( 'type' ) , value : '' } )
554
- }
555
- onInputChange = { ( value ) => hostForm . setValue ( 'value' , value ) }
556
- onSubmitTextField = { submitHost }
557
- />
558
- < MiniTable . ClearAndAddButtons
559
- addButtonCopy = "Add host filter"
560
- disableClear = { ! hostValue }
561
- onClear = { ( ) => hostForm . reset ( ) }
562
- onSubmit = { submitHost }
563
- />
564
- </ div >
541
+ < FormDivider />
542
+
543
+ < SideModal . Heading > Host filters</ SideModal . Heading >
544
+
545
+ < Message
546
+ variant = "info"
547
+ content = {
548
+ < >
549
+ Host filters match the “other end” of traffic from the
550
+ target’s perspective: for an inbound rule, they match the source of
551
+ traffic. For an outbound rule, they match the destination.
552
+ </ >
553
+ }
554
+ />
555
+ < DynamicTypeAndValueFields
556
+ sectionType = "host"
557
+ control = { hostForm . control }
558
+ valueType = { hostType }
559
+ items = { toComboboxItems ( hostFilterItems [ hostType ] ) }
560
+ // HACK: reset the whole subform, keeping type (because we just set
561
+ // it). most importantly, this resets isSubmitted so the form can go
562
+ // back to validating on submit instead of change
563
+ onTypeChange = { ( ) => hostForm . reset ( { type : hostForm . getValues ( 'type' ) , value : '' } ) }
564
+ onInputChange = { ( value ) => hostForm . setValue ( 'value' , value ) }
565
+ onSubmitTextField = { submitHost }
566
+ />
567
+ < MiniTable . ClearAndAddButtons
568
+ addButtonCopy = "Add host filter"
569
+ disableClear = { ! hostValue }
570
+ onClear = { ( ) => hostForm . reset ( ) }
571
+ onSubmit = { submitHost }
572
+ />
565
573
{ ! ! hosts . value . length && < TypeAndValueTable sectionType = "host" items = { hosts } /> }
566
574
567
575
{ error && (
0 commit comments