Use render callback approach

This commit is contained in:
tidy-dev 2023-04-14 11:27:33 -04:00
parent 086e6d5aaf
commit f1382bc630
2 changed files with 60 additions and 41 deletions

View file

@ -26,6 +26,9 @@ interface IRadioGroupProps<T> {
* The key argument corresponds to the key property of the selected item.
*/
readonly onSelectionChanged: (key: T) => void
/** Render radio button label contents */
readonly renderRadioButtonLabelContents: (key: T) => JSX.Element
}
/**
@ -39,11 +42,9 @@ export class RadioGroup<T extends string> extends React.Component<
}
private renderRadioButtons() {
const { children, radioButtonKeys, selectedKey } = this.props
const childrenArr = React.Children.toArray(children)
const { radioButtonKeys, selectedKey } = this.props
return childrenArr.map((child, index) => {
const key = radioButtonKeys[index]
return radioButtonKeys.map(key => {
const checked = selectedKey === key
return (
<RadioButton<T>
@ -53,7 +54,7 @@ export class RadioGroup<T extends string> extends React.Component<
onSelected={this.onSelectionChanged}
tabIndex={checked ? 0 : -1}
>
{child}
{this.props.renderRadioButtonLabelContents(key)}
</RadioButton>
)
})

View file

@ -70,6 +70,50 @@ export class Appearance extends React.Component<
this.props.onCustomThemeChanged(theme)
}
public renderThemeSwatch = (theme: ApplicationTheme) => {
const darkThemeImage = encodePathAsUrl(__dirname, 'static/ghd_dark.svg')
const lightThemeImage = encodePathAsUrl(__dirname, 'static/ghd_light.svg')
switch (theme) {
case ApplicationTheme.Light:
return (
<span>
<img src={lightThemeImage} alt="" />
<span className="theme-value-label">Light</span>
</span>
)
case ApplicationTheme.Dark:
return (
<span>
<img src={darkThemeImage} alt="" />
<span className="theme-value-label">Dark</span>
</span>
)
case ApplicationTheme.System:
/** Why three images? The system theme swatch uses the first image
* positioned relatively to get the label container size and uses the
* second and third positioned absolutely over first and third one
* clipped in half to render a split dark and light theme swatch. */
return (
<span>
<span className="system-theme-swatch">
<img src={lightThemeImage} alt="" />
<img src={lightThemeImage} alt="" />
<img src={darkThemeImage} alt="" />
</span>
<span className="theme-value-label">System</span>
</span>
)
case ApplicationTheme.HighContrast:
return (
<span>
<img src={darkThemeImage} alt="" />
<span className="theme-value-label">High Contrast</span>
</span>
)
}
}
public render() {
const { selectedTheme } = this.state
@ -81,51 +125,25 @@ export class Appearance extends React.Component<
)
}
const darkThemeImage = encodePathAsUrl(__dirname, 'static/ghd_dark.svg')
const lightThemeImage = encodePathAsUrl(__dirname, 'static/ghd_light.svg')
const themes = [
ApplicationTheme.Light,
ApplicationTheme.Dark,
...(supportsSystemThemeChanges() ? [ApplicationTheme.System] : []),
...(enableHighContrastTheme() ? [ApplicationTheme.HighContrast] : []),
]
return (
<DialogContent>
<h2 id="theme-heading">Theme</h2>
<RadioGroup<ApplicationTheme>
ariaLabelledBy="theme-heading"
className="theme-selector"
selectedKey={selectedTheme}
radioButtonKeys={[
ApplicationTheme.Light,
ApplicationTheme.Dark,
...(supportsSystemThemeChanges() ? [ApplicationTheme.System] : []),
...(enableHighContrastTheme()
? [ApplicationTheme.HighContrast]
: []),
]}
radioButtonKeys={themes}
onSelectionChanged={this.onSelectedThemeChanged}
>
<span>
<img src={lightThemeImage} alt="" />
<span className="theme-value-label">Light</span>
</span>
<span>
<img src={darkThemeImage} alt="" />
<span className="theme-value-label">Dark</span>
</span>
{supportsSystemThemeChanges() && (
<span>
<span className="system-theme-swatch">
<img src={lightThemeImage} alt="" />
<img src={lightThemeImage} alt="" />
<img src={darkThemeImage} alt="" />
</span>
<span className="theme-value-label">System</span>
</span>
)}
{enableHighContrastTheme() && (
<span>
<img src={darkThemeImage} alt="" />
<span className="theme-value-label">High Contrast</span>
</span>
)}
</RadioGroup>
renderRadioButtonLabelContents={this.renderThemeSwatch}
/>
<Row>
<CustomThemeSelector