shopify_app 12.0.0 → 17.2.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.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/ISSUE_TEMPLATE/bug-report.md +63 -0
  4. data/.github/ISSUE_TEMPLATE/config.yml +1 -0
  5. data/.github/ISSUE_TEMPLATE/feature-request.md +33 -0
  6. data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  7. data/.github/workflows/build.yml +41 -0
  8. data/.github/workflows/release.yml +24 -0
  9. data/.github/workflows/rubocop.yml +22 -0
  10. data/.gitignore +0 -2
  11. data/.rubocop.yml +14 -6
  12. data/CHANGELOG.md +180 -0
  13. data/CONTRIBUTING.md +76 -0
  14. data/Gemfile +5 -0
  15. data/Gemfile.lock +257 -0
  16. data/README.md +72 -487
  17. data/Rakefile +1 -0
  18. data/SECURITY.md +59 -0
  19. data/app/assets/images/storage_access.svg +1 -2
  20. data/app/assets/javascripts/shopify_app/itp_helper.js +6 -6
  21. data/app/assets/javascripts/shopify_app/storage_access.js +37 -7
  22. data/app/assets/javascripts/shopify_app/top_level_interaction.js +1 -1
  23. data/app/controllers/concerns/shopify_app/authenticated.rb +2 -1
  24. data/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb +26 -0
  25. data/app/controllers/concerns/shopify_app/require_known_shop.rb +39 -0
  26. data/app/controllers/concerns/shopify_app/shop_access_scopes_verification.rb +32 -0
  27. data/app/controllers/shopify_app/authenticated_controller.rb +1 -0
  28. data/app/controllers/shopify_app/callback_controller.rb +113 -23
  29. data/app/controllers/shopify_app/extension_verification_controller.rb +2 -7
  30. data/app/controllers/shopify_app/sessions_controller.rb +62 -14
  31. data/app/controllers/shopify_app/webhooks_controller.rb +6 -5
  32. data/app/views/shopify_app/partials/_button_styles.html.erb +41 -36
  33. data/app/views/shopify_app/partials/_card_styles.html.erb +3 -3
  34. data/app/views/shopify_app/partials/_empty_state_styles.html.erb +28 -59
  35. data/app/views/shopify_app/partials/_form_styles.html.erb +56 -0
  36. data/app/views/shopify_app/partials/_layout_styles.html.erb +16 -1
  37. data/app/views/shopify_app/partials/_typography_styles.html.erb +6 -6
  38. data/app/views/shopify_app/sessions/enable_cookies.html.erb +3 -8
  39. data/app/views/shopify_app/sessions/new.html.erb +38 -110
  40. data/app/views/shopify_app/sessions/request_storage_access.html.erb +2 -2
  41. data/app/views/shopify_app/sessions/top_level_interaction.html.erb +21 -22
  42. data/config/locales/de.yml +11 -11
  43. data/config/locales/fi.yml +1 -1
  44. data/config/locales/nl.yml +8 -8
  45. data/config/locales/pt-BR.yml +1 -1
  46. data/config/locales/th.yml +4 -4
  47. data/config/locales/vi.yml +22 -0
  48. data/config/locales/zh-CN.yml +1 -1
  49. data/config/routes.rb +1 -0
  50. data/docs/Quickstart.md +15 -87
  51. data/docs/Releasing.md +18 -14
  52. data/docs/Troubleshooting.md +129 -4
  53. data/docs/Upgrading.md +126 -0
  54. data/docs/shopify_app/authentication.md +124 -0
  55. data/docs/shopify_app/engine.md +82 -0
  56. data/docs/shopify_app/generators.md +127 -0
  57. data/docs/shopify_app/handling-access-scopes-changes.md +14 -0
  58. data/docs/shopify_app/script-tags.md +28 -0
  59. data/docs/shopify_app/session-repository.md +88 -0
  60. data/docs/shopify_app/testing.md +38 -0
  61. data/docs/shopify_app/webhooks.md +72 -0
  62. data/karma.conf.js +1 -1
  63. data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +5 -3
  64. data/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb +1 -0
  65. data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +2 -1
  66. data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +4 -8
  67. data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +5 -4
  68. data/lib/generators/shopify_app/add_webhook/templates/{webhook_job.rb → webhook_job.rb.tt} +5 -0
  69. data/lib/generators/shopify_app/app_proxy_controller/app_proxy_controller_generator.rb +4 -3
  70. data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb +3 -3
  71. data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_route.rb +10 -9
  72. data/lib/generators/shopify_app/authenticated_controller/authenticated_controller_generator.rb +1 -1
  73. data/lib/generators/shopify_app/controllers/controllers_generator.rb +2 -1
  74. data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +31 -3
  75. data/lib/generators/shopify_app/home_controller/templates/home_controller.rb +2 -0
  76. data/lib/generators/shopify_app/home_controller/templates/index.html.erb +66 -16
  77. data/lib/generators/shopify_app/home_controller/templates/unauthenticated_home_controller.rb +11 -0
  78. data/lib/generators/shopify_app/install/install_generator.rb +46 -11
  79. data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +1 -1
  80. data/lib/generators/shopify_app/install/templates/flash_messages.js +0 -2
  81. data/lib/generators/shopify_app/install/templates/omniauth.rb +3 -1
  82. data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +25 -0
  83. data/lib/generators/shopify_app/install/templates/shopify_provider.rb.tt +8 -0
  84. data/lib/generators/shopify_app/install/templates/user_agent.rb +2 -1
  85. data/lib/generators/shopify_app/products_controller/products_controller_generator.rb +19 -0
  86. data/lib/generators/shopify_app/products_controller/templates/products_controller.rb +8 -0
  87. data/lib/generators/shopify_app/routes/routes_generator.rb +1 -0
  88. data/lib/generators/shopify_app/routes/templates/routes.rb +10 -9
  89. data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +39 -7
  90. data/lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_scopes_column.erb +5 -0
  91. data/lib/generators/shopify_app/shop_model/templates/shop.rb +2 -1
  92. data/lib/generators/shopify_app/shopify_app_generator.rb +4 -3
  93. data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_access_scopes_column.erb +5 -0
  94. data/lib/generators/shopify_app/user_model/templates/user.rb +2 -1
  95. data/lib/generators/shopify_app/user_model/user_model_generator.rb +39 -7
  96. data/lib/generators/shopify_app/views/views_generator.rb +2 -1
  97. data/lib/shopify_app/access_scopes/noop_strategy.rb +13 -0
  98. data/lib/shopify_app/access_scopes/shop_strategy.rb +24 -0
  99. data/lib/shopify_app/access_scopes/user_strategy.rb +41 -0
  100. data/lib/shopify_app/configuration.rb +46 -11
  101. data/lib/shopify_app/controller_concerns/app_proxy_verification.rb +3 -3
  102. data/lib/shopify_app/controller_concerns/csrf_protection.rb +15 -0
  103. data/lib/shopify_app/controller_concerns/embedded_app.rb +3 -2
  104. data/lib/shopify_app/controller_concerns/localization.rb +1 -0
  105. data/lib/shopify_app/controller_concerns/login_protection.rb +105 -30
  106. data/lib/shopify_app/controller_concerns/payload_verification.rb +24 -0
  107. data/lib/shopify_app/controller_concerns/webhook_verification.rb +3 -18
  108. data/lib/shopify_app/engine.rb +27 -1
  109. data/lib/shopify_app/jobs/scripttags_manager_job.rb +1 -1
  110. data/lib/shopify_app/jobs/webhooks_manager_job.rb +1 -1
  111. data/lib/shopify_app/managers/scripttags_manager.rb +4 -3
  112. data/lib/shopify_app/managers/webhooks_manager.rb +4 -3
  113. data/lib/shopify_app/middleware/jwt_middleware.rb +42 -0
  114. data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +19 -45
  115. data/lib/shopify_app/omniauth/omniauth_configuration.rb +64 -0
  116. data/lib/shopify_app/session/in_memory_session_store.rb +7 -3
  117. data/lib/shopify_app/session/in_memory_shop_session_store.rb +16 -0
  118. data/lib/shopify_app/session/in_memory_user_session_store.rb +16 -0
  119. data/lib/shopify_app/session/jwt.rb +63 -0
  120. data/lib/shopify_app/session/null_user_session_store.rb +22 -0
  121. data/lib/shopify_app/session/session_repository.rb +36 -14
  122. data/lib/shopify_app/session/session_storage.rb +1 -10
  123. data/lib/shopify_app/session/shop_session_storage.rb +42 -0
  124. data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +58 -0
  125. data/lib/shopify_app/session/user_session_storage.rb +42 -0
  126. data/lib/shopify_app/session/user_session_storage_with_scopes.rb +58 -0
  127. data/lib/shopify_app/test_helpers/all.rb +2 -0
  128. data/lib/shopify_app/test_helpers/webhook_verification_helper.rb +17 -0
  129. data/lib/shopify_app/utils.rb +18 -5
  130. data/lib/shopify_app/version.rb +2 -1
  131. data/lib/shopify_app.rb +24 -5
  132. data/package.json +8 -9
  133. data/shopify_app.gemspec +15 -10
  134. data/translation.yml +1 -1
  135. data/yarn.lock +2120 -2168
  136. metadata +94 -20
  137. data/.github/ISSUE_TEMPLATE.md +0 -14
  138. data/.travis.yml +0 -27
  139. data/docs/install-on-dev-shop.png +0 -0
  140. data/docs/test-your-app.png +0 -0
  141. data/lib/generators/shopify_app/install/templates/shopify_app.rb +0 -15
  142. data/lib/generators/shopify_app/install/templates/shopify_provider.rb +0 -20
  143. data/lib/shopify_app/session/storage_strategies/shop_storage_strategy.rb +0 -23
  144. data/lib/shopify_app/session/storage_strategies/user_storage_strategy.rb +0 -24
  145. data/package-lock.json +0 -7224
