@sanity/ui 2.6.7-canary.0 → 2.6.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.
Files changed (59) hide show
  1. package/dist/index.d.mts +15 -51
  2. package/dist/index.d.ts +15 -51
  3. package/dist/index.esm.js +186 -120
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +186 -119
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +186 -120
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/theme.d.mts +14 -14
  10. package/dist/theme.d.ts +14 -14
  11. package/dist/theme.esm.js.map +1 -1
  12. package/dist/theme.js.map +1 -1
  13. package/dist/theme.mjs.map +1 -1
  14. package/package.json +53 -46
  15. package/src/core/__workshop__/constants.ts +36 -36
  16. package/src/core/components/autocomplete/autocomplete.tsx +1 -1
  17. package/src/core/components/breadcrumbs/breadcrumbs.tsx +6 -15
  18. package/src/core/components/dialog/dialog.tsx +21 -12
  19. package/src/core/components/dialog/styles.ts +8 -8
  20. package/src/core/components/menu/menu.tsx +18 -11
  21. package/src/core/components/menu/menuButton.tsx +11 -11
  22. package/src/core/components/menu/menuContext.ts +1 -1
  23. package/src/core/components/menu/useMenuController.ts +17 -11
  24. package/src/core/components/tab/tab.tsx +8 -8
  25. package/src/core/components/tab/tabPanel.tsx +1 -1
  26. package/src/core/components/toast/styles.ts +1 -2
  27. package/src/core/components/toast/useToast.ts +0 -1
  28. package/src/core/components/tree/tree.tsx +0 -1
  29. package/src/core/components/tree/treeItem.tsx +0 -1
  30. package/src/core/helpers/focus.ts +0 -1
  31. package/src/core/helpers/scroll.ts +0 -1
  32. package/src/core/hooks/_internal/index.ts +1 -0
  33. package/src/core/hooks/_internal/useUnique.ts +34 -0
  34. package/src/core/hooks/index.ts +2 -3
  35. package/src/core/hooks/useClickOutside.ts +72 -38
  36. package/src/core/hooks/useElementSize.ts +0 -1
  37. package/src/core/hooks/useMediaIndex/useMediaIndex.ts +10 -2
  38. package/src/core/hooks/usePrefersDark.ts +55 -10
  39. package/src/core/hooks/usePrefersReducedMotion.ts +56 -10
  40. package/src/core/primitives/avatar/styles.ts +42 -42
  41. package/src/core/primitives/badge/styles.ts +2 -2
  42. package/src/core/primitives/button/styles.ts +4 -4
  43. package/src/core/primitives/inline/styles.ts +2 -2
  44. package/src/core/primitives/popover/__workshop__/AlignedStory.tsx +7 -9
  45. package/src/core/primitives/popover/constants.ts +4 -4
  46. package/src/core/primitives/stack/styles.ts +2 -2
  47. package/src/core/primitives/tooltip/__workshop__/customPortal.tsx +7 -9
  48. package/src/core/primitives/tooltip/constants.ts +4 -4
  49. package/src/core/primitives/tooltip/tooltip.tsx +49 -68
  50. package/src/core/primitives/tooltip/tooltipDelayGroup/tooltipDelayGroupProvider.tsx +0 -1
  51. package/src/core/styles/font/responsiveFont.ts +8 -8
  52. package/src/core/theme/__workshop__/debug/story.tsx +11 -11
  53. package/src/core/utils/layer/layerProvider.tsx +0 -1
  54. package/src/core/utils/portal/__workshop__/named.tsx +8 -10
  55. package/src/core/utils/portal/portalProvider.tsx +13 -7
  56. package/src/theme/build/buildColorTheme.test.ts +13 -13
  57. package/src/theme/config/tokens/color/types.ts +14 -14
  58. package/src/theme/defaults/colorTokens.ts +36 -36
  59. package/src/core/hooks/useMatchMedia.ts +0 -46
