paris 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # paris
2
2
 
3
+ ## 0.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fc32202: Field: description position prop
8
+
9
+ ## 0.11.1
10
+
11
+ ### Patch Changes
12
+
13
+ - ef55a9d: Combobox: fix displayValue rendering when allowCustomValue is false
14
+
3
15
  ## 0.11.0
4
16
 
5
17
  ### Minor Changes
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "paris",
3
3
  "author": "Sanil Chawla <sanil@slingshot.fm> (https://sanil.co)",
4
4
  "description": "Paris is Slingshot's React design system. It's a collection of reusable components, design tokens, and guidelines that help us build consistent, accessible, and performant user interfaces.",
5
- "version": "0.11.0",
5
+ "version": "0.12.0",
6
6
  "homepage": "https://paris.slingshot.fm",
7
7
  "license": "MIT",
8
8
  "repository": {
@@ -112,7 +112,7 @@ export type ComboboxProps<T extends Record<string, any>> = {
112
112
  /**
113
113
  * A Combobox component is used to render a searchable select.
114
114
  *
115
- * When the selected option node is a strings, the combobox will act like an input even when an option is selected, allowing users to edit the selected option directly in order to pick a new one. To circumvent this and make selected options non-editable, pass nodes that are `Text` components instead.
115
+ * When the selected option node is a string, the combobox will act like an input even when an option is selected, allowing users to edit the selected option directly in order to pick a new one. To circumvent this and make selected options non-editable, pass nodes that are `Text` components instead.
116
116
  *
117
117
  * When `allowCustomValue` is `true`, a custom value option will be added to the dropdown. This option's text can be customized by passing a value for `customValueString`, where `%v` within the string is the user's input. You can provide an entirely custom node through `renderCustomValueOption`. By default, `onChange` will be called for every input change when custom values are allowed.
118
118
  *
@@ -134,6 +134,7 @@ export function Combobox<T extends Record<string, any> = Record<string, any>>({
134
134
  hideLabel,
135
135
  description,
136
136
  hideDescription,
137
+ descriptionPosition,
137
138
  placeholder,
138
139
  startEnhancer,
139
140
  endEnhancer,
@@ -166,6 +167,7 @@ export function Combobox<T extends Record<string, any> = Record<string, any>>({
166
167
  hideLabel={hideLabel}
167
168
  description={description}
168
169
  hideDescription={hideDescription}
170
+ descriptionPosition={descriptionPosition}
169
171
  disabled={disabled}
170
172
  overrides={{
171
173
  container: overrides?.container,
@@ -217,7 +219,7 @@ export function Combobox<T extends Record<string, any> = Record<string, any>>({
217
219
  {...overrides?.input}
218
220
  placeholder={placeholder}
219
221
  // value={query}
220
- displayValue={(allowCustomValue && typeof value?.node === 'string') ? () => value.node as string : undefined}
222
+ displayValue={() => value?.node as string}
221
223
  onChange={(e) => {
222
224
  setQuery(e.target.value);
223
225
  if (onInputChange) onInputChange(e.target.value);
@@ -31,10 +31,16 @@ export type FieldProps = {
31
31
  * Disables the field, disallowing user interaction.
32
32
  */
33
33
  disabled?: boolean;
34
+ /**
35
+ * Position of the description relative to the children/input.
36
+ * @default 'bottom'
37
+ */
38
+ descriptionPosition?: 'top' | 'bottom';
34
39
  overrides?: {
35
40
  container?: ComponentPropsWithoutRef<'div'>;
36
41
  label?: TextProps<'label'>;
37
42
  description?: TextProps<'p'>;
43
+ labelContainer?: ComponentPropsWithoutRef<'div'>;
38
44
  }
39
45
  };
40
46
 
@@ -53,74 +59,92 @@ export type FieldProps = {
53
59
  export const Field: FC<PropsWithChildren<FieldProps>> = ({
54
60
  htmlFor,
55
61
  disabled,
62
+ descriptionPosition = 'bottom',
56
63
  children,
57
64
  // className,
58
65
  ...props
59
- }) => (
60
- // Disable a11y rules because the container doesn't need to be focusable for screen readers; the input itself should receive focus instead.
61
- // The container is only made clickable for usability purposes.
62
- // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
63
- <div
64
- {...props.overrides?.container}
65
- className={clsx(
66
- props.overrides?.container?.className,
67
- styles.container,
68
- // className,
69
- )}
70
- onClick={(e) => {
71
- if (typeof window !== 'undefined' && htmlFor) {
72
- const input = document.getElementById(htmlFor);
73
- if (input && !disabled) {
74
- if (input.tagName === 'BUTTON') input.click();
75
- else input.focus();
76
- }
77
- }
78
- }}
79
- >
80
- {typeof props.label === 'string'
81
- ? (
82
- <Text
83
- {...props.overrides?.label}
84
- as="label"
85
- kind="paragraphSmall"
86
- htmlFor={htmlFor}
87
- className={clsx(
88
- styles.label,
89
- { [styles.hidden]: props.hideLabel },
90
- )}
91
- >
92
- {props.label}
93
- </Text>
94
- )
95
- : (
96
- <label htmlFor={htmlFor} className={clsx({ [styles.hidden]: props.hideLabel })}>
97
- {props.label}
98
- </label>
66
+ }) => {
67
+ const label = typeof props.label === 'string'
68
+ ? (
69
+ <Text
70
+ {...props.overrides?.label}
71
+ as="label"
72
+ kind="paragraphSmall"
73
+ htmlFor={htmlFor}
74
+ className={clsx(
75
+ styles.label,
76
+ { [styles.hidden]: props.hideLabel },
77
+ )}
78
+ >
79
+ {props.label}
80
+ </Text>
81
+ )
82
+ : (
83
+ <label htmlFor={htmlFor} className={clsx({ [styles.hidden]: props.hideLabel })}>
84
+ {props.label}
85
+ </label>
86
+ );
87
+
88
+ const description = typeof props.description === 'string'
89
+ ? (
90
+ <Text
91
+ id={`${htmlFor}-description`}
92
+ {...props.overrides?.description}
93
+ as="p"
94
+ kind="paragraphXSmall"
95
+ className={clsx(
96
+ styles.description,
97
+ { [styles.hidden]: !props.description || props.hideDescription },
98
+ props.overrides?.description?.className,
99
+ )}
100
+ >
101
+ {props.description}
102
+ </Text>
103
+ )
104
+ : (
105
+ <div
106
+ id={`${htmlFor}-description`}
107
+ className={clsx({ [styles.hidden]: !props.description || props.hideDescription })}
108
+ >
109
+ {props.description}
110
+ </div>
111
+ );
112
+
113
+ return (
114
+ // Disable a11y rules because the container doesn't need to be focusable for screen readers; the input itself should receive focus instead.
115
+ // The container is only made clickable for usability purposes.
116
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
117
+ <div
118
+ {...props.overrides?.container}
119
+ className={clsx(
120
+ props.overrides?.container?.className,
121
+ styles.container,
122
+ // className,
99
123
  )}
100
- {children}
101
- {typeof props.description === 'string'
102
- ? (
103
- <Text
104
- id={`${htmlFor}-description`}
105
- {...props.overrides?.description}
106
- as="p"
107
- kind="paragraphXSmall"
124
+ onClick={(e) => {
125
+ if (typeof window !== 'undefined' && htmlFor) {
126
+ const input = document.getElementById(htmlFor);
127
+ if (input && !disabled) {
128
+ if (input.tagName === 'BUTTON') input.click();
129
+ else input.focus();
130
+ }
131
+ }
132
+ }}
133
+ >
134
+ {descriptionPosition === 'top' ? (
135
+ <div
136
+ {...props.overrides?.labelContainer}
108
137
  className={clsx(
109
- styles.description,
110
- { [styles.hidden]: !props.description || props.hideDescription },
111
- props.overrides?.description?.className,
138
+ styles.labelContainer,
139
+ props.overrides?.labelContainer?.className,
112
140
  )}
113
141
  >
114
- {props.description}
115
- </Text>
116
- )
117
- : (
118
- <div
119
- id={`${htmlFor}-description`}
120
- className={clsx({ [styles.hidden]: !props.description || props.hideDescription })}
121
- >
122
- {props.description}
142
+ {label}
143
+ {description}
123
144
  </div>
124
- )}
125
- </div>
126
- );
145
+ ) : label}
146
+ {children}
147
+ {descriptionPosition === 'bottom' ? description : <></>}
148
+ </div>
149
+ );
150
+ };
@@ -106,7 +106,7 @@
106
106
  color: var(--pte-new-colors-contentDisabled);
107
107
  }
108
108
  }
