@dhis2-ui/css 10.16.1 → 10.16.3-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2-ui/css",
3
- "version": "10.16.1",
3
+ "version": "10.16.3-alpha.1",
4
4
  "description": "UI CSS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,13 +33,14 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@dhis2/prop-types": "^3.1.2",
36
- "@dhis2/ui-constants": "10.16.1",
36
+ "@dhis2/ui-constants": "10.16.3-alpha.1",
37
37
  "classnames": "^2.3.1",
38
38
  "prop-types": "^15.7.2"
39
39
  },
40
40
  "files": [
41
41
  "build",
42
- "types"
42
+ "types",
43
+ "src"
43
44
  ],
44
45
  "devDependencies": {
45
46
  "react": "^18.3.1",
@@ -0,0 +1,199 @@
1
+ import { theme } from '@dhis2/ui-constants'
2
+ import React from 'react'
3
+
4
+ const CssReset = () => (
5
+ <style jsx global>{`
6
+ html {
7
+ line-height: 1.15; /* 1 */
8
+ -webkit-text-size-adjust: 100%; /* 2 */
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ *,
13
+ *:before,
14
+ *:after {
15
+ font-family: ${theme.fonts};
16
+ box-sizing: inherit;
17
+ }
18
+
19
+ body {
20
+ margin: 0;
21
+ font-family: ${theme.fonts};
22
+ }
23
+
24
+ main {
25
+ display: block;
26
+ }
27
+
28
+ h1 {
29
+ font-size: 2em;
30
+ margin: 0.67em 0;
31
+ }
32
+
33
+ hr {
34
+ box-sizing: content-box; /* 1 */
35
+ height: 0; /* 1 */
36
+ overflow: visible; /* 2 */
37
+ }
38
+
39
+ pre {
40
+ font-family: monospace, monospace; /* 1 */
41
+ font-size: 1em; /* 2 */
42
+ }
43
+
44
+ a {
45
+ background-color: transparent;
46
+ }
47
+
48
+ abbr[title] {
49
+ border-bottom: none; /* 1 */
50
+ text-decoration: underline; /* 2 */
51
+ text-decoration: underline dotted; /* 2 */
52
+ }
53
+
54
+ b,
55
+ strong {
56
+ font-weight: bolder;
57
+ }
58
+
59
+ code,
60
+ kbd,
61
+ samp {
62
+ font-family: monospace, monospace; /* 1 */
63
+ font-size: 1em; /* 2 */
64
+ }
65
+
66
+ small {
67
+ font-size: 80%;
68
+ }
69
+
70
+ sub,
71
+ sup {
72
+ font-size: 75%;
73
+ line-height: 0;
74
+ position: relative;
75
+ vertical-align: baseline;
76
+ }
77
+
78
+ sub {
79
+ bottom: -0.25em;
80
+ }
81
+
82
+ sup {
83
+ top: -0.5em;
84
+ }
85
+
86
+ img {
87
+ border-style: none;
88
+ }
89
+
90
+ button,
91
+ input,
92
+ optgroup,
93
+ select,
94
+ textarea {
95
+ font-family: inherit; /* 1 */
96
+ font-size: 100%; /* 1 */
97
+ line-height: 1.15; /* 1 */
98
+ margin: 0; /* 2 */
99
+ }
100
+
101
+ button,
102
+ input {
103
+ /* 1 */
104
+ overflow: visible;
105
+ }
106
+
107
+ button,
108
+ select {
109
+ /* 1 */
110
+ text-transform: none;
111
+ }
112
+
113
+ button,
114
+ [type='button'],
115
+ [type='reset'],
116
+ [type='submit'] {
117
+ -webkit-appearance: button;
118
+ }
119
+
120
+ button::-moz-focus-inner,
121
+ [type='button']::-moz-focus-inner,
122
+ [type='reset']::-moz-focus-inner,
123
+ [type='submit']::-moz-focus-inner {
124
+ border-style: none;
125
+ padding: 0;
126
+ }
127
+
128
+ button:-moz-focusring,
129
+ [type='button']:-moz-focusring,
130
+ [type='reset']:-moz-focusring,
131
+ [type='submit']:-moz-focusring {
132
+ outline: 1px dotted ButtonText;
133
+ }
134
+
135
+ fieldset {
136
+ padding: 0.35em 0.75em 0.625em;
137
+ }
138
+
139
+ legend {
140
+ box-sizing: border-box; /* 1 */
141
+ color: inherit; /* 2 */
142
+ display: table; /* 1 */
143
+ max-width: 100%; /* 1 */
144
+ padding: 0; /* 3 */
145
+ white-space: normal; /* 1 */
146
+ }
147
+
148
+ progress {
149
+ vertical-align: baseline;
150
+ }
151
+
152
+ textarea {
153
+ overflow: auto;
154
+ }
155
+
156
+ [type='checkbox'],
157
+ [type='radio'] {
158
+ box-sizing: border-box; /* 1 */
159
+ padding: 0; /* 2 */
160
+ }
161
+
162
+ [type='number']::-webkit-inner-spin-button,
163
+ [type='number']::-webkit-outer-spin-button {
164
+ height: auto;
165
+ }
166
+
167
+ [type='search'] {
168
+ -webkit-appearance: textfield; /* 1 */
169
+ outline-offset: -2px; /* 2 */
170
+ }
171
+
172
+ [type='search']::-webkit-search-decoration {
173
+ -webkit-appearance: none;
174
+ }
175
+
176
+ ::-webkit-file-upload-button {
177
+ -webkit-appearance: button; /* 1 */
178
+ font: inherit; /* 2 */
179
+ }
180
+
181
+ details {
182
+ display: block;
183
+ }
184
+
185
+ summary {
186
+ display: list-item;
187
+ }
188
+
189
+ template {
190
+ display: none;
191
+ }
192
+
193
+ [hidden] {
194
+ display: none;
195
+ }
196
+ `}</style>
197
+ )
198
+
199
+ export { CssReset }
@@ -0,0 +1,43 @@
1
+ import React from 'react'
2
+ import { CssReset } from './index.js'
3
+
4
+ const description = `
5
+ A tool for adding a global normalization stylesheet into the DOM that applies DHIS2 styles.
6
+
7
+ - https://github.com/necolas/normalize.css
8
+ - https://www.paulirish.com/2012/box-sizing-border-box-ftw/
9
+
10
+ \`\`\`js
11
+ import { CssReset } from '@dhis2/ui'
12
+ \`\`\`
13
+ `
14
+
15
+ const App = ({ children }) => <div>{children}</div>
16
+
17
+ export default {
18
+ title: 'CSS Reset',
19
+ component: CssReset,
20
+ parameters: { docs: { description: { component: description } } },
21
+ }
22
+
23
+ export const Default = (args) => (
24
+ <App>
25
+ <CssReset {...args} />
26
+
27
+ <p>
28
+ The <code>CssReset</code> component injects a global normalization
29
+ stylesheet into the DOM that sets the DHIS2 application defaults.
30
+ </p>
31
+
32
+ <p>
33
+ This also sets the <code>font-family</code> on the <code>body</code>{' '}
34
+ element to the DHIS2 font, which allows it to trickle down to the
35
+ components as well.
36
+ </p>
37
+
38
+ <p>
39
+ Just include the component in your application, preferably as early
40
+ as possible to avoid FOUC.{' '}
41
+ </p>
42
+ </App>
43
+ )
@@ -0,0 +1 @@
1
+ export { CssReset } from './css-reset.js'
@@ -0,0 +1,43 @@
1
+ import React from 'react'
2
+ import { CssVariables } from './index.js'
3
+
4
+ export default { title: 'CssVariables' }
5
+ export const WithColors = () => (
6
+ <React.Fragment>
7
+ <CssVariables colors />
8
+ <div
9
+ id="custom"
10
+ style={{ backgroundColor: 'var(--colors-blue900)' }}
11
+ ></div>
12
+ </React.Fragment>
13
+ )
14
+ export const WithTheme = () => (
15
+ <React.Fragment>
16
+ <CssVariables theme />
17
+ <div
18
+ id="custom"
19
+ style={{ backgroundColor: 'var(--theme-primary900)' }}
20
+ ></div>
21
+ </React.Fragment>
22
+ )
23
+ export const WithLayers = () => (
24
+ <React.Fragment>
25
+ <CssVariables layers />
26
+ <div
27
+ id="custom"
28
+ style={{ zIndex: 'var(--layers-alert)', position: 'absolute' }}
29
+ ></div>
30
+ </React.Fragment>
31
+ )
32
+ export const WithSpacers = () => (
33
+ <React.Fragment>
34
+ <CssVariables spacers />
35
+ <div id="custom" style={{ margin: 'var(--spacers-dp4)' }}></div>
36
+ </React.Fragment>
37
+ )
38
+ export const WithElevations = () => (
39
+ <React.Fragment>
40
+ <CssVariables elevations />
41
+ <div id="custom" style={{ boxShadow: 'var(--elevations-e100)' }}></div>
42
+ </React.Fragment>
43
+ )
@@ -0,0 +1,53 @@
1
+ import * as theme from '@dhis2/ui-constants'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ const toPrefixedThemeSection = (themeSectionKey) =>
6
+ // eslint-disable-next-line import/namespace
7
+ Object.entries(theme[themeSectionKey]).reduce((prefixed, [key, value]) => {
8
+ prefixed[`${themeSectionKey}-${key}`] = value
9
+
10
+ return prefixed
11
+ }, {})
12
+
13
+ const toCustomPropertyString = (themeSection) =>
14
+ Object.entries(themeSection)
15
+ .map(([key, value]) => `--${key}: ${value};`)
16
+ .join('\n')
17
+
18
+ const CssVariables = ({
19
+ colors = false,
20
+ theme = false,
21
+ layers = false,
22
+ spacers = false,
23
+ elevations = false,
24
+ }) => {
25
+ const allowedProps = { colors, theme, layers, spacers, elevations }
26
+ const variables = Object.keys(allowedProps)
27
+ // Filter all props that are false
28
+ .filter((prop) => allowedProps[prop])
29
+ // Map props to corresponding theme section and prefixes keys with section name
30
+ .map(toPrefixedThemeSection)
31
+ // Map each section to a single string of css custom property declarations
32
+ .map(toCustomPropertyString)
33
+ // Join all the sections to a single string
34
+ .join('\n')
35
+
36
+ return (
37
+ <style jsx global>{`
38
+ html {
39
+ ${variables}
40
+ }
41
+ `}</style>
42
+ )
43
+ }
44
+
45
+ CssVariables.propTypes = {
46
+ colors: PropTypes.bool,
47
+ elevations: PropTypes.bool,
48
+ layers: PropTypes.bool,
49
+ spacers: PropTypes.bool,
50
+ theme: PropTypes.bool,
51
+ }
52
+
53
+ export { CssVariables }
@@ -0,0 +1,112 @@
1
+ import React from 'react'
2
+ import { CssVariables } from './index.js'
3
+
4
+ const description = `
5
+ A utility for adding DHIS2 theme variables to global CSS variables.
6
+
7
+ \`\`\`js
8
+ import { CssVariables } from '@dhis2/ui'
9
+ \`\`\`
10
+ `
11
+
12
+ const App = ({ children }) => <div>{children}</div>
13
+
14
+ export default {
15
+ title: 'CSS Variables',
16
+ component: CssVariables,
17
+ parameters: { docs: { description: { component: description } } },
18
+ }
19
+
20
+ export const AllVariables = (args) => (
21
+ <App>
22
+ <CssVariables {...args} />
23
+
24
+ <p>
25
+ The sections of the theme that should be inserted can be toggled
26
+ with flags, which allows the theme variables to be used as regular
27
+ CSS custom properties. So this{' '}
28
+ <span style={{ color: 'var(--colors-red500)' }}>text</span> uses the
29
+ vanilla CSS{' '}
30
+ <span style={{ color: 'var(--colors-blue500)' }}>
31
+ custom properties
32
+ </span>{' '}
33
+ set by the CssVariables component.
34
+ </p>
35
+ </App>
36
+ )
37
+ AllVariables.args = {
38
+ colors: true,
39
+ theme: true,
40
+ layers: true,
41
+ spacers: true,
42
+ elevations: true,
43
+ }
44
+
45
+ export const NoVariables = (args) => (
46
+ <App>
47
+ <CssVariables {...args} />
48
+
49
+ <p>By default no custom properties are inserted.</p>
50
+ </App>
51
+ )
52
+
53
+ export const Elevations = (args) => (
54
+ <App>
55
+ <CssVariables elevations {...args} />
56
+ <div
57
+ style={{
58
+ display: 'flex',
59
+ gap: '8px',
60
+ }}
61
+ >
62
+ <div
63
+ style={{
64
+ background: 'white',
65
+ boxShadow: 'var(--elevations-e100',
66
+ display: 'inline-block',
67
+ padding: '16px',
68
+ marginRight: '16px',
69
+ fontFamily: 'monospace',
70
+ }}
71
+ >
72
+ e100
73
+ </div>
74
+ <div
75
+ style={{
76
+ background: 'white',
77
+ boxShadow: 'var(--elevations-e200',
78
+ display: 'inline-block',
79
+ padding: '16px',
80
+ marginRight: '16px',
81
+ fontFamily: 'monospace',
82
+ }}
83
+ >
84
+ e200
85
+ </div>
86
+ <div
87
+ style={{
88
+ background: 'white',
89
+ boxShadow: 'var(--elevations-e300',
90
+ display: 'inline-block',
91
+ padding: '16px',
92
+ marginRight: '16px',
93
+ fontFamily: 'monospace',
94
+ }}
95
+ >
96
+ e300
97
+ </div>
98
+ <div
99
+ style={{
100
+ background: 'white',
101
+ boxShadow: 'var(--elevations-e400',
102
+ display: 'inline-block',
103
+ padding: '16px',
104
+ marginRight: '16px',
105
+ fontFamily: 'monospace',
106
+ }}
107
+ >
108
+ e400
109
+ </div>
110
+ </div>
111
+ </App>
112
+ )
@@ -0,0 +1,53 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a CssVariables component with colors flag is rendered', () => {
4
+ cy.visitStory('CssVariables', 'With colors')
5
+ })
6
+
7
+ Given('a CssVariables component with theme flag is rendered', () => {
8
+ cy.visitStory('CssVariables', 'With theme')
9
+ })
10
+
11
+ Given('a CssVariables component with layers flag is rendered', () => {
12
+ cy.visitStory('CssVariables', 'With layers')
13
+ })
14
+
15
+ Given('a CssVariables component with spacers flag is rendered', () => {
16
+ cy.visitStory('CssVariables', 'With spacers')
17
+ })
18
+
19
+ Given('a CssVariables component with elevations flag is rendered', () => {
20
+ cy.visitStory('CssVariables', 'With elevations')
21
+ })
22
+
23
+ Then('the colors css variables are set', () => {
24
+ cy.get('div#custom').should(
25
+ 'have.css',
26
+ 'background-color',
27
+ 'rgb(9, 51, 113)'
28
+ )
29
+ })
30
+
31
+ Then('the theme css variables are set', () => {
32
+ cy.get('div#custom').should(
33
+ 'have.css',
34
+ 'background-color',
35
+ 'rgb(9, 51, 113)'
36
+ )
37
+ })
38
+
39
+ Then('the layers css variables are set', () => {
40
+ cy.get('div#custom').should('have.css', 'z-index', '9999')
41
+ })
42
+
43
+ Then('the spacers css variables are set', () => {
44
+ cy.get('div#custom').should('have.css', 'margin', '4px')
45
+ })
46
+
47
+ Then('the elevations css variables are set', () => {
48
+ cy.get('div#custom').should(
49
+ 'have.css',
50
+ 'box-shadow',
51
+ 'rgba(33, 41, 52, 0.06) 0px 1px 2px 0px, rgba(33, 41, 52, 0.1) 0px 1px 3px 0px'
52
+ )
53
+ })
@@ -0,0 +1,21 @@
1
+ Feature: CssVariables sets css variables
2
+
3
+ Scenario: CssVariables with colors
4
+ Given a CssVariables component with colors flag is rendered
5
+ Then the colors css variables are set
6
+
7
+ Scenario: CssVariables with theme
8
+ Given a CssVariables component with theme flag is rendered
9
+ Then the theme css variables are set
10
+
11
+ Scenario: CssVariables with layers
12
+ Given a CssVariables component with layers flag is rendered
13
+ Then the layers css variables are set
14
+
15
+ Scenario: CssVariables with spacers
16
+ Given a CssVariables component with spacers flag is rendered
17
+ Then the spacers css variables are set
18
+
19
+ Scenario: CssVariables with elevations
20
+ Given a CssVariables component with elevations flag is rendered
21
+ Then the elevations css variables are set
@@ -0,0 +1 @@
1
+ export { CssVariables } from './css-variables.js'
package/src/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { CssReset } from './css-reset/index.js'
2
+ export { CssVariables } from './css-variables/index.js'