@@ -2,19 +2,14 @@
2
2
 
3
3
  module ShopifyApp
4
4
  class ExtensionVerificationController < ActionController::Base
5
+ include ShopifyApp::PayloadVerification
5
6
  protect_from_forgery with: :null_session
6
7
  before_action :verify_request
7
8
 
8
9
  private
9
10
 
10
11
  def verify_request
11
- hmac_header = request.headers['HTTP_X_SHOPIFY_HMAC_SHA256']
12
- request_body = request.body.read
13
- secret = ShopifyApp.configuration.secret
14
- digest = OpenSSL::Digest.new('sha256')
15
-
16
- expected_hmac = Base64.strict_encode64(OpenSSL::HMAC.digest(digest, secret, request_body))
17
- head(:unauthorized) unless ActiveSupport::SecurityUtils.secure_compare(expected_hmac, hmac_header)
12
+ head(:unauthorized) unless hmac_valid?(request.body.read)
18
13
  end
19
14
  end
20
15
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  module ShopifyApp
2
- class SessionsController < ActionController::Base # rubocop:disable Metrics/ClassLength
3
+ class SessionsController < ActionController::Base
3
4
  include ShopifyApp::LoginProtection
4
5
 
5
6
  layout false, only: :new
7
+
6
8
  after_action only: [:new, :create] do |controller|
