@rolemodel/optics 0.3.0 → 0.4.0

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.
@@ -1,36 +1,20 @@
1
1
  @mixin sidebar-rail-global {
2
2
  // Private API
3
3
  --__op-sidebar-width: var(--_op-sidebar-rail-width);
4
+ --__op-sidebar-brand-width: var(--_op-sidebar-rail-brand-width);
4
5
 
5
6
  // Elements
6
7
  .sidebar__content {
7
- gap: var(--_op-sidebar-link-spacing);
8
- }
9
-
10
- .sidebar__section-title,
11
- .sidebar__section-divider {
12
- display: none;
13
- }
14
-
15
- .sidebar__item {
16
- flex-direction: column;
17
- gap: var(--op-space-2x-small);
18
-
19
- .sidebar__item-icon {
20
- padding: var(--op-space-2x-small) var(--op-space-medium);
21
- transition: var(--_op-sidebar-transition);
22
- }
23
-
24
- &:hover .sidebar__item-icon {
25
- background-color: var(--_op-sidebar-icon-background-hover-color);
26
- }
27
-
28
- &.active .sidebar__item-icon {
29
- background-color: var(--_op-sidebar-icon-background-active-color);
30
- }
8
+ align-items: center;
31
9
 
32
- .sidebar__item-label {
33
- font-size: var(--op-font-x-small);
10
+ > * {
11
+ // Can't use extend but need to get icon behavior
12
+ width: var(--__op-btn-height);
13
+ min-width: var(--__op-btn-height);
14
+ justify-content: center;
15
+ padding: 0;
16
+ font-size: 0;
17
+ gap: 0;
34
18
  }
35
19
  }
36
20
  }
@@ -38,51 +22,21 @@
38
22
  @mixin sidebar-drawer-global {
39
23
  // Private API
40
24
  --__op-sidebar-width: var(--_op-sidebar-drawer-width);
25
+ --__op-sidebar-brand-width: var(--_op-sidebar-drawer-brand-width);
26
+ }
41
27
 
42
- .sidebar__content {
43
- padding: 0 var(--_op-sidebar-spacing);
44
- }
45
-
46
- .sidebar__section-title {
47
- overflow: hidden;
48
- height: var(--op-input-height-large);
49
- padding: var(--op-space-small) var(--op-space-medium);
50
- color: var(--_op-sidebar-text-color);
51
- font-size: var(--op-font-small);
52
- font-weight: var(--op-font-weight-bold);
53
- text-overflow: ellipsis;
54
- white-space: nowrap;
55
- }
56
-
57
- .sidebar__section-divider {
58
- border-bottom: var(--op-border-width) solid var(--_op-sidebar-text-color);
59
- margin: 0 var(--_op-sidebar-spacing);
60
- }
61
-
62
- .sidebar__item {
63
- height: var(--op-input-height-large);
64
- flex-direction: row;
65
- padding: var(--op-space-x-small) var(--op-space-medium);
66
- border-radius: var(--op-radius-pill);
67
- gap: var(--_op-sidebar-link-spacing);
68
-
69
- &:hover,
70
- &.active {
71
- transition: var(--_op-sidebar-transition);
72
- }
73
-
74
- &:hover {
75
- background-color: var(--_op-sidebar-icon-background-hover-color);
76
- color: var(--_op-sidebar-icon-text-hover-color);
77
-
78
- .sidebar__item-icon {
79
- color: var(--_op-sidebar-icon-text-hover-color);
80
- }
81
- }
28
+ @mixin sidebar-compact-global {
29
+ // Private API
30
+ --__op-sidebar-width: var(--_op-sidebar-compact-width);
31
+ --__op-sidebar-brand-width: var(--_op-sidebar-compact-brand-width);
82
32
 
83
- &.active {
84
- background-color: var(--_op-sidebar-icon-background-active-color);
85
- color: var(--_op-sidebar-icon-text-active-color);
33
+ // Elements
34
+ .sidebar__content {
35
+ > * {
36
+ // Can't use extend but need to get icon-with-label behavior
37
+ flex-direction: column;
38
+ padding: var(--op-space-small);
39
+ gap: var(--op-space-3x-small);
86
40
  }
87
41
  }
88
42
  }
@@ -90,51 +44,69 @@
90
44
  %sidebar-global {
91
45
  // Public API
92
46
  // Normal
93
- --_op-sidebar-background-color: var(--op-color-neutral-plus-seven);
94
- --_op-sidebar-text-color: var(--op-color-neutral-on-plus-seven);
95
-
96
- // Active
97
- --_op-sidebar-icon-background-active-color: var(--op-color-neutral-plus-three);
98
- --_op-sidebar-icon-text-active-color: var(--op-color-neutral-on-plus-three);
99
-
100
- // Hover
101
- --_op-sidebar-icon-background-hover-color: var(--op-color-neutral-plus-four);
102
- --_op-sidebar-icon-text-hover-color: var(--op-color-neutral-on-plus-four);
47
+ --_op-sidebar-background-color: var(--op-color-neutral-plus-eight);
48
+ --_op-sidebar-text-color: var(--op-color-neutral-on-plus-eight);
49
+ --_op-sidebar-border-color: var(--op-color-neutral-plus-four);
103
50
 
104
51
  // Width
105
52
  --_op-sidebar-rail-width: 8.8rem;
106
- --_op-sidebar-drawer-width: 25rem;
53
+ --_op-sidebar-compact-width: 16.9rem;
54
+ --_op-sidebar-drawer-width: 21.6rem;
55
+ --_op-sidebar-rail-brand-width: 7.728rem;
56
+ --_op-sidebar-compact-brand-width: 9.8rem;
57
+ --_op-sidebar-drawer-brand-width: 9.8rem;
107
58
 
108
59
  // Spacing
109
- --_op-sidebar-spacing: var(--op-space-medium);
110
- --_op-sidebar-link-spacing: var(--op-space-large);
60
+ --_op-sidebar-spacing: calc(var(--op-space-2x-large) + var(--op-space-2x-small));
61
+ --_op-sidebar-brand-spacing: var(--op-space-medium);
62
+ --_op-sidebar-content-spacing: var(--op-space-x-small);
63
+ --_op-sidebar-content-item-spacing: var(--op-space-2x-small);
111
64
 
112
65
  // Animation
113
66
  --_op-sidebar-transition: var(--op-transition-sidebar);
114
67
 
115
68
  // Private API
116
69
  --__op-sidebar-width: var(--_op-sidebar-drawer-width);
70
+ --__op-sidebar-brand-width: var(--_op-sidebar-drawer-brand-width);
117
71
 
118
72
  display: flex;
119
73
  width: var(--__op-sidebar-width);
74
+ min-width: var(--__op-sidebar-width);
120
75
  flex-direction: column;
121
- padding: var(--_op-sidebar-spacing) 0;
122
76
  background-color: var(--_op-sidebar-background-color);
77
+ box-shadow: var(--op-border-right) var(--_op-sidebar-border-color);
123
78
  color: var(--_op-sidebar-text-color);
124
- gap: var(--_op-sidebar-spacing);
125
79
  overflow-y: auto;
126
80
  transition: var(--_op-sidebar-transition);
127
81
 
128
82
  // Elements
129
83
  .sidebar__brand {
130
- display: block;
131
- padding: 0 var(--_op-sidebar-spacing);
84
+ height: var(--__op-sidebar-brand-width);
85
+ padding: var(--_op-sidebar-brand-spacing);
86
+ margin: 0 auto;
87
+
88
+ img {
89
+ height: 100%;
90
+ }
132
91
  }
133
92
 
134
93
  .sidebar__content {
135
94
  display: flex;
136
95
  flex-direction: column;
137
96
  flex-grow: 1;
97
+ padding: 0 var(--_op-sidebar-content-spacing);
98
+ gap: var(--_op-sidebar-content-item-spacing);
99
+
100
+ > * {
101
+ justify-content: flex-start;
102
+
103
+ .material-symbols-outlined {
104
+ /* stylelint-disable scss/at-extend-no-missing-placeholder */
105
+ @extend .icon--large;
106
+ @extend .icon--weight-bold;
107
+ /* stylelint-enable scss/at-extend-no-missing-placeholder */
108
+ }
109
+ }
138
110
 
139
111
  &.sidebar__content--start {
140
112
  justify-content: start;
@@ -149,61 +121,34 @@
149
121
  }
150
122
  }
151
123
 
152
- .sidebar__item {
153
- display: flex;
154
- align-items: center;
155
- color: var(--_op-sidebar-text-color);
156
- cursor: pointer;
157
- text-align: center;
158
- text-decoration: none;
159
-
160
- &:visited {
161
- color: var(--_op-sidebar-text-color);
162
- }
163
-
164
- &:hover,
165
- &.active {
166
- .sidebar__item-icon {
167
- --op-mso-weight: var(--op-font-weight-bold);
168
- }
169
- }
170
-
171
- &:hover .sidebar__item-icon {
172
- color: var(--_op-sidebar-text-color);
173
- }
174
-
175
- .sidebar__item-icon {
176
- /* stylelint-disable scss/at-extend-no-missing-placeholder */
177
- @extend .icon--x-large;
178
- /* stylelint-enable scss/at-extend-no-missing-placeholder */
124
+ // Modifiers
125
+ &.sidebar--padded {
126
+ padding: var(--_op-sidebar-spacing) 0;
127
+ }
179
128
 
180
- --op-mso-weight: var(--op-font-weight-medium);
129
+ // Drawer Modifier
130
+ &.sidebar--drawer:not(.sidebar--responsive) {
131
+ @include sidebar-drawer-global;
132
+ }
181
133
 
182
- display: flex;
183
- align-items: center;
184
- justify-content: center;
185
- border-radius: var(--op-radius-pill);
134
+ &.sidebar--drawer.sidebar--responsive {
135
+ @media (width > $breakpoint-medium) {
136
+ @include sidebar-drawer-global;
186
137
  }
187
138
 
188
- .sidebar__item-label {
189
- overflow: hidden;
190
- max-width: 90%;
191
- font-weight: var(--op-font-weight-medium);
192
- letter-spacing: var(--op-letter-spacing-navigation);
193
- line-height: var(--op-line-height-dense);
194
- text-overflow: ellipsis;
195
- white-space: nowrap;
139
+ @media (width <= $breakpoint-medium) {
140
+ @include sidebar-rail-global;
196
141
  }
197
142
  }
198
143
 
199
- // Modifiers
200
- &.sidebar--drawer:not(.sidebar--responsive) {
201
- @include sidebar-drawer-global;
144
+ // Compact Modifier
145
+ &.sidebar--compact:not(.sidebar--responsive) {
146
+ @include sidebar-compact-global;
202
147
  }
203
148
 
204
- &.sidebar--drawer.sidebar--responsive {
149
+ &.sidebar--compact.sidebar--responsive {
205
150
  @media (width > $breakpoint-medium) {
206
- @include sidebar-drawer-global;
151
+ @include sidebar-compact-global;
207
152
  }
208
153
 
209
154
  @media (width <= $breakpoint-medium) {
@@ -214,6 +159,10 @@
214
159
  &.sidebar--rail {
215
160
  @include sidebar-rail-global;
216
161
  }
162
+
163
+ &.sidebar--compact {
164
+ @include sidebar-compact-global;
165
+ }
217
166
  }
218
167
 
219
168
  .sidebar {
@@ -224,32 +173,7 @@
224
173
  .sidebar-primary {
225
174
  @extend %sidebar-global;
226
175
 
227
- // Normal
228
- --_op-sidebar-background-color: var(--op-color-primary-plus-seven);
229
- --_op-sidebar-text-color: var(--op-color-primary-on-plus-seven);
230
-
231
- // Active
232
- --_op-sidebar-icon-background-active-color: var(--op-color-primary-plus-three);
233
- --_op-sidebar-icon-text-active-color: var(--op-color-primary-on-plus-three);
234
-
235
- // Hover
236
- --_op-sidebar-icon-background-hover-color: var(--op-color-primary-plus-four);
237
- --_op-sidebar-icon-text-hover-color: var(--op-color-primary-on-plus-four);
238
- }
239
-
240
- // Subtle Primary
241
- .sidebar-subtle-primary {
242
- @extend %sidebar-global;
243
-
244
- // Normal
245
- --_op-sidebar-background-color: var(--op-color-primary-plus-max);
246
- --_op-sidebar-text-color: var(--op-color-primary-on-plus-max);
247
-
248
- // Active
249
- --_op-sidebar-icon-background-active-color: var(--op-color-primary-plus-three);
250
- --_op-sidebar-icon-text-active-color: var(--op-color-primary-on-plus-three);
251
-
252
- // Hover
253
- --_op-sidebar-icon-background-hover-color: var(--op-color-primary-plus-four);
254
- --_op-sidebar-icon-text-hover-color: var(--op-color-primary-on-plus-four);
176
+ --_op-sidebar-background-color: var(--op-color-primary-plus-six);
177
+ --_op-sidebar-text-color: var(--op-color-primary-on-plus-six);
178
+ --_op-sidebar-border-color: var(--op-color-primary-plus-four);
255
179
  }
@@ -2,14 +2,14 @@
2
2
 
3
3
  %table-global {
4
4
  // Public API
5
- // Cells (for padding, the appropriate variable is used when using the density modifiers)
6
- --_op-table-cell-padding-default: var(--op-space-small) var(--op-space-x-small);
7
- --_op-table-cell-padding-comfortable: var(--op-space-medium) var(--op-space-small);
8
- --_op-table-cell-padding-compact: var(--op-space-x-small) var(--op-space-2x-small);
5
+ // Cells (for height, the appropriate variable is used when using the density modifiers)
6
+ --_op-table-cell-height-default: calc(var(--op-space-scale-unit) * 4.4);
7
+ --_op-table-cell-height-comfortable: calc(var(--op-space-scale-unit) * 6.4);
8
+ --_op-table-cell-height-compact: calc(var(--op-space-scale-unit) * 3.4);
9
9
 
10
10
  // Private API
11
11
  // These allow for overriding specific padding versions easier.
12
- --__op-table-cell-padding: var(--_op-table-cell-padding-default);
12
+ --__op-table-cell-height: var(--_op-table-cell-height-default);
13
13
 
14
14
  width: 100%;
15
15
  border-radius: var(--op-radius-medium);
@@ -19,25 +19,32 @@
19
19
  table-layout: auto;
20
20
 
21
21
  thead {
22
- background-color: var(--op-color-neutral-plus-four);
23
- color: var(--op-color-neutral-on-plus-four);
22
+ background-color: var(--op-color-neutral-plus-eight);
23
+ box-shadow: inset var(--op-border-top) var(--op-border-color);
24
+ color: var(--op-color-neutral-on-plus-eight);
25
+
26
+ // This Currently does not work in Firefox since it does not support :has yet, but fails gracefully.
27
+ &:has(th input[type='checkbox']:checked) {
28
+ background-color: var(--op-color-primary-plus-seven);
29
+ color: var(--op-color-primary-on-plus-seven);
30
+ }
24
31
  }
25
32
 
26
33
  th {
27
- font-weight: var(--op-font-weight-normal);
34
+ font-weight: var(--op-font-weight-semi-bold);
28
35
  text-align: left;
29
- text-transform: uppercase;
30
36
  }
31
37
 
32
38
  tbody,
33
39
  tfoot {
34
- background-color: var(--op-color-background);
35
- color: var(--op-color-on-background);
40
+ background-color: var(--op-color-neutral-plus-max);
41
+ color: var(--op-color-neutral-on-plus-max);
36
42
  }
37
43
 
38
44
  th,
39
45
  td {
40
- padding: var(--__op-table-cell-padding);
46
+ height: var(--__op-table-cell-height);
47
+ padding: var(--op-space-2x-small) var(--op-space-small);
41
48
  font-size: var(--op-font-small);
42
49
  }
43
50
 
@@ -60,15 +67,15 @@
60
67
 
61
68
  // Table Density Modifiers
62
69
  &.table--default-density {
63
- --__op-table-cell-padding: var(--_op-table-cell-padding-default);
70
+ --__op-table-cell-height: var(--_op-table-cell-height-default);
64
71
  }
65
72
 
66
73
  &.table--comfortable-density {
67
- --__op-table-cell-padding: var(--_op-table-cell-padding-comfortable);
74
+ --__op-table-cell-height: var(--_op-table-cell-height-comfortable);
68
75
  }
69
76
 
70
77
  &.table--compact-density {
71
- --__op-table-cell-padding: var(--_op-table-cell-padding-compact);
78
+ --__op-table-cell-height: var(--_op-table-cell-height-compact);
72
79
  }
73
80
 
74
81
  // Striped Modifiers
@@ -194,8 +194,8 @@
194
194
  /**
195
195
  * @tokens Encoded Images
196
196
  */
197
- --op-form-dropdown-arrow-width: 1rem; // No way to string interpolate
198
- --op-form-dropdown-arrow: url("data:image/svg+xml,%3Csvg viewBox='0 0 10 7' version='1.1' xmlns='http://www.w3.org/2000/svg' width='10' height='7'%3E%3Cg transform='matrix(0.983953,0,0,1.00934,-9.22679,-3.65885)'%3E%3Cpath fill='%23d1d1d1' d='M9.37727 3.625l5.08154 6.93523L19.54036 3.625'/%3E%3C/g%3E%3C/svg%3E%0A");
197
+ --op-encoded-images-dropdown-arrow-width: var(--op-space-scale-unit); // No way to string interpolate
198
+ --op-encoded-images-dropdown-arrow: url("data:image/svg+xml,%3Csvg viewBox='0 0 10 7' version='1.1' xmlns='http://www.w3.org/2000/svg' width='10' height='7'%3E%3Cg transform='matrix(0.983953,0,0,1.00934,-9.22679,-3.65885)'%3E%3Cpath fill='%23d1d1d1' d='M9.37727 3.625l5.08154 6.93523L19.54036 3.625'/%3E%3C/g%3E%3C/svg%3E%0A");
199
199
  }
200
200
 
201
201
  @mixin fonts {
@@ -268,9 +268,14 @@
268
268
  * @tokens Input Focus
269
269
  * @presenter Shadow
270
270
  */
271
- --op-input-outer-focus: 0 0 0 var(--op-border-width-large) var(--op-color-primary-plus-four);
272
- --op-input-inner-focus: inset var(--op-border-all) var(--op-color-primary-minus-three);
273
- --op-input-focus: var(--op-input-inner-focus), var(--op-input-outer-focus);
271
+ --op-input-inner-focus: inset 0 0 0 var(--op-border-width-large);
272
+ --op-input-outer-focus: 0 0 0 var(--op-border-width-x-large);
273
+ --op-input-focus-primary: var(--op-input-inner-focus) var(--op-color-primary-plus-two),
274
+ var(--op-input-outer-focus) var(--op-color-primary-plus-five);
275
+ --op-input-focus-danger: var(--op-input-inner-focus) var(--op-color-alerts-danger-plus-two),
276
+ var(--op-input-outer-focus) var(--op-color-alerts-danger-plus-five);
277
+ --op-input-focus-warning: var(--op-input-inner-focus) var(--op-color-alerts-warning-plus-two),
278
+ var(--op-input-outer-focus) var(--op-color-alerts-warning-plus-five);
274
279
  }
275
280
 
276
281
  // We use SCSS variables outside the root since support for custom properties / css variables
@@ -627,9 +627,11 @@
627
627
  "animation": {
628
628
  "flash": "rm-slide-in-out-flash 5s normal forwards"
629
629
  },
630
- "form": {
631
- "dropdown": {
632
- "arrow": "url(\"data"
630
+ "encoded": {
631
+ "images": {
632
+ "dropdown": {
633
+ "arrow": "url(\"data"
634
+ }
633
635
  }
634
636
  },
635
637
  "space": {
@@ -670,13 +672,12 @@
670
672
  "x-large": "8.4rem"
671
673
  },
672
674
  "input": {
673
- "outer": {
674
- "focus": "0 0 0 var(--op-border-width-large) var(--op-color-primary-plus-four)"
675
- },
676
675
  "inner": {
677
- "focus": "inset var(--op-border-all) var(--op-color-primary-minus-three)"
676
+ "focus": "inset 0 0 0 var(--op-border-width-large)"
678
677
  },
679
- "focus": "var(--op-input-inner-focus), var(--op-input-outer-focus)"
678
+ "outer": {
679
+ "focus": "0 0 0 var(--op-border-width-x-large)"
680
+ }
680
681
  }
681
682
  }
682
683
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rolemodel/optics",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Optics is an scss package that provides base styles and components that can be integrated and customized in a variety of projects.",
5
5
  "main": "dist/scss/optics.scss",
6
6
  "scripts": {
@@ -9,15 +9,16 @@
9
9
  "build:css": "sass src/optics.scss dist/css/optics.css --load-path=node_modules/",
10
10
  "build:scss": "rsync -a src/ dist/scss --exclude stories",
11
11
  "build:tokens": "node build_token_json --source=src/core/tokens --output=dist/tokens/tokens.json",
12
- "storybook": "start-storybook -p 6006",
13
- "build-storybook": "build-storybook -o docs-build",
12
+ "storybook": "storybook dev -p 6006",
13
+ "build-storybook": "storybook build",
14
14
  "lint": "npm run lint:js && npm run lint:css",
15
15
  "lint-fix": "npm run lint:js --fix && npm run lint:css --fix",
16
16
  "lint:js": "eslint 'src/stories/**/*.js'",
17
17
  "lint:css": "stylelint 'src/**/*.(scss|css)'",
18
18
  "prettier": "prettier -w .",
19
19
  "prettier-check": "prettier -c .",
20
- "sanity-check": "npm run lint && npm run prettier && npm run build && npm run build-storybook && rm -rf ./dist && rm -rf ./docs-build"
20
+ "sanity-check": "npm run lint && npm run prettier && npm run build && npm run build-storybook && rm -rf ./dist && rm -rf ./storybook-static",
21
+ "generate": "node ./tools/generate.js"
21
22
  },
22
23
  "repository": {
23
24
  "type": "git",
@@ -45,32 +46,30 @@
45
46
  "tom-select": "^2.0.0"
46
47
  },
47
48
  "devDependencies": {
48
- "@babel/core": "^7.18.9",
49
- "@storybook/addon-actions": "^6.5.9",
50
- "@storybook/addon-docs": "^6.5.9",
51
- "@storybook/addon-essentials": "^6.5.9",
52
- "@storybook/addon-interactions": "^6.5.9",
53
- "@storybook/addon-links": "^6.5.9",
54
- "@storybook/addons": "^6.5.9",
55
- "@storybook/builder-webpack4": "^6.5.9",
56
- "@storybook/html": "^6.5.9",
57
- "@storybook/manager-webpack4": "^6.5.9",
58
- "@storybook/preset-scss": "^1.0.3",
59
- "@storybook/testing-library": "^0.0.13",
60
- "@storybook/theming": "^6.5.9",
61
- "babel-loader": "^8.2.5",
62
- "css-loader": "^5.2.7",
49
+ "@babel/preset-env": "^7.21.5",
50
+ "@storybook/addon-essentials": "^7.0.9",
51
+ "@storybook/addon-links": "^7.0.9",
52
+ "@storybook/addon-styling": "^1.0.6",
53
+ "@storybook/blocks": "^7.0.9",
54
+ "@storybook/html": "^7.0.9",
55
+ "@storybook/html-webpack5": "^7.0.9",
56
+ "@storybook/testing-library": "^0.0.14-next.2",
63
57
  "eslint": "^8.29.0",
64
58
  "eslint-config-prettier": "^8.5.0",
65
59
  "eslint-config-standard": "^17.0.0",
66
60
  "eslint-plugin-import": "^2.26.0",
67
61
  "eslint-plugin-n": "^15.6.0",
68
62
  "eslint-plugin-promise": "^6.1.1",
63
+ "eslint-plugin-storybook": "^0.6.12",
64
+ "generate-template-files": "^3.2.1",
69
65
  "postcss-scss": "^4.0.6",
70
66
  "prettier": "^2.8.1",
71
- "sass": "^1.53.0",
72
- "sass-loader": "^10.1.1",
73
- "storybook-design-token": "^2.9.0",
67
+ "react": "^18.2.0",
68
+ "react-dom": "^18.2.0",
69
+ "sass": "^1.62.1",
70
+ "sass-loader": "^13.2.2",
71
+ "storybook": "^7.0.9",
72
+ "storybook-design-token": "^3.0.0-beta.3",
74
73
  "style-loader": "^2.0.0",
75
74
  "stylelint": "^14.16.0",
76
75
  "stylelint-config-idiomatic-order": "^9.0.0",
@@ -1,98 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Button } from '@storybook/components'
3
-
4
- import { useGlobals } from '@storybook/api'
5
-
6
- // Destructuring like:
7
- // const [globals, setGlobals] = useGlobals()
8
- // or
9
- // setGlobals({ ...globals, themeMode: mode })
10
- // is not working so I had to work around it.
11
-
12
- const ModeButton = ({ children, mode, currentThemeMode, updateThemeMode }) => {
13
- const hoverState = useState(false)
14
- const hover = hoverState[0]
15
- const setHover = hoverState[1]
16
-
17
- const backgroundColor = () => {
18
- if (hover) {
19
- return 'rgba(30, 167, 253, 0.12)'
20
- }
21
- return currentThemeMode === mode ? 'rgba(30,167,253,0.07)' : 'transparent'
22
- }
23
-
24
- const textColor = () => {
25
- if (hover) {
26
- return '#1EA7FD'
27
- }
28
- return currentThemeMode === mode ? '#1EA7FD' : '#999'
29
- }
30
-
31
- const buttonStyles = (mode) => {
32
- return {
33
- borderRadius: 0,
34
- padding: 8,
35
- color: textColor(),
36
- backgroundColor: backgroundColor(),
37
- }
38
- }
39
-
40
- return (
41
- <Button
42
- onMouseEnter={() => setHover(true)}
43
- onMouseLeave={() => setHover(false)}
44
- style={buttonStyles(mode)}
45
- onClick={() => updateThemeMode(mode)}
46
- title={`Set canvas to ${mode} mode`}
47
- >
48
- {children}
49
- </Button>
50
- )
51
- }
52
-
53
- const ModeSwitcher = () => {
54
- const globalState = useGlobals()
55
- const globals = globalState[0]
56
- const setGlobals = globalState[1]
57
-
58
- const setCanvasDocumentThemeMode = (mode) => {
59
- const frame = document.getElementById('storybook-preview-iframe')
60
-
61
- if (frame) {
62
- const frameDocument = frame.contentWindow.document
63
- frameDocument.children[0].dataset.themeMode = mode
64
- }
65
- }
66
-
67
- const updateThemeMode = (mode) => {
68
- setCanvasDocumentThemeMode(mode)
69
- globals.themeMode = mode
70
- setGlobals(globals)
71
- }
72
-
73
- if (!globals.themeMode) {
74
- updateThemeMode('light')
75
- }
76
-
77
- const containerStyles = () => {
78
- return {
79
- border: '1px solid rgb(0 0 0 / 10%)',
80
- margin: 5,
81
- borderRadius: '3em',
82
- overflow: 'hidden',
83
- }
84
- }
85
-
86
- return (
87
- <div style={containerStyles()}>
88
- <ModeButton mode="light" currentThemeMode={globals.themeMode} updateThemeMode={updateThemeMode}>
89
- Light
90
- </ModeButton>
91
- <ModeButton mode="dark" currentThemeMode={globals.themeMode} updateThemeMode={updateThemeMode}>
92
- Dark
93
- </ModeButton>
94
- </div>
95
- )
96
- }
97
-
98
- export default ModeSwitcher