This commit is contained in:
nishthaAhujaa
2025-12-31 16:16:26 +05:30
parent 53c0bcbbbc
commit 1126cdf019

View File

@@ -1,6 +1,6 @@
import { Callout, DirectionalHint, Label, SearchBox, mergeStyleSets, useTheme } from "@fluentui/react";
import { Callout, DirectionalHint, Label, SearchBox, useTheme } from "@fluentui/react";
import * as React from "react";
import { FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { FunctionComponent, useCallback, useEffect, useRef, useState } from "react";
import { Subscription } from "../../../Contracts/DataModels";
interface Props {
@@ -21,114 +21,45 @@ export const SwitchSubscription: FunctionComponent<Props> = ({
const theme = useTheme();
const { semanticColors, palette } = theme;
const buttonStyles: React.CSSProperties = {
width: "100%",
height: "32px",
padding: "0 28px 0 8px",
border: `1px solid ${semanticColors.inputBorder || palette.neutralSecondary}`,
background: semanticColors.inputBackground || palette.white,
color: semanticColors.inputText || semanticColors.bodyText,
textAlign: "left",
cursor: "pointer",
position: "relative",
fontFamily: "inherit",
fontSize: "14px",
};
const listContainerStyles: React.CSSProperties = {
width: buttonRef.current?.offsetWidth || 300,
maxHeight: "400px",
display: "flex",
flexDirection: "column",
background: semanticColors.bodyBackground || palette.white,
};
const listStyles: React.CSSProperties = {
maxHeight: "300px",
overflowY: "auto",
background: semanticColors.bodyBackground || palette.white,
};
const hoverBackground = semanticColors.menuItemBackgroundHovered || palette.neutralLighterAlt;
const selectedBackground = semanticColors.menuItemBackgroundChecked || palette.neutralLighter;
const placeholderColor = semanticColors.bodySubtext || palette.neutralTertiary;
const classNames = useMemo(
() =>
mergeStyleSets({
container: {
display: "flex",
flexDirection: "column",
gap: 12,
},
trigger: {
width: "100%",
height: 32,
padding: "0 28px 0 8px",
border: `1px solid ${semanticColors.inputBorder || palette.neutralSecondary}`,
backgroundColor: semanticColors.inputBackground || palette.white,
color: semanticColors.inputText || semanticColors.bodyText,
textAlign: "left",
cursor: "pointer",
position: "relative",
fontFamily: "inherit",
fontSize: 14,
borderRadius: 2,
selectors: {
":hover": {
borderColor: semanticColors.inputBorderHovered || palette.neutralPrimary,
},
":focus-visible": {
outline: `1px solid ${semanticColors.focusBorder || palette.themePrimary}`,
outlineOffset: 1,
},
},
},
triggerText: {
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
display: "block",
},
triggerChevron: {
position: "absolute",
right: 8,
top: "50%",
transform: "translateY(-50%)",
pointerEvents: "none",
},
callout: {
backgroundColor: semanticColors.bodyBackground || palette.white,
},
listContainer: {
display: "flex",
flexDirection: "column",
maxHeight: 400,
backgroundColor: semanticColors.bodyBackground || palette.white,
},
list: {
maxHeight: 300,
overflowY: "auto",
},
item: {
padding: "8px 12px",
cursor: "pointer",
fontSize: 14,
color: semanticColors.bodyText,
backgroundColor: "transparent",
selectors: {
":hover": {
backgroundColor: hoverBackground,
},
},
},
itemSelected: {
backgroundColor: selectedBackground,
selectors: {
":hover": {
backgroundColor: selectedBackground,
},
},
},
emptyState: {
padding: "8px 12px",
color: placeholderColor,
},
}),
[hoverBackground, palette, placeholderColor, semanticColors, selectedBackground],
);
const searchBoxStyles = useMemo(
() => ({
root: {
padding: 8,
borderBottom: `1px solid ${semanticColors.inputBorder || palette.neutralLight}`,
background: semanticColors.bodyBackground || palette.white,
},
field: {
color: semanticColors.inputText || semanticColors.bodyText,
},
icon: {
color: placeholderColor,
},
clearButton: {
color: placeholderColor,
},
}),
[palette, placeholderColor, semanticColors],
);
const getItemStyles = (isSelected: boolean): React.CSSProperties => ({
padding: "8px 12px",
cursor: "pointer",
backgroundColor: isSelected ? selectedBackground : "transparent",
fontSize: "14px",
color: semanticColors.bodyText,
});
const closeDropdown = useCallback(() => {
setIsOpen(false);
@@ -190,18 +121,26 @@ export const SwitchSubscription: FunctionComponent<Props> = ({
);
return (
<div className={classNames.container}>
<div>
<Label>Subscription</Label>
<button
ref={buttonRef}
className="accountSwitchSubscriptionDropdown"
onClick={handleButtonClick}
className={classNames.trigger}
style={buttonStyles}
>
<span className={classNames.triggerText}>
<span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", display: "block" }}>
{selectedSubscription?.displayName || "Select a Subscription"}
</span>
<span className={classNames.triggerChevron}>
<span
style={{
position: "absolute",
right: "8px",
top: "50%",
transform: "translateY(-50%)",
pointerEvents: "none",
}}
>
</span>
</button>
@@ -213,33 +152,45 @@ export const SwitchSubscription: FunctionComponent<Props> = ({
isBeakVisible={false}
gapSpace={0}
setInitialFocus
calloutMinWidth={buttonRef.current?.offsetWidth || 280}
className={`${classNames.callout} accountSwitchSubscriptionDropdownMenu`}
className="accountSwitchSubscriptionDropdownMenu"
>
<div ref={calloutContentRef}>
<div className={classNames.listContainer}>
<div style={listContainerStyles}>
<SearchBox
placeholder="Filter subscriptions"
value={filterText}
onChange={(_, newValue) => setFilterText(newValue || "")}
styles={searchBoxStyles}
styles={{
root: {
padding: "8px",
borderBottom: `1px solid ${semanticColors.inputBorder || palette.neutralLight}`,
background: semanticColors.bodyBackground || palette.white,
},
field: {
color: semanticColors.inputText || semanticColors.bodyText,
},
}}
/>
<div className={classNames.list}>
<div style={listStyles}>
{filteredSubscriptions && filteredSubscriptions.length > 0 ? (
filteredSubscriptions.map((sub) => {
const isSelected = sub.subscriptionId === selectedSubscription?.subscriptionId;
const itemClassName = isSelected
? `${classNames.item} ${classNames.itemSelected}`
: classNames.item;
return (
<div key={sub.subscriptionId} onClick={() => handleSelect(sub)} className={itemClassName}>
{sub.displayName}
</div>
);
})
filteredSubscriptions.map((sub) => (
<div
key={sub.subscriptionId}
onClick={() => handleSelect(sub)}
style={getItemStyles(sub.subscriptionId === selectedSubscription?.subscriptionId)}
onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = hoverBackground)}
onMouseLeave={(e) =>
(e.currentTarget.style.backgroundColor =
sub.subscriptionId === selectedSubscription?.subscriptionId
? selectedBackground
: "transparent")
}
>
{sub.displayName}
</div>
))
) : (
<div className={classNames.emptyState}>No subscriptions found</div>
<div style={{ padding: "8px 12px", color: placeholderColor }}>No subscriptions found</div>
)}
</div>
</div>