7
9
  controller.response.headers.except!('X-Frame-Options')
8
10
  end
@@ -16,30 +18,35 @@ module ShopifyApp
16
18
  end
17
19
 
18
20
  def enable_cookies
19
- return unless validate_shop
21
+ return unless validate_shop_presence
20
22
 
21
23
  render(:enable_cookies, layout: false, locals: {
22
24
  does_not_have_storage_access_url: top_level_interaction_path(
23
- shop: sanitized_shop_name
25
+ shop: sanitized_shop_name,
26
+ return_to: params[:return_to]
24
27
  ),
25
28
  has_storage_access_url: login_url_with_optional_shop(top_level: true),
26
- app_home_url: granted_storage_access_path(shop: sanitized_shop_name),
29
+ app_target_url: granted_storage_access_path(
30
+ shop: sanitized_shop_name,
31
+ return_to: params[:return_to]
32
+ ),
27
33
  current_shopify_domain: current_shopify_domain,
28
34
  })
29
35
  end
30
36
 
31
37
  def top_level_interaction
32
38
  @url = login_url_with_optional_shop(top_level: true)
33
- validate_shop
39
+ validate_shop_presence
34
40
  end
35
41
 
36
42
  def granted_storage_access
37
- return unless validate_shop
43
+ return unless validate_shop_presence
38
44
 
