polaris_view_components 0.9.0 → 0.10.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.
@@ -2,6 +2,163 @@ import { Controller } from "@hotwired/stimulus";
2
2
 
3
3
  import { get } from "@rails/request.js";
4
4
 
5
+ const alpineNames = {
6
+ enterFromClass: "enter",
7
+ enterActiveClass: "enterStart",
8
+ enterToClass: "enterEnd",
9
+ leaveFromClass: "leave",
10
+ leaveActiveClass: "leaveStart",
11
+ leaveToClass: "leaveEnd"
12
+ };
13
+
14
+ const defaultOptions = {
15
+ transitioned: false,
16
+ hiddenClass: "hidden",
17
+ preserveOriginalClass: true,
18
+ removeToClasses: true
19
+ };
20
+
21
+ const useTransition = (controller, options = {}) => {
22
+ var _a, _b, _c;
23
+ const targetName = controller.element.dataset.transitionTarget;
24
+ let targetFromAttribute;
25
+ if (targetName) {
26
+ targetFromAttribute = controller[`${targetName}Target`];
27
+ }
28
+ const targetElement = (options === null || options === void 0 ? void 0 : options.element) || targetFromAttribute || controller.element;
29
+ if (!(targetElement instanceof HTMLElement || targetElement instanceof SVGElement)) return;
30
+ const dataset = targetElement.dataset;
31
+ const leaveAfter = parseInt(dataset.leaveAfter || "") || options.leaveAfter || 0;
32
+ const {transitioned: transitioned, hiddenClass: hiddenClass, preserveOriginalClass: preserveOriginalClass, removeToClasses: removeToClasses} = Object.assign(defaultOptions, options);
33
+ const controllerEnter = (_a = controller.enter) === null || _a === void 0 ? void 0 : _a.bind(controller);
34
+ const controllerLeave = (_b = controller.leave) === null || _b === void 0 ? void 0 : _b.bind(controller);
35
+ const controllerToggleTransition = (_c = controller.toggleTransition) === null || _c === void 0 ? void 0 : _c.bind(controller);
36
+ async function enter(event) {
37
+ if (controller.transitioned) return;
38
+ controller.transitioned = true;
39
+ controllerEnter && controllerEnter(event);
40
+ const enterFromClasses = getAttribute("enterFrom", options, dataset);
41
+ const enterActiveClasses = getAttribute("enterActive", options, dataset);
42
+ const enterToClasses = getAttribute("enterTo", options, dataset);
43
+ const leaveToClasses = getAttribute("leaveTo", options, dataset);
44
+ if (!!hiddenClass) {
45
+ targetElement.classList.remove(hiddenClass);
46
+ }
47
+ if (!removeToClasses) {
48
+ removeClasses(targetElement, leaveToClasses);
49
+ }
50
+ await transition(targetElement, enterFromClasses, enterActiveClasses, enterToClasses, hiddenClass, preserveOriginalClass, removeToClasses);
51
+ if (leaveAfter > 0) {
52
+ setTimeout((() => {
53
+ leave(event);
54
+ }), leaveAfter);
55
+ }
56
+ }
57
+ async function leave(event) {
58
+ if (!controller.transitioned) return;
59
+ controller.transitioned = false;
60
+ controllerLeave && controllerLeave(event);
61
+ const leaveFromClasses = getAttribute("leaveFrom", options, dataset);
62
+ const leaveActiveClasses = getAttribute("leaveActive", options, dataset);
63
+ const leaveToClasses = getAttribute("leaveTo", options, dataset);
64
+ const enterToClasses = getAttribute("enterTo", options, dataset);
65
+ if (!removeToClasses) {
66
+ removeClasses(targetElement, enterToClasses);
67
+ }
68
+ await transition(targetElement, leaveFromClasses, leaveActiveClasses, leaveToClasses, hiddenClass, preserveOriginalClass, removeToClasses);
69
+ if (!!hiddenClass) {
70
+ targetElement.classList.add(hiddenClass);
71
+ }
72
+ }
73
+ function toggleTransition(event) {
74
+ controllerToggleTransition && controllerToggleTransition(event);
75
+ if (controller.transitioned) {
76
+ leave();
77
+ } else {
78
+ enter();
79
+ }
80
+ }
81
+ async function transition(element, initialClasses, activeClasses, endClasses, hiddenClass, preserveOriginalClass, removeEndClasses) {
82
+ const stashedClasses = [];
83
+ if (preserveOriginalClass) {
84
+ initialClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));
85
+ activeClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));
86
+ endClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));
87
+ }
88
+ addClasses(element, initialClasses);
89
+ removeClasses(element, stashedClasses);
90
+ addClasses(element, activeClasses);
91
+ await nextAnimationFrame();
92
+ removeClasses(element, initialClasses);
93
+ addClasses(element, endClasses);
94
+ await afterTransition(element);
95
+ removeClasses(element, activeClasses);
96
+ if (removeEndClasses) {
97
+ removeClasses(element, endClasses);
98
+ }
99
+ addClasses(element, stashedClasses);
100
+ }
101
+ function initialState() {
102
+ controller.transitioned = transitioned;
103
+ if (transitioned) {
104
+ if (!!hiddenClass) {
105
+ targetElement.classList.remove(hiddenClass);
106
+ }
107
+ enter();
108
+ } else {
109
+ if (!!hiddenClass) {
110
+ targetElement.classList.add(hiddenClass);
111
+ }
112
+ leave();
113
+ }
114
+ }
115
+ function addClasses(element, classes) {
116
+ if (classes.length > 0) {
117
+ element.classList.add(...classes);
118
+ }
119
+ }
120
+ function removeClasses(element, classes) {
121
+ if (classes.length > 0) {
122
+ element.classList.remove(...classes);
123
+ }
124
+ }
125
+ initialState();
126
+ Object.assign(controller, {
127
+ enter: enter,
128
+ leave: leave,
129
+ toggleTransition: toggleTransition
130
+ });
131
+ return [ enter, leave, toggleTransition ];
132
+ };
133
+
134
+ function getAttribute(name, options, dataset) {
135
+ const datasetName = `transition${name[0].toUpperCase()}${name.substr(1)}`;
136
+ const datasetAlpineName = alpineNames[name];
137
+ const classes = options[name] || dataset[datasetName] || dataset[datasetAlpineName] || " ";
138
+ return isEmpty(classes) ? [] : classes.split(" ");
139
+ }
140
+
141
+ async function afterTransition(element) {
142
+ return new Promise((resolve => {
143
+ const duration = Number(getComputedStyle(element).transitionDuration.split(",")[0].replace("s", "")) * 1e3;
144
+ setTimeout((() => {
145
+ resolve(duration);
146
+ }), duration);
147
+ }));
148
+ }
149
+
150
+ async function nextAnimationFrame() {
151
+ return new Promise((resolve => {
152
+ requestAnimationFrame((() => {
153
+ requestAnimationFrame(resolve);
154
+ }));
155
+ }));
156
+ }
157
+
158
+ function isEmpty(str) {
159
+ return str.length === 0 || !str.trim();
160
+ }
161
+
5
162
  function debounce$1(fn, wait) {
6
163
  let timeoutId;
7
164
  return (...args) => {
@@ -204,11 +361,11 @@ class Dropzone extends Controller {
204
361
  size: String
205
362
  };
206
363
  files=[];
207
- acceptedFiles=[];
208
364
  rejectedFiles=[];
209
365
  _dragging=false;
210
366
  dragTargets=[];
211
367
  previewRendered=false;
368
+ _acceptedFiles=[];
212
369
  _size="large";
213
370
  connect() {
214
371
  document.body.addEventListener("click", this.onExternalTriggerClick);
@@ -302,6 +459,7 @@ class Dropzone extends Controller {
302
459
  onDirectUploadsEnd=() => {
303
460
  this.enable();
304
461
  this.clearFiles();
462
+ if (this.acceptedFiles.length === 0) return;
305
463
  this.loaderTarget.classList.remove("Polaris--hidden");
306
464
  };
307
465
  onDirectUploadInitialize=event => {
@@ -309,9 +467,15 @@ class Dropzone extends Controller {
309
467
  const {id: id, file: file} = detail;
310
468
  const dropzone = target.closest(".Polaris-DropZone");
311
469
  if (!dropzone) return;
312
- const content = dropzone.querySelector(`[data-file-name="${file.name}"]`);
313
- const progressBar = content.parentElement.querySelector('[data-target="progress-bar"]');
314
- progressBar.id = `direct-upload-${id}`;
470
+ if (this.acceptedFiles.length === 0) return;
471
+ if (this.sizeValue == "small") {
472
+ this.clearFiles();
473
+ this.loaderTarget.classList.remove("Polaris--hidden");
474
+ } else {
475
+ const content = dropzone.querySelector(`[data-file-name="${file.name}"]`);
476
+ const progressBar = content.parentElement.querySelector('[data-target="progress-bar"]');
477
+ progressBar.id = `direct-upload-${id}`;
478
+ }
315
479
  };
316
480
  onDirectUploadStart=event => {
317
481
  const {id: id} = event.detail;
@@ -381,6 +545,7 @@ class Dropzone extends Controller {
381
545
  this.toggleFileUpload(false);
382
546
  this.toggleErrorOverlay(true);
383
547
  const dropRejectedEvent = new CustomEvent("polaris-dropzone:drop-rejected", {
548
+ bubbles: true,
384
549
  detail: {
385
550
  rejectedFiles: this.rejectedFiles
386
551
  }
@@ -393,6 +558,7 @@ class Dropzone extends Controller {
393
558
  }
394
559
  this.toggleErrorOverlay(false);
395
560
  const dropAcceptedEvent = new CustomEvent("polaris-dropzone:drop-accepted", {
561
+ bubbles: true,
396
562
  detail: {
397
563
  acceptedFiles: this.acceptedFiles
398
564
  }
@@ -400,6 +566,7 @@ class Dropzone extends Controller {
400
566
  this.element.dispatchEvent(dropAcceptedEvent);
401
567
  }
402
568
  const dropEvent = new CustomEvent("polaris-dropzone:drop", {
569
+ bubbles: true,
403
570
  detail: {
404
571
  files: this.files,
405
572
  acceptedFiles: this.acceptedFiles,
@@ -517,6 +684,15 @@ class Dropzone extends Controller {
517
684
  sizeClassesToRemove.forEach((className => this.element.classList.remove(className)));
518
685
  this.element.classList.add(this.getSizeClass(val));
519
686
  }
687
+ get acceptedFiles() {
688
+ return this._acceptedFiles;
689
+ }
690
+ set acceptedFiles(val) {
691
+ this._acceptedFiles = val;
692
+ const list = new DataTransfer;
693
+ val.forEach((file => list.items.add(file)));
694
+ this.inputTarget.files = list.files;
695
+ }
520
696
  }
521
697
 
522
698
  function fileAccepted(file, accept) {
@@ -564,163 +740,6 @@ function isChangeEvent(event) {
564
740
  return event.type === "change";
565
741
  }
566
742
 
567
- const alpineNames = {
568
- enterFromClass: "enter",
569
- enterActiveClass: "enterStart",
570
- enterToClass: "enterEnd",
571
- leaveFromClass: "leave",
572
- leaveActiveClass: "leaveStart",
573
- leaveToClass: "leaveEnd"
574
- };
575
-
576
- const defaultOptions = {
577
- transitioned: false,
578
- hiddenClass: "hidden",
579
- preserveOriginalClass: true,
580
- removeToClasses: true
581
- };
582
-
583
- const useTransition = (controller, options = {}) => {
584
- var _a, _b, _c;
585
- const targetName = controller.element.dataset.transitionTarget;
586
- let targetFromAttribute;
587
- if (targetName) {
588
- targetFromAttribute = controller[`${targetName}Target`];
589
- }
590
- const targetElement = (options === null || options === void 0 ? void 0 : options.element) || targetFromAttribute || controller.element;
591
- if (!(targetElement instanceof HTMLElement || targetElement instanceof SVGElement)) return;
592
- const dataset = targetElement.dataset;
593
- const leaveAfter = parseInt(dataset.leaveAfter || "") || options.leaveAfter || 0;
594
- const {transitioned: transitioned, hiddenClass: hiddenClass, preserveOriginalClass: preserveOriginalClass, removeToClasses: removeToClasses} = Object.assign(defaultOptions, options);
595
- const controllerEnter = (_a = controller.enter) === null || _a === void 0 ? void 0 : _a.bind(controller);
596
- const controllerLeave = (_b = controller.leave) === null || _b === void 0 ? void 0 : _b.bind(controller);
597
- const controllerToggleTransition = (_c = controller.toggleTransition) === null || _c === void 0 ? void 0 : _c.bind(controller);
598
- async function enter(event) {
599
- if (controller.transitioned) return;
600
- controller.transitioned = true;
601
- controllerEnter && controllerEnter(event);
602
- const enterFromClasses = getAttribute("enterFrom", options, dataset);
603
- const enterActiveClasses = getAttribute("enterActive", options, dataset);
604
- const enterToClasses = getAttribute("enterTo", options, dataset);
605
- const leaveToClasses = getAttribute("leaveTo", options, dataset);
606
- if (!!hiddenClass) {
607
- targetElement.classList.remove(hiddenClass);
608
- }
609
- if (!removeToClasses) {
610
- removeClasses(targetElement, leaveToClasses);
611
- }
612
- await transition(targetElement, enterFromClasses, enterActiveClasses, enterToClasses, hiddenClass, preserveOriginalClass, removeToClasses);
613
- if (leaveAfter > 0) {
614
- setTimeout((() => {
615
- leave(event);
616
- }), leaveAfter);
617
- }
618
- }
619
- async function leave(event) {
620
- if (!controller.transitioned) return;
621
- controller.transitioned = false;
622
- controllerLeave && controllerLeave(event);
623
- const leaveFromClasses = getAttribute("leaveFrom", options, dataset);
624
- const leaveActiveClasses = getAttribute("leaveActive", options, dataset);
625
- const leaveToClasses = getAttribute("leaveTo", options, dataset);
626
- const enterToClasses = getAttribute("enterTo", options, dataset);
627
- if (!removeToClasses) {
628
- removeClasses(targetElement, enterToClasses);
629
- }
630
- await transition(targetElement, leaveFromClasses, leaveActiveClasses, leaveToClasses, hiddenClass, preserveOriginalClass, removeToClasses);
631
- if (!!hiddenClass) {
632
- targetElement.classList.add(hiddenClass);
633
- }
634
- }
635
- function toggleTransition(event) {
636
- controllerToggleTransition && controllerToggleTransition(event);
637
- if (controller.transitioned) {
638
- leave();
639
- } else {
640
- enter();
641
- }
642
- }
643
- async function transition(element, initialClasses, activeClasses, endClasses, hiddenClass, preserveOriginalClass, removeEndClasses) {
644
- const stashedClasses = [];
645
- if (preserveOriginalClass) {
646
- initialClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));
647
- activeClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));
648
- endClasses.forEach((cls => element.classList.contains(cls) && cls !== hiddenClass && stashedClasses.push(cls)));
649
- }
650
- addClasses(element, initialClasses);
651
- removeClasses(element, stashedClasses);
652
- addClasses(element, activeClasses);
653
- await nextAnimationFrame();
654
- removeClasses(element, initialClasses);
655
- addClasses(element, endClasses);
656
- await afterTransition(element);
657
- removeClasses(element, activeClasses);
658
- if (removeEndClasses) {
659
- removeClasses(element, endClasses);
660
- }
661
- addClasses(element, stashedClasses);
662
- }
663
- function initialState() {
664
- controller.transitioned = transitioned;
665
- if (transitioned) {
666
- if (!!hiddenClass) {
667
- targetElement.classList.remove(hiddenClass);
668
- }
669
- enter();
670
- } else {
671
- if (!!hiddenClass) {
672
- targetElement.classList.add(hiddenClass);
673
- }
674
- leave();
675
- }
676
- }
677
- function addClasses(element, classes) {
678
- if (classes.length > 0) {
679
- element.classList.add(...classes);
680
- }
681
- }
682
- function removeClasses(element, classes) {
683
- if (classes.length > 0) {
684
- element.classList.remove(...classes);
685
- }
686
- }
687
- initialState();
688
- Object.assign(controller, {
689
- enter: enter,
690
- leave: leave,
691
- toggleTransition: toggleTransition
692
- });
693
- return [ enter, leave, toggleTransition ];
694
- };
695
-
696
- function getAttribute(name, options, dataset) {
697
- const datasetName = `transition${name[0].toUpperCase()}${name.substr(1)}`;
698
- const datasetAlpineName = alpineNames[name];
699
- const classes = options[name] || dataset[datasetName] || dataset[datasetAlpineName] || " ";
700
- return isEmpty(classes) ? [] : classes.split(" ");
701
- }
702
-
703
- async function afterTransition(element) {
704
- return new Promise((resolve => {
705
- const duration = Number(getComputedStyle(element).transitionDuration.split(",")[0].replace("s", "")) * 1e3;
706
- setTimeout((() => {
707
- resolve(duration);
708
- }), duration);
709
- }));
710
- }
711
-
712
- async function nextAnimationFrame() {
713
- return new Promise((resolve => {
714
- requestAnimationFrame((() => {
715
- requestAnimationFrame(resolve);
716
- }));
717
- }));
718
- }
719
-
720
- function isEmpty(str) {
721
- return str.length === 0 || !str.trim();
722
- }
723
-
724
743
  class Frame extends Controller {
725
744
  static targets=[ "navigationOverlay", "navigation", "saveBar" ];
726
745
  connect() {
@@ -2392,7 +2411,11 @@ class TextField extends Controller {
2392
2411
  this.valueValue = this.inputTarget.value;
2393
2412
  }
2394
2413
  clear() {
2414
+ const oldValue = this.value;
2395
2415
  this.value = null;
2416
+ if (this.value != oldValue) {
2417
+ this.inputTarget.dispatchEvent(new Event("change"));
2418
+ }
2396
2419
  }
2397
2420
  increase() {
2398
2421
  this.changeNumber(1);
@@ -116,6 +116,15 @@ a.Polaris-Tag__Button {
116
116
  justify-content: center;
117
117
  }
118
118
 
119
+ &--sizeMedium {
120
+ justify-content: center;
121
+ text-align: center;
122
+
123
+ .Polaris-Stack.Polaris-Stack--alignmentCenter {
124
+ justify-content: center;
125
+ }
126
+ }
127
+
119
128
  &--sizeSmall {
120
129
  padding: 0;
121
130
  justify-content: center;
@@ -137,5 +146,33 @@ a.Polaris-Tag__Button {
137
146
  align-items: center;
138
147
  text-align: center;
139
148
  justify-content: center;
149
+
150
+ .Polaris-Spinner--sizeSmall {
151
+ height: 20px;
152
+ }
153
+ }
154
+ }
155
+
156
+ /* ActionMenu */
157
+ .Polaris-ActionMenu {
158
+ &--mobile {
159
+ @media (min-width: 768px){
160
+ display: none;
161
+ }
162
+ }
163
+
164
+ &--desktop {
165
+ display: none;
166
+
167
+ @media (min-width: 768px){
168
+ display: block;
169
+ }
170
+ }
171
+ }
172
+
173
+ /* Page Pagination */
174
+ @media (max-width: 768px){
175
+ .Polaris-Page-Header__PaginationWrapper {
176
+ display: none;
140
177
  }
141
178
  }
@@ -2325,6 +2325,13 @@ a.Polaris-Tag__Button {
2325
2325
  text-align: center;
2326
2326
  justify-content: center;
2327
2327
  }
2328
+ .Polaris-DropZone__Preview--sizeMedium {
2329
+ justify-content: center;
2330
+ text-align: center;
2331
+ }
2332
+ .Polaris-DropZone__Preview--sizeMedium .Polaris-Stack.Polaris-Stack--alignmentCenter {
2333
+ justify-content: center;
2334
+ }
2328
2335
  .Polaris-DropZone__Preview--sizeSmall {
2329
2336
  padding: 0;
2330
2337
  justify-content: center;
@@ -2343,3 +2350,26 @@ a.Polaris-Tag__Button {
2343
2350
  text-align: center;
2344
2351
  justify-content: center;
2345
2352
  }
2353
+ .Polaris-DropZone__Loader .Polaris-Spinner--sizeSmall {
2354
+ height: 20px;
2355
+ }
2356
+ /* ActionMenu */
2357
+ @media (min-width: 768px){
2358
+ .Polaris-ActionMenu--mobile {
2359
+ display: none
2360
+ }
2361
+ }
2362
+ .Polaris-ActionMenu--desktop {
2363
+ display: none;
2364
+ }
2365
+ @media (min-width: 768px){
2366
+ .Polaris-ActionMenu--desktop {
2367
+ display: block
2368
+ }
2369
+ }
2370
+ /* Page Pagination */
2371
+ @media (max-width: 768px){
2372
+ .Polaris-Page-Header__PaginationWrapper {
2373
+ display: none;
2374
+ }
2375
+ }
@@ -5,6 +5,7 @@ class Polaris::ActionList::ItemComponent < Polaris::Component
5
5
  def initialize(
6
6
  url: nil,
7
7
  icon: nil,
8
+ icon_name: nil,
8
9
  help_text: nil,
9
10
  active: false,
10
11
  destructive: false,
@@ -12,7 +13,7 @@ class Polaris::ActionList::ItemComponent < Polaris::Component
12
13
  **system_arguments
13
14
  )
14
15
  @url = url
15
- @icon = icon
16
+ @icon = icon || icon_name
16
17
  @help_text = help_text
17
18
  @active = active
18
19
  @destructive = destructive
@@ -6,9 +6,9 @@
6
6
  </span>
7
7
  <% end %>
8
8
 
9
- <% if icon.present? %>
9
+ <% if icon.present? || @icon_name.present? %>
10
10
  <div class="Polaris-Button__Icon">
11
- <%= icon %>
11
+ <%= icon.presence || polaris_icon(name: @icon_name) %>
12
12
  </div>
13
13
  <% if content.present? %>
14
14
  &nbsp;
@@ -4,10 +4,12 @@
4
4
  class="Polaris-DropZone__Overlay Polaris-VisuallyHidden"
5
5
  data-polaris-dropzone-target="overlay"
6
6
  >
7
- <%= render Polaris::StackComponent.new(vertical: true, spacing: :tight) do |stack| %>
8
- <% stack.item do %>
9
- <%= render Polaris::DisplayTextComponent.new(size: :small) do %>
10
- <%= @overlay_text %>
7
+ <% unless @size == :small %>
8
+ <%= render Polaris::StackComponent.new(vertical: true, spacing: :tight) do |stack| %>
9
+ <% stack.item do %>
10
+ <%= render Polaris::DisplayTextComponent.new(size: :small) do %>
11
+ <%= @overlay_text %>
12
+ <% end %>
11
13
  <% end %>
12
14
  <% end %>
13
15
  <% end %>
@@ -68,7 +70,7 @@
68
70
  <% end %>
69
71
 
70
72
  <div class="Polaris-DropZone__Loader Polaris--hidden" data-polaris-dropzone-target="loader">
71
- <%= polaris_spinner %>
73
+ <%= polaris_spinner(size: (@size == :small) ? :small : :large) %>
72
74
  </div>
73
75
  </div>
74
76
 
@@ -86,7 +88,8 @@
86
88
  class: [
87
89
  "Polaris-DropZone__Preview",
88
90
  "Polaris-DropZone__Preview--singleFile": !@multiple,
89
- "Polaris-DropZone__Preview--sizeSmall": @size == :small
91
+ "Polaris-DropZone__Preview--sizeMedium": @size == :medium,
92
+ "Polaris-DropZone__Preview--sizeSmall": @size == :small,
90
93
  ]
91
94
  ) do %>
92
95
  <% if @size.in?(%i[small]) %>
@@ -74,7 +74,9 @@ module Polaris
74
74
  def popover_arguments
75
75
  {
76
76
  sectioned: @sectioned,
77
- style: ("width: #{@width}" if @width.present?)
77
+ style: ("width: #{@width}" if @width.present?),
78
+ position: :below,
79
+ alignment: :left
78
80
  }
79
81
  end
80
82
 
@@ -5,9 +5,9 @@
5
5
  </span>
6
6
  <% end %>
7
7
 
8
- <% if icon.present? %>
8
+ <% if icon.present? || @icon_name.present? %>
9
9
  <div class="Polaris-Button__Icon">
10
- <%= icon %>
10
+ <%= icon || polaris_icon(name: @icon_name) %>
11
11
  </div>
12
12
  <% if content.present? %>
13
13
  &nbsp;
@@ -42,6 +42,7 @@ module Polaris
42
42
  remove_underline: false,
43
43
  size: SIZE_DEFAULT,
44
44
  text_align: TEXT_ALIGN_DEFAULT,
45
+ icon_name: nil,
45
46
  **system_arguments
46
47
  )
47
48
  @tag = url.present? ? "a" : "button"
@@ -52,6 +53,7 @@ module Polaris
52
53
  @loading = loading
53
54
  @disclosure = fetch_or_fallback(DISCLOSURE_OPTIONS, disclosure, DISCLOSURE_DEFAULT)
54
55
  @disclosure = :down if @disclosure === true
56
+ @icon_name = icon_name
55
57
 
56
58
  @system_arguments = system_arguments
57
59
  @system_arguments[:type] = submit ? "submit" : "button"
@@ -92,7 +94,7 @@ module Polaris
92
94
  def system_arguments
93
95
  @system_arguments[:classes] = class_names(
94
96
  @system_arguments[:classes],
95
- "Polaris-Button--iconOnly": icon.present? && content.blank?
97
+ "Polaris-Button--iconOnly": (icon.present? || @icon_name.present?) && content.blank?
96
98
  )
97
99
  @system_arguments
98
100
  end