Skip to content

Commit 7cb5198

Browse files
alan412lizlooney
andauthored
Pr colorblind theme (#151)
* First pass at colorblind themes * Change methods to look like functions * cleanup to reuse default blockly styles where it makes sense * Make menu more visible with light themes * if( -> if ( --------- Co-authored-by: Liz Looney <[email protected]>
1 parent 596a5c4 commit 7cb5198

File tree

11 files changed

+163
-159
lines changed

11 files changed

+163
-159
lines changed

package-lock.json

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

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
"@ant-design/icons": "^6.0.0",
88
"@ant-design/v5-patch-for-react-19": "^1.0.3",
99
"@blockly/theme-dark": "^8.0.1",
10+
"@blockly/theme-deuteranopia": "7.0.1",
11+
"@blockly/theme-tritanopia": "7.0.1",
12+
"@blockly/theme-highcontrast": "7.0.1",
1013
"@tailwindcss/postcss": "^4.1.10",
1114
"@types/react": "^19.0.2",
1215
"@types/react-dom": "^19.0.2",

src/blocks/mrc_class_method_def.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* @author [email protected] (Alan Smith)
2121
*/
2222
import * as Blockly from 'blockly';
23-
import { MRC_STYLE_CLASS_BLOCKS } from '../themes/styles';
23+
import { MRC_STYLE_FUNCTIONS } from '../themes/styles';
2424
import { createFieldNonEditableText } from '../fields/FieldNonEditableText'
2525
import { createFieldFlydown } from '../fields/field_flydown';
2626
import { Order } from 'blockly/python';
@@ -88,7 +88,7 @@ const CLASS_METHOD_DEF = {
8888
this.appendDummyInput("TITLE")
8989
.appendField('', 'NAME');
9090
this.setOutput(false);
91-
this.setStyle(MRC_STYLE_CLASS_BLOCKS);
91+
this.setStyle(MRC_STYLE_FUNCTIONS);
9292
this.appendStatementInput('STACK').appendField('');
9393
this.mrcParameters = [];
9494
this.setPreviousStatement(false);

src/reactComponents/BlocklyComponent.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
import * as React from 'react';
2222
import * as Blockly from 'blockly/core';
2323
import * as locale from 'blockly/msg/en';
24-
import * as MrcDarkTheme from '../themes/mrc_theme_dark';
25-
import * as MrcLightTheme from '../themes/mrc_theme_light';
24+
import { themes } from '../themes/mrc_themes';
2625
import {pluginInfo as HardwareConnectionsPluginInfo} from '../blocks/utils/connection_checker';
2726

2827
import 'blockly/blocks'; // Includes standard blocks like controls_if, logic_compare, etc.
@@ -80,14 +79,15 @@ const BlocklyComponent = React.forwardRef<BlocklyComponentType | null, BlocklyCo
8079
const workspaceRef = React.useRef<Blockly.WorkspaceSvg | null>(null);
8180

8281
const getBlocklyTheme = (): Blockly.Theme => {
83-
if (theme === 'dark' || theme === 'compact-dark') {
84-
return MrcDarkTheme.theme;
82+
const blocklyTheme = 'mrc_theme_' + theme.replace(/-/g, '_');
83+
// Find the theme by key
84+
const themeObj = themes.find(t => t.name === blocklyTheme);
85+
if (!themeObj) {
86+
throw new Error(`Theme not found: ${blocklyTheme}`);
8587
}
86-
if (theme === 'light' || theme === 'compact') {
87-
return MrcLightTheme.theme;
88-
}
89-
// Default to light theme if unknown
90-
return MrcLightTheme.theme;
88+
89+
// Return the corresponding Blockly theme
90+
return themeObj;
9191
};
9292

9393
/** Creates the Blockly workspace configuration object. */

src/reactComponents/CodeDisplay.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,12 @@ const COPY_ERROR_MESSAGE_PREFIX = 'Could not copy code: ';
5555
*/
5656
export default function CodeDisplay(props: CodeDisplayProps): React.JSX.Element {
5757
const syntaxHighligherFromTheme = (theme: string) => {
58-
switch (theme) {
59-
case 'dark':
60-
case 'compact-dark':
61-
return dracula;
62-
case 'light':
63-
case 'compact':
64-
return oneLight;
65-
default:
66-
return dracula; // Default to dracula if theme is unknown
58+
const isDarkTheme = theme.endsWith('-dark') || theme === 'dark';
59+
60+
if (isDarkTheme){
61+
return dracula
6762
}
63+
return oneLight
6864
}
6965

7066
const { token } = Antd.theme.useToken();
@@ -122,4 +118,4 @@ export default function CodeDisplay(props: CodeDisplayProps): React.JSX.Element
122118
{renderCodeBlock()}
123119
</Antd.Flex>
124120
);
125-
}
121+
}

src/reactComponents/ThemeModal.tsx

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
CheckOutlined,
1010
MoonOutlined,
1111
SunOutlined,
12-
DesktopOutlined,
1312
} from '@ant-design/icons';
1413

1514
export interface ThemeOption {
@@ -40,16 +39,28 @@ const THEME_OPTIONS: ThemeOption[] = [
4039
description: 'Easy on the eyes for low-light environments',
4140
},
4241
{
43-
key: 'compact',
44-
name: 'Compact Theme',
45-
icon: <DesktopOutlined />,
46-
description: 'More content in less space',
42+
key: 'tritanopia',
43+
name: 'Tritanopia Theme',
44+
icon: <SunOutlined />,
45+
description: 'Designed for those with Tritanopia color blindness',
46+
},
47+
{
48+
key: 'tritanopia-dark',
49+
name: 'Tritanopia Dark',
50+
icon: <MoonOutlined />,
51+
description: 'Dark theme for those with Tritanopia color blindness',
52+
},
53+
{
54+
key: 'deuteranopia',
55+
name: 'Deuteranopia Theme',
56+
icon: <SunOutlined />,
57+
description: 'Designed for those with Deuteranopia color blindness',
4758
},
4859
{
49-
key: 'compact-dark',
50-
name: 'Compact Dark',
51-
icon: <BgColorsOutlined />,
52-
description: 'Dark theme with compact layout',
60+
key: 'deuteranopia-dark',
61+
name: 'Deuteranopia Dark',
62+
icon: <MoonOutlined />,
63+
description: 'Dark theme for those with Deuteranopia color blindness',
5364
},
5465
];
5566

@@ -195,15 +206,16 @@ export default ThemeModal;
195206

196207
export const antdThemeFromString = (theme: string): Antd.ThemeConfig => {
197208
let compact = false;
209+
198210
if (theme == 'compact-dark') {
199211
compact = true;
200-
theme = 'dark';
201212
}
202213
else if (theme == 'compact') {
203214
compact = true;
204-
theme = 'light';
205215
}
206-
if (theme === 'dark') {
216+
const isDarkTheme = theme.endsWith('-dark') || theme === 'dark';
217+
218+
if (isDarkTheme) {
207219
return {
208220
algorithm: compact ? [Antd.theme.darkAlgorithm, Antd.theme.compactAlgorithm] : Antd.theme.darkAlgorithm,
209221
components: {
@@ -219,7 +231,7 @@ export const antdThemeFromString = (theme: string): Antd.ThemeConfig => {
219231
}
220232
}
221233
}
222-
else if (theme === 'light') {
234+
else {
223235
return {
224236
algorithm: compact ? [Antd.theme.defaultAlgorithm, Antd.theme.compactAlgorithm] : Antd.theme.defaultAlgorithm,
225237
components: {
@@ -230,10 +242,12 @@ export const antdThemeFromString = (theme: string): Antd.ThemeConfig => {
230242
triggerColor: '#000000',
231243
},
232244
Menu: {
245+
darkItemDisabledColor: '#cccccc',
233246
darkItemBg: '#ffffff',
234247
darkSubMenuItemBg: '#ffffff',
235-
darkItemColor: '#000000',
248+
darkItemColor: '#666666',
236249
darkItemSelectedColor: '#000000',
250+
darkItemHoverColor: '#000000',
237251
}
238252
}
239253
}

src/themes/external_themes.d.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/themes/mrc_theme_dark.ts

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/themes/mrc_theme_light.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/themes/mrc_themes.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import * as Blockly from 'blockly/core';
2+
3+
import DeuteranopiaTheme from '@blockly/theme-deuteranopia';
4+
import TritanopiaTheme from '@blockly/theme-tritanopia';
5+
import HighContrastTheme from '@blockly/theme-highcontrast';
6+
7+
import { add_mrc_styles } from './styles';
8+
9+
export const DARK_THEME_NAME = 'mrc_theme_dark';
10+
export const LIGHT_THEME_NAME = 'mrc_theme_light';
11+
export const DEUTERANOPIA_THEME_NAME = 'mrc_theme_deuteranopia';
12+
export const TRITANOPIA_THEME_NAME = 'mrc_theme_tritanopia';
13+
export const HIGHCONTRAST_THEME_NAME = 'mrc_theme_highcontrast';
14+
export const DEUTERANOPIA_DARK_THEME_NAME = 'mrc_theme_deuteranopia_dark';
15+
export const TRITANOPIA_DARK_THEME_NAME = 'mrc_theme_tritanopia_dark';
16+
export const HIGHCONTRAST_DARK_THEME_NAME = 'mrc_theme_highcontrast_dark';
17+
18+
const create_theme = function (name: string, base: Blockly.Theme, dark: boolean = false): Blockly.Theme {
19+
let newTheme = Blockly.Theme.defineTheme(name, {
20+
name: name,
21+
base: base,
22+
});
23+
if (dark) {
24+
// These all come from the Blockly Dark theme plugin at
25+
// https://github.com/google/blockly-samples/blob/master/plugins/theme-dark/src/index.ts
26+
newTheme.setComponentStyle('workspaceBackgroundColour', '#1e1e1e');
27+
newTheme.setComponentStyle('toolboxBackgroundColour', '#333');
28+
newTheme.setComponentStyle('toolboxForegroundColour', '#fff');
29+
newTheme.setComponentStyle('flyoutBackgroundColour', '#252526');
30+
newTheme.setComponentStyle('flyoutForegroundColour', '#ccc');
31+
newTheme.setComponentStyle('flyoutOpacity', 1);
32+
newTheme.setComponentStyle('scrollbarColour', '#797979');
33+
newTheme.setComponentStyle('insertionMarkerColour', '#fff');
34+
newTheme.setComponentStyle('insertionMarkerOpacity', 0.3);
35+
newTheme.setComponentStyle('scrollbarOpacity', 0.4);
36+
newTheme.setComponentStyle('cursorColour', '#d0d0d0');
37+
}
38+
return add_mrc_styles(newTheme);
39+
};
40+
41+
const create_themes = function (): Blockly.Theme[] {
42+
return [
43+
create_theme(DARK_THEME_NAME, Blockly.Themes.Classic, true),
44+
create_theme(LIGHT_THEME_NAME, Blockly.Themes.Classic),
45+
create_theme(DEUTERANOPIA_THEME_NAME, DeuteranopiaTheme),
46+
create_theme(TRITANOPIA_THEME_NAME, TritanopiaTheme),
47+
create_theme(HIGHCONTRAST_THEME_NAME, HighContrastTheme),
48+
create_theme(DEUTERANOPIA_DARK_THEME_NAME, DeuteranopiaTheme, true),
49+
create_theme(TRITANOPIA_DARK_THEME_NAME, TritanopiaTheme, true),
50+
create_theme(HIGHCONTRAST_DARK_THEME_NAME, HighContrastTheme, true),
51+
];
52+
};
53+
54+
export const themes = create_themes();

0 commit comments

Comments
 (0)