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 * 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"; import { Subscription } from "../../../Contracts/DataModels";
interface Props { interface Props {
@@ -21,114 +21,45 @@ export const SwitchSubscription: FunctionComponent<Props> = ({
const theme = useTheme(); const theme = useTheme();
const { semanticColors, palette } = theme; 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 hoverBackground = semanticColors.menuItemBackgroundHovered || palette.neutralLighterAlt;
const selectedBackground = semanticColors.menuItemBackgroundChecked || palette.neutralLighter; const selectedBackground = semanticColors.menuItemBackgroundChecked || palette.neutralLighter;
const placeholderColor = semanticColors.bodySubtext || palette.neutralTertiary; const placeholderColor = semanticColors.bodySubtext || palette.neutralTertiary;
const classNames = useMemo( const getItemStyles = (isSelected: boolean): React.CSSProperties => ({
() => padding: "8px 12px",
mergeStyleSets({ cursor: "pointer",
container: { backgroundColor: isSelected ? selectedBackground : "transparent",
display: "flex", fontSize: "14px",
flexDirection: "column", color: semanticColors.bodyText,
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 closeDropdown = useCallback(() => { const closeDropdown = useCallback(() => {
setIsOpen(false); setIsOpen(false);
@@ -190,18 +121,26 @@ export const SwitchSubscription: FunctionComponent<Props> = ({
); );
return ( return (
<div className={classNames.container}> <div>
<Label>Subscription</Label> <Label>Subscription</Label>
<button <button
ref={buttonRef} ref={buttonRef}
className="accountSwitchSubscriptionDropdown" className="accountSwitchSubscriptionDropdown"
onClick={handleButtonClick} 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"} {selectedSubscription?.displayName || "Select a Subscription"}
</span> </span>
<span className={classNames.triggerChevron}> <span
style={{
position: "absolute",
right: "8px",
top: "50%",
transform: "translateY(-50%)",
pointerEvents: "none",
}}
>
</span> </span>
</button> </button>
@@ -213,33 +152,45 @@ export const SwitchSubscription: FunctionComponent<Props> = ({
isBeakVisible={false} isBeakVisible={false}
gapSpace={0} gapSpace={0}
setInitialFocus setInitialFocus
calloutMinWidth={buttonRef.current?.offsetWidth || 280} className="accountSwitchSubscriptionDropdownMenu"
className={`${classNames.callout} accountSwitchSubscriptionDropdownMenu`}
> >
<div ref={calloutContentRef}> <div ref={calloutContentRef}>
<div className={classNames.listContainer}> <div style={listContainerStyles}>
<SearchBox <SearchBox
placeholder="Filter subscriptions" placeholder="Filter subscriptions"
value={filterText} value={filterText}
onChange={(_, newValue) => setFilterText(newValue || "")} 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 && filteredSubscriptions.length > 0 ? (
filteredSubscriptions.map((sub) => { filteredSubscriptions.map((sub) => (
const isSelected = sub.subscriptionId === selectedSubscription?.subscriptionId; <div
const itemClassName = isSelected key={sub.subscriptionId}
? `${classNames.item} ${classNames.itemSelected}` onClick={() => handleSelect(sub)}
: classNames.item; style={getItemStyles(sub.subscriptionId === selectedSubscription?.subscriptionId)}
onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = hoverBackground)}
return ( onMouseLeave={(e) =>
<div key={sub.subscriptionId} onClick={() => handleSelect(sub)} className={itemClassName}> (e.currentTarget.style.backgroundColor =
{sub.displayName} sub.subscriptionId === selectedSubscription?.subscriptionId
</div> ? 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>
</div> </div>