109
-
109
+
110
110
  &[data-status="error"] {
111
111
  color: var(--pte-new-colors-contentNegative);
112
112
 
@@ -114,7 +114,7 @@
114
114
  color: var(--pte-new-colors-contentNegative);
115
115
  }
116
116
  }
117
-
117
+
118
118
  &[data-status="success"] {
119
119
  color: var(--pte-new-colors-contentPositive);
120
120
 
@@ -158,6 +158,14 @@
158
158
  gap: 8px;
159
159
  }
160
160
 
161
+ .labelContainer {
162
+ display: flex;
163
+ flex-direction: column;
164
+ gap: 2px;
165
+ align-items: flex-start;
166
+ justify-content: flex-start;
167
+ }
168
+
161
169
  // Use double selector to ensure specificity is higher than the default styles
162
170
  .label.label {
163
171
  color: var(--pte-new-colors-contentPrimary);
@@ -177,4 +185,4 @@
177
185
  &::-webkit-calendar-picker-indicator {
178
186
  display: none;
179
187
  }
180
- }
188
+ }
@@ -71,6 +71,7 @@ export const Input: FC<InputProps & ComponentPropsWithoutRef<'input'>> = forward
71
71
  hideLabel,
72
72
  description,
73
73
  hideDescription,
74
+ descriptionPosition,
74
75
  startEnhancer,