39
45
  session['shopify.granted_storage_access'] = true
40
46
 
41
- params = { shop: @shop }
42
- redirect_to("#{return_address}?#{params.to_query}")
47
+ copy_return_to_param_to_session
48
+
49
+ redirect_to(return_address_with_params({ shop: @shop }))
43
50
  end
44
51
 
45
52
  def destroy
@@ -54,7 +61,9 @@ module ShopifyApp
54
61
  return render_invalid_shop_error unless sanitized_shop_name.present?
55
62
  session['shopify.omniauth_params'] = { shop: sanitized_shop_name }
56
63
 
57
- session[:return_to] = params[:return_to] if params[:return_to]
64
+ copy_return_to_param_to_session
65
+
66
+ set_user_tokens_option
58
67
 
59
68
  if user_agent_can_partition_cookies
60
69
  authenticate_with_partitioning
@@ -83,7 +92,38 @@ module ShopifyApp
83
92
  end
84
93
  end
85
94
 
86
- def validate_shop
95
+ # Override shop_session_by_cookie from LoginProtection to bypass allow_cookie_authentication
96
+ # setting check because session cookies are justified at top level
97
+ def shop_session_by_cookie
98
+ return unless session[:shop_id].present?
99
+ ShopifyApp::SessionRepository.retrieve_shop_session(session[:shop_id])
100
+ end
101
+
102
+ # rubocop:disable Lint/SuppressedException
103
+ def set_user_tokens_option
104
+ current_shop_session = shop_session
105
+
106
+ if current_shop_session.blank?
107
+ session[:user_tokens] = false
108
+ return
109
+ end
110
+
111
+ session[:user_tokens] = ShopifyApp::SessionRepository.user_storage.present?
112
+
113
+ ShopifyAPI::Session.temp(
114
+ domain: current_shop_session.domain,
115
+ token: current_shop_session.token,
116
+ api_version: current_shop_session.api_version
117
+ ) do
118
+ ShopifyAPI::Metafield.find(:token_validity_bogus_check)
119
+ end
120
+ rescue ActiveResource::UnauthorizedAccess
121
+ session[:user_tokens] = false
122
+ rescue StandardError
123
+ end
124
+ # rubocop:enable Lint/SuppressedException
125
+
126
+ def validate_shop_presence
87
127
  @shop = sanitized_shop_name
88
128
  unless @shop
89
129
  render_invalid_shop_error
@@ -93,9 +133,13 @@ module ShopifyApp
93
133
  true
94
134
  end
95
135
 
136
+ def copy_return_to_param_to_session
137
+ session[:return_to] = RedirectSafely.make_safe(params[:return_to], '/') if params[:return_to]
138
+ end
139
+
96
140
  def render_invalid_shop_error
97
141
  flash[:error] = I18n.t('invalid_shop_url')
98
- redirect_to return_address
142
+ redirect_to(return_address)
99
143
  end
100
144
 
101
145
  def enable_cookie_access
@@ -106,7 +150,7 @@ module ShopifyApp
106
150
  end
107
151
 
108
152
  def authenticate_in_context
109
- redirect_to "#{main_app.root_path}auth/shopify"
153
+ redirect_to("#{main_app.root_path}auth/shopify")
110
154
  end
111
155
 
112
156
  def authenticate_at_top_level
@@ -133,10 +177,14 @@ module ShopifyApp
133
177
  layout: false,
