Skip to content

Commit b99bccc

Browse files
authored
Theme with logos (#16)
Add theme specific colorscheme logos
1 parent 4a85b37 commit b99bccc

23 files changed

+683
-90
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66

77
# pnpm pack outputs
88
/diamondlightsource-sci-react-ui-*.tgz
9+
/storybook-static/

.storybook/main.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ const config: StorybookConfig = {
88
"@chromatic-com/storybook",
99
"@storybook/addon-interactions",
1010
'@storybook/addon-links',
11-
'@storybook/addon-toolbars',
1211
'storybook-dark-mode'
1312
],
1413
framework: {

.storybook/preview.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import {CssBaseline} from "@mui/material";
33
import type { Preview } from "@storybook/react";
44

55
import {ThemeProvider} from '../src'
6-
import {BaseTheme, DiamondTheme} from '../src'
6+
import {GenericTheme, DiamondTheme} from '../src'
77

88
import {ThemeSwapper, TextLight, TextDark} from "./ThemeSwapper";
99

10-
const TextThemeBase = 'Theme: Base'
10+
const TextThemeBase = 'Theme: Generic'
1111
const TextThemeDiamond = 'Theme: Diamond'
1212

1313
export const decorators = [
@@ -26,7 +26,7 @@ export const decorators = [
2626
const selectedThemeMode = context.globals.themeMode || TextLight;
2727

2828
return <ThemeProvider
29-
theme={(selectedTheme == TextThemeBase) ? BaseTheme : DiamondTheme}
29+
theme={(selectedTheme == TextThemeBase) ? GenericTheme : DiamondTheme}
3030
defaultMode={(selectedThemeMode == TextLight) ? "light" : "dark"}
3131
>
3232
<CssBaseline/>

pnpm-lock.yaml

Lines changed: 17 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

readme.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,41 @@ First use the ThemeProvider and supply a theme.
2020

2121
```js
2222
import {
23-
ThemeProvider,
23+
ThemeProvider,
2424
DiamondTheme
2525
} from "@diamondlightsource/sci-react-ui";
2626

2727
root.render(
28-
<ThemeProvider theme={DiamondTheme}>
29-
<App />
30-
</ThemeProvider>
28+
<ThemeProvider theme={DiamondTheme}>
29+
<App />
30+
</ThemeProvider>
3131
)
3232
```
3333

34-
There are currently two themes, `BaseTheme` or `DiamondTheme`, but you can adapt your own.
34+
There are currently two themes, `GenericTheme` or `DiamondTheme`, but you can - and should - adapt your own.
3535

3636
There are various components, here's an example of how to use the NavBar:
3737

3838
```js
3939
import {Container, Typography} from "@mui/material";
4040
import {
41-
Navbar,
42-
NavLink,
43-
NavLinks
41+
Navbar,
42+
NavLink,
43+
NavLinks
4444
} from "@diamondlightsource/sci-react-ui";
4545

4646
function App() {
47-
return <>
48-
<Navbar>
49-
<NavLinks key="links">
50-
<NavLink href="#" key="first">A link</NavLink>
51-
</NavLinks>
52-
</Navbar>
53-
<Container>
54-
<Typography variant="h2">Scientific UI Collection</Typography>
55-
<Typography>A collection of science based React components.</Typography>
56-
</Container>
57-
</>
47+
return <>
48+
<Navbar>
49+
<NavLinks key="links">
50+
<NavLink href="#" key="first">A link</NavLink>
51+
</NavLinks>
52+
</Navbar>
53+
<Container>
54+
<Typography variant="h2">Scientific UI Collection</Typography>
55+
<Typography>A collection of science based React components.</Typography>
56+
</Container>
57+
</>
5858
}
5959
export default App;
6060
```
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Meta, StoryObj } from "@storybook/react";
2+
import { ImageColorSchemeSwitch } from "./ImageColorSchemeSwitch";
3+
4+
import imageDark from "../public/generic/logo-dark.svg"
5+
import imageLight from "../public/generic/logo-light.svg"
6+
7+
const meta: Meta<typeof ImageColorSchemeSwitch> = {
8+
title: "SciReactUI/Control/ImageColorSchemeSwitch",
9+
component: ImageColorSchemeSwitch,
10+
tags: ["autodocs"],
11+
parameters: {
12+
docs: {
13+
description: {
14+
component: 'Switch between an image depending on the color scheme mode, light or dark versions'
15+
},
16+
},
17+
},
18+
};
19+
20+
export default meta;
21+
type Story = StoryObj<typeof meta>;
22+
23+
export const SwitchingImage: Story = {
24+
args: {
25+
image: {
26+
src: imageDark,
27+
srcDark: imageLight,
28+
alt: "Testing Switching Image",
29+
width: "100"
30+
}
31+
},
32+
parameters: {
33+
docs: {
34+
description: {
35+
story: 'This image changes depending on the color scheme mode selected.'
36+
},
37+
},
38+
},
39+
};
40+
41+
42+
export const LargeSwitchingImage: Story = {
43+
args: {
44+
image: {
45+
src: imageDark,
46+
srcDark: imageLight,
47+
alt: "Testing Switching Image",
48+
width: "300"
49+
}
50+
},
51+
};
52+
53+
export const NonSwitchingImage: Story = {
54+
args: {
55+
image: {
56+
src: imageLight,
57+
alt: "Testing Non-Switching Image",
58+
width: "300"
59+
}
60+
},
61+
parameters: {
62+
docs: {
63+
description: {
64+
story: 'This image only has a single src so will NOT switch when the color scheme mode switches.'
65+
},
66+
},
67+
},
68+
};
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import "@testing-library/jest-dom";
2+
import { render } from "@testing-library/react";
3+
4+
import { ImageColorSchemeSwitch, getLogoSrc } from "./ImageColorSchemeSwitch";
5+
6+
jest.mock("@mui/material", () => {
7+
return {
8+
useColorScheme: jest.fn().mockReturnValue({mode:"dark"})
9+
};
10+
})
11+
12+
describe("ImageColorSchemeSwitch", () => {
13+
const testVals = {
14+
src: "src/light",
15+
alt: "test-alt"
16+
};
17+
18+
function getRenderImg( image: any) {
19+
const {getByAltText} = render(<ImageColorSchemeSwitch image={{...testVals, ...image}}/>);
20+
21+
const img = getByAltText(testVals.alt)
22+
expect(img).toBeInTheDocument()
23+
return img
24+
}
25+
26+
it("should render without errors", () => {
27+
render(<ImageColorSchemeSwitch image={{...testVals}}/>);
28+
});
29+
30+
it("should have src and alt by default", () => {
31+
const img = getRenderImg({})
32+
33+
expect(img).toHaveAttribute("alt", testVals.alt)
34+
expect(img).toHaveAttribute("src", testVals.src)
35+
36+
expect(img).not.toHaveAttribute("width")
37+
expect(img).not.toHaveAttribute("height")
38+
});
39+
40+
it("should have width 123", () => {
41+
const width = "123";
42+
43+
const img = getRenderImg({width})
44+
expect(img).toHaveAttribute("width", width)
45+
expect(img).not.toHaveAttribute("height")
46+
});
47+
48+
it("should have width 123 and height 124", () => {
49+
const width = "123",
50+
height = "124";
51+
52+
const img = getRenderImg({width,height})
53+
54+
expect(img).toHaveAttribute("width", width)
55+
expect(img).toHaveAttribute("height", height)
56+
});
57+
58+
it("should have alternate src", () => {
59+
const srcDark = "src/dark";
60+
61+
const img = getRenderImg({srcDark})
62+
63+
expect(img).toHaveAttribute("src", srcDark)
64+
});
65+
})
66+
67+
describe("getLogoSrc", ()=>{
68+
const srcLight = "src/light",
69+
srcDark = "src/dark";
70+
71+
it("should be null if no image", () => {
72+
// @ts-ignore: invalid input
73+
expect(getLogoSrc(null,"")).toStrictEqual(undefined);
74+
// @ts-ignore: invalid input, calm down ts
75+
expect(getLogoSrc()).toStrictEqual(undefined);
76+
});
77+
78+
it("should be srcLight if no srcDark", () => {
79+
expect(getLogoSrc({src:srcLight, alt:""},"light")).toStrictEqual(srcLight);
80+
});
81+
82+
it("should be srcLight if mode is dark but no srcDark", () => {
83+
expect(getLogoSrc({src:srcLight, alt:""},"dark")).toStrictEqual(srcLight);
84+
});
85+
86+
it("should be srcLight if srcDark but mode light", () => {
87+
expect(getLogoSrc( {src: srcLight, srcDark: srcDark, alt:""},"light")).toStrictEqual(srcLight);
88+
});
89+
90+
it("should be srcDark if mode dark", () => {
91+
expect( getLogoSrc({src:"src/light", srcDark:srcDark, alt:""},"dark")).toStrictEqual(srcDark);
92+
});
93+
94+
})
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {useColorScheme} from "@mui/material";
2+
3+
type ImageColorSchemeSwitchType = {
4+
src: string,
5+
srcDark?: string,
6+
alt: string
7+
width?: string,
8+
height?: string,
9+
}
10+
11+
interface ImageColorSchemeSwitchProps {
12+
image: ImageColorSchemeSwitchType;
13+
}
14+
15+
export function getLogoSrc(image:ImageColorSchemeSwitchType, mode: string) {
16+
if( !image ) {
17+
return undefined;
18+
}
19+
20+
if( image.srcDark === undefined ) {
21+
return image.src;
22+
}
23+
24+
return mode === "dark" ? image.srcDark : image.src;
25+
}
26+
27+
const ImageColorSchemeSwitch = ({image}: ImageColorSchemeSwitchProps ) => {
28+
const {mode} = useColorScheme();
29+
if( !mode ) return <></>
30+
31+
const src: string | undefined = getLogoSrc(image, mode)
32+
33+
return <img
34+
src={src}
35+
alt={image.alt}
36+
width={image.width}
37+
height={image.height}
38+
/>
39+
}
40+
41+
export {ImageColorSchemeSwitch}
42+
export type {ImageColorSchemeSwitchProps, ImageColorSchemeSwitchType}

0 commit comments

Comments
 (0)