@stackoverflow/stacks 1.4.1 → 1.5.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,39 @@
1
- //
2
- // STACK OVERFLOW
3
- // SPINNER
4
- //
5
- // This CSS comes from Stacks, our CSS & Pattern library for rapidly building
6
- // Stack Overflow. For documentation of all these classes and how to contribute,
7
- // visit https://stackoverflow.design/
8
- //
9
- // TABLE OF CONTENTS
10
- // • BASE STYLE
11
- //
12
- // ============================================================================
13
- // $ SPINNER BASE STYLE
14
- // ----------------------------------------------------------------------------
15
-
16
1
  .s-spinner {
17
- position: relative;
18
- width: var(--su-static24);
19
- height: var(--su-static24);
20
- text-align: left; // When within a parent that has text-align: center, the spinner's entire container spins, not just the spinner. Let's force text-align left so things spin internally.
2
+ --_sp-baw: calc(var(--su-static1) * 3); // 3px
3
+ --_sp-size: var(--su-static24);
4
+
5
+ // MODIFIERS
6
+ &&__xs {
7
+ --_sp-baw: var(--su-static1);
8
+ --_sp-size: var(--su-static12);
9
+ }
10
+ &&__sm {
11
+ --_sp-baw: var(--su-static2);
12
+ --_sp-size: var(--su-static16);
13
+ }
14
+ &&__md {
15
+ --_sp-baw: var(--su-static4);
16
+ --_sp-size: var(--su-static32);
17
+ }
18
+ &&__lg {
19
+ --_sp-baw: var(--su-static6);
20
+ --_sp-size: var(--su-static48);
21
+ }
21
22
 
23
+ // CHILD ELEMENTS
22
24
  &:before,
23
25
  &:after {
26
+ border: var(--_sp-baw) solid currentColor;
27
+
28
+ border-radius: var(--br-circle);
24
29
  content: '';
30
+ height: 100%;
25
31
  position: absolute;
26
32
  width: 100%;
27
- height: 100%;
28
- border: 3px solid currentColor;
29
- border-radius: var(--br-circle);
30
33
  }
31
34
  &:before {
32
35
  opacity: 0.25;
33
- transform: rotate(90deg); // (*)
36
+ transform: rotate(90deg); // [1]
34
37
  }
35
38
  &:after {
36
39
  border-top-color: transparent;
@@ -39,99 +42,43 @@
39
42
  animation: s-spinner-rotate 0.9s infinite cubic-bezier(0.5, 0.1, 0.5, 0.9);
40
43
  }
41
44
 
42
- &.s-spinner__xs {
43
- width: var(--su-static12);
44
- height: var(--su-static12);
45
- &:before,
46
- &:after {
47
- border-width: 1px;
48
- }
49
- }
50
-
51
- &.s-spinner__sm {
52
- width: var(--su-static16);
53
- height: var(--su-static16);
54
- &:before,
55
- &:after {
56
- border-width: var(--su-static2);
57
- }
58
- }
59
-
60
- &.s-spinner__md {
61
- width: var(--su-static32);
62
- height: var(--su-static32);
63
- &:before,
64
- &:after {
65
- border-width: var(--su-static4);
66
- }
67
- }
68
-
69
- &.s-spinner__lg {
70
- width: var(--su-static48);
71
- height: var(--su-static48);
72
- &:before,
73
- &:after {
74
- border-width: var(--su-static6);
75
- }
76
- }
45
+ height: var(--_sp-size);
46
+ width: var(--_sp-size);
77
47
 
78
- // Cross-browser fixes. These are all practically no-ops, so we could just specify them
79
- // without browser hacks, but that would be punishing non-broken browsers with extra
80
- // unnecessary compositing work.
81
- &,
82
- &:before,
83
- &:after {
84
- // Safari: At least at 1dpp resolution, Safari crops the transformed elements
85
- // too aggressively, leading to a very visible flat edge part of the circle.
86
- // This invisible box shadow increases the area that the effects work on and thus
87
- // makes the circle round again.
88
- //
89
- // Targeting only Safari:
90
- // https://browserstrangeness.bitbucket.io/css_hacks.html#safari
91
- @media not all and (min-resolution: 0.001dpcm) {
92
- @supports (-webkit-appearance:none) and (stroke-color:transparent) {
93
- box-shadow: 0 0 0 2px transparent;
94
- }
95
- }
96
- }
48
+ position: relative;
49
+ text-align: left; // [2]
97
50
  }
98
51
 
