Skip to content

Commit a4018e9

Browse files
authored
Feature/Refactor theming to use CSS variables (#159)
* Fix linting error * Add local request mocks * Add theme CSS variables * Fix logic error in ResultGroupRow * Transform all js theme variables to CSS variables * Fix up the tests * Clean up * Remove old theme file and fix injecting theme to plugins * Fix plugin dev env * Add border-radius to theme * Add variable for page background * Add more component variables for theming * Add variables to input label and result group last cell * Add more CSS variables to various component * Add line element variable * Update border variables * Fix up page streching too wide * Add variable for runwarning * Add variables to sticky header * Add theming to timeline and taskview * Improve font size theming and add new variables
1 parent 6f2f34a commit a4018e9

File tree

126 files changed

+1776
-1183
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+1776
-1183
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,7 @@ yarn-error.log*
2727
# Ignore plugins in development
2828
/plugin-api/dev/plugins/*
2929
# except dev-plugin which is used as example
30-
!/plugin-api/dev/plugins/dev-plugin
30+
!/plugin-api/dev/plugins/dev-plugin
31+
32+
# Do not include mock service worker
33+
/public/mockServiceWorker.js

cypress.config.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ export default defineConfig({
66
framework: "create-react-app",
77
bundler: "webpack",
88
},
9-
specPattern: "**/*.test.cypress.{js,ts,jsx,tsx}"
9+
specPattern: "**/*.test.cypress.{js,ts,jsx,tsx}",
10+
},
11+
12+
e2e: {
13+
setupNodeEvents(on, config) {
14+
// implement node event listeners here
15+
},
1016
},
1117
});

docs/styles.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@ Styles are implemented with [styled-components](https://styled-components.com/).
44

55
## Theme
66

7-
The theme mostly includes colors and some component-specific styles. Colors should mostly be used from the theme e.g.
7+
Theming is implemented with CSS variables. You can implement your own theme by providing your own theme css file to index.html or editing existing theme and rebuilding the application.
88

99
```javascript
1010
import styled from 'styled-components';
1111

1212
const StyledElement = styled.div`
13-
background: ${(props) => props.theme.color.bg.dark};
13+
background: var(--color-bg-primary);
1414
`;
1515
```
1616

17-
- [Theme file](../src/theme/index.tsx)
18-
- [Theme type definition](../src/styled.d.ts)
17+
- [Theme file](../src/theme/theme.css)
1918

2019
## Notes
2120

package.json

+10-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"i18next": "^22.4.15",
99
"idb": "^7.1.1",
1010
"markdown-to-jsx": "^7.2.0",
11+
"msw": "^2.7.0",
1112
"polished": "^4.2.2",
1213
"query-string": "^6.13.1",
1314
"react": "^18.2.0",
@@ -27,6 +28,7 @@
2728
},
2829
"scripts": {
2930
"start": "cross-env DISABLE_NEW_JSX_TRANSFORM=true react-scripts start",
31+
"start-with-mocks": "cross-env DISABLE_NEW_JSX_TRANSFORM=true REACT_APP_ENABLE_MOCKS=true react-scripts start",
3032
"build": "cross-env DISABLE_NEW_JSX_TRANSFORM=true react-scripts build",
3133
"cypress:open": "cypress open",
3234
"cypress:run": "cypress run",
@@ -38,8 +40,9 @@
3840
"eject": "react-scripts eject",
3941
"format": "prettier --write src",
4042
"dev:plugin": "concurrently --kill-others --names \"PLUGIN-SERVE,DEV\" -c \"bgBlue.bold,bgMagenta.bold\" \"npm:dev-plugin-serve\" \"npm:dev-plugin-cypress\"",
41-
"dev-plugin-serve": "serve ./plugin-api",
42-
"dev-plugin-cypress": "cypress open-ct --config-file ./cypress.plugin-dev.config.ts"
43+
"dev-plugin-serve": "serve ./plugin-api -p 5000",
44+
"dev-plugin-cypress": "cypress open-ct --config-file ./cypress.plugin-dev.config.ts",
45+
"init-mocks": "msw init ./public --save"
4346
},
4447
"browserslist": {
4548
"production": [
@@ -87,5 +90,10 @@
8790
},
8891
"resolutions": {
8992
"@types/react": "^18.0.0"
93+
},
94+
"msw": {
95+
"workerDirectory": [
96+
"public"
97+
]
9098
}
9199
}

src/App.tsx

+30-34
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import React, { useEffect, useState } from 'react';
22
import { BrowserRouter as Router, Route } from 'react-router-dom';
33
import { QueryParamProvider } from 'use-query-params';
4-
import { ThemeProvider } from 'styled-components';
54
import { useTranslation } from 'react-i18next';
65

76
import Root from './pages/Root';
87