@@ -11,14 +11,14 @@ export interface TabProps {
11
11
  * The `id` of the correlating `TabPanel` component.
12
12
  */
13
13
  'aria-controls': string
14
- 'id': string
15
- 'icon'?: React.ElementType | React.ReactNode
16
- 'focused'?: boolean
17
- 'fontSize'?: number | number[]
18
- 'label'?: React.ReactNode
19
- 'padding'?: number | number[]
20
- 'selected'?: boolean
21
- 'tone'?: ButtonTone
14
+ id: string
15
+ icon?: React.ElementType | React.ReactNode
16
+ focused?: boolean
17
+ fontSize?: number | number[]
18
+ label?: React.ReactNode
19
+ padding?: number | number[]
20
+ selected?: boolean
21
+ tone?: ButtonTone
22
22
  }
23
23
 
24
24
  const CustomButton = styled(Button)`
@@ -9,7 +9,7 @@ export interface TabPanelProps extends BoxProps {
9
9
  * The `id` of the correlating `Tab` component.
10
10
  */
11
11
  'aria-labelledby': string
12
- 'id': string
12
+ id: string
13
13
  }
14
14
 
15
15
  /**
@@ -14,12 +14,11 @@ const loadingAnimation = keyframes`
14
14
  }
15
15
  100% {
16
16
  width: 100%;
17
- }
17
+ }
18
18
  `
19
19
 
20
20
  const LOADING_BAR_HEIGHT = 2
21
21
 
22
- // @TODO get rid of $duration modifier, set data attribute instead and use stable selector
23
22
  export function rootStyles(
24
23
  props: {$duration?: number; tone: ThemeColorStateToneKey} & ThemeProps,
25
24
  ): ReturnType<typeof css> {
@@ -13,7 +13,6 @@ export function useToast(): ToastContextValue {
13
13
  throw new Error('useToast(): missing context value')
14
14
  }
15
15
 
16
- // @TODO context and hooks doesn't really work like this, there will never be a mismatch between the provider and the consumer, we can remove these version specifiers
17
16
  // NOTE: This check is for future-compatiblity
18
17
  // - If the value is not an object, it’s not compatible with the current version
19
18
  // - If the value is an object, but doesn’t have `version: 0.0`, it’s not compatible with the current version
@@ -84,7 +84,6 @@ export const Tree = memo(
84
84
  })
85
85
  }, [])
86
86
 
87
- // @TODO split out into separate contexts
88
87
  const contextValue: TreeContextValue = useMemo(
89
88
  () => ({
90
89
  version: 0.0,
@@ -76,7 +76,6 @@ export const TreeItem = memo(function TreeItem(
76
76
  const focused = tree.focusedElement === rootRef.current
77
77
  const expanded = itemState?.expanded === undefined ? expandedProp : itemState?.expanded || false
78
78
  const tabIndex = tree.focusedElement && tree.focusedElement === rootRef.current ? 0 : -1
79
- // @TODO split out into separate contexts
80
79
  const contextValue = useMemo(
81
80
  () => ({...tree, level: tree.level + 1, path: itemPath}),
82
81
  [itemPath, tree],
@@ -15,7 +15,6 @@ import {
15
15
  * @internal
16
16
  */
17
17
  export function _hasFocus(element: HTMLElement): boolean {
18
- // @TODO verify this is not called during render
19
18
  return Boolean(document.activeElement) && element.contains(document.activeElement)
20
19
  }
21
20
 
@@ -4,7 +4,6 @@
4
4
  export function _isScrollable(el: Node): boolean {
5
5
  if (!(el instanceof Element)) return false
6
6
 
7
- // @TODO check if this is called during render
8
7
  const style = window.getComputedStyle(el)
9
8
 
10
9
  return (
@@ -0,0 +1 @@
1
+ export * from './useUnique'
@@ -0,0 +1,34 @@
1
+ import {useRef} from 'react'
2
+
3
+ /**
4
+ * This is a React hook to make sure that a record identity is the same on every render. Uses strict
5
+ * equality comparison (eg by identity), and only goes one level deep.
6
+ *
7
+ * @internal
8
+ */
9
+ type Comparable = Record<string | number | symbol, unknown> | undefined | null
10
+
11
+ export function useUnique<ValueType extends Comparable = Comparable>(value: ValueType): ValueType {
12
+ const valueRef = useRef<ValueType>(value)
13
+
14
+ if (!_isEqual(valueRef.current, value)) {
15
+ valueRef.current = value
16
+ }
17
+
18
+ return valueRef.current
19
+ }
20
+
21
+ function _isEqual(objA: Comparable, objB: Comparable): boolean {
22
+ if (!objA || !objB) {
23
+ return objA === objB
24
+ }
25
+
26
+ const keysA = Object.keys(objA)
27
+ const keysB = Object.keys(objB)
28
+
29
+ if (keysA.length !== keysB.length) {
30
+ return false
31
+ }
32
+
33
+ return keysA.every((key) => objA[key] === objB[key])
34
+ }
@@ -1,11 +1,10 @@
1
1
  export * from './useArrayProp'
2
2
  export * from './useClickOutside'
3
- export * from './useCustomValidity'
4
3
  export * from './useElementRect'
5
4
  export * from './useElementSize'
6
- export * from './useForwardedRef'
7
5
  export * from './useGlobalKeyDown'
8
- export * from './useMatchMedia'
9
6
  export * from './useMediaIndex'
10
7
  export * from './usePrefersDark'
11
8
  export * from './usePrefersReducedMotion'
9
+ export * from './useForwardedRef'
10
+ export * from './useCustomValidity'
@@ -1,65 +1,99 @@
1
- import {useEffect} from 'react'
2
- import {useEffectEvent} from 'use-effect-event'
1
+ import {useEffect, useRef, useState} from 'react'
3
2
  import {EMPTY_ARRAY} from '../constants'
4
3
 
5
4
  /**
6
5
  * @public
7
6
  */
8
- export type ClickOutsideListener = (event: MouseEvent | TouchEvent) => void
7
+ export type ClickOutsideListener = (event: MouseEvent) => void
8
+
9
+ function _getElements(
10
+ element: HTMLElement | null,
11
+ elementsArg: Array<HTMLElement | HTMLElement[] | null>,
12
+ ): HTMLElement[] {
13
+ const ret = [element]
14
+
15
+ for (const el of elementsArg) {
16
+ if (Array.isArray(el)) {
17
+ ret.push(...el)
18
+ } else {
19
+ ret.push(el)
20
+ }
21
+ }
22
+
23
+ return ret.filter(Boolean) as HTMLElement[]
24
+ }
9
25
 
10
26
  /**
11
- * Use the callback version of `elementsArg` if you're using `useRef` to handle elements:
12
- * ```tsx
13
- * useClickOutside(
14
- * () => {},
15
- * () => [ref.current],
16
- * )
17
- *
18
27
  * @public