99
52
  .is-loading {
100
- position: relative;
101
- padding-left: 2.2em;
53
+ --_li-offset: 0.6em;
54
+ --_il-size: 1.23076923em;
102
55
 
103
- &:before {
56
+ &:before,
57
+ &:after {
58
+ border-radius: var(--br-circle);
59
+ border-style: solid;
60
+ border-width: var(--su-static2);
104
61
  content: "";
62
+ height: var(--_il-size);
63
+ left: var(--_li-offset);
105
64
  position: absolute;
106
- opacity: 0.3;
107
- left: 0.6em;
108
- top: calc(50% - 0.6em);
109
- width: 1.23076923em;
110
- height: 1.23076923em;
111
- border-width: 2px;
112
- border-style: solid;
65
+ top: calc(50% - var(--_li-offset));
66
+ width: var(--_il-size);
67
+ }
68
+ &:before {
113
69
  border-color: currentColor;
114
- border-radius: var(--br-circle);
70
+ opacity: 0.3;
115
71
  }
116
-
117
72
  &:after {
118
- content: "";
119
- position: absolute;
120
- left: 0.6em;
121
- top: calc(50% - 0.6em);
122
- width: 1.23076923em;
123
- height: 1.23076923em;
124
- border-width: 2px;
125
- border-style: solid;
73
+ animation: s-spinner-rotate 0.9s infinite cubic-bezier(0.5, 0.1, 0.5, 0.9);
126
74
  border-color: transparent;
127
75
  border-left-color: currentColor;
128
- border-radius: var(--br-circle);
129
- animation: s-spinner-rotate 0.9s infinite
130
- cubic-bezier(0.5, 0.1, 0.5, 0.9);
131
- // see _stacks-spinner.less for an explanation of the following two
132
- filter: invert(0); // (*)
133
- transform-origin: 50% 50% 1px; // (*)
76
+ filter: invert(0); // [1]
77
+ transform-origin: 50% 50% 1px; // [1]
134
78
  }
79
+
80
+ padding-left: 2.2em;
81
+ position: relative;
135
82
  }
136
83
 
137
84
  // Keyframes
@@ -142,4 +89,7 @@
142
89
  to {
143
90
  transform: rotate(360deg);
144
91
  }
145
- }
92
+ }
93
+
94
+ // [1] no-op to reduce wobble in Edge. More info: https://github.com/StackExchange/Stacks/blob/d2af26aca06c47e3f1f7a638e49b221a9e28e450/lib/css/components/_stacks-spinner.less#L16-L26
95
+ // [2] When within a parent that has text-align: center, the spinner's entire container spins, not just the spinner. Let's force text-align left so things spin internally.
@@ -23,6 +23,23 @@
23
23
  text-decoration: none;
24
24
  });
25
25
 
26
+ // STATES
27
+ &.is-selected {
28
+ &,
29
+ a&,
30
+ a&:active,
31
+ a&:hover,
32
+ a&:focus {
33
+ background-color: var(--_ta-bg-selected);
34
+ border-color: var(--_ta-bc-selected);
35
+ color: var(--_ta-fc-selected);
36
+
37
+ .highcontrast-mode({
38
+ border-color: currentColor;
39
+ });
40
+ }
41
+ }
42
+
26
43
  // MODIFIERS
27
44
  // Sizes
28
45
  &&__xs {
@@ -157,7 +174,6 @@
157
174
  max-width: calc(var(--su-static16) + var(--su-static2));
158
175
  }
159
176
 
160
-
161
177
  // INTERACTION
162
178
  a&:not(.is-selected) {
163
179
  &:hover,
@@ -172,22 +188,6 @@
172
188
  });
173
189
  }
174
190
  }
175
- // Selected
176
- &.is-selected {
177
- &,
178
- a&,
179
- a&:active,
180
- a&:hover,
181
- a&:focus {
182
- background-color: var(--_ta-bg-selected);
183
- border-color: var(--_ta-bc-selected);
184
- color: var(--_ta-fc-selected);
185
-
186
- .highcontrast-mode({
187
- border-color: currentColor;
188
- });
189
- }
190
- }
191
191
 
192
192
  background-color: var(--_ta-bg);
193
193
  border: var(--su-static1) solid var(--_ta-bc);
