Truncate long country lists with a popover
AWS-scale region lists blew out subprocessor cards. Cap the visible labels and open the rest from a +N trigger using a new Base UI Popover in the v2 kit. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -20,7 +20,11 @@
|
|||||||
|
|
||||||
import { BuildingsIcon, MapPinSimpleIcon } from "@phosphor-icons/react";
|
import { BuildingsIcon, MapPinSimpleIcon } from "@phosphor-icons/react";
|
||||||
import { faviconUrl } from "@probo/helpers";
|
import { faviconUrl } from "@probo/helpers";
|
||||||
|
import { Popover } from "@probo/ui/src/v2/Popover/Popover";
|
||||||
|
import { PopoverPopup } from "@probo/ui/src/v2/Popover/PopoverPopup";
|
||||||
|
import { PopoverTrigger } from "@probo/ui/src/v2/Popover/PopoverTrigger";
|
||||||
import { Text } from "@probo/ui/src/v2/typography/Text";
|
import { Text } from "@probo/ui/src/v2/typography/Text";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { graphql, useFragment } from "react-relay";
|
import { graphql, useFragment } from "react-relay";
|
||||||
|
|
||||||
import { BackdropCard } from "#/components/BackdropCard/BackdropCard";
|
import { BackdropCard } from "#/components/BackdropCard/BackdropCard";
|
||||||
@@ -30,6 +34,8 @@ import { useCountryLabel } from "../_lib/useCountryLabel";
|
|||||||
import type { SubprocessorListItem_subprocessor$key } from "./__generated__/SubprocessorListItem_subprocessor.graphql";
|
import type { SubprocessorListItem_subprocessor$key } from "./__generated__/SubprocessorListItem_subprocessor.graphql";
|
||||||
import { subprocessorListItem } from "./variants";
|
import { subprocessorListItem } from "./variants";
|
||||||
|
|
||||||
|
const VISIBLE_COUNTRY_COUNT = 5;
|
||||||
|
|
||||||
const subprocessorListItemFragment = graphql`
|
const subprocessorListItemFragment = graphql`
|
||||||
fragment SubprocessorListItem_subprocessor on Subprocessor @throwOnFieldError {
|
fragment SubprocessorListItem_subprocessor on Subprocessor @throwOnFieldError {
|
||||||
name
|
name
|
||||||
@@ -47,9 +53,11 @@ interface SubprocessorListItemProps {
|
|||||||
// description, and the hosting regions.
|
// description, and the hosting regions.
|
||||||
export function SubprocessorListItem({ subprocessorKey }: SubprocessorListItemProps) {
|
export function SubprocessorListItem({ subprocessorKey }: SubprocessorListItemProps) {
|
||||||
const subprocessor = useFragment(subprocessorListItemFragment, subprocessorKey);
|
const subprocessor = useFragment(subprocessorListItemFragment, subprocessorKey);
|
||||||
|
const { t } = useTranslation("subprocessors");
|
||||||
const countryLabel = useCountryLabel();
|
const countryLabel = useCountryLabel();
|
||||||
const logoUrl = faviconUrl(subprocessor.websiteUrl);
|
const logoUrl = faviconUrl(subprocessor.websiteUrl);
|
||||||
const countries = subprocessor.countries.map(countryLabel).join(", ");
|
const visibleCodes = subprocessor.countries.slice(0, VISIBLE_COUNTRY_COUNT);
|
||||||
|
const hiddenCodes = subprocessor.countries.slice(VISIBLE_COUNTRY_COUNT);
|
||||||
const slots = subprocessorListItem();
|
const slots = subprocessorListItem();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -71,11 +79,34 @@ export function SubprocessorListItem({ subprocessorKey }: SubprocessorListItemPr
|
|||||||
{subprocessor.description}
|
{subprocessor.description}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
{countries !== "" && (
|
{subprocessor.countries.length > 0 && (
|
||||||
<div className={slots.region()}>
|
<div className={slots.region()}>
|
||||||
<MapPinSimpleIcon className={slots.regionIcon()} />
|
<MapPinSimpleIcon className={slots.regionIcon()} />
|
||||||
<Text size={1} color="gold">
|
<Text size={1} color="gold">
|
||||||
{countries}
|
{visibleCodes.map(countryLabel).join(", ")}
|
||||||
|
{hiddenCodes.length > 0 && (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger
|
||||||
|
className={slots.moreTrigger()}
|
||||||
|
aria-label={t("regions.moreRegions", { count: hiddenCodes.length })}
|
||||||
|
>
|
||||||
|
+
|
||||||
|
{hiddenCodes.length}
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverPopup>
|
||||||
|
<div className={slots.moreList()}>
|
||||||
|
{hiddenCodes.map(code => (
|
||||||
|
<Text key={code} size={1} color="neutral" highContrast>
|
||||||
|
{countryLabel(code)}
|
||||||
|
</Text>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</PopoverPopup>
|
||||||
|
</Popover>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -30,5 +30,12 @@ export const subprocessorListItem = tv({
|
|||||||
logoFallbackIcon: "text-sand-9",
|
logoFallbackIcon: "text-sand-9",
|
||||||
region: "flex items-start gap-1",
|
region: "flex items-start gap-1",
|
||||||
regionIcon: "size-4 shrink-0 text-gold-11",
|
regionIcon: "size-4 shrink-0 text-gold-11",
|
||||||
|
// Button reset so the +N control keeps the Text line box (and pin alignment).
|
||||||
|
moreTrigger: [
|
||||||
|
"inline border-0 bg-transparent p-0 font-medium align-baseline",
|
||||||
|
"cursor-pointer underline-offset-2 hover:underline",
|
||||||
|
"outline-none focus-visible:underline",
|
||||||
|
],
|
||||||
|
moreList: "flex flex-wrap gap-x-2 gap-y-1",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Weltweit",
|
"global": "Weltweit",
|
||||||
"eu": "Europäische Union"
|
"eu": "Europäische Union",
|
||||||
|
"moreRegions": "{{count}} weitere Regionen anzeigen"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Global",
|
"global": "Global",
|
||||||
"eu": "European Union"
|
"eu": "European Union",
|
||||||
|
"moreRegions": "Show {{count}} more regions"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Internacional",
|
"global": "Internacional",
|
||||||
"eu": "Unión Europea"
|
"eu": "Unión Europea",
|
||||||
|
"moreRegions": "Mostrar {{count}} regiones más"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "International",
|
"global": "International",
|
||||||
"eu": "Union européenne"
|
"eu": "Union européenne",
|
||||||
|
"moreRegions": "Afficher {{count}} régions supplémentaires"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Global",
|
"global": "Global",
|
||||||
"eu": "Uni Eropa"
|
"eu": "Uni Eropa",
|
||||||
|
"moreRegions": "Tampilkan {{count}} wilayah lainnya"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Globale",
|
"global": "Globale",
|
||||||
"eu": "Unione Europea"
|
"eu": "Unione Europea",
|
||||||
|
"moreRegions": "Mostra altre {{count}} regioni"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "グローバル",
|
"global": "グローバル",
|
||||||
"eu": "欧州連合"
|
"eu": "欧州連合",
|
||||||
|
"moreRegions": "他{{count}}件の地域を表示"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "글로벌",
|
"global": "글로벌",
|
||||||
"eu": "유럽연합"
|
"eu": "유럽연합",
|
||||||
|
"moreRegions": "지역 {{count}}개 더 보기"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Globalny",
|
"global": "Globalny",
|
||||||
"eu": "Unia Europejska"
|
"eu": "Unia Europejska",
|
||||||
|
"moreRegions": "Pokaż {{count}} więcej regionów"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Global",
|
"global": "Global",
|
||||||
"eu": "União Europeia"
|
"eu": "União Europeia",
|
||||||
|
"moreRegions": "Mostrar mais {{count}} regiões"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Küresel",
|
"global": "Küresel",
|
||||||
"eu": "Avrupa Birliği"
|
"eu": "Avrupa Birliği",
|
||||||
|
"moreRegions": "{{count}} bölge daha göster"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "Глобально",
|
"global": "Глобально",
|
||||||
"eu": "Європейський Союз"
|
"eu": "Європейський Союз",
|
||||||
|
"moreRegions": "Показати ще {{count}} регіонів"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
},
|
},
|
||||||
"regions": {
|
"regions": {
|
||||||
"global": "全球",
|
"global": "全球",
|
||||||
"eu": "欧盟"
|
"eu": "欧盟",
|
||||||
|
"moreRegions": "显示另外 {{count}} 个地区"
|
||||||
},
|
},
|
||||||
"categories": {
|
"categories": {
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
|
|||||||
44
packages/ui/src/v2/Popover/Popover.stories.tsx
Normal file
44
packages/ui/src/v2/Popover/Popover.stories.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import { Button } from "../Button/Button";
|
||||||
|
import { Text } from "../typography/Text";
|
||||||
|
|
||||||
|
import { Popover } from "./Popover";
|
||||||
|
import { PopoverPopup } from "./PopoverPopup";
|
||||||
|
import { PopoverTrigger } from "./PopoverTrigger";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "v2/Popover",
|
||||||
|
component: Popover,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Default() {
|
||||||
|
return (
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger render={<Button variant="soft" color="neutral">Open popover</Button>} />
|
||||||
|
<PopoverPopup>
|
||||||
|
<Text size={2} color="neutral" highContrast>
|
||||||
|
Popover content goes here.
|
||||||
|
</Text>
|
||||||
|
</PopoverPopup>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
packages/ui/src/v2/Popover/Popover.tsx
Normal file
30
packages/ui/src/v2/Popover/Popover.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
||||||
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
|
// Root of the popover (Radix "Popover"). Controlled the same way as Base UI's
|
||||||
|
// Popover: `open` / `onOpenChange`, or left uncontrolled. See contrib/claude/ui.md.
|
||||||
|
export type PopoverProps = ComponentProps<typeof BasePopover.Root>;
|
||||||
|
|
||||||
|
export function Popover(props: PopoverProps) {
|
||||||
|
return <BasePopover.Root {...props} />;
|
||||||
|
}
|
||||||
54
packages/ui/src/v2/Popover/PopoverPopup.tsx
Normal file
54
packages/ui/src/v2/Popover/PopoverPopup.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
||||||
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
|
import { popoverPopup } from "./variants";
|
||||||
|
|
||||||
|
export type PopoverPopupProps
|
||||||
|
= & Omit<ComponentProps<typeof BasePopover.Popup>, "className">
|
||||||
|
& {
|
||||||
|
className?: string;
|
||||||
|
// Positioner placement passthrough.
|
||||||
|
side?: ComponentProps<typeof BasePopover.Positioner>["side"];
|
||||||
|
align?: ComponentProps<typeof BasePopover.Positioner>["align"];
|
||||||
|
sideOffset?: ComponentProps<typeof BasePopover.Positioner>["sideOffset"];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Portal + positioner + styled popup. Content-agnostic — callers compose children.
|
||||||
|
export function PopoverPopup(props: PopoverPopupProps) {
|
||||||
|
const {
|
||||||
|
className, children,
|
||||||
|
side = "bottom", align = "start", sideOffset = 4,
|
||||||
|
...popupProps
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BasePopover.Portal>
|
||||||
|
{/* z-3 on the Positioner so the portaled root wins over in-page z-1. */}
|
||||||
|
<BasePopover.Positioner className="z-3" side={side} align={align} sideOffset={sideOffset}>
|
||||||
|
<BasePopover.Popup className={popoverPopup({ className })} {...popupProps}>
|
||||||
|
{children}
|
||||||
|
</BasePopover.Popup>
|
||||||
|
</BasePopover.Positioner>
|
||||||
|
</BasePopover.Portal>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
packages/ui/src/v2/Popover/PopoverTrigger.tsx
Normal file
30
packages/ui/src/v2/Popover/PopoverTrigger.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
||||||
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
|
// The element that opens the popover. Compose a Button via `render` to style it,
|
||||||
|
// or pass className/children for a native button trigger.
|
||||||
|
export type PopoverTriggerProps = ComponentProps<typeof BasePopover.Trigger>;
|
||||||
|
|
||||||
|
export function PopoverTrigger(props: PopoverTriggerProps) {
|
||||||
|
return <BasePopover.Trigger {...props} />;
|
||||||
|
}
|
||||||
32
packages/ui/src/v2/Popover/variants.ts
Normal file
32
packages/ui/src/v2/Popover/variants.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import { tv } from "tailwind-variants/lite";
|
||||||
|
|
||||||
|
// Floating popover surface (Radix "Popover" over Base UI). Same panel look as
|
||||||
|
// DropdownPopup; content-agnostic so callers compose arbitrary children.
|
||||||
|
|
||||||
|
export const popoverPopup = tv({
|
||||||
|
base: [
|
||||||
|
"max-w-sm origin-(--transform-origin) rounded-3 bg-sand-1 p-3 shadow-5 outline-none",
|
||||||
|
"transition-[scale,opacity] duration-150 ease-out data-starting-style:scale-95 data-starting-style:opacity-0",
|
||||||
|
"data-ending-style:scale-95 data-ending-style:opacity-0",
|
||||||
|
],
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user