@charcoal-ui/react 4.0.0-beta.3 → 4.0.0-beta.5

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 (176) hide show
  1. package/dist/_lib/useClassNames.d.ts +2 -2
  2. package/dist/_lib/useClassNames.d.ts.map +1 -1
  3. package/dist/components/Checkbox/CheckboxInput/index.d.ts +11 -0
  4. package/dist/components/Checkbox/CheckboxInput/index.d.ts.map +1 -0
  5. package/dist/components/Checkbox/CheckboxWithLabel.d.ts +9 -0
  6. package/dist/components/Checkbox/CheckboxWithLabel.d.ts.map +1 -0
  7. package/dist/components/Checkbox/index.d.ts +12 -21
  8. package/dist/components/Checkbox/index.d.ts.map +1 -1
  9. package/dist/components/Clickable/index.d.ts +10 -13
  10. package/dist/components/Clickable/index.d.ts.map +1 -1
  11. package/dist/components/DropdownSelector/Popover/index.d.ts +1 -2
  12. package/dist/components/DropdownSelector/Popover/index.d.ts.map +1 -1
  13. package/dist/components/DropdownSelector/index.d.ts.map +1 -1
  14. package/dist/components/FieldLabel/index.d.ts +1 -0
  15. package/dist/components/FieldLabel/index.d.ts.map +1 -1
  16. package/dist/components/IconButton/index.d.ts +7 -5
  17. package/dist/components/IconButton/index.d.ts.map +1 -1
  18. package/dist/components/LoadingSpinner/index.d.ts +1 -0
  19. package/dist/components/LoadingSpinner/index.d.ts.map +1 -1
  20. package/dist/components/Modal/Dialog/index.d.ts +6 -24
  21. package/dist/components/Modal/Dialog/index.d.ts.map +1 -1
  22. package/dist/components/Modal/ModalPlumbing.d.ts +10 -3
  23. package/dist/components/Modal/ModalPlumbing.d.ts.map +1 -1
  24. package/dist/components/Modal/index.d.ts +2 -2
  25. package/dist/components/Modal/index.d.ts.map +1 -1
  26. package/dist/components/Modal/useCustomModalOverlay.d.ts.map +1 -1
  27. package/dist/components/Radio/index.d.ts +6 -8
  28. package/dist/components/Radio/index.d.ts.map +1 -1
  29. package/dist/components/SegmentedControl/index.d.ts +1 -0
  30. package/dist/components/SegmentedControl/index.d.ts.map +1 -1
  31. package/dist/components/Switch/SwitchInput/index.d.ts +9 -0
  32. package/dist/components/Switch/SwitchInput/index.d.ts.map +1 -0
  33. package/dist/components/Switch/SwitchWithLabel.d.ts +9 -0
  34. package/dist/components/Switch/SwitchWithLabel.d.ts.map +1 -0
  35. package/dist/components/Switch/index.d.ts +4 -15
  36. package/dist/components/Switch/index.d.ts.map +1 -1
  37. package/dist/components/TagItem/index.d.ts +14 -15
  38. package/dist/components/TagItem/index.d.ts.map +1 -1
  39. package/dist/components/TextArea/index.d.ts +28 -18
  40. package/dist/components/TextArea/index.d.ts.map +1 -1
  41. package/dist/components/TextField/index.d.ts +32 -19
  42. package/dist/components/TextField/index.d.ts.map +1 -1
  43. package/dist/core/CharcoalProvider.d.ts +1 -1
  44. package/dist/core/CharcoalProvider.d.ts.map +1 -1
  45. package/dist/index.cjs.js +456 -1079
  46. package/dist/index.cjs.js.map +1 -1
  47. package/dist/index.css +790 -0
  48. package/dist/index.css.map +1 -1
  49. package/dist/index.d.ts +1 -2
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.esm.js +454 -1075
  52. package/dist/index.esm.js.map +1 -1
  53. package/dist/styled.d.ts +4 -4
  54. package/package.json +17 -19
  55. package/src/_lib/useClassNames.ts +3 -9
  56. package/src/components/Checkbox/CheckboxInput/__snapshots__/index.story.storyshot +77 -0
  57. package/src/components/Checkbox/CheckboxInput/index.css +111 -0
  58. package/src/components/Checkbox/CheckboxInput/index.story.tsx +51 -0
  59. package/src/components/Checkbox/CheckboxInput/index.tsx +47 -0
  60. package/src/components/Checkbox/CheckboxWithLabel.tsx +24 -0
  61. package/src/components/Checkbox/__snapshots__/index.story.storyshot +103 -538
  62. package/src/components/Checkbox/index.css +21 -0
  63. package/src/components/Checkbox/index.story.tsx +48 -78
  64. package/src/components/Checkbox/index.tsx +32 -162
  65. package/src/components/Clickable/__snapshots__/index.story.storyshot +2 -78
  66. package/src/components/Clickable/index.css +41 -0
  67. package/src/components/Clickable/index.story.tsx +1 -1
  68. package/src/components/Clickable/index.tsx +25 -85
  69. package/src/components/DropdownSelector/ListItem/__snapshots__/index.story.storyshot +10 -135
  70. package/src/components/DropdownSelector/Popover/index.tsx +1 -2
  71. package/src/components/DropdownSelector/__snapshots__/index.story.storyshot +308 -1014
  72. package/src/components/DropdownSelector/index.tsx +9 -38
  73. package/src/components/FieldLabel/index.css +35 -0
  74. package/src/components/FieldLabel/index.tsx +15 -105
  75. package/src/components/IconButton/__snapshots__/index.story.storyshot +18 -296
  76. package/src/components/IconButton/index.css +118 -0
  77. package/src/components/IconButton/index.story.tsx +16 -39
  78. package/src/components/IconButton/index.tsx +41 -118
  79. package/src/components/LoadingSpinner/__snapshots__/LoadingSpinnerIcon.story.storyshot +2 -17
  80. package/src/components/LoadingSpinner/__snapshots__/index.story.storyshot +79 -29
  81. package/src/components/LoadingSpinner/index.css +42 -0
  82. package/src/components/LoadingSpinner/index.story.tsx +18 -7
  83. package/src/components/LoadingSpinner/index.tsx +26 -52
  84. package/src/components/Modal/Dialog/index.css +44 -0
  85. package/src/components/Modal/Dialog/index.tsx +13 -57
  86. package/src/components/Modal/ModalPlumbing.css +40 -0
  87. package/src/components/Modal/ModalPlumbing.tsx +22 -61
  88. package/src/components/Modal/__snapshots__/index.story.storyshot +459 -1881
  89. package/src/components/Modal/index.css +36 -0
  90. package/src/components/Modal/index.tsx +27 -74
  91. package/src/components/Modal/useCustomModalOverlay.tsx +5 -4
  92. package/src/components/Radio/__snapshots__/index.story.storyshot +51 -776
  93. package/src/components/Radio/index.css +97 -0
  94. package/src/components/Radio/index.story.tsx +20 -30
  95. package/src/components/Radio/index.test.tsx +0 -1
  96. package/src/components/Radio/index.tsx +60 -170
  97. package/src/components/SegmentedControl/__snapshots__/index.story.storyshot +30 -260
  98. package/src/components/SegmentedControl/index.css +50 -0
  99. package/src/components/SegmentedControl/index.tsx +20 -89
  100. package/src/components/Switch/SwitchInput/index.css +82 -0
  101. package/src/components/Switch/SwitchInput/index.tsx +40 -0
  102. package/src/components/Switch/SwitchWithLabel.tsx +24 -0
  103. package/src/components/Switch/__snapshots__/index.story.storyshot +34 -538
  104. package/src/components/Switch/index.css +23 -0
  105. package/src/components/Switch/index.story.tsx +15 -18
  106. package/src/components/Switch/index.tsx +43 -140
  107. package/src/components/TagItem/__snapshots__/index.story.storyshot +212 -1063
  108. package/src/components/TagItem/index.css +140 -0
  109. package/src/components/TagItem/index.story.tsx +44 -161
  110. package/src/components/TagItem/index.tsx +76 -220
  111. package/src/components/TextArea/TextArea.story.tsx +62 -24
  112. package/src/components/TextArea/__snapshots__/TextArea.story.storyshot +1024 -792
  113. package/src/components/TextArea/index.tsx +68 -89
  114. package/src/components/TextField/TextField.story.tsx +77 -67
  115. package/src/components/TextField/__snapshots__/TextField.story.storyshot +1152 -1274
  116. package/src/components/TextField/index.tsx +77 -103
  117. package/src/components/a11y.test.tsx +1 -1
  118. package/src/core/CharcoalProvider.tsx +1 -1
  119. package/src/index.ts +0 -7
  120. package/src/type.d.ts +6 -0
  121. package/dist/components/Button/index.story.d.ts +0 -22
  122. package/dist/components/Button/index.story.d.ts.map +0 -1
  123. package/dist/components/Button/index.test.d.ts +0 -2
  124. package/dist/components/Button/index.test.d.ts.map +0 -1
  125. package/dist/components/Checkbox/index.story.d.ts +0 -8
  126. package/dist/components/Checkbox/index.story.d.ts.map +0 -1
  127. package/dist/components/Clickable/index.story.d.ts +0 -6
  128. package/dist/components/Clickable/index.story.d.ts.map +0 -1
  129. package/dist/components/DropdownSelector/ListItem/index.story.d.ts +0 -9
  130. package/dist/components/DropdownSelector/ListItem/index.story.d.ts.map +0 -1
  131. package/dist/components/DropdownSelector/MenuList/index.story.d.ts +0 -8
  132. package/dist/components/DropdownSelector/MenuList/index.story.d.ts.map +0 -1
  133. package/dist/components/DropdownSelector/Popover/index.story.d.ts +0 -5
  134. package/dist/components/DropdownSelector/Popover/index.story.d.ts.map +0 -1
  135. package/dist/components/DropdownSelector/index.story.d.ts +0 -19
  136. package/dist/components/DropdownSelector/index.story.d.ts.map +0 -1
  137. package/dist/components/Icon/index.story.d.ts +0 -6
  138. package/dist/components/Icon/index.story.d.ts.map +0 -1
  139. package/dist/components/IconButton/index.story.d.ts +0 -9
  140. package/dist/components/IconButton/index.story.d.ts.map +0 -1
  141. package/dist/components/LoadingSpinner/LoadingSpinnerIcon.story.d.ts +0 -8
  142. package/dist/components/LoadingSpinner/LoadingSpinnerIcon.story.d.ts.map +0 -1
  143. package/dist/components/LoadingSpinner/index.story.d.ts +0 -6
  144. package/dist/components/LoadingSpinner/index.story.d.ts.map +0 -1
  145. package/dist/components/Modal/index.story.d.ts +0 -21
  146. package/dist/components/Modal/index.story.d.ts.map +0 -1
  147. package/dist/components/MultiSelect/context.d.ts +0 -14
  148. package/dist/components/MultiSelect/context.d.ts.map +0 -1
  149. package/dist/components/MultiSelect/index.d.ts +0 -36
  150. package/dist/components/MultiSelect/index.d.ts.map +0 -1
  151. package/dist/components/MultiSelect/index.story.d.ts +0 -82
  152. package/dist/components/MultiSelect/index.story.d.ts.map +0 -1
  153. package/dist/components/MultiSelect/index.test.d.ts +0 -2
  154. package/dist/components/MultiSelect/index.test.d.ts.map +0 -1
  155. package/dist/components/Radio/index.story.d.ts +0 -26
  156. package/dist/components/Radio/index.story.d.ts.map +0 -1
  157. package/dist/components/Radio/index.test.d.ts +0 -2
  158. package/dist/components/Radio/index.test.d.ts.map +0 -1
  159. package/dist/components/SegmentedControl/index.story.d.ts +0 -7
  160. package/dist/components/SegmentedControl/index.story.d.ts.map +0 -1
  161. package/dist/components/Switch/index.story.d.ts +0 -9
  162. package/dist/components/Switch/index.story.d.ts.map +0 -1
  163. package/dist/components/TagItem/index.story.d.ts +0 -16
  164. package/dist/components/TagItem/index.story.d.ts.map +0 -1
  165. package/dist/components/TextArea/TextArea.story.d.ts +0 -9
  166. package/dist/components/TextArea/TextArea.story.d.ts.map +0 -1
  167. package/dist/components/TextField/TextField.story.d.ts +0 -22
  168. package/dist/components/TextField/TextField.story.d.ts.map +0 -1
  169. package/dist/components/a11y.test.d.ts +0 -2
  170. package/dist/components/a11y.test.d.ts.map +0 -1
  171. package/src/components/LoadingSpinner/LoadingSpinnerIcon.story.tsx +0 -13
  172. package/src/components/MultiSelect/__snapshots__/index.story.storyshot +0 -1066
  173. package/src/components/MultiSelect/context.ts +0 -23
  174. package/src/components/MultiSelect/index.story.tsx +0 -216
  175. package/src/components/MultiSelect/index.test.tsx +0 -263
  176. package/src/components/MultiSelect/index.tsx +0 -281
