polpo 0.1.1 → 0.1.2

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 (121) hide show
  1. package/.storybook/theme.ts +2 -2
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/README.md +2 -5
  4. package/dist/chunk-CFYQBHH5.js +3 -0
  5. package/dist/chunk-CFYQBHH5.js.map +1 -0
  6. package/dist/chunk-MAWW6AA7.js +3 -0
  7. package/dist/chunk-MAWW6AA7.js.map +1 -0
  8. package/dist/get-modal-position-drle0OjP.d.cts +49 -0
  9. package/dist/get-modal-position-drle0OjP.d.ts +49 -0
  10. package/dist/helpers.cjs +1 -1
  11. package/dist/helpers.cjs.map +1 -1
  12. package/dist/helpers.d.cts +9 -2
  13. package/dist/helpers.d.ts +9 -2
  14. package/dist/helpers.js +1 -1
  15. package/dist/hooks.cjs +1 -1
  16. package/dist/hooks.cjs.map +1 -1
  17. package/dist/hooks.d.cts +59 -21
  18. package/dist/hooks.d.ts +59 -21
  19. package/dist/hooks.js +1 -1
  20. package/dist/ui.cjs +601 -389
  21. package/dist/ui.cjs.map +1 -1
  22. package/dist/ui.d.cts +97 -77
  23. package/dist/ui.d.ts +97 -77
  24. package/dist/ui.js +585 -373
  25. package/dist/ui.js.map +1 -1
  26. package/dist/use-modal-in-container-DiNW1PE_.d.cts +34 -0
  27. package/dist/use-modal-in-container-neGo-kMk.d.ts +34 -0
  28. package/package.json +2 -2
  29. package/src/components/buttons/button/button.stories.tsx +4 -4
  30. package/src/components/buttons/button/button.style.ts +10 -5
  31. package/src/components/buttons/button/button.tsx +7 -19
  32. package/src/components/cards/flip-card/flip-card.tsx +1 -1
  33. package/src/components/cursor/cursor.stories.tsx +35 -0
  34. package/src/components/cursor/cursor.style.ts +73 -0
  35. package/src/components/cursor/cursor.tsx +49 -0
  36. package/src/components/cursor/index.ts +1 -0
  37. package/src/components/form/checkbox/checkbox.stories.tsx +51 -0
  38. package/src/components/form/checkbox/checkbox.style.ts +73 -37
  39. package/src/components/form/checkbox/checkbox.tsx +38 -4
  40. package/src/components/form/field/field.stories.tsx +5 -1
  41. package/src/components/form/field/field.style.ts +12 -0
  42. package/src/components/form/field/field.tsx +3 -1
  43. package/src/components/form/field/field.types.ts +6 -0
  44. package/src/components/form/input-color/input-color.style.ts +5 -4
  45. package/src/components/form/input-color/input-color.tsx +41 -44
  46. package/src/components/form/radio/radio.stories.tsx +29 -5
  47. package/src/components/form/radio/radio.style.ts +45 -24
  48. package/src/components/form/radio/radio.tsx +22 -3
  49. package/src/components/form/select/options.tsx +119 -67
  50. package/src/components/form/select/select.stories.tsx +103 -42
  51. package/src/components/form/select/select.style.ts +10 -92
  52. package/src/components/form/select/select.tsx +19 -42
  53. package/src/components/form/select/select.types.ts +4 -21
  54. package/src/components/form/slider/slider.style.ts +2 -0
  55. package/src/components/icon/icons/social.tsx +17 -1
  56. package/src/components/index.ts +1 -0
  57. package/src/components/infinity-scroll/infinity-scroll.tsx +1 -1
  58. package/src/components/line/line.stories.tsx +3 -4
  59. package/src/components/modals/action-modal/action-modal.stories.tsx +58 -39
  60. package/src/components/modals/action-modal/action-modal.style.ts +13 -25
  61. package/src/components/modals/action-modal/action-modal.tsx +68 -70
  62. package/src/components/modals/aside-modal/aside-modal.stories.tsx +11 -15
  63. package/src/components/modals/aside-modal/aside-modal.style.ts +17 -37
  64. package/src/components/modals/aside-modal/aside-modal.tsx +41 -43
  65. package/src/components/modals/confirmation-modal/confirmation-modal.stories.tsx +21 -9
  66. package/src/components/modals/index.ts +2 -0
  67. package/src/components/modals/menu/index.ts +1 -0
  68. package/src/components/modals/menu/menu.stories.tsx +69 -0
  69. package/src/components/modals/menu/menu.style.ts +62 -0
  70. package/src/components/modals/menu/menu.tsx +142 -0
  71. package/src/components/modals/modal/backdrop.tsx +70 -0
  72. package/src/components/modals/modal/index.ts +1 -0
  73. package/src/components/modals/modal/modal.stories.tsx +325 -0
  74. package/src/components/modals/modal/modal.style.ts +62 -2
  75. package/src/components/modals/modal/modal.tsx +82 -123
  76. package/src/components/modals/portal/index.ts +1 -0
  77. package/src/components/modals/portal/portal.tsx +18 -0
  78. package/src/components/tabs/tabs-list.tsx +13 -10
  79. package/src/components/tabs/tabs.style.ts +48 -43
  80. package/src/components/tag/tag.stories.tsx +11 -12
  81. package/src/components/tag/tag.style.ts +9 -4
  82. package/src/components/tag/tag.tsx +2 -12
  83. package/src/components/tooltips/tooltip/tooltip.stories.tsx +5 -2
  84. package/src/components/tooltips/tooltip/tooltip.style.ts +37 -6
  85. package/src/components/tooltips/tooltip/tooltip.tsx +33 -19
  86. package/src/components/typography/typography.stories.tsx +3 -1
  87. package/src/components/typography/typography.tsx +21 -0
  88. package/src/contexts/theme-context/theme.animations.ts +91 -2
  89. package/src/contexts/theme-context/theme.defaults.ts +1 -1
  90. package/src/core/http-client.ts +49 -47
  91. package/src/core/variants/color.ts +3 -30
  92. package/src/core/variants/radius.ts +12 -41
  93. package/src/core/variants/size.ts +8 -33
  94. package/src/helpers/get-modal-position-relative-to-screen.ts +86 -0
  95. package/src/helpers/get-modal-position.ts +173 -28
  96. package/src/helpers/index.ts +1 -0
  97. package/src/hooks/index.ts +9 -3
  98. package/src/hooks/use-click-outside.ts +32 -0
  99. package/src/hooks/use-cookie.ts +124 -0
  100. package/src/hooks/use-dimensions.ts +11 -14
  101. package/src/hooks/use-dom-container.ts +32 -0
  102. package/src/hooks/use-event-listener.ts +4 -4
  103. package/src/hooks/use-geolocation.ts +63 -0
  104. package/src/hooks/use-in-view.ts +9 -11
  105. package/src/hooks/use-intersection-observer.ts +19 -0
  106. package/src/hooks/use-modal-in-container.ts +60 -52
  107. package/src/hooks/use-modal-transition.ts +54 -0
  108. package/src/hooks/use-modal.ts +21 -0
  109. package/src/hooks/use-mouse-position.ts +55 -7
  110. package/src/hooks/use-resize-observer.ts +18 -0
  111. package/src/stories/GettingStarted.mdx +2 -6
  112. package/svg/Name=npm, Category=social.svg +3 -0
  113. package/dist/chunk-M4KRSYE7.js +0 -3
  114. package/dist/chunk-M4KRSYE7.js.map +0 -1
  115. package/dist/chunk-U5XSMSKZ.js +0 -3
  116. package/dist/chunk-U5XSMSKZ.js.map +0 -1
  117. package/dist/get-modal-position-DPftPoU2.d.cts +0 -28
  118. package/dist/get-modal-position-DPftPoU2.d.ts +0 -28
  119. package/src/components/form/select/select-option.tsx +0 -84
  120. package/src/hooks/use-observer.ts +0 -18
  121. package/src/hooks/use-on-click-outside-ref.ts +0 -17