19
28
  */
20
29
  export function useClickOutside(
21
30
  listener: ClickOutsideListener,
22
- elementsArg:
23
- | Array<HTMLElement | HTMLElement[] | null>
24
- | (() => Array<HTMLElement | HTMLElement[] | null>) = EMPTY_ARRAY,
31
+ elementsArg: Array<HTMLElement | HTMLElement[] | null> = EMPTY_ARRAY,
25
32
  boundaryElement?: HTMLElement | null,
26
- ): void {
27
- /**
28
- * The `useEffectEvent` hook allow us to always see the latest value of `listener`, `elementsArg` and `boundaryElement` without needing to
29
- * juggle `useState`, `useRef` and `useState` to make sure the `mousedown` event listener isn't constantly being added and removed.
30
- */
31
- const eventHandler = useEffectEvent((evt: MouseEvent | TouchEvent) => {
32
- const target = evt.target
33
-
34
- if (!(target instanceof Node)) {
35
- return
36
- }
33
+ ): (el: HTMLElement | null) => void {
34
+ const [element, setElement] = useState<HTMLElement | null>(null)
35
+ const [elements, setElements] = useState(() => _getElements(element, elementsArg))
36
+ const elementsRef = useRef(elements)
37
+
38
+ useEffect(() => {
39
+ const prevElements = elementsRef.current
40
+ const nextElements = _getElements(element, elementsArg)
41
+
42
+ if (prevElements.length !== nextElements.length) {
43
+ setElements(nextElements)
44
+ elementsRef.current = nextElements
37
45
 
38
- if (boundaryElement && !boundaryElement.contains(target)) {
39
46
  return
40
47
  }
41
48
 
42
- const resolvedElements = Array.isArray(elementsArg) ? elementsArg : elementsArg()
43
- const elements = resolvedElements.flat()
44
-
45
- for (const el of elements) {
46
- if (!el) continue
49
+ for (const el of prevElements) {
50
+ if (!nextElements.includes(el)) {
51
+ setElements(nextElements)
52
+ elementsRef.current = nextElements
47
53
 
48
- if (target === el || el.contains(target)) {
49
54
  return
50
55
  }
51
56
  }
52
57
 
53
- listener(evt)
54
- })
58
+ for (const el of nextElements) {
59
+ if (!prevElements.includes(el)) {
60
+ setElements(nextElements)
61
+ elementsRef.current = nextElements
62
+
63
+ return
64
+ }
65
+ }
66
+ }, [element, elementsArg])
55
67
 
56
68
  useEffect(() => {
57
- document.addEventListener('mousedown', eventHandler)
58
- document.addEventListener('touchstart', eventHandler)
69
+ if (!listener) return undefined
70
+
71
+ const handleWindowMouseDown = (evt: MouseEvent) => {
72
+ const target = evt.target
73
+
74
+ if (!(target instanceof Node)) {
75
+ return
76
+ }
77
+
78
+ if (boundaryElement && !boundaryElement.contains(target)) {
79
+ return
80
+ }
81
+
82
+ for (const el of elements) {
83
+ if (target === el || el.contains(target)) {
84
+ return
85
+ }
86
+ }
87
+
88
+ listener(evt)
89
+ }
90
+
91
+ window.addEventListener('mousedown', handleWindowMouseDown)
59
92
 
60
93
  return () => {
61
- document.removeEventListener('mousedown', eventHandler)
62
- document.removeEventListener('touchstart', eventHandler)
94
+ window.removeEventListener('mousedown', handleWindowMouseDown)
63
95
  }
64
- }, [eventHandler])
96
+ }, [boundaryElement, listener, elements])
97
+
98
+ return setElement
65
99
  }
@@ -6,7 +6,6 @@ import {ElementSize, _elementSizeObserver} from '../observers/elementSizeObserve
6
6
  * @beta
7
7
  */
8
8
  export function useElementSize(element: HTMLElement | null): ElementSize | null {
9
- // @TODO we can probably use something in framer-motion or @floating-ui instead of rolling our own
10
9
  const [size, setSize] = useState<ElementSize | null>(null)
11
10
 
12
11
  useEffect(() => {
@@ -1,4 +1,4 @@
1
- import {useMemo, useSyncExternalStore} from 'react'
1
+ import {useSyncExternalStore} from 'react'
2
2
  import {useTheme_v2} from '../../theme'
3
3
 
4
4
  /**
@@ -9,6 +9,8 @@ export interface _MediaStore {
9
9
  getSnapshot: () => number
10
10
  }
11
11
 
12
+ const MEDIA_STORE_CACHE = new WeakMap<number[], _MediaStore>()
13
+
12
14
  type MediaQueryMinWidth = `(min-width: ${number}px)`
13
15
  type MediaQueryMaxWidth = `(max-width: ${number}px)`
14
16
  type MediaQueryMinMaxWidth = `${MediaQueryMinWidth} and ${MediaQueryMaxWidth}`
@@ -95,7 +97,13 @@ function getServerSnapshot() {
95
97
  */
96
98
  export function useMediaIndex(): number {
97
99
  const {media} = useTheme_v2()
98
- const store = useMemo(() => _createMediaStore(media), [media])
100
+
101
+ let store = MEDIA_STORE_CACHE.get(media)
102
+
103
+ if (!store) {
104
+ store = _createMediaStore(media)
105
+ MEDIA_STORE_CACHE.set(media, store)
106
+ }
99
107
 
100
108
  return useSyncExternalStore(store.subscribe, store.getSnapshot, getServerSnapshot)
101
109
  }
@@ -1,16 +1,61 @@
1
- import {useMatchMedia} from './useMatchMedia'
1
+ import {useSyncExternalStore} from 'react'
2
+
3
+ let MEDIA_QUERY_CACHE: MediaQueryList | undefined
2
4
 
3
5
  /**
4
- * Returns true if a dark color scheme is preferred, false if a light color scheme is preferred or the preference is not known.
5
- *
6
- * @param getServerSnapshot - Only called during server-side rendering, and hydration if using hydrateRoot. Since the server environment doesn't have access to the DOM, we can't determine the current value of the media query and we assume `(prefers-color-scheme: light)` since it's the most common scheme (https://react.dev/reference/react/useSyncExternalStore#adding-support-for-server-rendering)
7
- *
8
- * If you persist the detected preference in a cookie or a header then you may implement your own server snapshot to read it.
9
- * Chrome supports reading the `prefers-color-scheme` media query from a header if the server response: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-Prefers-Color-Scheme
10
- * @example https://gist.github.com/stipsan/13c0cccf8dfc34f4b44bb1b984baf7df
6
+ * Lazy init the matchMedia instance
7
+ */
8
+ function getMatchMedia(): MediaQueryList {
9
+ if (!MEDIA_QUERY_CACHE) {
10
+ // As this function is only called during `subscribe` and `getSnapshot`, we can assume that the
11
+ // the `window` global is available and we're in a browser environment
12
+ MEDIA_QUERY_CACHE = window.matchMedia('(prefers-color-scheme: dark)')
13
+ }
14
+
15
+ return MEDIA_QUERY_CACHE
16
+ }
17
+
18
+ /**
19
+ * As the query is the same for all instances of this hook, we can cache the matchMedia instance
20
+ * and have cheap `change` event listeners, while getSnapshot always reads from the same
21
+ * matchMedia instance and we don't get any tearing.
22
+ * Tearing in this context means the bad edge case in React concurrent render mdoe
23
+ * where you sometimes would end up with some components doing render while seeing `usePrefersDark() === true` while others would see `usePrefersDark() === false`
24
+ * during the same render.
25
+ * By using `useSyncExternalStore` every component only sees the same value during the same render, and always re-render when it changes no matter
26
+ * what React.memo boundaries there might be between the layers..
27
+ */
28
+ function subscribe(onStoreChange: () => void): () => void {
29
+ const matchMedia = getMatchMedia()
30
+
31
+ matchMedia.addEventListener('change', onStoreChange)
32
+
33
+ return () => matchMedia.removeEventListener('change', onStoreChange)
34
+ }
35
+
36
+ /**
37
+ * Only called client-side, when using createRoot, or after hydration is complete when using hydrateRoot.
38
+ * It's important that this function does not create new objects or arrays when called:
39
+ * https://beta.reactjs.org/apis/react/useSyncExternalStore#im-getting-an-error-the-result-of-getsnapshot-should-be-cached
40
+ */
41
+ function getSnapshot() {
42
+ return getMatchMedia().matches
43
+ }
44
+
45
+ /**
46
+ * Only called during server-side rendering, and hydration if using hydrateRoot
47
+ * Since the server environment doesn't have access to the DOM, we can't determine the current value of the media query
48
+ * and we assume `(prefers-color-scheme: light)` since it's the most common scheme
11
49
  *
50
+ * @link https://beta.reactjs.org/apis/react/useSyncExternalStore#adding-support-for-server-rendering
51
+ */
52
+ function getServerSnapshot() {
53
+ return false
54
+ }
55
+
56
+ /**
12
57
  * @public
13
58
  */
14
- export function usePrefersDark(getServerSnapshot = () => false): boolean {
15
- return useMatchMedia('(prefers-color-scheme: dark)', getServerSnapshot)
59
+ export function usePrefersDark(): boolean {
60
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)
16
61
  }
@@ -1,16 +1,62 @@
1
- import {useMatchMedia} from './useMatchMedia'
1
+ import {useSyncExternalStore} from 'react'
2
+
3
+ let MEDIA_QUERY_CACHE: MediaQueryList | undefined
2
4
 
3
5
  /**
4
- * Returns true if motion should be reduced
5
- *
6
- * @param getServerSnapshot - Only called during server-side rendering, and hydration if using hydrateRoot. Since the server environment doesn't have access to the DOM, we can't determine the current value of the media query and we assume `(prefers-reduced-motion: no-preference)` since it's the most common scheme (https://react.dev/reference/react/useSyncExternalStore#adding-support-for-server-rendering)
7
- *
8
- * If you persist the detected preference in a cookie or a header then you may implement your own server snapshot to read it.
9
- * Chrome supports reading the `prefers-reduced-motion` media query from a header if the server response: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-Prefers-Reduced-Motion
10
- * @example https://gist.github.com/stipsan/0c0f839a27842249cada893e9fb7767b
6
+ * Lazy init the matchMedia instance
7
+ */
8
+ function getMatchMedia(): MediaQueryList {
9
+ if (!MEDIA_QUERY_CACHE) {
10
+ // As this function is only called during `subscribe` and `getSnapshot`, we can assume that the
11
+ // the `window` global is available and we're in a browser environment
12
+ MEDIA_QUERY_CACHE = window.matchMedia('(prefers-reduced-motion: reduce)')
13
+ }
14
+
15
+ return MEDIA_QUERY_CACHE
16
+ }
17
+
18
+ /**
19
+ * As the query is the same for all instances of this hook, we can cache the matchMedia instance
20
+ * and have cheap `change` event listeners, while getSnapshot always reads from the same
21
+ * matchMedia instance and we don't get any tearing.
22
+ * Tearing in this context means the bad edge case in React concurrent render mdoe
23
+ * where you sometimes would end up with some components doing render while seeing `usePrefersDark() === true` while others would see `usePrefersDark() === false`
24
+ * during the same render.
25
+ * By using `useSyncExternalStore` every component only sees the same value during the same render, and always re-render when it changes no matter
26
+ * what React.memo boundaries there might be between the layers..
27
+ */
28
+ function subscribe(onStoreChange: () => void): () => void {
29
+ const matchMedia = getMatchMedia()
30
+
31
+ matchMedia.addEventListener('change', onStoreChange)
32
+
33
+ return () => matchMedia.removeEventListener('change', onStoreChange)
34
+ }
35
+
36
+ /**
37
+ * Only called client-side, when using createRoot, or after hydration is complete when using hydrateRoot.
38
+ * It's important that this function does not create new objects or arrays when called:
39
+ * https://beta.reactjs.org/apis/react/useSyncExternalStore#im-getting-an-error-the-result-of-getsnapshot-should-be-cached
40
+ */
41
+ function getSnapshot() {
42
+ return getMatchMedia().matches
43
+ }
44
+
45
+ /**
46
+ * Only called during server-side rendering, and hydration if using hydrateRoot
47
+ * Since the server environment doesn't have access to the DOM, we can't determine the current value of the media query
48
+ * and we assume `(prefers-reduced-motion: no-preference)` since it's the most common scheme
11
49
  *
50
+ * @link https://beta.reactjs.org/apis/react/useSyncExternalStore#adding-support-for-server-rendering
51
+ */
52
+ function getServerSnapshot() {
53
+ return false
54
+ }
55
+
56
+ /**
57
+ * Returns true if motion should be reduced
12
58
  * @public
13
59
  */
14
- export function usePrefersReducedMotion(getServerSnapshot = () => false): boolean {
15
- return useMatchMedia('(prefers-reduced-motion: reduce)', getServerSnapshot)
60
+ export function usePrefersReducedMotion(): boolean {
61
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)
16
62
  }
@@ -14,24 +14,24 @@ export const avatarStyle = {
14
14
 
15
15
  function avatarArrowStyle(): CSSObject {
16
16
  return {
17
- 'position': 'absolute',
18
- 'boxSizing': 'border-box',
19
- 'zIndex': 0,
20
- 'opacity': 0,
21
- 'transition': 'all 0.2s linear',
22
- 'transform': 'rotate(-90deg) translate3d(0, 6px, 0)',
23
- 'left': 0,
24
- 'right': 0,
25
- 'top': 0,
26
- 'bottom': 0,
17
+ position: 'absolute',
18
+ boxSizing: 'border-box',
19
+ zIndex: 0,
20
+ opacity: 0,
21
+ transition: 'all 0.2s linear',
22
+ transform: 'rotate(-90deg) translate3d(0, 6px, 0)',
23
+ left: 0,
24
+ right: 0,
25
+ top: 0,
26
+ bottom: 0,
27
27
 
28
28
  '& > svg': {
29
- 'width': '11px',
30
- 'height': '7px',
31
- 'position': 'absolute',
32
- 'top': '-5px',
33
- 'left': '50%',
34
- 'transform': 'translateX(-6px)',
29
+ width: '11px',
30
+ height: '7px',
31
+ position: 'absolute',
32
+ top: '-5px',
33
+ left: '50%',
34
+ transform: 'translateX(-6px)',
35
35
 
36
36
  '&:not([hidden])': {
37
37
  display: 'block',
@@ -63,11 +63,11 @@ export function avatarRootStyle(props: AvatarRootStyleProps & ThemeProps): CSSOb
63
63
  '--avatar-bg-color': `var(--card-avatar-${$color}-bg-color)`,
64
64
  '--avatar-fg-color': `var(--card-avatar-${$color}-fg-color)`,
65
65
 
66
- 'backgroundColor': 'var(--avatar-bg-color)',
67
- 'position': 'relative',
68
- 'boxSizing': 'border-box',
69
- 'userSelect': 'none',
70
- 'boxShadow': '0 0 0 1px var(--card-bg-color)',
66
+ backgroundColor: 'var(--avatar-bg-color)',
67
+ position: 'relative',
68
+ boxSizing: 'border-box',
69
+ userSelect: 'none',
70
+ boxShadow: '0 0 0 1px var(--card-bg-color)',
71
71
 
72
72
  '&[data-status="inactive"]': {
73
73
  opacity: 0.5,
@@ -81,14 +81,14 @@ export function avatarRootStyle(props: AvatarRootStyleProps & ThemeProps): CSSOb
81
81
 
82
82
  /* &:is(button) */
83
83
  '&[data-as="button"]': {
84
- 'WebkitFontSmoothing': 'inherit',
85
- 'appearance': 'none',
86
- 'margin': 0,
87
- 'padding': 0,
88
- 'border': 0,
89
- 'font': 'inherit',
90
- 'color': 'inherit',
91
- 'outline': 'none',
84
+ WebkitFontSmoothing: 'inherit',
85
+ appearance: 'none',
86
+ margin: 0,
87
+ padding: 0,
88
+ border: 0,
89
+ font: 'inherit',
90
+ color: 'inherit',
91
+ outline: 'none',
92
92
 
93
93
  '&:focus': {
94
94
  boxShadow: focusRingStyle({focusRing: avatar.focusRing}),
@@ -110,9 +110,9 @@ export function responsiveAvatarSizeStyle(
110
110
  const avatarSize = avatar.sizes[size] || avatar.sizes[0]
111
111
 
112
112
  return {
113
- 'width': rem(avatarSize.size),
114
- 'height': rem(avatarSize.size),
115
- 'borderRadius': rem(avatarSize.size / 2),
113
+ width: rem(avatarSize.size),
114
+ height: rem(avatarSize.size),
115
+ borderRadius: rem(avatarSize.size / 2),
116
116
 
117
117
  '&>svg': {
118
118
  width: rem(avatarSize.size),
@@ -131,14 +131,14 @@ export function avatarImageStyle(): CSSObject {
131
131
 
132
132
  export function avatarInitialsStyle(): CSSObject {
133
133
  return {
134
- 'width': '100%',
135
- 'height': '100%',
136
- 'color': 'var(--avatar-fg-color)',
137
- 'alignItems': 'center',
138
- 'justifyContent': 'center',
139
- 'textTransform': 'uppercase',
140
- 'textAlign': 'center',
141
- 'borderRadius': '50%',
134
+ width: '100%',
135
+ height: '100%',
136
+ color: 'var(--avatar-fg-color)',
137
+ alignItems: 'center',
138
+ justifyContent: 'center',
139
+ textTransform: 'uppercase',
140
+ textAlign: 'center',
141
+ borderRadius: '50%',
142
142
 
143
143
  '&:not([hidden])': {
144
144
  display: 'flex',
@@ -155,8 +155,8 @@ function avatarBgStrokeStyle(): CSSObject {
155
155
 
156
156
  function avatarStrokeStyle(): CSSObject {
157
157
  return {
158
- 'strokeWidth': '2px',
159
- 'stroke': 'var(--avatar-bg-color)',
158
+ strokeWidth: '2px',
159
+ stroke: 'var(--avatar-bg-color)',
160
160
 
161
161
  '[data-status="editing"] &': {
162
162
  strokeDasharray: '2 4',
@@ -8,8 +8,8 @@ export function badgeStyle(props: BadgeStyleProps): CSSObject {
8
8
  '--card-bg-color': `var(--card-badge-${$tone}-bg-color)`,
9
9
  '--card-fg-color': `var(--card-badge-${$tone}-fg-color)`,
10
10
 
11
- 'backgroundColor': 'var(--card-bg-color)',
12
- 'cursor': 'default',
11
+ backgroundColor: 'var(--card-bg-color)',
12
+ cursor: 'default',
13
13
 
14
14
  '&:not([hidden])': {
15
15
  display: 'inline-block',
@@ -81,12 +81,12 @@ export function buttonColorStyles(
81
81
  return [
82
82
  _cardColorStyle(baseColor, color.enabled),
83
83
  {
84
- 'backgroundColor': 'var(--card-bg-color)',
85
- 'color': 'var(--card-fg-color)',
86
- 'boxShadow': focusRingBorderStyle(border),
84
+ backgroundColor: 'var(--card-bg-color)',
85
+ color: 'var(--card-fg-color)',
86
+ boxShadow: focusRingBorderStyle(border),
87
87
  '&:disabled, &[data-disabled="true"]': _cardColorStyle(baseColor, color.disabled),
88
88
  "&:not([data-disabled='true'])": {
89
- 'boxShadow': combineBoxShadow(
89
+ boxShadow: combineBoxShadow(
90
90
  focusRingBorderStyle(border),
91
91
  shadow ? defaultBoxShadow : undefined,
92
92
  ),
@@ -4,7 +4,7 @@ import {ResponsiveInlineSpaceStyleProps} from './types'
4
4
 
5
5
  export function inlineBaseStyle(): CSSObject {
6
6
  return {
7
- 'lineHeight': 0,
7
+ lineHeight: 0,
8
8
 
9
9
  '&&:not([hidden])': {
10
10
  display: 'block',
@@ -24,7 +24,7 @@ export function inlineSpaceStyle(props: ResponsiveInlineSpaceStyleProps & ThemeP
24
24
  const _space = rem(spaceIndex === 0.5 ? space[1] / 2 : space[spaceIndex])
25
25
 
26
26
  return {
27
- 'margin': `-${_space} 0 0 -${_space}`,
27
+ margin: `-${_space} 0 0 -${_space}`,
28
28
  '& > div': {padding: `${_space} 0 0 ${_space}`},
29
29
  }
30
30
  })