134
178
  locals: {
135
179
  does_not_have_storage_access_url: top_level_interaction_path(
136
- shop: sanitized_shop_name
180
+ shop: sanitized_shop_name,
181
+ return_to: session[:return_to]
137
182
  ),
138
183
  has_storage_access_url: login_url_with_optional_shop(top_level: true),
139
- app_home_url: granted_storage_access_path(shop: sanitized_shop_name),
184
+ app_target_url: granted_storage_access_path(
185
+ shop: sanitized_shop_name,
186
+ return_to: session[:return_to]
187
+ ),
140
188
  current_shopify_domain: current_shopify_domain,
141
189
  }
142
190
  )
@@ -1,14 +1,15 @@
1
+ # frozen_string_literal: true
1
2
  module ShopifyApp
3
+ class MissingWebhookJobError < StandardError; end
4
+
2
5
  class WebhooksController < ActionController::Base
3
6
  include ShopifyApp::WebhookVerification
4
7
 
5
- class ShopifyApp::MissingWebhookJobError < StandardError; end
6
-
7
8
  def receive
8
9
  params.permit!
9
- job_args = {shop_domain: shop_domain, webhook: webhook_params.to_h}
10
+ job_args = { shop_domain: shop_domain, webhook: webhook_params.to_h }
10
11
  webhook_job_klass.perform_later(job_args)
11
- head :no_content
12
+ head(:ok)
12
13
  end
13
14
 
14
15
  private
@@ -18,7 +19,7 @@ module ShopifyApp
18
19
  end
19
20
 
20
21
  def webhook_job_klass
21
- webhook_job_klass_name.safe_constantize or raise ShopifyApp::MissingWebhookJobError
22
+ webhook_job_klass_name.safe_constantize || raise(ShopifyApp::MissingWebhookJobError)
22
23
  end
23
24
 
24
25
  def webhook_job_klass_name(type = webhook_type)
@@ -1,6 +1,5 @@
1
1
  <style>