@@ -1,103 +1,73 @@
1
- import { action } from '@storybook/addon-actions'
2
1
  import Checkbox from '.'
3
2
  import { Meta, StoryObj } from '@storybook/react'
3
+ import { useCallback, useState } from 'react'
4
4
 
5
5
  export default {
6
6
  title: 'Checkbox',
7
7
  component: Checkbox,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
8
11
  } as Meta<typeof Checkbox>
9
12
 
10
- export const Labelled: StoryObj<typeof Checkbox> = {
11
- args: {
12
- checked: false,
13
- defaultChecked: false,
14
- disabled: false,
15
- readonly: false,
16
- invalid: false,
13
+ export const Default: StoryObj<typeof Checkbox> = {
14
+ argTypes: {
15
+ checked: { type: 'boolean' },
16
+ children: { type: 'string' },
17
+ disabled: { type: 'boolean' },
18
+ invalid: { type: 'boolean' },
19
+ readOnly: { type: 'boolean' },
17
20
  },
18
- render: (props) => {
19
- return (
20
- <div>
21
- <div style={{ marginBottom: '1em' }}>
22
- <Checkbox
23
- {...props}
24
- name="labelled"
25
- label="label"
26
- onBlur={action('blur')}
27
- onClick={action('click')}
28
- onChange={action('change')}
29
- onFocus={action('focus')}
30
- >
31
- 同意する
32
- </Checkbox>
33
- </div>
21
+ render: function Render(props) {
22
+ const [checked, setChecked] = useState(props.checked)
23
+ const handleChange = useCallback((isSelected: boolean) => {
24
+ setChecked(isSelected)
25
+ }, [])
34
26
 
35
- <div>
36
- <Checkbox
37
- {...props}
38
- name="labelled"
39
- label="label"
40
- onBlur={action('blur')}
41
- onClick={action('click')}
42
- onChange={action('change')}
43
- onFocus={action('focus')}
44
- >
45
- <span style={{ width: 200, display: 'block' }}>
46
- 同意する同意する同意する同意する同意する同意する同意する同意する同意する同意する同意する同意する同意する
47
- </span>
48
- </Checkbox>
49
- </div>
50
- </div>
27
+ return (
28
+ <Checkbox
29
+ {...props}
30
+ checked={checked ?? props.checked}
31
+ onChange={handleChange}
32
+ />
51
33
  )
52
34
  },
53
35
  }
54
36
 
55
- export const Invalid: StoryObj<typeof Checkbox> = {
56
- args: {
57
- checked: false,
58
- defaultChecked: false,
59
- disabled: false,
60
- readonly: false,
37
+ export const Label: StoryObj<typeof Checkbox> = {
38
+ render: () => {
39
+ return <Checkbox>Checkbox</Checkbox>
61
40
  },
62
- render: (props) => {
41
+ }
42
+
43
+ export const Checked: StoryObj<typeof Checkbox> = {
44
+ render: () => {
45
+ return <Checkbox checked>Checked</Checkbox>
46
+ },
47
+ }
48
+
49
+ export const Disabled: StoryObj<typeof Checkbox> = {
50
+ render: () => {
51
+ return <Checkbox disabled>Disabled</Checkbox>
52
+ },
53
+ }
54
+
55
+ export const ReadOnly: StoryObj<typeof Checkbox> = {
56
+ render: () => {
63
57
  return (
64
- <Checkbox
65
- {...props}
66
- name="labelled"
67
- label="label"
68
- invalid
69
- onBlur={action('blur')}
70
- onClick={action('click')}
71
- onChange={action('change')}
72
- onFocus={action('focus')}
73
- >
74
- 同意する
58
+ <Checkbox checked name="labelled" readOnly>
59
+ ReadOnly
75
60
  </Checkbox>
76
61
  )
77
62
  },
78
63
  }
79
64
 
80
- export const Unlabelled: StoryObj<typeof Checkbox> = {
81
- args: {
82
- checked: false,
83
- defaultChecked: false,
84
- disabled: false,
85
- readonly: false,
86
- invalid: false,
87
- },
88
- render: (props) => {
65
+ export const Invalid: StoryObj<typeof Checkbox> = {
66
+ render: () => {
89
67
  return (
90
- <div>
91
- <Checkbox
92
- {...props}
93
- name="unlabelled"
94
- label="label"
95
- onBlur={action('blur')}
96
- onClick={action('click')}
97
- onChange={action('change')}
98
- onFocus={action('focus')}
99
- />
100
- </div>
68
+ <Checkbox name="labelled" invalid>
69
+ Invalid
70
+ </Checkbox>
101
71
  )
102
72
  },
103
73
  }
@@ -1,169 +1,39 @@
1
- import { forwardRef, memo, useMemo } from 'react'
2
- import * as React from 'react'
3
- import styled, { css } from 'styled-components'
4
- import { useCheckbox } from '@react-aria/checkbox'
5
- import { useObjectRef } from '@react-aria/utils'
6
- import { useToggleState } from 'react-stately'
7
-
8
- import type { AriaCheckboxProps } from '@react-types/checkbox'
9
- import Icon from '../Icon'
10
- import { focusVisibleFocusRingCss } from '@charcoal-ui/styled'
11
-
12
- type CheckboxLabelProps =
13
- | {
14
- children: React.ReactNode
15
- }
16
- | {
17
- label: string
18
- }
19
-
20
- export type CheckboxProps = CheckboxLabelProps & {
21
- readonly id?: string
22
- readonly name?: string
23
- readonly className?: string
24
-
25
- readonly checked?: boolean
26
- readonly defaultChecked?: boolean
27
- readonly disabled?: boolean
28
- readonly readonly?: boolean
29
- readonly invalid?: boolean
30
-
31
- readonly onClick?: () => void
32
- readonly onChange?: (isSelected: boolean) => void
33
- readonly onBlur?: () => void
34
- readonly onFocus?: () => void
35
- }
36
-
37
- const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
38
- function CheckboxInner({ invalid = false, ...props }, ref) {
39
- const ariaCheckboxProps = useMemo<AriaCheckboxProps>(
40
- () => ({
41
- ...props,
42
- isInValid: invalid,
43
- isSelected: props.checked,
44
- defaultSelected: props.defaultChecked,
45
- validationState: invalid ? 'invalid' : 'valid',
46
- // children がいない場合は aria-label をつけないといけない
47
- 'aria-label': 'children' in props ? undefined : props.label,
48
- isDisabled: props.disabled,
49
- }),
50
- [invalid, props]
1
+ import './index.css'
2
+
3
+ import { forwardRef, memo } from 'react'
4
+ import { useId } from '@react-aria/utils'
5
+ import CheckboxInput, { CheckboxInputProps } from './CheckboxInput'
6
+ import { CheckboxWithLabel } from './CheckboxWithLabel'
7
+
8
+ export type CheckboxProps = CheckboxInputProps
9
+
10
+ const Checkbox = forwardRef<HTMLInputElement, CheckboxInputProps>(
11
+ function Checkbox({ disabled, className, id, children, ...props }, ref) {
12
+ const htmlId = useId(id)
13
+ const noChildren = children === undefined
14
+ const input = (
15
+ <CheckboxInput
16
+ {...props}
17
+ className={noChildren ? className : undefined}
18
+ disabled={disabled}
19
+ id={htmlId}
20
+ ref={ref}
21
+ />
51
22
  )
52
- const state = useToggleState(ariaCheckboxProps)
53
- const objectRef = useObjectRef(ref)
54
-
55
- const { inputProps } = useCheckbox(ariaCheckboxProps, state, objectRef)
56
- const isDisabled = (props.disabled ?? false) || (props.readonly ?? false)
57
-
23
+ if (noChildren) {
24
+ return input
25
+ }
58
26
  return (
59
- <InputRoot aria-disabled={isDisabled} className={props.className}>
60
- <CheckboxRoot>
61
- <CheckboxInput
62
- type="checkbox"
63
- {...inputProps}
64
- readOnly={props.readonly}
65
- />
66
- <CheckboxInputOverlay aria-hidden={true} checked={inputProps.checked}>
67
- <Icon name="24/Check" unsafeNonGuidelineScale={2 / 3} />
68
- </CheckboxInputOverlay>
69
- </CheckboxRoot>
70
-
71
- {'children' in props && <InputLabel>{props.children}</InputLabel>}
72
- </InputRoot>
27
+ <CheckboxWithLabel
28
+ className={className}
29
+ disabled={disabled}
30
+ id={htmlId}
31
+ input={input}
32
+ >
33
+ {children}
34
+ </CheckboxWithLabel>
73
35
  )
74
36
  }
75
37
  )
76
38
 
77
39
  export default memo(Checkbox)
78
-
79
- const hiddenCss = css`
80
- visibility: hidden;
81
- `
82
-
83
- const InputRoot = styled.label`
84
- position: relative;
85
- display: flex;
86
-
87
- cursor: pointer;
88
-
89
- gap: 4px;
90
- &:disabled,
91
- &[aria-disabled]:not([aria-disabled='false']) {
92
- cursor: default;
93
- opacity: 0.32;
94
- }
95
- `
96
-
97
- const CheckboxRoot = styled.div`
98
- position: relative;
99
- `
100
-
101
- const CheckboxInput = styled.input`
102
- &[type='checkbox'] {
103
- appearance: none;
104
- display: block;
105
- cursor: pointer;
106
- margin: 0;
107
- width: 20px;
108
- height: 20px;
109
- border-radius: 4px;
110
- transition: 0.2s box-shadow, 0.2s background-color;
111
-
112
- &:disabled {
113
- cursor: default;
114
- }
115
- &:read-only {
116
- cursor: default;
117
- }
118
-
119
- &:checked {
120
- background-color: var(--charcoal-brand);
121
-
122
- &:not(:disabled):not([aria-disabled]),
123
- &[aria-disabled='false'] {
124
- &:hover {
125
- background-color: var(--charcoal-brand-hover);
126
- }
127
- &:active {
128
- background-color: var(--charcoal-brand-press);
129
- }
130
- }
131
- }
132
-
133
- &:not(:disabled):not([aria-disabled]),
134
- &[aria-disabled='false'] {
135
- ${focusVisibleFocusRingCss}
136
- &[aria-invalid='true'] {
137
- box-shadow: 0 0 0 4px rgba(255, 43, 0, 0.32);
138
- }
139
- }
140
-
141
- &:not(:checked) {
142
- border-width: 2px;
143
- border-style: solid;
144
- border-color: var(--charcoal-text4);
145
- }
146
- }
147
- `
148
-
149
- const CheckboxInputOverlay = styled.div<{ checked?: boolean }>`
150
- position: absolute;
151
- top: -2px;
152
- left: -2px;
153
- box-sizing: border-box;
154
- display: flex;
155
- align-items: center;
156
- justify-content: center;
157
- width: 24px;
158
- height: 24px;
159
- color: var(--charcoal-text5);
160
-
161
- ${({ checked }) => checked !== true && hiddenCss};
162
- `
163
-
164
- const InputLabel = styled.div`
165
- color: var(--charcoal-text2);
166
- font-size: 14px;
167
- /** checkbox の height が 20px なのでcheckbox と text が揃っているように見せるために行ボックスの高さを 20px にしている */
168
- line-height: 20px;
169
- `
@@ -1,49 +1,11 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`Storybook Tests Clickable Button 1`] = `
4
- .c0 {
5
- cursor: pointer;
6
- -webkit-appearance: none;
7
- -moz-appearance: none;
8
- appearance: none;
9
- background: transparent;
10
- padding: 0;
11
- border-style: none;
12
- outline: none;
13
- color: inherit;
14
- text-rendering: inherit;
15
- -webkit-letter-spacing: inherit;
16
- -moz-letter-spacing: inherit;
17
- -ms-letter-spacing: inherit;
18
- letter-spacing: inherit;
19
- word-spacing: inherit;
20
- -webkit-text-decoration: none;
21
- text-decoration: none;
22
- font: inherit;
23
- margin: 0;
24
- overflow: visible;
25
- text-transform: none;
26
- }
27
-
28
- .c0:disabled,
29
- .c0[aria-disabled]:not([aria-disabled=false]) {
30
- cursor: default;
31
- }
32
-
33
- .c0:focus {
34
- outline: none;
35
- }
36
-
37
- .c0::-moz-focus-inner {
38
- border-style: none;
39
- padding: 0;
40
- }
41
-
42
4
  <div
43
5
  data-dark={false}
44
6
  >
45
7
  <button
46
- className="c0"
8
+ className="charcoal-clickable"
47
9
  onClick={[Function]}
48
10
  >
49
11
  button
@@ -52,49 +14,11 @@ exports[`Storybook Tests Clickable Button 1`] = `
52
14
  `;
53
15
 
54
16
  exports[`Storybook Tests Clickable Link 1`] = `
55
- .c0 {
56
- cursor: pointer;
57
- -webkit-appearance: none;
58
- -moz-appearance: none;
59
- appearance: none;
60
- background: transparent;
61
- padding: 0;
62
- border-style: none;
63
- outline: none;
64
- color: inherit;
65
- text-rendering: inherit;
66
- -webkit-letter-spacing: inherit;
67
- -moz-letter-spacing: inherit;
68
- -ms-letter-spacing: inherit;
69
- letter-spacing: inherit;
70
- word-spacing: inherit;
71
- -webkit-text-decoration: none;
72
- text-decoration: none;
73
- font: inherit;
74
- margin: 0;
75
- overflow: visible;
76
- text-transform: none;
77
- }
78
-
79
- .c0:disabled,
80
- .c0[aria-disabled]:not([aria-disabled=false]) {
81
- cursor: default;
82
- }
83
-
84
- .c0:focus {
85
- outline: none;
86
- }
87
-
88
- .c0::-moz-focus-inner {
89
- border-style: none;
90
- padding: 0;
91
- }
92
-
93
17
  <div
94
18
  data-dark={false}
95
19
  >
96
20
  <a
97
- className="c0"
21
+ className="charcoal-clickable"
98
22
  href="#"
99
23
  onClick={[Function]}
100
24
  >
@@ -0,0 +1,41 @@
1
+ .charcoal-clickable {
2
+ cursor: pointer;
3
+
4
+ /* Reset button appearance */
5
+ appearance: none;
6
+ background: transparent;
7
+ padding: 0;
8
+ border-style: none;
9
+ outline: none;
10
+ color: inherit;
11
+ text-rendering: inherit;
12
+ letter-spacing: inherit;
13
+ word-spacing: inherit;
14
+ text-decoration: none;
15
+
16
+ /* Change the font styles in all browsers. */
17
+ font: inherit;
18
+
19
+ /* Remove the margin in Firefox and Safari. */
20
+ margin: 0;
21
+
22
+ /* Show the overflow in Edge. */
23
+ overflow: visible;
24
+
25
+ /* Remove the inheritance of text transform in Firefox. */
26
+ text-transform: none;
27
+ }
28
+
29
+ .charcoal-clickable:disabled,
30
+ .charcoal-clickable[aria-disabled]:not([aria-disabled='false']) {
31
+ cursor: default;
32
+ }
33
+
34
+ .charcoal-clickable:focus {
35
+ outline: none;
36
+ }
37
+
38
+ .charcoal-clickable::-moz-focus-inner {
39
+ border-style: none;
40
+ padding: 0;
41
+ }
@@ -13,7 +13,7 @@ export const Button: StoryObj = {
13
13
 
14
14
  export const Link: StoryObj = {
15
15
  render: () => (
16
- <Clickable to="#" onClick={action('click')}>
16
+ <Clickable as="a" href="#" onClick={action('click')}>
17
17
  link
18
18
  </Clickable>
19
19
  ),
@@ -1,91 +1,31 @@
1
- import * as React from 'react'
2
- import styled from 'styled-components'
3
- import {
4
- LinkProps,
5
- useComponentAbstraction,
6
- } from '../../core/ComponentAbstraction'
7
- import { disabledSelector } from '@charcoal-ui/utils'
1
+ import React, { useMemo, forwardRef } from 'react'
2
+ import { useClassNames } from '../../_lib/useClassNames'
3
+ import './index.css'
8
4
 
9
- interface BaseProps {
5
+ export type ClickableProps<T extends React.ElementType = 'button'> = {
10
6
  /**
11
- * クリックの無効化
7
+ * The component used for root element.
8
+ * @type T extends React.ElementType = 'button'
12
9
  */
13
- disabled?: boolean
14
- }
15
-
16
- interface LinkBaseProps {
10
+ as?: T
17
11
  /**
18
- * リンクのURL。指定するとbuttonタグではなくaタグとして描画される
12
+ * The as property of the component specified by the Button component's as attribute.
19
13
  */
20
- to: string
21
- }
22
-
23
- export type ClickableProps =
24
- | (BaseProps & Omit<React.ComponentPropsWithoutRef<'button'>, 'disabled'>)
25
- | (BaseProps & LinkBaseProps & Omit<LinkProps, 'to'>)
26
- export type ClickableElement = HTMLButtonElement & HTMLAnchorElement
27
-
28
- const Clickable = React.forwardRef<ClickableElement, ClickableProps>(
29
- function Clickable(props, ref) {
30
- const { Link } = useComponentAbstraction()
31
- const isLink = 'to' in props
32
- const as = isLink ? Link : 'button'
33
- const ariaDisabled = isLink && props.disabled === true ? true : undefined
34
- let rest = props
35
- if (isLink) {
36
- const { disabled, ..._rest } = props
37
- rest = _rest
38
- }
39
- return (
40
- <StyledClickableDiv
41
- {...rest}
42
- ref={ref}
43
- as={as}
44
- aria-disabled={ariaDisabled}
45
- />
46
- )
47
- }
48
- )
14
+ componentAs?: React.ComponentPropsWithRef<T>['as']
15
+ } & Omit<React.ComponentPropsWithRef<T>, 'as'>
16
+
17
+ const Clickable = forwardRef(function Clickable<T extends React.ElementType>(
18
+ { componentAs, as, ...props }: ClickableProps<T>,
19
+ ref: React.ForwardedRef<HTMLButtonElement>
20
+ ) {
21
+ const className = useClassNames('charcoal-clickable', props.className)
22
+
23
+ const Component = useMemo(() => as ?? 'button', [as])
24
+
25
+ return (
26
+ <Component {...props} ref={ref} className={className} as={componentAs} />
27
+ )
28
+ }) as <T extends React.ElementType = 'button'>(
29
+ p: ClickableProps<T>
30
+ ) => JSX.Element
49
31
  export default Clickable
50
-
51
- const StyledClickableDiv = styled.div`
52
- cursor: pointer;
53
-
54
- ${disabledSelector} {
55
- cursor: default;
56
- }
57
-
58
- /* Reset button appearance */
59
- appearance: none;
60
- background: transparent;
61
- padding: 0;
62
- border-style: none;
63
- outline: none;
64
- color: inherit;
65
- text-rendering: inherit;
66
- letter-spacing: inherit;
67
- word-spacing: inherit;
68
- text-decoration: none;
69
-
70
- &:focus {
71
- outline: none;
72
- }
73
-
74
- /* Change the font styles in all browsers. */
75
- font: inherit;
76
-
77
- /* Remove the margin in Firefox and Safari. */
78
- margin: 0;
79
-
80
- /* Show the overflow in Edge. */
81
- overflow: visible;
82
-
83
- /* Remove the inheritance of text transform in Firefox. */
84
- text-transform: none;
85
-
86
- /* Remove the inner border and padding in Firefox. */
87
- &::-moz-focus-inner {
88
- border-style: none;
89
- padding: 0;
90
- }
91
- `