@moises.ai/design-system 4.19.5 → 4.19.7

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": "@moises.ai/design-system",
3
- "version": "4.19.5",
3
+ "version": "4.19.7",
4
4
  "description": "Design System package based on @radix-ui/themes with custom defaults",
5
5
  "private": false,
6
6
  "type": "module",
@@ -67,6 +67,7 @@ The \`options\` prop accepts an array of objects with the following types:
67
67
  icon: <Icon />, // Optional, icon displayed before the label
68
68
  onClick: () => {}, // Function called when clicked
69
69
  disabled: false, // Optional, disables the item when true
70
+ allowClickWhenDisabled: false, // Optional, keeps disabled look but still fires onClick (e.g. paywall)
70
71
  keybinding: '⌘C', // Optional, displays a keyboard shortcut
71
72
  rightIcon: <Icon />, // Optional, icon displayed on the right side
72
73
  color: 'red' | 'cyan', // Optional: custom color for this item
@@ -114,6 +115,7 @@ The \`options\` prop accepts an array of objects with the following types:
114
115
  checked: true, // Whether the checkbox is checked (always reserves space for checkmark)
115
116
  onChange: (checked) => {}, // Function called when toggled, receives new checked state
116
117
  disabled: false, // Optional, disables the checkbox when true
118
+ allowClickWhenDisabled: false, // Optional, keeps disabled look but still allows interaction (e.g. paywall)
117
119
  keybinding: '⌘C', // Optional, displays a keyboard shortcut
118
120
  rightIcon: <Icon />, // Optional, icon displayed on the right side
119
121
  color: 'red' | 'cyan', // Optional: custom color for this checkbox item
@@ -310,6 +312,69 @@ export const StayOpenAfterSelect = {
310
312
  },
311
313
  }
312
314
 
315
+ export const AllowClickWhenDisabled = {
316
+ render: () => {
317
+ const [lastAction, setLastAction] = useState('none yet')
318
+
319
+ const options = [
320
+ {
321
+ type: 'item',
322
+ key: 'edit',
323
+ label: 'Edit',
324
+ onClick: () => setLastAction('Edit'),
325
+ },
326
+ {
327
+ type: 'item',
328
+ key: 'disabled',
329
+ label: 'Disabled (no click)',
330
+ disabled: true,
331
+ onClick: () => setLastAction('Disabled item clicked'),
332
+ },
333
+ {
334
+ type: 'item',
335
+ key: 'premium',
336
+ label: 'Premium feature',
337
+ secondaryText: 'Looks disabled, still clickable',
338
+ secondaryTextPosition: 'bottom',
339
+ disabled: true,
340
+ allowClickWhenDisabled: true,
341
+ onClick: () => setLastAction('Paywall opened'),
342
+ },
343
+ { type: 'separator', key: 'sep1' },
344
+ {
345
+ type: 'checkbox',
346
+ key: 'premium-checkbox',
347
+ label: 'Premium checkbox',
348
+ checked: false,
349
+ disabled: true,
350
+ allowClickWhenDisabled: true,
351
+ onChange: () => setLastAction('Paywall opened from checkbox'),
352
+ },
353
+ ]
354
+
355
+ return (
356
+ <Flex direction="column" gap="2" align="center" height="320px">
357
+ <ContextMenu options={options}>
358
+ <Flex
359
+ justify="center"
360
+ align="center"
361
+ style={{
362
+ padding: '50px',
363
+ border: '1px dashed gray',
364
+ borderRadius: '8px',
365
+ }}
366
+ >
367
+ Right-click here
368
+ </Flex>
369
+ </ContextMenu>
370
+ <div style={{ fontSize: '14px', color: '#4b5563' }}>
371
+ Last action: {lastAction}
372
+ </div>
373
+ </Flex>
374
+ )
375
+ },
376
+ }
377
+
313
378
  const ItemPlaygroundComponent = ({
314
379
  size,
315
380
  // Item 1
@@ -321,6 +386,7 @@ const ItemPlaygroundComponent = ({
321
386
  item1Keybinding,
322
387
  item1ShowRightIcon,
323
388
  item1Disabled,
389
+ item1AllowClickWhenDisabled,
324
390
  item1Color,
325
391
  // Item 2
326
392
  item2Type,
@@ -331,6 +397,7 @@ const ItemPlaygroundComponent = ({
331
397
  item2Keybinding,
332
398
  item2ShowRightIcon,
333
399
  item2Disabled,
400
+ item2AllowClickWhenDisabled,
334
401
  item2Color,
335
402
  // Submenu
336
403
  showSubmenu,
@@ -343,6 +410,7 @@ const ItemPlaygroundComponent = ({
343
410
  subItemShowIcon,
344
411
  subItemKeybinding,
345
412
  subItemDisabled,
413
+ subItemAllowClickWhenDisabled,
346
414
  }) => {
347
415
  const [item1IsChecked, setItem1IsChecked] = useState(false)
348
416
  const [item2IsChecked, setItem2IsChecked] = useState(true)
@@ -358,6 +426,7 @@ const ItemPlaygroundComponent = ({
358
426
  keybinding: item1Keybinding || undefined,
359
427
  rightIcon: item1ShowRightIcon ? <DotsVerticalIcon /> : undefined,
360
428
  disabled: item1Disabled,
429
+ allowClickWhenDisabled: item1AllowClickWhenDisabled,
361
430
  color: item1Color === 'default' ? undefined : item1Color,
362
431
  ...(item1Type === 'checkbox'
363
432
  ? {
@@ -379,6 +448,7 @@ const ItemPlaygroundComponent = ({
379
448
  keybinding: item2Keybinding || undefined,
380
449
  rightIcon: item2ShowRightIcon ? <DotsVerticalIcon /> : undefined,
381
450
  disabled: item2Disabled,
451
+ allowClickWhenDisabled: item2AllowClickWhenDisabled,
382
452
  color: item2Color === 'default' ? undefined : item2Color,
383
453
  ...(item2Type === 'checkbox'
384
454
  ? {
@@ -399,6 +469,7 @@ const ItemPlaygroundComponent = ({
399
469
  icon: subItemShowIcon ? <GearIcon /> : undefined,
400
470
  keybinding: subItemKeybinding || undefined,
401
471
  disabled: subItemDisabled,
472
+ allowClickWhenDisabled: subItemAllowClickWhenDisabled,
402
473
  ...(subItemType === 'checkbox'
403
474
  ? {
404
475
  checked: subItemIsChecked,
@@ -467,6 +538,7 @@ export const Playground = {
467
538
  item1Keybinding: '⌘ C',
468
539
  item1ShowRightIcon: true,
469
540
  item1Disabled: false,
541
+ item1AllowClickWhenDisabled: false,
470
542
  item1Color: 'default',
471
543
  // Item 2
472
544
  item2Type: 'checkbox',
@@ -477,6 +549,7 @@ export const Playground = {
477
549
  item2Keybinding: '⌘ S',
478
550
  item2ShowRightIcon: false,
479
551
  item2Disabled: false,
552
+ item2AllowClickWhenDisabled: false,
480
553
  item2Color: 'default',
481
554
  // Submenu
482
555
  showSubmenu: true,
@@ -489,6 +562,7 @@ export const Playground = {
489
562
  subItemShowIcon: false,
490
563
  subItemKeybinding: '',
491
564
  subItemDisabled: false,
565
+ subItemAllowClickWhenDisabled: false,
492
566
  },
493
567
  argTypes: {
494
568
  size: {
@@ -540,6 +614,11 @@ export const Playground = {
540
614
  description: 'Disabled state',
541
615
  table: { category: 'Item 1' },
542
616
  },
617
+ item1AllowClickWhenDisabled: {
618
+ control: { type: 'boolean' },
619
+ description: 'Keep disabled look but still allow click',
620
+ table: { category: 'Item 1' },
621
+ },
543
622
  item1Color: {
544
623
  options: ['default', 'red', 'cyan'],
545
624
  control: { type: 'select' },
@@ -589,6 +668,11 @@ export const Playground = {
589
668
  description: 'Disabled state',
590
669
  table: { category: 'Item 2' },
591
670
  },
671
+ item2AllowClickWhenDisabled: {
672
+ control: { type: 'boolean' },
673
+ description: 'Keep disabled look but still allow click',
674
+ table: { category: 'Item 2' },
675
+ },
592
676
  item2Color: {
593
677
  options: ['default', 'red', 'cyan'],
594
678
  control: { type: 'select' },
@@ -652,6 +736,12 @@ export const Playground = {
652
736
  table: { category: 'Sub Item' },
653
737
  if: { arg: 'showSubmenu' },
654
738
  },
739
+ subItemAllowClickWhenDisabled: {
740
+ control: { type: 'boolean' },
741
+ description: 'Keep disabled look but still allow click',
742
+ table: { category: 'Sub Item' },
743
+ if: { arg: 'showSubmenu' },
744
+ },
655
745
  },
656
746
  render: (args) => <ItemPlaygroundComponent {...args} />,
657
747
  }
@@ -79,6 +79,7 @@ The \`options\` prop accepts an array of objects with the following types:
79
79
  icon: <Icon />, // Optional, icon displayed before the label
80
80
  onClick: () => {}, // Function called when clicked
81
81
  disabled: false, // Optional, disables the item when true
82
+ allowClickWhenDisabled: false, // Optional, keeps disabled look but still fires onClick (e.g. paywall)
82
83
  keybinding: '⌘C', // Optional, displays a keyboard shortcut
83
84
  rightIcon: <Icon />, // Optional, icon displayed on the right side
84
85
  color: 'red' | 'cyan', // Optional: custom color for this item
@@ -127,6 +128,7 @@ The \`options\` prop accepts an array of objects with the following types:
127
128
  checked: true, // Whether the checkbox is checked (always reserves space for checkmark)
128
129
  onChange: (checked) => {}, // Function called when toggled, receives new checked state
129
130
  disabled: false, // Optional, disables the checkbox when true
131
+ allowClickWhenDisabled: false, // Optional, keeps disabled look but still allows interaction (e.g. paywall)
130
132
  keybinding: '⌘C', // Optional, displays a keyboard shortcut
131
133
  rightIcon: <Icon />, // Optional, icon displayed on the right side
132
134
  color: 'red' | 'cyan', // Optional: custom color for this checkbox item
@@ -559,6 +561,66 @@ export const CustomWithSwitch = {
559
561
  },
560
562
  }
561
563
 
564
+ export const AllowClickWhenDisabled = {
565
+ render: () => {
566
+ const [lastAction, setLastAction] = useState('none yet')
567
+
568
+ const options = [
569
+ {
570
+ type: 'item',
571
+ key: 'edit',
572
+ label: 'Edit',
573
+ onClick: () => setLastAction('Edit'),
574
+ },
575
+ {
576
+ type: 'item',
577
+ key: 'disabled',
578
+ label: 'Disabled (no click)',
579
+ disabled: true,
580
+ onClick: () => setLastAction('Disabled item clicked'),
581
+ },
582
+ {
583
+ type: 'item',
584
+ key: 'premium',
585
+ label: 'Premium feature',
586
+ secondaryText: 'Looks disabled, still clickable',
587
+ secondaryTextPosition: 'bottom',
588
+ disabled: true,
589
+ allowClickWhenDisabled: true,
590
+ onClick: () => setLastAction('Paywall opened'),
591
+ },
592
+ { type: 'separator', key: 'sep1' },
593
+ {
594
+ type: 'checkbox',
595
+ key: 'premium-checkbox',
596
+ label: 'Premium checkbox',
597
+ checked: false,
598
+ disabled: true,
599
+ allowClickWhenDisabled: true,
600
+ onChange: () => setLastAction('Paywall opened from checkbox'),
601
+ },
602
+ ]
603
+
604
+ return (
605
+ <Flex direction="column" gap="2" align="center" height="320px">
606
+ <DropdownMenu
607
+ side="bottom"
608
+ align="end"
609
+ trigger={
610
+ <IconButton>
611
+ <DotsVerticalIcon />
612
+ </IconButton>
613
+ }
614
+ options={options}
615
+ />
616
+ <div style={{ fontSize: '14px', color: '#4b5563' }}>
617
+ Last action: {lastAction}
618
+ </div>
619
+ </Flex>
620
+ )
621
+ },
622
+ }
623
+
562
624
  const ItemPlaygroundComponent = ({
563
625
  size,
564
626
  // Item 1
@@ -570,6 +632,7 @@ const ItemPlaygroundComponent = ({
570
632
  item1Keybinding,
571
633
  item1ShowRightIcon,
572
634
  item1Disabled,
635
+ item1AllowClickWhenDisabled,
573
636
  item1Color,
574
637
  // Item 2
575
638
  item2Type,
@@ -580,6 +643,7 @@ const ItemPlaygroundComponent = ({
580
643
  item2Keybinding,
581
644
  item2ShowRightIcon,
582
645
  item2Disabled,
646
+ item2AllowClickWhenDisabled,
583
647
  item2Color,
584
648
  // Submenu
585
649
  showSubmenu,
@@ -592,6 +656,7 @@ const ItemPlaygroundComponent = ({
592
656
  subItemShowIcon,
593
657
  subItemKeybinding,
594
658
  subItemDisabled,
659
+ subItemAllowClickWhenDisabled,
595
660
  }) => {
596
661
  const [item1IsChecked, setItem1IsChecked] = useState(false)
597
662
  const [item2IsChecked, setItem2IsChecked] = useState(true)
@@ -607,6 +672,7 @@ const ItemPlaygroundComponent = ({
607
672
  keybinding: item1Keybinding || undefined,
608
673
  rightIcon: item1ShowRightIcon ? <DotsVerticalIcon /> : undefined,
609
674
  disabled: item1Disabled,
675
+ allowClickWhenDisabled: item1AllowClickWhenDisabled,
610
676
  color: item1Color === 'default' ? undefined : item1Color,
611
677
  ...(item1Type === 'checkbox'
612
678
  ? {
@@ -628,6 +694,7 @@ const ItemPlaygroundComponent = ({
628
694
  keybinding: item2Keybinding || undefined,
629
695
  rightIcon: item2ShowRightIcon ? <DotsVerticalIcon /> : undefined,
630
696
  disabled: item2Disabled,
697
+ allowClickWhenDisabled: item2AllowClickWhenDisabled,
631
698
  color: item2Color === 'default' ? undefined : item2Color,
632
699
  ...(item2Type === 'checkbox'
633
700
  ? {
@@ -648,6 +715,7 @@ const ItemPlaygroundComponent = ({
648
715
  icon: subItemShowIcon ? <GearIcon /> : undefined,
649
716
  keybinding: subItemKeybinding || undefined,
650
717
  disabled: subItemDisabled,
718
+ allowClickWhenDisabled: subItemAllowClickWhenDisabled,
651
719
  ...(subItemType === 'checkbox'
652
720
  ? {
653
721
  checked: subItemIsChecked,
@@ -712,6 +780,7 @@ export const Playground = {
712
780
  item1Keybinding: '⌘ C',
713
781
  item1ShowRightIcon: true,
714
782
  item1Disabled: false,
783
+ item1AllowClickWhenDisabled: false,
715
784
  item1Color: 'default',
716
785
  // Item 2
717
786
  item2Type: 'checkbox',
@@ -722,6 +791,7 @@ export const Playground = {
722
791
  item2Keybinding: '⌘ S',
723
792
  item2ShowRightIcon: false,
724
793
  item2Disabled: false,
794
+ item2AllowClickWhenDisabled: false,
725
795
  item2Color: 'default',
726
796
  // Submenu
727
797
  showSubmenu: true,
@@ -734,6 +804,7 @@ export const Playground = {
734
804
  subItemShowIcon: false,
735
805
  subItemKeybinding: '',
736
806
  subItemDisabled: false,
807
+ subItemAllowClickWhenDisabled: false,
737
808
  },
738
809
  argTypes: {
739
810
  size: {
@@ -785,6 +856,11 @@ export const Playground = {
785
856
  description: 'Disabled state',
786
857
  table: { category: 'Item 1' },
787
858
  },
859
+ item1AllowClickWhenDisabled: {
860
+ control: { type: 'boolean' },
861
+ description: 'Keep disabled look but still allow click',
862
+ table: { category: 'Item 1' },
863
+ },
788
864
  item1Color: {
789
865
  options: ['default', 'red', 'cyan'],
790
866
  control: { type: 'select' },
@@ -834,6 +910,11 @@ export const Playground = {
834
910
  description: 'Disabled state',
835
911
  table: { category: 'Item 2' },
836
912
  },
913
+ item2AllowClickWhenDisabled: {
914
+ control: { type: 'boolean' },
915
+ description: 'Keep disabled look but still allow click',
916
+ table: { category: 'Item 2' },
917
+ },
837
918
  item2Color: {
838
919
  options: ['default', 'red', 'cyan'],
839
920
  control: { type: 'select' },
@@ -897,6 +978,12 @@ export const Playground = {
897
978
  table: { category: 'Sub Item' },
898
979
  if: { arg: 'showSubmenu' },
899
980
  },
981
+ subItemAllowClickWhenDisabled: {
982
+ control: { type: 'boolean' },
983
+ description: 'Keep disabled look but still allow click',
984
+ table: { category: 'Sub Item' },
985
+ if: { arg: 'showSubmenu' },
986
+ },
900
987
  },
901
988
  render: (args) => <ItemPlaygroundComponent {...args} />,
902
989
  }
@@ -4,23 +4,9 @@ export const ArrowRightIcon = ({
4
4
  className,
5
5
  ...props
6
6
  }) => (
7
- <svg
8
- xmlns="http://www.w3.org/2000/svg"
9
- width={width}
10
- height={height}
11
- viewBox="0 0 24 24"
12
- fill="none"
13
- className={className}
14
- {...props}
15
- >
16
- <path
17
- d="M13 18L19 12L13 6M18 12L5 12"
18
- stroke="currentColor"
19
- strokeWidth="1.5"
20
- strokeLinecap="round"
21
- strokeLinejoin="round"
22
- />
23
- </svg>
7
+ <svg xmlns="http://www.w3.org/2000/svg" width={width} height={height} viewBox="0 0 24 24" fill="none" {...props} aria-label="Arrow Right Icon">
8
+ <path d="M13.1429 19L20 12L13.1429 5M18.8571 12L4 12" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
9
+ </svg>
24
10
  )
25
11
 
26
12
  ArrowRightIcon.displayName = 'ArrowRightIcon'
@@ -137,10 +137,9 @@
137
137
  }
138
138
  }
139
139
 
140
- .menuItem[data-disabled] {
140
+ .menuItem[data-disabled],
141
+ .menuItemDisabledClickable {
141
142
  color: var(--neutral-alpha-7);
142
- cursor: not-allowed;
143
- pointer-events: none;
144
143
 
145
144
  & .label,
146
145
  & .secondaryTextBottom,
@@ -159,6 +158,15 @@
159
158
  }
160
159
  }
161
160
 
161
+ .menuItem[data-disabled] {
162
+ cursor: not-allowed;
163
+ pointer-events: none;
164
+ }
165
+
166
+ .menuItemDisabledClickable {
167
+ cursor: pointer;
168
+ }
169
+
162
170
  .menuSeparator {
163
171
  height: 1px;
164
172
  background-color: var(--neutral-alpha-3);
@@ -298,6 +306,10 @@
298
306
  background-color: var(--neutral-alpha-3);
299
307
  }
300
308
 
309
+ .menuItem.menuItemDisabledClickable[data-highlighted] {
310
+ background-color: transparent;
311
+ }
312
+
301
313
  .menuSubContent {
302
314
  min-width: 242px;
303
315
  }
@@ -18,6 +18,11 @@ export const createRenderItem = (MenuPrimitives) => {
18
18
  closeMenu,
19
19
  showSelectedItemBackground = true,
20
20
  ) => {
21
+ const isDisabled = Boolean(opt.disabled)
22
+ const allowClickWhenDisabled = Boolean(opt.allowClickWhenDisabled)
23
+ const isRadixDisabled = isDisabled && !allowClickWhenDisabled
24
+ const isDisabledClickable = isDisabled && allowClickWhenDisabled
25
+
21
26
  switch (opt.type) {
22
27
  case 'custom':
23
28
  return (
@@ -27,13 +32,17 @@ export const createRenderItem = (MenuPrimitives) => {
27
32
  styles.menuItem,
28
33
  styles.menuCustomRender,
29
34
  styles[`menuItem-size-${size}`],
35
+ {
36
+ [styles.menuItemDisabledClickable]: isDisabledClickable,
37
+ },
30
38
  )}
31
39
  onSelect={(event) => {
32
40
  if (!closeOnSelect) {
33
41
  event.preventDefault()
34
42
  }
35
43
  }}
36
- disabled={opt.disabled}
44
+ disabled={isRadixDisabled}
45
+ aria-disabled={isDisabledClickable || undefined}
37
46
  asChild
38
47
  >
39
48
  {opt.customRender(closeMenu)}
@@ -104,8 +113,9 @@ export const createRenderItem = (MenuPrimitives) => {
104
113
  styles.menuItem,
105
114
  styles[`menuItem-size-${size}`],
106
115
  {
107
- [styles.red]: opt.color === 'red' && !opt.disabled,
108
- [styles.cyan]: opt.color === 'cyan' && !opt.disabled,
116
+ [styles.red]: opt.color === 'red' && !isDisabled,
117
+ [styles.cyan]: opt.color === 'cyan' && !isDisabled,
118
+ [styles.menuItemDisabledClickable]: isDisabledClickable,
109
119
  },
110
120
  )}
111
121
  onSelect={(event) => {
@@ -115,7 +125,8 @@ export const createRenderItem = (MenuPrimitives) => {
115
125
  opt.onClick?.()
116
126
  onSelectionChange?.(opt)
117
127
  }}
118
- disabled={opt.disabled}
128
+ disabled={isRadixDisabled}
129
+ aria-disabled={isDisabledClickable || undefined}
119
130
  >
120
131
  {opt.icon && <span className={styles.leftIcon}>{opt.icon}</span>}
121
132
  <div className={styles.labelContainer}>
@@ -163,11 +174,13 @@ export const createRenderItem = (MenuPrimitives) => {
163
174
  [styles.menuItemSelected]:
164
175
  opt.checked && showSelectedItemBackground,
165
176
  [styles[`menuItem-size-${size}`]]: size,
166
- [styles.red]: opt.color === 'red' && !opt.disabled,
167
- [styles.cyan]: opt.color === 'cyan' && !opt.disabled,
177
+ [styles.red]: opt.color === 'red' && !isDisabled,
178
+ [styles.cyan]: opt.color === 'cyan' && !isDisabled,
179
+ [styles.menuItemDisabledClickable]: isDisabledClickable,
168
180
  },
169
181
  )}
170
- disabled={opt.disabled}
182
+ disabled={isRadixDisabled}
183
+ aria-disabled={isDisabledClickable || undefined}
171
184
  >
172
185
  <span className={styles.checkboxIndicatorSlot}>
173
186
  <MenuPrimitives.ItemIndicator