@@ -1,145 +1,94 @@
1
- //
2
- // STACK OVERFLOW
3
- // TOGGLE SWITCHES
4
- //
5
- // This CSS comes from Stacks, our CSS & Pattern library for rapidly building
6
- // Stack Overflow. For documentation of all these classes and how to contribute,
7
- // visit https://stackoverflow.design/
8
- //
9
- // ============================================================================
10
- // $ BASE STYLE
11
- // ----------------------------------------------------------------------------
12
1
  .s-toggle-switch {
13
- position: relative;
14
-
15
- input[type="checkbox"] {
16
- // Hide the checkbox underneath the .s-toggle-switch--indicator.
17
- margin: 0; // guard against production adding 5px of margin to these
18
- opacity: 0;
19
- position: absolute;
20
- left: 0;
21
- top: 0;
22
- width: 44px;
23
- height: 24px;
24
- cursor: pointer;
25
-
26
- + .s-toggle-switch--indicator {
27
- pointer-events: none;
28
- outline: 0;
29
- display: block;
30
- width: 44px;
31
- height: 24px;
32
- position: relative;
33
- background: var(--black-300);
34
- border-radius: 1000px;
35
- padding: 3px;
36
- transition: left 0.2s ease;
37
-
38
- &:after,
39
- &:before {
40
- position: relative;
41
- display: block;
42
- content: "";
43
- width: 50%;
44
- height: 100%;
45
- }
46
-
47
- &:after {
48
- left: 0;
49
- border-radius: 50%;
50
- background: @white;
51
- transition: left 0.1s ease;
52
-
53
- .highcontrast-mode({
54
- background: var(--white);
55
- });
56
- }
57
-
58
- &:before {
59
- display: none;
60
- }
61
- }
62
-
63
- &:checked + .s-toggle-switch--indicator {
64
- background: var(--green-400);
65
-
66
- &:after {
67
- left: 50%;
2
+ --_ts-bg: var(--black-300);
3
+ --_ts-bg-ps: left center;
4
+ --_ts-bs-color: transparent;
5
+ // multiple
6
+ --_ts-multiple-bg: unset;
7
+ --_ts-multiple-fc: var(--black-500);
8
+
9
+ // TODO split single and multiple toggle into two seperate components
10
+ &&__multiple {
11
+ input[type="radio"] {
12
+ &:checked {
13
+ + label {
14
+ &.s-toggle-switch--label-off {
15
+ --_ts-multiple-bg: var(--black-500);
16
+ --_ts-multiple-fc: var(--white);
17
+ .dark-mode({ --_ts-multiple-bg: var(--black-350); });
18
+ }
19
+ &:not(.s-toggle-switch--label-off) {
20
+ --_ts-multiple-bg: var(--green-400);
21
+ --_ts-multiple-fc: @white;
22
+ .highcontrast-mode({ --_ts-multiple-fc: var(--white); });
23
+ }
24
+ }
25
+ &:focus + label {
26
+ --_ts-bs-color: var(--focus-ring-success);
27
+ &.s-toggle-switch--label-off { --_ts-bs-color: var(--focus-ring-muted); }
28
+ }
68
29
  }
69
- }
70
-
71
- &:focus + .s-toggle-switch--indicator {
72
- box-shadow: 0 0 0 var(--su-static4) var(--focus-ring-muted);
73
- }
74
-
75
- &:checked:focus + .s-toggle-switch--indicator {
76
- box-shadow: 0 0 0 var(--su-static4) var(--focus-ring-success);
77
- }
78
- }
79
30
 
80
- &.s-toggle-switch__multiple {
81
- display: flex;
82
- align-items: stretch;
83
-
84
- // First hide the radio buttons
85
- input[type="radio"] {
86
- position: absolute;
87
31
  left: -999em;
88
- opacity: 0;
89
32
  margin: 0;
33
+ opacity: 0;
34
+ position: absolute;
90
35
  }
91
-
92
- // Next modifications to option cells
93
36
  label {
94
- // Style the base label
95
- width: 100%;
96
- margin: 0;
97
- padding: 0.5em 0.7em;
37
+ background-color: var(--_ts-multiple-bg);
38
+ box-shadow: 0 0 0 var(--su-static4) var(--_ts-bs-color);
39
+ color: var(--_ts-multiple-fc);
40
+
98
41
  border-radius: 1000px;
99
- color: var(--black-500);
42
+ cursor: pointer;
100
43
  font-size: var(--fs-body1);
101
44
  font-weight: 400;
102
45
  line-height: 1;
46
+ margin: 0;
47
+ padding: 0.5em 0.7em;
103
48
  text-align: center;
104
49
  white-space: nowrap;
105
- cursor: pointer;
106
-
50
+ width: 100%;
107
51
  -webkit-touch-callout: none;
108
52
  -webkit-user-select: none;
109
53
  user-select: none;
110
54
  }
111
55
 
112
- // If the input is selected, style its label accordingly.
113
- input[type="radio"]:checked {
114
- + label {
115
- &.s-toggle-switch--label-off {
116
- background-color: var(--black-500);
117
- color: var(--white);
118
-
119
- .dark-mode({
120
- background-color: var(--black-350);
121
- // color: var(--black);
122
- });
123
- }
56
+ align-items: stretch;
57
+ display: flex;
58
+ }
124
59
 
125
- // Color activated options green
126
- &:not(.s-toggle-switch--label-off) {
127
- background-color: var(--green-400);
128
- color: @white;
60
+ input[type="checkbox"], // TODO DEPRECATED: drop support for nested input[type="checkbox"]
61
+ input[type="checkbox"]& {
62
+ &:checked {
63
+ --_ts-bg: var(--green-400);
64
+ --_ts-bg-ps: right center;
129
65
 
130
- .highcontrast-mode({
131
- color: var(--white);
132
- });
133
- }
66
+ &:focus {
67
+ --_ts-bs-color: var(--focus-ring-success);
134
68
  }
69
+ }
70
+ &:focus {
71
+ --_ts-bs-color: var(--focus-ring-muted);
72
+ outline: none;
73
+ }
74
+ &[disabled] {
75
+ cursor: default;
76
+ }
135
77
 
136
- &:focus + label.s-toggle-switch--label-off {
137
- box-shadow: 0 0 0 var(--su-static4) var(--focus-ring-muted);
138
- }
78
+ background-color: var(--_ts-bg);
79
+ background-position: var(--_ts-bg-ps);
80
+ box-shadow: 0 0 0 var(--su-static4) var(--_ts-bs-color);
139
81
 
140
- &:focus + label:not(.s-toggle-switch--label-off) {
141
- box-shadow: 0 0 0 var(--su-static4) var(--focus-ring-success);
142
- }
143
- }
82
+ appearance: none;
83
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); // The white dot within the toggle
84
+ background-size: contain;
85
+ background-repeat: no-repeat;
86
+ border-radius: 1000px;
87
+ cursor: pointer;
88
+ height: var(--su-static24);
89
+ margin: 0; // guard against production adding 5px of margin to these
90
+ transition: background-position 0.2s ease;
91
+ vertical-align: top;
92
+ width: calc(var(--su-static48) - var(--su-static4));
144
93
  }
145
94
  }
@@ -1,28 +1,20 @@
1
- //
2
- // STACK OVERFLOW
3
- // FILE UPLOAD -- DYNAMIC PARTS
4
- //
5
- // This CSS comes from Stacks, our CSS & Pattern library for rapidly building
6
- // Stack Overflow. For documentation of all these classes and how to contribute,
7
- // visit https://stackoverflow.design/
8
-
9
1
  .s-uploader {
10
2
  --_up-bg: var(--black-025);
11
3
  --_up-bg-focus: var(--black-050);
12
4
  --_up-bg-bc: var(--black-150);
13
5
  --_up-focus-ring-color: var(--focus-ring);
14
- // Static custom properties (not redefined but repeated enough to warrant a custom property)
15
6
  --_up-bg-b-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='5' ry='5' stroke='%23000000' stroke-width='8' stroke-dasharray='7%2c 22' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e");
16
7
 
8
+ // CONTEXTUAL STYLES
17
9
  .highcontrast-mode({ --_up-bg-bc-hc: var(--black-400); });
18
10
 
19
- // MODIFIERS
20
- &.is-active {
21
- --_up-bg: var(--black-050);
22
- --_up-bg-bc: var(--black-200);
23
- }
24
- &.is-disabled {
25
- opacity: var(--_o-disabled-static);
11
+ // STATES
12
+ &.has-error,
13
+ &.has-success,
14
+ &.has-warning {
15
+ .s-link {
16
+ color: var(--_up-link-fc);
17
+ }
26
18
  }
27
19
  &.has-error {
28
20
  --_up-bg: var(--red-050);
@@ -48,21 +40,28 @@
48
40
  --_up-focus-ring-color: var(--focus-ring-warning);
49
41
  --_up-link-fc: var(--yellow-900);
50
42
  }
51
- &.has-error,
52
- &.has-success,
53
- &.has-warning {
54
- .s-link {
55
- color: var(--_up-link-fc);
56
- }
43
+ &.is-active {
44
+ --_up-bg: var(--black-050);
45
+ --_up-bg-bc: var(--black-200);
46
+ }
47
+ &.is-disabled {
48
+ opacity: var(--_o-disabled-static);
57
49
  }
58
50
 
51
+
59
52
  // CHILD ELEMENTS
60
- // This is for safari shadow DOM
61
- // see https://github.com/StackExchange/Stacks/pull/690#issuecomment-861028193
62
- input[type="file"]::file-selector-button {
63
- cursor: pointer;
64
- }
65
53
  & &--container {
54
+ &:before { // Add the dashed border as an SVG background mask
55
+ -webkit-mask-image: var(--_up-bg-b-image);
56
+ mask-image: var(--_up-bg-b-image);
57
+ background-color: var(--_up-bg-bc-hc-state, var(--_up-bg-bc-hc, var(--_up-bg-bc)));
58
+ content: '';
59
+ border-radius: var(--br-lg);
60
+ display: block;
61
+ position: absolute;
62
+ inset: 0;
63
+ }
64
+
66
65
  align-items: center;
67
66
  background-color: var(--_up-bg);
68
67
  border-radius: var(--br-lg);
@@ -73,20 +72,13 @@
73
72
  padding: var(--su8) var(--su16);
74
73
  position: relative;
75
74
  text-align: center;
76
-
77
- // Add the dashed border as an SVG background mask
78
- &:before {
79
- -webkit-mask-image: var(--_up-bg-b-image);
80
- mask-image: var(--_up-bg-b-image);
81
- background-color: var(--_up-bg-bc-hc-state, var(--_up-bg-bc-hc, var(--_up-bg-bc)));
82
- content: '';
83
- border-radius: var(--br-lg);
84
- display: block;
85
- position: absolute;
86
- inset: 0;
87
- }
88
75
  }
89
76
  & &--input {
77
+ &:focus:focus-visible + .s-uploader--container {
78
+ background-color: var(--_up-bg-focus);
79
+ box-shadow: 0 0 0 var(--su-static4) var(--_up-focus-ring-color);
80
+ }
81
+
90
82
  cursor: pointer;
91
83
  height: 100%;
92
84
  inset: 0;
@@ -94,26 +86,12 @@
94
86
  position: absolute;
95
87
  width: 100%;
96
88
  z-index: var(--zi-selected);
97
-
98
- &:focus:focus-visible + .s-uploader--container {
99
- background-color: var(--_up-bg-focus);
100
- box-shadow: 0 0 0 var(--su-static4) var(--_up-focus-ring-color);
101
- }
102
89
  }
103
90
  & &--preview {
104
91
  max-width: 100%;
105
92
  pointer-events: none;
106
93
  }
107
94
  & &--preview-thumbnail {
108
- background-color: var(--white);
109
- border-radius: var(--br-sm);
110
- box-shadow: var(--bs-md);
111
- max-height: var(--su-static128);
112
- max-width: 100%;
113
- overflow: hidden;
114
- text-overflow: ellipsis;
115
- white-space: nowrap;
116
-
117
95
  .highcontrast-mode({ border: 1px solid var(--black); });
118
96
 
119
97
  &:is(img) {
@@ -124,11 +102,17 @@
124
102
  &:not(img) {
125
103
  padding: var(--su16);
126
104
  }
105
+
106
+ background-color: var(--white);
107
+ border-radius: var(--br-sm);
108
+ box-shadow: var(--bs-md);
109
+ max-height: var(--su-static128);
110
+ max-width: 100%;
111
+ overflow: hidden;
112
+ text-overflow: ellipsis;
113
+ white-space: nowrap;
127
114
  }
128
115
  & &--previews {
129
- max-width: 100%;
130
- text-align: left;
131
-
132
116
  &.has-multiple {
133
117
  display: block;
134
118
  height: auto;
@@ -151,7 +135,6 @@
151
135
  white-space: nowrap;
152
136
  }
153
137
  }
154
-
155
138
  .s-uploader--preview-thumbnail {
156
139
  color: transparent;
157
140
  height: var(--su-static32);
@@ -168,6 +151,9 @@
168
151
  }
169
152
  }
170
153
  }
154
+
155
+ max-width: 100%;
156
+ text-align: left;
171
157
  }
172
158
  & &--previews-heading {
173
159
  color: var(--black-900);
@@ -181,6 +167,11 @@
181
167
  top: var(--su8);
182
168
  z-index: var(--zi-active);
183
169
  }
170
+ // This is for safari shadow DOM
171
+ // see https://github.com/StackExchange/Stacks/pull/690#issuecomment-861028193
172
+ input[type="file"]::file-selector-button {
173
+ cursor: pointer;
174
+ }
184
175
 
185
176
  position: relative;
186
177
  }