@sanity/ui 5.0.0-alpha.11 → 5.0.0-alpha.13

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": "@sanity/ui",
3
- "version": "5.0.0-alpha.11",
3
+ "version": "5.0.0-alpha.13",
4
4
  "description": "Sanity UI Library",
5
5
  "keywords": [
6
6
  "components",
@@ -1,4 +1,5 @@
1
1
  import clsx from 'clsx'
2
+ import {cloneElement, createElement, isValidElement, type ComponentType, type SVGProps} from 'react'
2
3
 
3
4
  import {getProps} from '../../utils/getProps'
4
5
  import {suffixClassName} from '../../utils/suffixClassName'
@@ -7,18 +8,27 @@ import {type IconProps, iconProps} from './icon.props'
7
8
  const iconClassName = suffixClassName('sui-Icon')
8
9
 
9
10
  /** @public */
10
- export function Icon({size = 2, ...props}: IconProps) {
11
- const {className, style, icon: Component, ...rest} = getProps({size, ...props}, iconProps)
11
+ export function Icon({icon, size = 2, ...props}: IconProps) {
12
+ const {className, style, ...rest} = getProps({size, ...props}, iconProps)
13
+ const iconElement = isValidElement(icon) ? icon : null
14
+ const ariaLabel =
15
+ props['aria-label'] || (iconElement ? iconElement.props['aria-label'] : undefined)
12
16
 
13
- return (
14
- <Component
15
- className={clsx(iconClassName, className)}
16
- data-ui="Icon"
17
- style={style}
18
- aria-hidden={props['aria-label'] ? undefined : true}
19
- {...rest}
20
- />
21
- )
17
+ const svgProps = {
18
+ 'className': clsx(
19
+ iconClassName,
20
+ className,
21
+ iconElement ? iconElement.props.className : undefined,
22
+ ),
23
+ 'style': iconElement ? {...iconElement.props.style, ...style} : style,
24
+ 'data-ui': 'Icon',
25
+ 'aria-hidden': ariaLabel ? undefined : true,
26
+ ...rest,
27
+ }
28
+
29
+ return iconElement
30
+ ? cloneElement(iconElement, svgProps)
31
+ : createElement(icon as ComponentType<SVGProps<SVGSVGElement>>, svgProps)
22
32
  }
23
33
 
24
34
  export type {IconProps}
@@ -13,7 +13,7 @@ export interface IconProps
13
13
  /**
14
14
  * The icon component to render.
15
15
  */
16
- icon: React.ComponentType<SVGProps<SVGSVGElement>>
16
+ icon: React.ComponentType<SVGProps<SVGSVGElement>> | React.ReactElement<SVGProps<SVGSVGElement>>
17
17
  /**
18
18
  * Sets icon size.
19
19
  */
@@ -25,5 +25,6 @@
25
25
  @import './skip-to-content/skip-to-content.css';
26
26
  @import './switch/switch.css';
27
27
  @import './text/text.css';
28
+ @import './text-input/text-input.css';
28
29
  @import './tooltip/tooltip.css';
29
30
  @import './visually-hidden/visually-hidden.css';
@@ -16,13 +16,7 @@ export function Select({density = 'regular', hasError = false, ...props}: Select
16
16
  const anchorId = useId()
17
17
  const anchorName = `--anchor-${anchorId}`
18
18
 
19
- const selectClasses = clsx(
20
- selectClassName,
21
- hasError && 'sui-error',
22
- 'sui-radius2',
23
- 'sui-width-full',
24
- className,
25
- )
19
+ const selectClasses = clsx(selectClassName, 'sui-radius2', 'sui-width-full', className)
26
20
 
27
21
  const iconClasses = `sui-position-absolute sui-display-flex sui-align-items-center sui-px1`
28
22
 
@@ -21,12 +21,12 @@
21
21
  /**
22
22
  * Error
23
23
  */
24
- .sui-Select.sui-error {
24
+ .sui-Select[aria-invalid="true"] {
25
25
  --border-color: var(--error-separator);
26
26
  --color: var(--error-foreground);
27
27
  }
28
28
 
29
- .sui-Select.sui-error + [data-ui="Select-icon"] svg {
29
+ .sui-Select[aria-invalid="true"] + [data-ui="Select-icon"] svg {
30
30
  color: var(--error-foreground);
31
31
  }
32
32
 
@@ -2,22 +2,14 @@ import {formElementDensityProps, type FormElementDensityProps} from '../../props
2
2
  import {type PropDef} from '../../types/PropDef'
3
3
 
4
4
  /** @public */
5
- export type SelectProps = React.ComponentProps<'select'> &
6
- FormElementDensityProps & {
7
- /**
8
- * Disables the select element, blocking interactions and hiding it from screen readers.
9
- */
10
- disabled?: boolean
11
- /**
12
- * Used to trigger styling for invalid states.
13
- */
14
- hasError?: boolean
15
- }
5
+ export interface SelectProps extends React.ComponentProps<'select'>, FormElementDensityProps {
6
+ /**
7
+ * Used to trigger styling for invalid states.
8
+ */
9
+ hasError?: boolean
10
+ }
16
11
 
17
12
  export const selectProps: Record<string, PropDef> = {
18
- disabled: {
19
- type: 'boolean',
20
- },
21
13
  hasError: {
22
14
  type: 'boolean',
23
15
  },
@@ -0,0 +1,32 @@
1
+ import clsx from 'clsx'
2
+
3
+ import {getProps} from '../../utils/getProps'
4
+ import {suffixClassName} from '../../utils/suffixClassName'
5
+ import {type TextInputProps, textInputProps} from './textInput.props'
6
+
7
+ const textInputClassName = suffixClassName('sui-TextInput')
8
+
9
+ /** @public */
10
+ export function TextInput({
11
+ density = 'regular',
12
+ hasError = false,
13
+ type = 'text',
14
+ ...props
15
+ }: TextInputProps) {
16
+ const {className, style, ...rest} = getProps({density, ...props}, textInputProps)
17
+
18
+ const textInputClasses = clsx(textInputClassName, 'sui-radius2', 'sui-width-full', className)
19
+
20
+ return (
21
+ <input
22
+ type={type}
23
+ className={textInputClasses}
24
+ style={style}
25
+ data-ui="TextInput"
26
+ {...rest}
27
+ aria-invalid={hasError || undefined}
28
+ />
29
+ )
30
+ }
31
+
32
+ export type {TextInputProps}
@@ -0,0 +1,49 @@
1
+ .sui-TextInput {
2
+ --background-color: var(--backdrop);
3
+ --border-color: var(--separator-high);
4
+ --color: var(--foreground-high);
5
+ background-color: var(--background-color);
6
+ border: 1px solid var(--border-color);
7
+ font: var(--form-element-text);
8
+ color: var(--color);
9
+ }
10
+
11
+ .sui-TextInput::placeholder {
12
+ color: oklch(from var(--color) l c h / var(--placeholder-opacity));
13
+ }
14
+
15
+ /**
16
+ * Error
17
+ */
18
+ .sui-TextInput[aria-invalid="true"] {
19
+ --border-color: var(--error-separator);
20
+ --color: var(--error-foreground);
21
+ }
22
+
23
+ /**
24
+ * Hover - uses relative border/background colours to darken/lighten in both normal & error state
25
+ */
26
+ .sui-TextInput:hover {
27
+ border-color: light-dark(
28
+ oklch(from var(--border-color) calc(l - var(--hover-lightness-delta)) c h),
29
+ oklch(from var(--border-color) calc(l + var(--hover-lightness-delta)) c h)
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Disabled
35
+ */
36
+ .sui-TextInput:disabled {
37
+ --background-color: var(--inert-background);
38
+ --border-color: var(--separator-low);
39
+ --color: var(--inert-foreground);
40
+ pointer-events: none;
41
+ }
42
+
43
+ /**
44
+ * Focus
45
+ */
46
+ .sui-TextInput:focus-visible {
47
+ outline: var(--focus-outline);
48
+ outline-offset: var(--focus-offset);
49
+ }
@@ -0,0 +1,41 @@
1
+ import {formElementDensityProps, type FormElementDensityProps} from '../../props/formElement'
2
+ import {type PropDef} from '../../types/PropDef'
3
+
4
+ export const TEXT_INPUT_EXCLUDED_TYPES = [
5
+ 'button',
6
+ 'checkbox',
7
+ 'color',
8
+ 'file',
9
+ 'hidden',
10
+ 'image',
11
+ 'radio',
12
+ 'range',
13
+ 'reset',
14
+ 'submit',
15
+ ] as const
16
+
17
+ /** @public */
18
+ export type TextInputExcludedTypes = (typeof TEXT_INPUT_EXCLUDED_TYPES)[number]
19
+
20
+ /** @public */
21
+ export type TextInputType = Exclude<React.HTMLInputTypeAttribute, TextInputExcludedTypes>
22
+
23
+ /** @public */
24
+ export interface TextInputProps
25
+ extends Omit<React.ComponentProps<'input'>, 'type'>, FormElementDensityProps {
26
+ /**
27
+ * Used to trigger styling for invalid states.
28
+ */
29
+ hasError?: boolean
30
+ /**
31
+ * The html `type` attribute, with non-text based types excluded.
32
+ */
33
+ type?: TextInputType
34
+ }
35
+
36
+ export const textInputProps: Record<string, PropDef> = {
37
+ hasError: {
38
+ type: 'boolean',
39
+ },
40
+ ...formElementDensityProps,
41
+ }
@@ -2,7 +2,7 @@
2
2
  --backdrop: light-dark(var(--white), var(--black));
3
3
  --brand-background: #eb5228;
4
4
  --brand-foreground: var(--black);
5
- --placeholder-opacity: var(--opacity-mid);
5
+ --placeholder-opacity: 0.64;
6
6
  --overlay-opacity: var(--opacity-mid);
7
7
  /* State */
8
8
  --active-background-normal: light-dark(var(--blue-50), var(--blue-950));
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  'use client'
2
2
 
3
+ export * from './components/badge/Badge'
3
4
  export * from './components/box/Box'
4
5
  export * from './components/button/Button'
5
6
  export * from './components/card/Card'
@@ -29,6 +30,7 @@ export * from './components/skip-to-content/SkipToContent'
29
30
  export * from './components/spinner/Spinner'
30
31
  export * from './components/switch/Switch'
31
32
  export * from './components/text/Text'
33
+ export * from './components/text-input/TextInput'
32
34
  export * from './components/tooltip/Tooltip'
33
35
  export * from './components/tooltip-group/TooltipGroup'
34
36
  export * from './components/v-stack/VStack'
@@ -65,4 +67,3 @@ export type {TextSize} from './types/Text'
65
67
  export type {TextAlign} from './types/TextAlign'
66
68
  export type {FontWeight} from './types/FontWeight'
67
69
  export type {Tone} from './types/Tone'
68
- export * from './components/badge/Badge'
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is generated by scripts/write-version.js. Do not edit.
2
- export const VERSION = '500alpha11'
3
- export const HASH = '8b95a0'
2
+ export const VERSION = '500alpha13'
3
+ export const HASH = '0ef1ec'