75
76
  endEnhancer,
76
77
  disabled,
@@ -86,6 +87,7 @@ export const Input: FC<InputProps & ComponentPropsWithoutRef<'input'>> = forward
86
87
  description={description}
87
88
  hideDescription={hideDescription}
88
89
  disabled={disabled}
90
+ descriptionPosition={descriptionPosition}
89
91
  overrides={{
90
92
  container: {
91
93
  ...overrides?.container,
@@ -98,6 +98,7 @@ export const Select = forwardRef(function <T = Record<string, any>>({
98
98
  hideLabel,
99
99
  description,
100
100
  hideDescription,
101
+ descriptionPosition,
101
102
  placeholder,
102
103
  startEnhancer,
103
104
  endEnhancer,
@@ -115,6 +116,7 @@ export const Select = forwardRef(function <T = Record<string, any>>({
115
116
  hideLabel={hideLabel}
116
117
  description={description}
117
118
  hideDescription={hideDescription}
119
+ descriptionPosition={descriptionPosition}
118
120
  disabled={disabled}
119
121
  overrides={{
120
122
  container: overrides?.container,
@@ -26,6 +26,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, InputProps & ComponentPr
26
26
  hideLabel,
27
27
  description,
28
28
  hideDescription,
29
+ descriptionPosition,
29
30
  startEnhancer,
30
31
  endEnhancer,
31
32
  disabled,
@@ -41,6 +42,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, InputProps & ComponentPr
41
42
  hideLabel={hideLabel}
42
43
  description={description}
43
44
  hideDescription={hideDescription}
45
+ descriptionPosition={descriptionPosition}
44
46
  disabled={disabled}
45
47
  overrides={{
46
48
  container: overrides?.container,