Skip to content

Commit 6e17d29

Browse files
Add side modal heading (#2533)
* Add side modal heading * Remove commented input legend * very important mt-2 * cut one word to cut a whole line out of the targets info box --------- Co-authored-by: David Crespo <[email protected]>
1 parent 1dbb740 commit 6e17d29

File tree

2 files changed

+81
-71
lines changed

2 files changed

+81
-71
lines changed

app/forms/firewall-rules-common.tsx

Lines changed: 79 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ import { useVpcSelector } from '~/hooks/use-params'
3636
import { Badge } from '~/ui/lib/Badge'
3737
import { toComboboxItems, type ComboboxItem } from '~/ui/lib/Combobox'
3838
import { FormDivider } from '~/ui/lib/Divider'
39+
import { FieldLabel } from '~/ui/lib/FieldLabel'
3940
import { Message } from '~/ui/lib/Message'
4041
import * as MiniTable from '~/ui/lib/MiniTable'
42+
import { SideModal } from '~/ui/lib/SideModal'
4143
import { TextInputHint } from '~/ui/lib/TextInput'
4244
import { KEYS } from '~/ui/util/keys'
4345
import { ALL_ISH } from '~/util/consts'
@@ -415,46 +417,50 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
415417

416418
{/* Really this should be its own <form>, but you can't have a form inside a form,
417419
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>
424427
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{' '}
428433
<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+
/>
453459
{!!targets.value.length && <TypeAndValueTable sectionType="target" items={targets} />}
454460

455461
<FormDivider />
456462

457-
<h3 className="mb-4 text-sans-2xl">Filters</h3>
463+
<SideModal.Heading>Filters</SideModal.Heading>
458464
<Message
459465
variant="info"
460466
content={
@@ -468,12 +474,12 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
468474
/>
469475

470476
<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
472478
text styling on the label */}
473479
<div className="mt-2">
474-
<label id="portRange-label" htmlFor="portRange" className="text-sans-lg">
480+
<FieldLabel id="portRange-label" htmlFor="portRange">
475481
Port filters
476-
</label>
482+
</FieldLabel>
477483
<TextInputHint id="portRange-help-text" className="mb-2">
478484
A single destination port (1234) or a range (1234&ndash;2345)
479485
</TextInputHint>
@@ -523,45 +529,47 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
523529
)}
524530

525531
<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>
527536
<ProtocolField control={control} protocol="TCP" />
528537
<ProtocolField control={control} protocol="UDP" />
529538
<ProtocolField control={control} protocol="ICMP" />
530539
</fieldset>
531540

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 &ldquo;other end&rdquo; of traffic from the
539-
target&rsquo;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 &ldquo;other end&rdquo; of traffic from the
550+
target&rsquo;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+
/>
565573
{!!hosts.value.length && <TypeAndValueTable sectionType="host" items={hosts} />}
566574

567575
{error && (

app/ui/lib/SideModal.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ function SideModalBody({ children }: { children?: ReactNode }) {
170170

171171
SideModal.Body = SideModalBody
172172

173+
SideModal.Heading = classed.div`text-sans-semi-xl`
174+
173175
SideModal.Section = classed.div`p-8 space-y-6 border-secondary`
174176

175177
SideModal.Footer = ({ children, error }: { children: ReactNode; error?: boolean }) => (

0 commit comments

Comments
 (0)