98
import GlobalStyle from './GlobalStyle';
109
import './theme/font/roboto.css';
11-
import theme from './theme';
1210

1311
import { Page } from './components/Structure';
1412
import AppBar from './components/AppBar';
@@ -42,38 +40,36 @@ const App: React.FC = () => {
4240
}, []);
4341

4442
return (
45-
<ThemeProvider theme={theme}>
46-
<ErrorBoundary message={t('error.application-error')}>
47-
<NotificationsProvider>
48-
<TimezoneProvider>
49-
<PluginsProvider>
50-
<LoggingProvider>
51-
<GlobalStyle />
52-
<Router basename={appBasePath}>
53-
<QueryParamProvider ReactRouterRoute={Route}>
54-
{flagsReceived ? (
55-
<>
56-
<TopNavPlugin />
57-
<Notifications />
58-
<Announcements />
59-
<AppBar />
60-
<Page>
61-
<Root />
62-
</Page>
63-
<Logger />
64-
</>
65-
) : (
66-
<FeatureFlagLoader />
67-
)}
68-
</QueryParamProvider>
69-
</Router>
70-
</LoggingProvider>
71-
<PluginRegisterSystem />
72-
</PluginsProvider>
73-
</TimezoneProvider>
74-
</NotificationsProvider>
75-
</ErrorBoundary>
76-
</ThemeProvider>
43+
<ErrorBoundary message={t('error.application-error')}>
44+
<NotificationsProvider>
45+
<TimezoneProvider>
46+
<PluginsProvider>
47+
<LoggingProvider>
48+
<GlobalStyle />
49+
<Router basename={appBasePath}>
50+
<QueryParamProvider ReactRouterRoute={Route}>
51+
{flagsReceived ? (
52+
<>
53+
<TopNavPlugin />
54+
<Notifications />
55+
<Announcements />
56+
<AppBar />
57+
<Page>
58+
<Root />
59+
</Page>
60+
<Logger />
61+
</>
62+
) : (
63+
<FeatureFlagLoader />
64+
)}
65+
</QueryParamProvider>
66+
</Router>
67+
</LoggingProvider>
68+
<PluginRegisterSystem />
69+
</PluginsProvider>
70+
</TimezoneProvider>
71+
</NotificationsProvider>
72+
</ErrorBoundary>
7773
);
7874
};
7975

src/GlobalStyle.tsx

+10-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createGlobalStyle, css } from 'styled-components';
22
import { normalize } from 'polished';
3+
import './theme/theme.css';
34