2
2
  .Polaris-Button {
3
- fill:#637381;
4
3
  position:relative;
5
4
  display:-webkit-inline-box;
6
5
  display:-ms-inline-flexbox;
@@ -15,12 +14,14 @@
15
14
  min-width:3.6rem;
16
15
  margin:0;
17
16
  padding:0.7rem 1.6rem;
18
- background:linear-gradient(to bottom, white, #f9fafb);
19
- border:1px solid #c4cdd5;
20
- box-shadow:0 1px 0 0 rgba(22, 29, 37, 0.05);
21
- border-radius:3px;
17
+ background-color:#ffffff;
18
+ border:1px solid #babfc3;
19
+ border-top-color: #c9cccf;
20
+ border-bottom-color: #babfc4;
21
+ box-shadow:0 1px 0 0 rgba(0, 0, 0, 0.05);
22
+ border-radius:4px;
22
23
  line-height:1;
23
- color:#212b36;
24
+ color:#202223;
24
25
  text-align:center;
25
26
  cursor:pointer;
26
27
  -webkit-user-select:none;
@@ -29,30 +30,44 @@
29
30
  user-select:none;
30
31
  text-decoration:none;
31
32
  transition-property:background, border, box-shadow;
32
- transition-duration:200ms;
33
+ transition-duration:100ms;
33
34
  transition-timing-function:cubic-bezier(0.64, 0, 0.35, 1);
34
35
  }
35
36
 
36
37
  .Polaris-Button:hover {
37
- background:linear-gradient(to bottom, #f9fafb, #f4f6f8);
38
- border-color:#c4cdd5;
38
+ background-color:#f6f6f7;
39
39
  }
40
40
 
41
41
  .Polaris-Button:focus {
42
- border-color:#5c6ac4;
43
42
  outline:0;
44
- box-shadow:0 0 0 1px #5c6ac4;
43
+ }
44
+
45
+ .Polaris-Button:focus:after {
46
+ box-shadow:0 0 0 .2rem #448fff;
47
+ }
48
+
49
+ .Polaris-Button:after {
50
+ content:'';
51
+ position:absolute;
52
+ z-index:1;
53
+ top:-.2rem;
54
+ right:-.2rem;
55
+ bottom:-.2rem;
56
+ left:-.2rem;
57
+ display:block;
58
+ pointer-events:none;
59
+ box-shadow:0 0 0 -.2rem #448fff;
60
+ transition:box-shadow 100ms cubic-bezier(0.64, 0, 0.35, 1);
61
+ border-radius:5px;
45
62
  }
46
63
 
47
64
  .Polaris-Button:active {
48
- background:linear-gradient(to bottom, #f4f6f8, #f4f6f8);
49
- border-color:#c4cdd5;
50
- box-shadow:0 0 0 0 transparent, inset 0 1px 1px 0 rgba(99, 115, 129, 0.1), inset 0 1px 4px 0 rgba(99, 115, 129, 0.2);
65
+ background-color:#f1f2f3);
51
66
  }
52
67
 
53
68
  .Polaris-Button__Content {
54
- font-size:1.5rem;
55
- font-weight:400;
69
+ font-size:1.4rem;
70
+ font-weight:500;
56
71
  line-height:1.6rem;
57
72
  text-transform:initial;
58
73
  letter-spacing:initial;
@@ -70,35 +85,25 @@
70
85
  min-height:1px;
71
86
  }
72
87
 
73
- @media (min-width: 40em) {
74
- .Polaris-Button__Content {
75
- font-size:1.4rem;
76
- }
77
- }
78
-
79
88
  .Polaris-Button--primary {
80
- background:linear-gradient(to bottom, #6371c7, #5563c1);
81
- border-color:#3f4eae;
82
- box-shadow:inset 0 1px 0 0 #6774c8, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 0 0 transparent;
89
+ background-color:#008060;
90
+ border-color:transparent;
91
+ border-width:0;
83
92
  color:white;
84
- fill:white;
85
93
  }
86
94
 
87
95
  .Polaris-Button--primary:hover {
88
- background:linear-gradient(to bottom, #5c6ac4, #4959bd);
89
- border-color:#3f4eae;
96
+ background-color:#006e52;
97
+ border-color:transparent;
90
98
  color:white;
91
- text-decoration:none;
92
99
  }
93
100
 
94
- .Polaris-Button--primary:focus {
95
- border-color:#202e78;
96
- box-shadow:inset 0 1px 0 0 #6f7bcb, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 0 1px #202e78;
101
+ .Polaris-Button--primary:active {
102
+ background-color:#005e46;
103
+ border-color:transparent;
97
104
  }
98
105
 
99
- .Polaris-Button--primary:active {
100
- background:linear-gradient(to bottom, #3f4eae, #3f4eae);
101
- border-color:#38469b;
102
- box-shadow:inset 0 0 0 0 transparent, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 1px 0 #38469b;
106
+ .Polaris-Button--sizeLarge {
107
+ padding:1.1rem 2.4rem;
103
108
  }
104
109
  </style>
@@ -11,7 +11,7 @@
11
11
 
12
12
  @media (min-width: 30.625em) {
13
13
  .Polaris-Card {
14
- border-radius:3px;
14
+ border-radius:8px;
15
15
  }
16
16
  }
17
17
 
@@ -24,10 +24,10 @@
24
24
  }
25
25
 
26
26
  .Polaris-Card__Section + .Polaris-Card__Section {
27
- border-top:1px solid #dfe3e8;
27
+ border-top:.1rem solid #e4e5e7;
28
28
  }
29
29
 
30
30
  .Polaris-Card__Section--subdued {
31
- background-color:#f9fafb;
31
+ background-color:#fafbfb;
32
32
  }
33
33
  </style>
@@ -11,8 +11,8 @@
11
11
  -ms-flex-align:center;
12
12
  align-items:center;
13
13
  width:100%;
14
- margin:2rem auto 0 auto;
15
- padding:2rem 0;
14
+ margin:0 auto;
15
+ padding:2rem 0 6rem;
16
16
  max-width:99.8rem;
17
17
  }
18
18
 
@@ -24,33 +24,22 @@
24
24
  }
25
25
 
26
26
  .Polaris-EmptyState__Section {
27
- position:relative;
28
27
  display:-webkit-box;
29
28
  display:-ms-flexbox;
30
29
  display:flex;
31
30
  -webkit-box-orient:vertical;
32
- -webkit-box-direction:normal;
33
- -ms-flex-direction:column;
34
- flex-direction:column;
31
+ -webkit-box-direction:reverse;
32
+ -ms-flex-direction:column-reverse;
33
+ flex-direction:column-reverse;
35
34
  -webkit-box-flex:1;
36
35
  -ms-flex:1 1 auto;
37
36
  flex:1 1 auto;
37
+ -webkit-box-align:center;
38
+ -ms-flex-align:center;
39
+ align-items:center;
38
40
  width:100%;
39
41
  }
40
42
 
41
- @media (min-width: 46.5em) {
42
- .Polaris-EmptyState__Section {
43
- left:2rem;
44
- -webkit-box-orient:horizontal;
45
- -webkit-box-direction:normal;
46
- -ms-flex-direction:row;
47
- flex-direction:row;
48
- -webkit-box-align:center;
49
- -ms-flex-align:center;
50
- align-items:center;
51
- }
52
- }
53
-
54
43
  .Polaris-EmptyState__ImageContainer,
55
44
  .Polaris-EmptyState__DetailsContainer {
56
45
  -webkit-box-flex:1;
@@ -58,6 +47,7 @@
58
47
  flex:1 1 auto;
59
48
  padding:0;
60
49
  margin:0;
50
+ text-align:center;
61
51
  }
62
52
 
63
53
  @media (min-width: 46.5em) {
@@ -68,37 +58,32 @@
68
58
  }
69
59
  }
70
60
 
71
- @media (max-width: 30.625em) {
72
- .Polaris-EmptyState__ImageContainer,
73
- .Polaris-EmptyState__DetailsContainer {
74
- overflow-x:hidden;
75
- }
76
- }
77
-
78
61
  .Polaris-EmptyState__Details {
79
- position:relative;
80
- z-index:10;
81
- padding:0 1.6rem;
82
- width:33.6rem;
83
- }
84
-
85
- @media (min-width: 30.625em) {
86
- .Polaris-EmptyState__Details {
87
- padding:0;
88
- }
62
+ max-width:40rem;
63
+ display:-webkit-box;
64
+ display:-ms-flexbox;
65
+ display: flex;
66
+ -webkit-box-orient:vertical;
67
+ -webkit-box-direction:normal;
68
+ -ms-flex-direction:column;
69
+ flex-direction: column;
70
+ -webkit-box-align:center;
71
+ -ms-flex-align:center;
72
+ align-items: center;
89
73
  }
90
74
 
91
75
  .Polaris-EmptyState__Content {
92
- font-size:1.6rem;
76
+ margin-top: 1.6rem;
77
+ font-size:1.5rem;
93
78
  font-weight:400;
94
- line-height:2.4rem;
95
- color:#637381;
79
+ line-height:2rem;
80
+ color:#6d7175;
81
+ padding-bottom: .8rem;
96
82
  }
97
83
 
98
84
  @media (min-width: 40em) {
99
85
  .Polaris-EmptyState__Content {
100
- font-size:2rem;
101
- line-height:2.8rem;
86
+ font-size:1.4rem;
102
87
  }
103
88
  }
104
89
 
@@ -107,23 +92,7 @@
107
92
  }
108
93
 
109
94
  .Polaris-EmptyState__Image {
110
- display: none;
111
- }
112
-
113
- @media (min-width: 30.625em) {
114
- .Polaris-EmptyState__Image {
115
- display: block;
116
- margin-left:-60%;
117
- margin-top:-30%;
118
- width:200%;
119
- }
120
- }
121
-
122
- @media (min-width: 46.5em) {
123
- .Polaris-EmptyState__Image {
124
- margin-top:0;
125
- margin-left:-90%;
126
- width:200%;
127
- }
95
+ margin: 0;
96
+ width: auto;
128
97
  }
129
98
  </style>