@@ -1,18 +1,40 @@
1
1
  import { useMemo } from 'react';
2
+ import { DefaultTheme, useTheme } from 'styled-components';
2
3
 
4
+ import { ColorVariants } from '../../../core/variants';
3
5
  import { Icon, IconNameT } from '../../icon';
4
6
  import { Typography } from '../../typography';
5
7
  import { Controller } from '../controller';
6
8
  import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
7
9
 
8
- import { CheckboxContainerStyle, CheckboxStyle } from './checkbox.style';
10
+ import { CheckboxContainerStyle, CheckboxFillStyle, CheckboxStyle } from './checkbox.style';
9
11
 
10
12
  import { useInputHandlers } from '@polpo/hooks';
11
13
 
14
+ type CheckboxColor = {
15
+ color: string;
16
+ colorIcon: string;
17
+ };
18
+
19
+ const getCheckboxColor = (theme: DefaultTheme, color: `${ColorVariants}`): CheckboxColor => {
20
+ const checkboxColors: Record<ColorVariants, CheckboxColor> = {
21
+ [ColorVariants.Primary]: { color: theme.colors.primary.main, colorIcon: theme.colors.primary.contrast },
22
+ [ColorVariants.Secondary]: { color: theme.colors.secondary.main, colorIcon: theme.colors.secondary.contrast },
23
+ [ColorVariants.Tertiary]: { color: theme.colors.tertiary.main, colorIcon: theme.colors.tertiary.contrast },
24
+ [ColorVariants.Info]: { color: theme.colors.info.main, colorIcon: theme.colors.info.contrast },
25
+ [ColorVariants.Active]: { color: theme.colors.active.main, colorIcon: theme.colors.active.contrast },
26
+ [ColorVariants.Warning]: { color: theme.colors.warning.main, colorIcon: theme.colors.warning.contrast },
27
+ [ColorVariants.Alert]: { color: theme.colors.alert.main, colorIcon: theme.colors.alert.contrast },
28
+ };
29
+
30
+ return checkboxColors[color] ?? checkboxColors[ColorVariants.Primary];
31
+ };
32
+
12
33
  type CheckboxProps = {
13
- label?: string;
34
+ label?: React.ReactNode;
14
35
  placeholder?: never;
15
36
  icon?: IconNameT;
37
+ color?: `${ColorVariants}`;
16
38
  };
