Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
},
"devDependencies": {
"@octokit/rest": "^19.0.7",
"@patternfly/patternfly": "^6.5.0-prerelease.33",
"@patternfly/patternfly": "^6.5.0-prerelease.37",
"@patternfly/react-code-editor": "^6.5.0-prerelease.26",
"@patternfly/react-core": "^6.5.0-prerelease.24",
"@patternfly/react-table": "^6.5.0-prerelease.24",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,15 @@ import React, { useState } from 'react';
import {
Select,
SelectGroup,
SelectList,
SelectOption,
MenuToggle,
MenuSearch,
MenuSearchInput,
ToggleGroup,
ToggleGroupItem,
Icon,
Divider,
Spinner,
Label,
Popover,
Button
Spinner
} from '@patternfly/react-core';
import { HelpIcon, ExternalLinkAltIcon } from '@patternfly/react-icons';
import { useTheme, THEME_TYPES } from '../../hooks/useTheme';

const SunIcon = (
Expand Down Expand Up @@ -50,6 +44,14 @@ const DesktopIcon = (
</svg>
);

const ThemeVariantGroupLabel = () => {
return (
<div className="pf-v6-c-menu__group-title" id="theme-selector-variant-title">
Theme
</div>
);
};

const ColorSchemeGroupLabel = () => {
return (
<div className="pf-v6-c-menu__group-title" id="theme-selector-color-scheme-title">
Expand All @@ -58,60 +60,34 @@ const ColorSchemeGroupLabel = () => {
);
};

const HighContrastGroupLabel = () => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);

const ContrastModeGroupLabel = () => {
return (
<div className="pf-v6-c-menu__group-title">
High contrast{' '}
<Popover
onClick={(e) => e.stopPropagation()}
headerContent={'Under development'}
headerComponent="h1"
bodyContent={
'We are still working to add high contrast support across all PatternFly components and extensions. This beta allows you to preview our progress.'
}
footerContent={
<Button
icon={<ExternalLinkAltIcon />}
component="a"
isInline
variant="link"
href="/design-foundations/theming"
target="_blank"
>
Learn more
</Button>
}
aria-label="More info about high contrast"
appendTo={() => document.body}
>
<Button variant="plain" hasNoPadding icon={<HelpIcon />} aria-label="High contrast help" />
</Popover>{' '}
&nbsp;
<Label color="blue" isCompact>
Beta
</Label>
<div className="pf-v6-c-menu__group-title" id="theme-selector-contrast-title">
Contrast mode
</div>
);
};

export const ThemeSelector = ({ id }) => {
const { mode: themeVariant, setMode: setThemeVariant, modes: themeVariantModes } = useTheme(THEME_TYPES.THEME_VARIANT);
const { mode: themeMode, setMode: setThemeMode, modes: colorModes } = useTheme(THEME_TYPES.COLOR);
const {
mode: highContrastMode,
setMode: setHighContrastMode,
modes: highContrastModes
} = useTheme(THEME_TYPES.HIGH_CONTRAST);
mode: contrastMode,
setMode: setContrastMode,
modes: contrastModes
} = useTheme(THEME_TYPES.CONTRAST);
const [isThemeSelectOpen, setIsThemeSelectOpen] = useState(false);

const handleThemeChange = (_event, selectedMode) => {
setThemeMode(selectedMode);
setIsThemeSelectOpen(false);
const handleThemeVariantChange = (evt) => {
setThemeVariant(evt.currentTarget.id);
};

const handleHighContrastThemeSelection = (evt) => {
setHighContrastMode(evt.currentTarget.id);
const handleThemeChange = (evt) => {
setThemeMode(evt.currentTarget.id);
};

const handleContrastModeChange = (evt) => {
setContrastMode(evt.currentTarget.id);
};

const getThemeDisplayText = (mode) => {
Expand All @@ -126,6 +102,9 @@ export const ThemeSelector = ({ id }) => {
};

const getThemeIcon = (mode) => {
if (!colorModes) {
return <Spinner size="sm" />;
}
switch (mode) {
case colorModes.LIGHT:
return SunIcon;
Expand All @@ -134,16 +113,14 @@ export const ThemeSelector = ({ id }) => {
case colorModes.SYSTEM:
return DesktopIcon;
default:
return <Spinner size="sm" />;
return DesktopIcon; // Default to system icon
}
};

return (
<Select
id={id}
isOpen={isThemeSelectOpen}
selected={themeMode}
onSelect={handleThemeChange}
onOpenChange={(isOpen) => setIsThemeSelectOpen(isOpen)}
toggle={(toggleRef) => (
<MenuToggle
Expand All @@ -162,50 +139,86 @@ export const ThemeSelector = ({ id }) => {
preventOverflow: true
}}
>
<SelectGroup label={ThemeVariantGroupLabel}>
<MenuSearch>
<MenuSearchInput>
<ToggleGroup aria-labelledby="theme-selector-variant-title">
<ToggleGroupItem
text="Default"
buttonId={themeVariantModes.DEFAULT}
isSelected={themeVariant === themeVariantModes.DEFAULT}
onChange={handleThemeVariantChange}
/>
<ToggleGroupItem
text="Unified"
buttonId={themeVariantModes.UNIFIED}
isSelected={themeVariant === themeVariantModes.UNIFIED}
onChange={handleThemeVariantChange}
/>
</ToggleGroup>
</MenuSearchInput>
</MenuSearch>
</SelectGroup>
<Divider />
<SelectGroup label={ColorSchemeGroupLabel}>
<SelectList aria-labelledby="theme-selector-color-scheme-title">
<SelectOption value={colorModes.SYSTEM} icon={DesktopIcon} description="Follow system preference">
System
</SelectOption>
<SelectOption value={colorModes.LIGHT} icon={SunIcon} description="Always use light mode">
Light
</SelectOption>
<SelectOption value={colorModes.DARK} icon={MoonIcon} description="Always use dark mode">
Dark
</SelectOption>
</SelectList>
<MenuSearch>
<MenuSearchInput>
<ToggleGroup aria-labelledby="theme-selector-color-scheme-title">
<ToggleGroupItem
text="System"
buttonId={colorModes.SYSTEM}
isSelected={themeMode === colorModes.SYSTEM}
onChange={handleThemeChange}
/>
<ToggleGroupItem
text="Light"
buttonId={colorModes.LIGHT}
isSelected={themeMode === colorModes.LIGHT}
onChange={handleThemeChange}
/>
<ToggleGroupItem
text="Dark"
buttonId={colorModes.DARK}
isSelected={themeMode === colorModes.DARK}
onChange={handleThemeChange}
/>
</ToggleGroup>
</MenuSearchInput>
</MenuSearch>
</SelectGroup>
<Divider />
<SelectGroup label={ContrastModeGroupLabel}>
<MenuSearch>
<MenuSearchInput>
<ToggleGroup aria-labelledby="theme-selector-contrast-title">
<ToggleGroupItem
text="System"
buttonId={contrastModes.SYSTEM}
isSelected={contrastMode === contrastModes.SYSTEM}
onChange={handleContrastModeChange}
/>
<ToggleGroupItem
text="Default"
buttonId={contrastModes.DEFAULT}
isSelected={contrastMode === contrastModes.DEFAULT}
onChange={handleContrastModeChange}
/>
<ToggleGroupItem
text="High contrast"
buttonId={contrastModes.HIGH_CONTRAST}
isSelected={contrastMode === contrastModes.HIGH_CONTRAST}
onChange={handleContrastModeChange}
/>
<ToggleGroupItem
text="Glass"
buttonId={contrastModes.GLASS}
isSelected={contrastMode === contrastModes.GLASS}
onChange={handleContrastModeChange}
/>
</ToggleGroup>
</MenuSearchInput>
</MenuSearch>
</SelectGroup>
{process.env.hasHighContrastSwitcher && (
<>
<Divider />
<SelectGroup label={HighContrastGroupLabel}>
<MenuSearch>
<MenuSearchInput>
<ToggleGroup aria-label="High contrast theme switcher">
<ToggleGroupItem
text="System"
buttonId={highContrastModes.SYSTEM}
isSelected={highContrastMode === highContrastModes.SYSTEM}
onChange={handleHighContrastThemeSelection}
/>
<ToggleGroupItem
text="On"
buttonId={highContrastModes.ON}
isSelected={highContrastMode === highContrastModes.ON}
onChange={handleHighContrastThemeSelection}
/>
<ToggleGroupItem
text="Off"
buttonId={highContrastModes.OFF}
isSelected={highContrastMode === highContrastModes.OFF}
onChange={handleHighContrastThemeSelection}
/>
</ToggleGroup>
</MenuSearchInput>
</MenuSearch>
</SelectGroup>
</>
)}
</Select>
);
};
Loading