@@ -4,17 +4,20 @@ import {
44 BookOpenIcon ,
55 InformationCircleIcon ,
66 LockClosedIcon ,
7- MagnifyingGlassIcon ,
87 PencilSquareIcon ,
98 PlusIcon ,
109 TrashIcon ,
1110} from "@heroicons/react/20/solid" ;
12- import { Form , type MetaFunction , Outlet , useActionData , useFetcher , useNavigation , useRevalidator } from "@remix-run/react" ;
1311import {
14- type ActionFunctionArgs ,
15- type LoaderFunctionArgs ,
16- json ,
17- } from "@remix-run/server-runtime" ;
12+ Form ,
13+ type MetaFunction ,
14+ Outlet ,
15+ useActionData ,
16+ useFetcher ,
17+ useNavigation ,
18+ useRevalidator ,
19+ } from "@remix-run/react" ;
20+ import { type ActionFunctionArgs , type LoaderFunctionArgs , json } from "@remix-run/server-runtime" ;
1821import { useEffect , useMemo , useState } from "react" ;
1922import { typedjson , useTypedLoaderData } from "remix-typedjson" ;
2023import { z } from "zod" ;
@@ -30,9 +33,9 @@ import { Fieldset } from "~/components/primitives/Fieldset";
3033import { FormButtons } from "~/components/primitives/FormButtons" ;
3134import { FormError } from "~/components/primitives/FormError" ;
3235import { Header2 } from "~/components/primitives/Headers" ;
33- import { InfoPanel } from "~/components/primitives/InfoPanel" ;
3436import { Input } from "~/components/primitives/Input" ;
3537import { InputGroup } from "~/components/primitives/InputGroup" ;
38+ import { SearchInput } from "~/components/primitives/SearchInput" ;
3639import { Label } from "~/components/primitives/Label" ;
3740import { NavBar , PageAccessories , PageTitle } from "~/components/primitives/PageHeader" ;
3841import { Paragraph } from "~/components/primitives/Paragraph" ;
@@ -50,6 +53,7 @@ import { SimpleTooltip } from "~/components/primitives/Tooltip";
5053import { prisma } from "~/db.server" ;
5154import { useEnvironment } from "~/hooks/useEnvironment" ;
5255import { useFuzzyFilter } from "~/hooks/useFuzzyFilter" ;
56+ import { useSearchParams } from "~/hooks/useSearchParam" ;
5357import { useOrganization } from "~/hooks/useOrganizations" ;
5458import { useProject } from "~/hooks/useProject" ;
5559import { redirectWithSuccessMessage } from "~/models/message.server" ;
@@ -76,7 +80,11 @@ import { UserAvatar } from "~/components/UserProfilePhoto";
7680import { VercelIntegrationService } from "~/services/vercelIntegration.server" ;
7781import { fromPromise } from "neverthrow" ;
7882import { logger } from "~/services/logger.server" ;
79- import { shouldSyncEnvVar , isPullEnvVarsEnabledForEnvironment , type TriggerEnvironmentType } from "~/v3/vercel/vercelProjectIntegrationSchema" ;
83+ import {
84+ shouldSyncEnvVar ,
85+ isPullEnvVarsEnabledForEnvironment ,
86+ type TriggerEnvironmentType ,
87+ } from "~/v3/vercel/vercelProjectIntegrationSchema" ;
8088
8189export const meta : MetaFunction = ( ) => {
8290 return [
@@ -92,10 +100,11 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
92100
93101 try {
94102 const presenter = new EnvironmentVariablesPresenter ( ) ;
95- const { environmentVariables, environments, hasStaging, vercelIntegration } = await presenter . call ( {
96- userId,
97- projectSlug : projectParam ,
98- } ) ;
103+ const { environmentVariables, environments, hasStaging, vercelIntegration } =
104+ await presenter . call ( {
105+ userId,
106+ projectSlug : projectParam ,
107+ } ) ;
99108
100109 return typedjson ( {
101110 environmentVariables,
@@ -123,7 +132,9 @@ const schema = z.discriminatedUnion("action", [
123132 action : z . literal ( "update-vercel-sync" ) ,
124133 key : z . string ( ) ,
125134 environmentType : z . enum ( [ "PRODUCTION" , "STAGING" , "PREVIEW" , "DEVELOPMENT" ] ) ,
126- syncEnabled : z . union ( [ z . literal ( "true" ) , z . literal ( "false" ) ] ) . transform ( ( val ) => val === "true" ) ,
135+ syncEnabled : z
136+ . union ( [ z . literal ( "true" ) , z . literal ( "false" ) ] )
137+ . transform ( ( val ) => val === "true" ) ,
127138 } ) ,
128139] ) ;
129140
@@ -249,15 +260,21 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
249260
250261export default function Page ( ) {
251262 const [ revealAll , setRevealAll ] = useState ( false ) ;
252- const { environmentVariables, environments, vercelIntegration } = useTypedLoaderData < typeof loader > ( ) ;
263+ const { environmentVariables, environments, vercelIntegration } =
264+ useTypedLoaderData < typeof loader > ( ) ;
253265 const organization = useOrganization ( ) ;
254266 const project = useProject ( ) ;
255267 const environment = useEnvironment ( ) ;
256- const { filterText, setFilterText, filteredItems } =
257- useFuzzyFilter < EnvironmentVariableWithSetValues > ( {
258- items : environmentVariables ,
259- keys : [ "key" , "value" , "environment.type" , "environment.branchName" ] ,
260- } ) ;
268+ const { value } = useSearchParams ( ) ;
269+ const urlSearch = value ( "search" ) ?? "" ;
270+ const { setFilterText, filteredItems } = useFuzzyFilter < EnvironmentVariableWithSetValues > ( {
271+ items : environmentVariables ,
272+ keys : [ "key" , "value" , "environment.type" , "environment.branchName" ] ,
273+ } ) ;
274+
275+ useEffect ( ( ) => {
276+ setFilterText ( urlSearch ) ;
277+ } , [ urlSearch , setFilterText ] ) ;
261278
262279 // Add isFirst and isLast to each environment variable
263280 // They're set based on if they're the first or last time that `key` has been seen in the list
@@ -314,18 +331,10 @@ export default function Page() {
314331 < div className = { cn ( "flex h-full flex-col" ) } >
315332 { environmentVariables . length > 0 && (
316333 < div className = "flex items-center justify-between gap-2 px-2 py-2" >
317- < Input
318- placeholder = "Search variables"
319- variant = "tertiary"
320- icon = { MagnifyingGlassIcon }
321- fullWidth = { true }
322- value = { filterText }
323- onChange = { ( e ) => setFilterText ( e . target . value ) }
324- autoFocus
325- />
326- < div className = "flex items-center justify-end gap-2" >
334+ < SearchInput placeholder = "Search variables…" autoFocus />
335+ < div className = "flex items-center justify-end gap-1.5" >
327336 < Switch
328- variant = "small"
337+ variant = "secondary/ small"
329338 label = "Reveal values"
330339 checked = { revealAll }
331340 onCheckedChange = { ( e ) => setRevealAll ( e . valueOf ( ) ) }
@@ -351,7 +360,16 @@ export default function Page() {
351360 Value
352361 </ TableHeaderCell >
353362 < TableHeaderCell className = { vercelIntegration ?. enabled ? "w-[13%]" : "w-[15%]" } >
354- Environment
363+ < SimpleTooltip
364+ button = {
365+ < span className = "flex items-center gap-1" >
366+ Environment
367+ < InformationCircleIcon className = "size-4 text-text-dimmed" />
368+ </ span >
369+ }
370+ content = "Dev environment variables specified here will be overridden by ones in your .env file when running locally."
371+ className = "max-w-60"
372+ />
355373 </ TableHeaderCell >
356374 { vercelIntegration ?. enabled && (
357375 < TableHeaderCell className = "w-[8%]" >
@@ -458,10 +476,11 @@ export default function Page() {
458476 />
459477 < span className = "text-sm" > { variable . updatedByUser . name } </ span >
460478 </ div >
461- ) : ( variable . lastUpdatedBy ?. type === "integration" && variable . lastUpdatedBy ?. integration === 'vercel' ) ? (
479+ ) : variable . lastUpdatedBy ?. type === "integration" &&
480+ variable . lastUpdatedBy ?. integration === "vercel" ? (
462481 < div className = "flex items-center gap-2" >
463- < VercelLogo className = "size-4 text-text-dimmed group-hover/table-row:text-text-bright transition-colors " />
464- < span className = "text-sm text-text-dimmed group-hover/table-row:text-text-bright capitalize transition-colors " >
482+ < VercelLogo className = "size-4 text-text-dimmed transition-colors group-hover/table-row:text-text-bright" />
483+ < span className = "text-sm capitalize text-text-dimmed transition-colors group-hover/table-row:text-text-bright" >
465484 { variable . lastUpdatedBy . integration }
466485 </ span >
467486 </ div >
@@ -475,7 +494,7 @@ export default function Page() {
475494 </ TableCell >
476495 < TableCellMenu
477496 isSticky
478- className = "w-0 [&:has(.group-hover/table-row:block)]:w-auto"
497+ className = "[&:has(.group-hover/table-row:block)]:w-auto w-0 "
479498 hiddenButtons = {
480499 < >
481500 < EditEnvironmentVariablePanel
@@ -514,13 +533,6 @@ export default function Page() {
514533 ) }
515534 </ TableBody >
516535 </ Table >
517-
518- < div className = "-mt-px w-full border-t border-grid-dimmed" >
519- < InfoPanel icon = { InformationCircleIcon } variant = "minimal" panelClassName = "max-w-fit" >
520- Dev environment variables specified here will be overridden by ones in your .env file
521- when running locally.
522- </ InfoPanel >
523- </ div >
524536 </ div >
525537 < Outlet />
526538 </ PageBody >
@@ -561,9 +573,12 @@ function EditEnvironmentVariablePanel({
561573 return (
562574 < Dialog open = { isOpen } onOpenChange = { setIsOpen } >
563575 < DialogTrigger asChild >
564- < Button variant = "small-menu-item" LeadingIcon = { PencilSquareIcon } fullWidth textAlignLeft >
565-
566- </ Button >
576+ < Button
577+ variant = "small-menu-item"
578+ LeadingIcon = { PencilSquareIcon }
579+ fullWidth
580+ textAlignLeft
581+ > </ Button >
567582 </ DialogTrigger >
568583 < DialogContent >
569584 < DialogHeader > Edit environment variable</ DialogHeader >
@@ -715,14 +730,7 @@ function VercelSyncCheckbox({
715730 if ( ! pullEnvVarsEnabledForEnv ) {
716731 return (
717732 < SimpleTooltip
718- button = {
719- < Switch
720- variant = "small"
721- checked = { false }
722- disabled
723- onCheckedChange = { ( ) => { } }
724- />
725- }
733+ button = { < Switch variant = "small" checked = { false } disabled onCheckedChange = { ( ) => { } } /> }
726734 content = "Enable 'Pull env vars before build' for this environment in Vercel settings."
727735 />
728736 ) ;
0 commit comments