17
39
 
18
40
  export const Checkbox = ({
@@ -29,6 +51,7 @@ export const Checkbox = ({
29
51
  autoComplete = 'off',
30
52
  icon = 'checkmark',
31
53
  label,
54
+ color = ColorVariants.Primary,
32
55
  /*
33
56
  * isDirty = false,
34
57
  * isTouched = false,
@@ -36,6 +59,7 @@ export const Checkbox = ({
36
59
  * error,
37
60
  */
38
61
  }: UnControlledComponentProps<CheckboxProps, boolean>) => {
62
+ const theme = useTheme();
39
63
  const id = useMemo(() => crypto.randomUUID(), []);
40
64
  const { handlers } = useInputHandlers<HTMLInputElement>({
41
65
  onChange: e => setValue(e.target.checked),
@@ -43,10 +67,20 @@ export const Checkbox = ({
43
67
  onFocus: onFocus,
44
68
  });
45
69
 
70
+ const checkboxColor = getCheckboxColor(theme, color);
71
+
46
72
  return (
47
- <CheckboxContainerStyle className={className} style={style}>
73
+ <CheckboxContainerStyle
74
+ $color={checkboxColor.color}
75
+ $colorIcon={checkboxColor.colorIcon}
76
+ className={className}
77
+ style={style}
78
+ onClick={e => e.stopPropagation()}
79
+ >
48
80
  <CheckboxStyle className={value ? 'is-checked' : ''}>
49
- <Icon name={icon} className='checkbox-icon' />
81
+ <CheckboxFillStyle>
82
+ <Icon name={icon} className='checkbox-icon' />
83
+ </CheckboxFillStyle>
50
84
  <input
51
85
  id={id}
52
86
  type='checkbox'
@@ -3,6 +3,8 @@ import { ContainerDecorator } from '../form.stories.types';
3
3
 
4
4
  import { Field } from './field';
5
5
 
6
+ import { FieldOrientation, FieldVariant } from '@polpo/ui';
7
+
6
8
  import type { Meta, StoryObj } from '@storybook/react';
7
9
 
8
10
  export const FieldSharedArgTypes: Meta<typeof Field>['argTypes'] = {
@@ -10,7 +12,8 @@ export const FieldSharedArgTypes: Meta<typeof Field>['argTypes'] = {
10
12
  rightIcon: { options: [undefined, ...IconNames.toSorted()] },
11
13
  leftIcon: { options: [undefined, ...IconNames.toSorted()] },
12
14
  errorIcon: { options: [undefined, ...IconNames.toSorted()] },
13
- variant: { control: 'select', options: [undefined, 'full-border', 'content-border', 'line'] },
15
+ fieldOrientation: { control: 'inline-radio', options: Object.values(FieldOrientation) },
16
+ variant: { control: 'select', options: [undefined, ...Object.values(FieldVariant)] },
14
17
  };
15
18
 
16
19
  export const FieldSharedArgs: StoryObj<typeof Field>['args'] = {
@@ -37,6 +40,7 @@ const meta: Meta<typeof Field> = {
37
40
  ...FieldSharedArgs,
38
41
  leftIcon: 'facebook',
39
42
  rightIcon: 'airplane',
43
+ fieldOrientation: 'vertical',
40
44
  },
41
45
  decorators: [ContainerDecorator],
42
46
  };
@@ -2,7 +2,9 @@ import styled from 'styled-components';
2
2
 
3
3
  export const FieldStyle = styled.section`
4
4
  display: grid;
5
+ grid-auto-columns: auto;
5
6
  gap: 0.5em;
7
+ transition: all 200ms ease;
6
8
 
7
9
  .field-content {
8
10
  display: grid;
@@ -76,4 +78,14 @@ export const FieldStyle = styled.section`
76
78
  padding: 0 1em;
77
79
  }
78
80
  }
81
+
82
+ &.variant-inline {
83
+ grid-auto-flow: column;
84
+ padding: 0.5em 0;
85
+ align-items: center;
86
+
87
+ .field-label {
88
+ width: auto;
89
+ }
90
+ }
79
91
  `;
@@ -4,7 +4,7 @@ import { Icon, IconNameT } from '../../icon';
4
4
  import { Typography } from '../../typography';
5
5
 
6
6
  import { FieldStyle } from './field.style';
7
- import { FieldProps, FieldVariant } from './field.types';
7
+ import { FieldOrientation, FieldProps, FieldVariant } from './field.types';
8
8
 
9
9
  import { useClassNames } from '@polpo/hooks';
10
10
 
@@ -27,6 +27,7 @@ const FieldComponent = (
27
27
  error,
28
28
  onClickLeftIcon,
29
29
  onClickRightIcon,
30
+ fieldOrientation = FieldOrientation.VERTICAL,
30
31
  children,
31
32
  isFocus = false,
32
33
  variant,
@@ -39,6 +40,7 @@ const FieldComponent = (
39
40
  'variant-content-border': variant === FieldVariant.CONTENT_BORDER,
40
41
  'variant-content-line': variant === FieldVariant.CONTENT_LINE,
41
42
  'variant-full-border': variant === FieldVariant.FULL_BORDER,
43
+ 'variant-inline': fieldOrientation === FieldOrientation.HORIZONTAL,
42
44
  });
43
45
 
44
46
  const handleClick = (callback?: () => void) => (e: React.MouseEvent) => {
@@ -8,6 +8,11 @@ export enum FieldVariant {
8
8
  CONTENT_LINE = 'line',
9
9
  }
10
10
 
11
+ export enum FieldOrientation {
12
+ HORIZONTAL = 'horizontal',
13
+ VERTICAL = 'vertical',
14
+ }
15
+
11
16
  type FieldSharedProps = {
12
17
  rightIcon?: IconNameT;
13
18
  leftIcon?: IconNameT;
@@ -23,6 +28,7 @@ export type FieldProps = FieldSharedProps & {
23
28
  id: string;
24
29
  error?: string;
25
30
  isFocus?: boolean;
31
+ fieldOrientation?: `${FieldOrientation}`;
26
32
  };
27
33
 
28
34
  export type InputFieldProps<T> = T & FieldSharedProps;
@@ -1,17 +1,20 @@
1
1
  import styled from 'styled-components';
2
2
 
3
+ import { Modal } from '../../modals';
4
+
3
5
  export const InputColorStyle = styled.section`
4
6
  display: grid;
5
7
  grid-auto-flow: column;
6
8
  align-items: center;
7
9
  justify-content: start;
10
+ gap: 0.5em;
8
11
 
9
12
  .input-color-value {
10
13
  margin-left: 10px;
11
14
  }
12
15
 
13
16
  .color-input {
14
- padding: 0 1em;
17
+ padding-right: 1em;
15
18
  border-radius: inherit;
16
19
  width: 100%;
17
20
  font-size: ${props => props.theme.constants.typography.label.fontSize};
@@ -41,9 +44,7 @@ export const InputColorBoxStyle = styled.section`
41
44
  }
42
45
  `;
43
46
 
44
- export const InputColorSelectorStyle = styled.section`
45
- position: fixed;
46
- z-index: 1;
47
+ export const InputColorSelectorStyle = styled(Modal)`
47
48
  display: grid;
48
49
  gap: 10px;
49
50
  background: ${props => props.theme.colors.background.main};
@@ -1,17 +1,16 @@
1
1
  import Color from 'color';
2
- import { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { HexAlphaColorPicker, HexColorInput } from 'react-colorful';
4
4
  import useEyeDropper from 'use-eye-dropper';
5
5
 
6
6
  import { Icon } from '../../icon';
7
- import { Modal } from '../../modals';
8
7
  import { Controller } from '../controller';
9
8
  import { Field, InputFieldProps } from '../field';
10
9
  import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
11
10
 
12
11
  import { InputColorBoxStyle, InputColorSelectorStyle, InputColorStyle } from './input-color.style';
13
12
 
14
- import { useInputHandlers, useModalInContainer } from '@polpo/hooks';
13
+ import { useInputHandlers } from '@polpo/hooks';
15
14
 
16
15
  type ColorProps = InputFieldProps<{
17
16
  showValueText?: boolean;
@@ -43,6 +42,8 @@ export const InputColor = ({
43
42
  const { open, isSupported } = useEyeDropper();
44
43
  const [inputValue, setInputValue] = useState<string>(value);
45
44
  const id = useMemo(() => crypto.randomUUID(), []);
45
+ const containerRef = useRef<HTMLElement>(null);
46
+ const [isOpen, setIsOpen] = useState(false);
46
47
  const { handlers, isFocus } = useInputHandlers({
47
48
  onChange: e => setInputValue(e.target.value),
48
49
  onBlur: e => {
@@ -54,10 +55,6 @@ export const InputColor = ({
54
55
  onFocus && onFocus(e);
55
56
  },
56
57
  });
57
- const { modalRef, isVisible, setIsVisible, modalStyle, containerRef } = useModalInContainer({
58
- position: 'bottom',
59
- distancePercentage: 0,
60
- });
61
58
 
62
59
  const borderColor = useMemo(() => {
63
60
  const color = Color(value === '' ? '#000000' : value);
@@ -88,13 +85,7 @@ export const InputColor = ({
88
85
 
89
86
  return (
90
87
  <Field id={id} error={error} isFocus={isFocus} {...fieldProps}>
91
- <InputColorStyle
92
- onClick={e => {
93
- e.stopPropagation();
94
- setIsVisible(true);
95
- }}
96
- ref={containerRef}
97
- >
88
+ <InputColorStyle onClick={() => setIsOpen(true)} ref={containerRef}>
98
89
  <InputColorBoxStyle
99
90
  className={className}
100
91
  style={{
@@ -103,36 +94,7 @@ export const InputColor = ({
103
94
  color: value,
104
95
  ...style,
105
96
  }}
106
- >
107
- <Modal id='input-color' isOpen={isVisible}>
108
- <InputColorSelectorStyle ref={modalRef} style={modalStyle}>
109
- <HexAlphaColorPicker id={id} color={value} onChange={setValue} />
110
- <section className='color-input-container'>
111
- {isSupported() ? (
112
- <Icon
113
- name='dropper'
114
- onClick={() => {
115
- void openEyeDropper();
116
- }}
117
- />
118
- ) : (
119
- <span />
120
- )}
121
- <HexColorInput
122
- className='color-input'
123
- id={id}
124
- name={name}
125
- color={value}
126
- placeholder='Type a color'
127
- prefixed
128
- alpha
129
- onChange={setValue}
130
- />
131
- <span />
132
- </section>
133
- </InputColorSelectorStyle>
134
- </Modal>
135
- </InputColorBoxStyle>
97
+ />
136
98
  {showValueText ? (
137
99
  <input
138
100
  id={id}
@@ -148,6 +110,41 @@ export const InputColor = ({
148
110
  />
149
111
  ) : null}
150
112
  </InputColorStyle>
113
+
114
+ <InputColorSelectorStyle
115
+ id='input-color'
116
+ isOpen={isOpen}
117
+ onClose={() => setIsOpen(false)}
118
+ position='bottom right'
119
+ offset={5}
120
+ backdrop='transparent'
121
+ containerRef={containerRef}
122
+ >
123
+ <HexAlphaColorPicker id={id} color={value} onChange={setValue} />
124
+ <section className='color-input-container'>
125
+ {isSupported() ? (
126
+ <Icon
127
+ name='dropper'
128
+ onClick={() => {
129
+ void openEyeDropper();
130
+ }}
131
+ />
132
+ ) : (
133
+ <span />
134
+ )}
135
+ <HexColorInput
136
+ className='color-input'
137
+ id={id}
138
+ name={name}
139
+ color={value}
140
+ placeholder='Type a color'
141
+ prefixed
142
+ alpha
143
+ onChange={setValue}
144
+ />
145
+ <span />
146
+ </section>
147
+ </InputColorSelectorStyle>
151
148
  </Field>
152
149
  );
153
150
  };
@@ -1,6 +1,7 @@
1
1
  import { useState } from 'react';
2
2
 
3
- import { Grid } from '../../../layouts';
3
+ import { ColorVariants } from '../../../core/variants';
4
+ import { Grid, SectionLayout } from '../../../layouts';
4
5
  import { UnControlledComponentArgTypes } from '../form.stories.types';
5
6
 
6
7
  import { Radio } from './radio';
@@ -15,6 +16,7 @@ const meta: Meta<typeof Radio> = {
15
16
  label: { control: 'text' },
16
17
  radioValue: { control: false },
17
18
  placeholder: { table: { disable: true } },
19
+ color: { control: { type: 'inline-radio', options: Object.values(ColorVariants) } },
18
20
  },
19
21
  args: {
20
22
  label: 'Option A',
@@ -26,10 +28,10 @@ const meta: Meta<typeof Radio> = {
26
28
  return (
27
29
  <Grid gap='0.4em'>
28
30
  <Radio {...args} name='radio' value={value} radioValue='A' setValue={setValue} />
29
- <Radio name='radio' value={value} label='Option B' radioValue='B' setValue={setValue} />
30
- <Radio name='radio' value={value} label='Option C' radioValue='C' setValue={setValue} />
31
- <Radio name='radio' value={value} label='Option D' radioValue='D' setValue={setValue} />
32
- <Radio name='radio' value={value} label='Option E' radioValue='E' setValue={setValue} />
31
+ <Radio {...args} name='radio' value={value} label='Option B' radioValue='B' setValue={setValue} />
32
+ <Radio {...args} name='radio' value={value} label='Option C' radioValue='C' setValue={setValue} />
33
+ <Radio {...args} name='radio' value={value} label='Option D' radioValue='D' setValue={setValue} />
34
+ <Radio {...args} name='radio' value={value} label='Option E' radioValue='E' setValue={setValue} />
33
35
  </Grid>
34
36
  );
35
37
  },
@@ -41,3 +43,25 @@ type Story = StoryObj<typeof Radio>;
41
43
  export const Default: Story = {
42
44
  args: {},
43
45
  };
46
+
47
+ export const Colors: Story = {
48
+ args: {},
49
+ argTypes: {
50
+ color: { control: false },
51
+ },
52
+ render: args => {
53
+ const [value, setValue] = useState('Primary');
54
+
55
+ return (
56
+ <SectionLayout>
57
+ <Radio {...args} color='primary' value={value} setValue={setValue} radioValue='Primary' label='Primary' />
58
+ <Radio {...args} color='secondary' value={value} setValue={setValue} radioValue='Secondary' label='Secondary' />
59
+ <Radio {...args} color='tertiary' value={value} setValue={setValue} radioValue='Tertiary' label='Tertiary' />
60
+ <Radio {...args} color='info' value={value} setValue={setValue} radioValue='Info' label='Info' />
61
+ <Radio {...args} color='active' value={value} setValue={setValue} radioValue='Active' label='Active' />
62
+ <Radio {...args} color='warning' value={value} setValue={setValue} radioValue='Warning' label='Warning' />
63
+ <Radio {...args} color='alert' value={value} setValue={setValue} radioValue='Alert' label='Alert' />
64
+ </SectionLayout>
65
+ );
66
+ },
67
+ };
@@ -1,33 +1,24 @@
1
1
  import styled from 'styled-components';
2
2
 
3
+ export const RadioFillStyle = styled.section`
4
+ transition: all 200ms ease-out;
5
+ border-radius: inherit;
6
+ margin: auto;
7
+ width: 0;
8
+ height: 0;
9
+ `;
10
+
3
11
  export const RadioStyle = styled.section`
4
12
  border-radius: 50%;
5
- background: ${props => props.theme.colors.gray9};
6
- color: ${props => props.theme.colors.gray6};
7
- border: 2px solid;
13
+ background: ${props => props.theme.colors.background.paper};
8
14
  transition: all 300ms ease;
15
+ width: 1.4em;
16
+ height: 1.4em;
17
+ outline: 2px solid;
18
+ display: flex;
9
19
  position: relative;
10
20
  padding: 2px;
11
21
 
12
- .radio-dot {
13
- width: 1em;
14
- height: 1em;
15
- border-radius: 50%;
16
- display: block;
17
- opacity: 0;
18
- transition: opacity 300ms ease;
19
- background: ${props => props.theme.colors.primary.main};
20
- }
21
-
22
- &.is-checked {
23
- background: ${props => props.theme.colors.primary.contrast};
24
- color: ${props => props.theme.colors.primary.main};
25
-
26
- .radio-dot {
27
- opacity: 1;
28
- }
29
- }
30
-
31
22
  .radio-input {
32
23
  position: absolute;
33
24
  top: 0;
@@ -40,7 +31,11 @@ export const RadioStyle = styled.section`
40
31
  }
41
32
  `;
42
33
 
43
- export const RadioContainerStyle = styled.section`
34
+ type RadioContainerStyleProps = {
35
+ $color: string;
36
+ };
37
+
38
+ export const RadioContainerStyle = styled.section<RadioContainerStyleProps>`
44
39
  display: flex;
45
40
  align-items: center;
46
41
  gap: 1em;
@@ -51,8 +46,34 @@ export const RadioContainerStyle = styled.section`
51
46
  user-select: none;
52
47
  }
53
48
 
49
+ ${RadioStyle} {
50
+ color: ${props => props.$color};
51
+
52
+ &.is-checked {
53
+ ${RadioFillStyle} {
54
+ width: 100%;
55
+ height: 100%;
56
+ background: ${props => props.$color};
57
+ }
58
+ }
59
+ }
60
+
54
61
  ${RadioStyle}:hover,
55
62
  &:has(.radio-label:hover) ${RadioStyle} {
56
- box-shadow: 0 0 0 0.4em ${props => props.theme.colors.primary.main}88;
63
+ box-shadow: 0 0 0 0.4em ${props => props.$color}88;
64
+
65
+ ${RadioFillStyle} {
66
+ width: 20%;
67
+ height: 20%;
68
+ background: ${props => props.$color}88;
69
+ }
70
+
71
+ &:is(.is-checked) {
72
+ ${RadioFillStyle} {
73
+ width: 80%;
74
+ height: 80%;
75
+ background: ${props => props.$color};
76
+ }
77
+ }
57
78
  }
58
79
  `;
@@ -1,17 +1,34 @@
1
1
  import { useMemo } from 'react';
2
+ import { DefaultTheme, useTheme } from 'styled-components';
2
3
 
4
+ import { ColorVariants } from '../../../core/variants';
3
5
  import { Typography } from '../../typography';
4
6
  import { Controller } from '../controller';
5
7
  import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
6
8
 
7
- import { RadioContainerStyle, RadioStyle } from './radio.style';
9
+ import { RadioContainerStyle, RadioFillStyle, RadioStyle } from './radio.style';
8
10
 
9
11
  import { useInputHandlers } from '@polpo/hooks';
10
12
 
13
+ const getRadioColor = (theme: DefaultTheme, color: `${ColorVariants}`): string => {
14
+ const radioColors: Record<ColorVariants, string> = {
15
+ [ColorVariants.Primary]: theme.colors.primary.main,
16
+ [ColorVariants.Secondary]: theme.colors.secondary.main,
17
+ [ColorVariants.Tertiary]: theme.colors.tertiary.main,
18
+ [ColorVariants.Info]: theme.colors.info.main,
19
+ [ColorVariants.Active]: theme.colors.active.main,
20
+ [ColorVariants.Warning]: theme.colors.warning.main,
21
+ [ColorVariants.Alert]: theme.colors.alert.main,
22
+ };
23
+
24
+ return radioColors[color] ?? radioColors[ColorVariants.Primary];
25
+ };
26
+
11
27
  type RadioProps = {
12
28
  label?: string;
13
29
  radioValue: string;
14
30
  placeholder?: never;
31
+ color?: `${ColorVariants}`;
15
32
  };
16
33
 
17
34
  export const Radio = ({
@@ -28,6 +45,7 @@ export const Radio = ({
28
45
  autoComplete = 'off',
29
46
  radioValue,
30
47
  label,
48
+ color = ColorVariants.Primary,
31
49
  /*
32
50
  * isDirty = false,
33
51
  * isTouched = false,
@@ -35,6 +53,7 @@ export const Radio = ({
35
53
  * error,
36
54
  */
37
55
  }: UnControlledComponentProps<RadioProps, string>) => {
56
+ const theme = useTheme();
38
57
  const id = useMemo(() => crypto.randomUUID(), []);
39
58
  const { handlers } = useInputHandlers({
40
59
  onChange: e => setValue(e.target.value),
@@ -43,9 +62,9 @@ export const Radio = ({
43
62
  });
44
63
 
45
64
  return (
46
- <RadioContainerStyle className={className} style={style}>
65
+ <RadioContainerStyle $color={getRadioColor(theme, color)} className={className} style={style}>
47
66
  <RadioStyle className={radioValue === value ? 'is-checked' : ''}>
48
- <span className='radio-dot' />
67
+ <RadioFillStyle />
49
68
  <input
50
69
  id={id}
51
70
  type='radio'