45
// Introduce global css as `css` ttl for prettier formatting
56
const globalCSS = css`
@@ -13,50 +14,35 @@ const globalCSS = css`
1314
}
1415
1516
body {
16-
font-family:
17-
'Roboto',
18-
-apple-system,
19-
BlinkMacSystemFont,
20-
'Segoe UI',
21-
'Roboto',
22-
'Oxygen',
23-
'Ubuntu',
24-
'Cantarell',
25-
'Fira Sans',
26-
'Droid Sans',
27-
'Helvetica Neue',
28-
sans-serif;
17+
font-family: var(--font-family-primary);
2918
-webkit-font-smoothing: antialiased;
3019
-moz-osx-font-smoothing: grayscale;
31-
color: ${(p) => p.theme.color.text.dark};
20+
color: var(--color-text-primary);
21+
background: var(--layout-color-bg);
3222
}
3323
3424
a {
35-
color: ${(p) => p.theme.color.text.blue};
36-
}
37-
38-
code {
39-
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
25+
color: var(--color-text-highlight);
4026
}
4127
4228
dt {
43-
font-weight: 600;
29+
font-weight: var(--font-weight-semibold);
4430
}
4531
4632
dd {
4733
margin-inline-start: 0;
4834
}
4935
5036
.muted {
51-
color: ${(p) => p.theme.color.text.light};
37+
color: var(--color-text-light);
5238
}
5339
5440
h1,
5541
h2,
5642
h3,
5743
h4,
5844
h5 {
59-
font-weight: 600;
45+
font-weight: var(--font-weight-semibold);
6046
}
6147
6248
* {
@@ -69,8 +55,8 @@ const globalCSS = css`
6955
}
7056
7157
code {
72-
font-family: 'RobotoMono', monospace;
73-
font-size: 0.75rem;
58+
font-family: var(--font-family-code);
59+
font-size: var(--font-size-4);
7460
}
7561
`;
7662

src/components/Announcement/__tests__/Announcement.test.cypress.tsx

+4-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import React from 'react';
22
import { mount } from '@cypress/react';
3-
import { ThemeProvider } from 'styled-components';
4-
import { BrowserRouter as Router, Route } from 'react-router-dom';
5-
import { QueryParamProvider } from 'use-query-params';
6-
import theme from '../../../theme';
73
import Announcements from '..';
84

95
import NotificationsResponse from '../../../../cypress/fixtures/notifications_response.json';
6+
import TestWrapper from '../../../utils/testing';
107

118
describe('Announcements test', () => {
129
it('Announcements basic', () => {
@@ -20,13 +17,9 @@ describe('Announcements test', () => {
2017
}).as('NotificationsMockData');
2118

2219
mount(
23-
<ThemeProvider theme={theme}>
24-
<Router>
25-
<QueryParamProvider ReactRouterRoute={Route}>
26-
<Announcements />
27-
</QueryParamProvider>
28-
</Router>
29-
</ThemeProvider>,
20+
<TestWrapper>
21+
<Announcements />
22+
</TestWrapper>,
3023
);
3124

3225
// test that the notifications are rendered correctly

src/components/Announcement/index.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,10 @@ const AnnouncementItemContainer = styled.div<{ type: NotificationType; open: boo
192192
text-align: left;
193193
margin: 0rem auto ${(p) => (p.last ? '2.5rem' : '1rem')};
194194
width: 100%;
195-
background: ${({ theme, type }) => theme.notification[type].bg};
196-
color: ${({ theme, type }) => theme.notification[type].fg};
195+
background: ${({ type }) => `var(--notification-${type}-bg, --notification-default-bg)`};
196+
color: ${({ type }) => `var(--notification-${type}-text-color, --notification-default-text-color)`};
197197
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.25);
198-
border-radius: 0.25rem;
198+
border-radius: var(--radius-primary);
199199
transition: opacity 0.25s;
200200
font-size: 1rem;
201201
line-height: 1.5rem;
@@ -204,7 +204,7 @@ const AnnouncementItemContainer = styled.div<{ type: NotificationType; open: boo
204204
align-items: center;
205205
206206
a {
207-
color: ${({ theme, type }) => theme.notification[type].fg};
207+
color: ${({ type }) => `var(--notification-${type}-text-color, --notification-default-text-color)`};
208208
}
209209
210210
img {
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
11
import React from 'react';
22
import { mount } from '@cypress/react';
3-
import { ThemeProvider } from 'styled-components';
4-
import { BrowserRouter as Router, Route } from 'react-router-dom';
5-
import { QueryParamProvider } from 'use-query-params';
6-
import theme from '../../../theme';
73
import AppBar from '..';
84
import { PluginsProvider } from '../../Plugins/PluginManager';
5+
import TestWrapper from '../../../utils/testing';
96

107
describe('AppBar test', () => {
118
it('AppBar basic', () => {
129
cy.viewport(1000, 600);
1310
mount(
14-
<ThemeProvider theme={theme}>
15-
<PluginsProvider>
16-
<Router>
17-
<QueryParamProvider ReactRouterRoute={Route}>
18-
<AppBar />
19-
</QueryParamProvider>
20-
</Router>
21-
</PluginsProvider>
22-
</ThemeProvider>,
11+
<PluginsProvider>
12+
<TestWrapper>
13+
<AppBar />
14+
</TestWrapper>
15+
</PluginsProvider>,
2316
);
2417
// test all of the AppBars child components render
2518
cy.get('[data-testid="page-logo-image"]').should('exist');
2619
cy.get('[data-testid="home-button"]').should('exist');
27-
cy.get('[data-testid="breadcrumb-button-container"]').should('exist');
20+
cy.get('[data-testid="breadcrumb-goto-input-inactive"]').should('exist');
2821
cy.get('[data-testid="helpmenu-toggle"]').should('exist');
2922
});
3023
});

src/components/AppBar/index.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,24 @@ export default AppBar;
4040
//
4141

4242
const Wrapper = styled.header`
43-
max-width: ${(p) => p.theme.layout.maxWidth}px;
43+
max-width: var(--layout-max-width);
4444
display: flex;
4545
align-items: center;
4646
justify-content: flex-start;
4747
position: sticky;
4848
top: 0;
4949
left: 0;
5050
right: 0;
51-
min-height: ${(p) => p.theme.layout.appbarHeight}rem;
51+
min-height: var(--layout-application-bar-height);
5252
margin: 0 auto;
53-
padding: ${(p) => p.theme.layout.pagePaddingY}rem ${(p) => p.theme.layout.pagePaddingX}rem;
54-
background: ${(p) => p.theme.color.bg.white};
53+
padding: var(--layout-page-padding-y) var(--layout-page-padding-x);
54+
background: var(--color-bg-primary);
5555
z-index: 999;
5656
flex-direction: column;
5757
`;
5858

5959
const Logo = styled.img`
60-
height: ${(p) => p.theme.layout.appbarLogoHeight}rem;
60+
height: var(--layout-application-bar-logo-height);
6161
`;
6262

6363
const LogoLink = styled(Link)`

0 commit comments

Comments
 (0)