@planningcenter/tapestry-react 2.9.0-rc.4 → 2.9.0-rc.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 (51) hide show
  1. package/dist/cjs/Button/Button.js +15 -4
  2. package/dist/cjs/FilterLayout/FilterLayout.js +5 -3
  3. package/dist/cjs/TimeField/utils.js +12 -6
  4. package/dist/cjs/ToggleSwitch/ToggleSwitch.js +99 -0
  5. package/dist/cjs/ToggleSwitch/ToggleSwitch.test.js +67 -0
  6. package/dist/cjs/ToggleSwitch/index.js +15 -0
  7. package/dist/cjs/index.d.js +13 -1
  8. package/dist/cjs/index.js +5 -1
  9. package/dist/cjs/system/colors/colors.js +17 -0
  10. package/dist/cjs/system/default-theme.js +3 -0
  11. package/dist/cjs/system/plugins/color.js +3 -1
  12. package/dist/cjs/system/style-names.js +1 -1
  13. package/dist/cjs/utils.js +0 -9
  14. package/dist/esm/Button/Button.js +15 -4
  15. package/dist/esm/FilterLayout/FilterLayout.js +5 -3
  16. package/dist/esm/TimeField/utils.js +12 -6
  17. package/dist/esm/ToggleSwitch/ToggleSwitch.js +80 -0
  18. package/dist/esm/ToggleSwitch/ToggleSwitch.test.js +57 -0
  19. package/dist/esm/ToggleSwitch/index.js +2 -0
  20. package/dist/esm/index.d.js +2 -0
  21. package/dist/esm/index.js +1 -0
  22. package/dist/esm/system/colors/colors.js +18 -1
  23. package/dist/esm/system/default-theme.js +3 -0
  24. package/dist/esm/system/plugins/color.js +3 -1
  25. package/dist/esm/system/style-names.js +1 -1
  26. package/dist/esm/utils.js +1 -9
  27. package/dist/types/Button/Button.d.ts +5 -1
  28. package/dist/types/ToggleSwitch/ToggleSwitch.d.ts +22 -0
  29. package/dist/types/ToggleSwitch/ToggleSwitch.test.d.ts +1 -0
  30. package/dist/types/ToggleSwitch/index.d.ts +2 -0
  31. package/dist/types/index.d.ts +5 -0
  32. package/dist/types/system/style-names.d.ts +2 -2
  33. package/package.json +1 -1
  34. package/src/Button/Button.tsx +26 -3
  35. package/src/FilterLayout/FilterLayout.tsx +9 -6
  36. package/src/TimeField/TimeField.mdx +1 -1
  37. package/src/TimeField/utils.js +11 -13
  38. package/src/ToggleSwitch/ToggleSwitch.mdx +56 -0
  39. package/src/ToggleSwitch/ToggleSwitch.test.tsx +51 -0
  40. package/src/ToggleSwitch/ToggleSwitch.tsx +106 -0
  41. package/src/ToggleSwitch/index.ts +2 -0
  42. package/src/index.d.ts +5 -0
  43. package/src/index.js +1 -0
  44. package/src/system/colors/colors.js +20 -1
  45. package/src/system/default-theme.ts +3 -0
  46. package/src/system/plugins/color.js +3 -0
  47. package/src/system/style-names.ts +1 -0
  48. package/src/utils.js +0 -8
  49. package/dist/cjs/TimeField/legacy_TimeField.js +0 -274
  50. package/dist/esm/TimeField/legacy_TimeField.js +0 -271
  51. package/src/TimeField/legacy_TimeField.js +0 -278
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import { render, fireEvent } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/extend-expect';
4
+ import ToggleSwitch from './ToggleSwitch';
5
+ describe('ToggleSwitch component', function () {
6
+ it('should render with default properties', function () {
7
+ var _render = render( /*#__PURE__*/React.createElement(ToggleSwitch, {
8
+ isActive: false,
9
+ label: "Toggle me",
10
+ onClick: function onClick() {}
11
+ })),
12
+ getByRole = _render.getByRole;
13
+
14
+ var toggleButton = getByRole('button');
15
+ expect(toggleButton).toBeInTheDocument();
16
+ });
17
+ it('should call onClick when clicked', function () {
18
+ var mockOnClick = jest.fn();
19
+
20
+ var _render2 = render( /*#__PURE__*/React.createElement(ToggleSwitch, {
21
+ isActive: false,
22
+ label: "Toggle me",
23
+ onClick: mockOnClick
24
+ })),
25
+ getByRole = _render2.getByRole;
26
+
27
+ var toggleButton = getByRole('button');
28
+ fireEvent.click(toggleButton);
29
+ expect(mockOnClick).toHaveBeenCalled();
30
+ });
31
+ it('should display the label', function () {
32
+ var label = 'Toggle me';
33
+
34
+ var _render3 = render( /*#__PURE__*/React.createElement(ToggleSwitch, {
35
+ isActive: false,
36
+ label: label,
37
+ onClick: function onClick() {}
38
+ })),
39
+ getByText = _render3.getByText;
40
+
41
+ expect(getByText(label)).toBeInTheDocument();
42
+ });
43
+ it('should apply active color when isActive is true', function () {
44
+ var activeColor = 'green';
45
+
46
+ var _render4 = render( /*#__PURE__*/React.createElement(ToggleSwitch, {
47
+ backgroundColor: activeColor,
48
+ isActive: true,
49
+ label: "Toggle me",
50
+ onClick: function onClick() {}
51
+ })),
52
+ getByRole = _render4.getByRole;
53
+
54
+ var toggleButton = getByRole('button');
55
+ expect(toggleButton).toHaveStyle("background-color: " + activeColor);
56
+ });
57
+ });
@@ -0,0 +1,2 @@
1
+ export * from './ToggleSwitch';
2
+ export { ToggleSwitch as default } from './ToggleSwitch';
@@ -57,6 +57,7 @@ export var Table;
57
57
  export var Tabs;
58
58
  export var TextArea;
59
59
  export var TimeField;
60
+ export var ToggleSwitch;
60
61
  export var Toolbar;
61
62
  export var TokenInput;
62
63
  export var Tooltip;
@@ -107,5 +108,6 @@ export * from './StackView';
107
108
  export * from './Tab';
108
109
  export * from './Text';
109
110
  export * from './TileView';
111
+ export * from './ToggleSwitch';
110
112
  export * from './ThemeProvider';
111
113
  export * from './WrapView';
package/dist/esm/index.js CHANGED
@@ -78,6 +78,7 @@ export { default as TextArea } from './TextArea';
78
78
  export { default as ThemeProvider } from './ThemeProvider';
79
79
  export { default as TileView } from './TileView';
80
80
  export { default as TimeField } from './TimeField';
81
+ export { default as ToggleSwitch } from './ToggleSwitch';
81
82
  export { default as Toolbar } from './Toolbar';
82
83
  export { default as TokenInput } from './TokenInput';
83
84
  export { default as Tooltip } from './Tooltip';
@@ -1,5 +1,22 @@
1
- import { flattenPalette } from './utils';
1
+ import { flattenPalette } from './utils'; // NOTE: this is a solution for using the UX palette in Tapestry-React
2
+ // that will likely be replaced with a tokenized palette in the future
3
+
4
+ var tapestry = {
5
+ create: {
6
+ create35: 'hsl(86deg 91% 35% / 100%)'
7
+ },
8
+ grays: {
9
+ light: {
10
+ neutral62: 'hsl(0deg 0% 62% / 100%)',
11
+ neutral81: 'hsl(0deg 0% 81% / 100%)'
12
+ }
13
+ },
14
+ interaction: {
15
+ interaction66: 'hsl(221deg 91% 66% / 100%)'
16
+ }
17
+ };
2
18
  export var palette = {
19
+ tapestry: tapestry,
3
20
  primary: {
4
21
  lightest: 'hsl(88, 24%, 92%)',
5
22
  lighter: 'hsl(88, 32%, 86%)',
@@ -60,6 +60,9 @@ var defaultTheme = {
60
60
  xxl: 9
61
61
  },
62
62
  trackColor: 'primary-lighter'
63
+ },
64
+ toggleSwitch: {
65
+ backgroundColor: 'interaction66'
63
66
  }
64
67
  };
65
68
  export default defaultTheme;
@@ -11,8 +11,9 @@ function color(_ref, theme) {
11
11
  borderTopColor = _ref.borderTopColor,
12
12
  color = _ref.color,
13
13
  fill = _ref.fill,
14
+ outlineColor = _ref.outlineColor,
14
15
  stroke = _ref.stroke,
15
- styles = _objectWithoutPropertiesLoose(_ref, ["backgroundColor", "borderColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "fill", "stroke"]);
16
+ styles = _objectWithoutPropertiesLoose(_ref, ["backgroundColor", "borderColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "fill", "outlineColor", "stroke"]);
16
17
 
17
18
  var colorProps = {
18
19
  backgroundColor: backgroundColor,
@@ -23,6 +24,7 @@ function color(_ref, theme) {
23
24
  borderTopColor: borderTopColor,
24
25
  color: color,
25
26
  fill: fill,
27
+ outlineColor: outlineColor,
26
28
  stroke: stroke
27
29
  };
28
30
  Object.keys(colorProps).forEach(function (key) {
@@ -1,5 +1,5 @@
1
1
  export var nativeStyleNames = ['alignContent', 'alignItems', 'alignSelf', 'alignmentBaseline', 'animation', 'animationDelay', 'animationDirection', 'animationDuration', 'animationFillMode', 'animationIterationCount', 'animationName', 'animationPlayState', 'animationTimingFunction', 'backfaceVisibility', 'background', 'backgroundAttachment', 'backgroundBlendMode', 'backgroundClip', 'backgroundImage', 'backgroundOrigin', 'backgroundPosition', 'backgroundPositionX', 'backgroundPositionY', 'backgroundRepeat', 'backgroundSize', 'baselineShift', 'border', 'borderBottom', 'borderBottomLeftRadius', 'borderBottomRightRadius', 'borderBottomStyle', 'borderBottomWidth', 'borderCollapse', 'borderImage', 'borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth', 'borderLeft', 'borderLeftStyle', 'borderLeftWidth', 'borderRadius', 'borderRight', 'borderRightStyle', 'borderRightWidth', 'borderSpacing', 'borderStyle', 'borderTop', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderTopStyle', 'borderTopWidth', 'borderWidth', 'bottom', 'boxShadow', 'boxSizing', 'breakAfter', 'breakBefore', 'breakInside', 'clear', 'clip', 'clipPath', 'clipRule', 'columnCount', 'columnFill', 'columnGap', 'columnRule', 'columnRuleColor', 'columnRuleStyle', 'columnRuleWidth', 'columnSpan', 'columnWidth', 'columns', 'contain', 'content', 'counterIncrement', 'counterReset', 'cursor', 'direction', 'display', 'fillOpacity', 'fillRule', 'filter', 'flex', 'flexBasis', 'flexDirection', 'flexFlow', 'flexGrow', 'flexShrink', 'flexWrap', 'font', 'fontFamily', 'fontFeatureSettings', 'fontKerning', 'fontSize', 'fontStretch', 'fontStyle', 'fontVariant', 'fontVariantCaps', 'fontVariantLigatures', 'fontVariantNumeric', 'fontWeight', 'gap', 'gridArea', 'gridAutoColumns', 'gridAutoFlow', 'gridAutoRows', 'gridColumn', 'gridColumnEnd', 'gridColumnGap', 'gridColumnStart', 'gridGap', 'gridRow', 'gridRowEnd', 'gridRowGap', 'gridRowStart', 'gridTemplate', 'gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows', 'height', 'imageRendering', 'isolation', 'justifyContent', 'justifyItems', 'justifySelf', 'left', 'letterSpacing', 'lightingColor', 'lineHeight', 'listStyle', 'listStyleImage', 'listStylePosition', 'listStyleType', 'margin', 'marginBottom', 'marginLeft', 'marginRight', 'marginTop', 'mask', 'maskType', 'maxHeight', 'maxWidth', 'minHeight', 'minWidth', 'mixBlendMode', 'motion', 'objectFit', 'objectPosition', 'opacity', 'order', 'outline', 'outlineColor', 'outlineOffset', 'outlineStyle', 'outlineWidth', 'overflow', 'overflowWrap', 'overflowX', 'overflowY', 'padding', 'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop', 'pageBreakAfter', 'pageBreakBefore', 'pageBreakInside', 'perspective', 'perspectiveOrigin', 'placeItems', 'placeSelf', 'pointerEvents', 'position', 'resize', 'right', 'strokeDasharray', 'strokeDashoffset', 'strokeLinecap', 'strokeLinejoin', 'strokeMiterlimit', 'strokeOpacity', 'strokeWidth', 'tabSize', 'tableLayout', 'textAlign', 'textDecoration', 'textIndent', 'textOrientation', 'textOverflow', 'textRendering', 'textShadow', 'textTransform', 'top', 'touchAction', 'transform', 'transformOrigin', 'transformStyle', 'transition', 'transitionDelay', 'transitionDuration', 'transitionProperty', 'transitionTimingFunction', 'verticalAlign', 'visibility', 'clipPath', 'filter', 'userSelect', 'WebkitOverflowScrolling', 'writingMode', 'whiteSpace', 'width', 'willChange', 'wordBreak', 'wordSpacing', 'wordWrap', 'zIndex'];
2
- export var colorStyleNames = ['backgroundColor', 'borderColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'fill', 'stroke'];
2
+ export var colorStyleNames = ['backgroundColor', 'borderColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'fill', 'outlineColor', 'stroke'];
3
3
  export var customStyleNames = ['css', 'column', 'columnStart', 'columnEnd', 'row', 'rowStart', 'rowEnd', 'basis', 'elevation', 'grow', 'marginHorizontal', 'marginVertical', 'paddingHorizontal', 'paddingVertical', 'radius', 'radiusTop', 'radiusRight', 'radiusBottom', 'radiusLeft', 'x', 'y', 'rotate', 'scale', 'uppercase', 'shrink', 'wrap', 'strokeAlign', 'strokeWeight'];
4
4
  export var stylePropNames = [].concat(nativeStyleNames, colorStyleNames, customStyleNames);
5
5
  export var pseudoPropNames = ['active', 'focus', 'hover'];
package/dist/esm/utils.js CHANGED
@@ -352,14 +352,6 @@ function isArray(value) {
352
352
  function isFunction(value) {
353
353
  return value && value.constructor === Function;
354
354
  }
355
- /**
356
- * Determines if value is a number
357
- */
358
-
359
-
360
- function isNumber(value) {
361
- return /^[0-9]$/i.test(value);
362
- }
363
355
  /**
364
356
  * Determines if a value is present in an array by
365
357
  * performing a shallow equal check on each item.
@@ -829,4 +821,4 @@ function mergeProps() {
829
821
  }, {});
830
822
  }
831
823
 
832
- export { cloneChildren, composeEvents, composeMultipleEvents, createCSSProperty, deselectCurrentTextRange, generateId, getCSSProperty, getClosestFocusableElement, getClosestViewport, getInteractiveChildElements, getRect, getScrollbarWidth, getTabbableSiblings, getTextWidth, insertAtIndex, isArray, isElementInteractive, isFunction, isIOS, isNumber, isValueInArray, joinChildren, lockScroll, mergeProps, noop, objectToCSSProperties, padNumber, pageViewChange, range, removeAtIndex, renderIndexedGroup, reorderArray, shallowEqual, selectFullTextRange, stopImmediatePropagation, stopPropagationClick, supportsPassiveEvents, trapFocus };
824
+ export { cloneChildren, composeEvents, composeMultipleEvents, createCSSProperty, deselectCurrentTextRange, generateId, getCSSProperty, getClosestFocusableElement, getClosestViewport, getInteractiveChildElements, getRect, getScrollbarWidth, getTabbableSiblings, getTextWidth, insertAtIndex, isArray, isElementInteractive, isFunction, isIOS, isValueInArray, joinChildren, lockScroll, mergeProps, noop, objectToCSSProperties, padNumber, pageViewChange, range, removeAtIndex, renderIndexedGroup, reorderArray, shallowEqual, selectFullTextRange, stopImmediatePropagation, stopPropagationClick, supportsPassiveEvents, trapFocus };
@@ -19,6 +19,10 @@ declare type ButtonProps = {
19
19
  * Pass styles for when the button is focused.
20
20
  */
21
21
  focus?: object;
22
+ /**
23
+ * Pass styles for when the button is keyboard-focused.
24
+ */
25
+ focusVisible?: object;
22
26
  /**
23
27
  * Pass styles for when the button is hovered.
24
28
  */
@@ -102,7 +106,7 @@ export declare namespace Button {
102
106
  visible?: boolean;
103
107
  variants?: object;
104
108
  mediaQueries?: object;
105
- } & Pick<React.CSSProperties, "alignContent" | "alignItems" | "alignSelf" | "alignmentBaseline" | "animation" | "animationDelay" | "animationDirection" | "animationDuration" | "animationFillMode" | "animationIterationCount" | "animationName" | "animationPlayState" | "animationTimingFunction" | "backfaceVisibility" | "background" | "backgroundAttachment" | "backgroundBlendMode" | "backgroundClip" | "backgroundImage" | "backgroundOrigin" | "backgroundPosition" | "backgroundPositionX" | "backgroundPositionY" | "backgroundRepeat" | "backgroundSize" | "baselineShift" | "border" | "borderBottom" | "borderBottomLeftRadius" | "borderBottomRightRadius" | "borderBottomStyle" | "borderBottomWidth" | "borderCollapse" | "borderImage" | "borderImageOutset" | "borderImageRepeat" | "borderImageSlice" | "borderImageSource" | "borderImageWidth" | "borderLeft" | "borderLeftStyle" | "borderLeftWidth" | "borderRadius" | "borderRight" | "borderRightStyle" | "borderRightWidth" | "borderSpacing" | "borderStyle" | "borderTop" | "borderTopLeftRadius" | "borderTopRightRadius" | "borderTopStyle" | "borderTopWidth" | "borderWidth" | "bottom" | "boxShadow" | "boxSizing" | "breakAfter" | "breakBefore" | "breakInside" | "clear" | "clip" | "clipPath" | "clipRule" | "columnCount" | "columnFill" | "columnGap" | "columnRule" | "columnRuleColor" | "columnRuleStyle" | "columnRuleWidth" | "columnSpan" | "columnWidth" | "columns" | "contain" | "content" | "counterIncrement" | "counterReset" | "cursor" | "direction" | "display" | "fillOpacity" | "fillRule" | "filter" | "flex" | "flexBasis" | "flexDirection" | "flexFlow" | "flexGrow" | "flexShrink" | "flexWrap" | "font" | "fontFamily" | "fontFeatureSettings" | "fontKerning" | "fontSize" | "fontStretch" | "fontStyle" | "fontVariant" | "fontVariantCaps" | "fontVariantLigatures" | "fontVariantNumeric" | "fontWeight" | "gap" | "gridArea" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridColumn" | "gridColumnEnd" | "gridColumnGap" | "gridColumnStart" | "gridGap" | "gridRow" | "gridRowEnd" | "gridRowGap" | "gridRowStart" | "gridTemplate" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "imageRendering" | "isolation" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lightingColor" | "lineHeight" | "listStyle" | "listStyleImage" | "listStylePosition" | "listStyleType" | "margin" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "mask" | "maskType" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "mixBlendMode" | "motion" | "objectFit" | "objectPosition" | "opacity" | "order" | "outline" | "outlineColor" | "outlineOffset" | "outlineStyle" | "outlineWidth" | "overflow" | "overflowWrap" | "overflowX" | "overflowY" | "padding" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "pageBreakAfter" | "pageBreakBefore" | "pageBreakInside" | "perspective" | "perspectiveOrigin" | "placeItems" | "placeSelf" | "pointerEvents" | "position" | "resize" | "right" | "strokeDasharray" | "strokeDashoffset" | "strokeLinecap" | "strokeLinejoin" | "strokeMiterlimit" | "strokeOpacity" | "strokeWidth" | "tabSize" | "tableLayout" | "textAlign" | "textDecoration" | "textIndent" | "textOrientation" | "textOverflow" | "textRendering" | "textShadow" | "textTransform" | "top" | "touchAction" | "transform" | "transformOrigin" | "transformStyle" | "transition" | "transitionDelay" | "transitionDuration" | "transitionProperty" | "transitionTimingFunction" | "verticalAlign" | "visibility" | "userSelect" | "WebkitOverflowScrolling" | "writingMode" | "whiteSpace" | "width" | "willChange" | "wordBreak" | "wordSpacing" | "wordWrap" | "zIndex"> & Partial<Record<"backgroundColor" | "borderColor" | "borderBottomColor" | "borderLeftColor" | "borderRightColor" | "borderTopColor" | "color" | "fill" | "stroke", import("type-fest").LiteralUnion<"background" | "foreground" | "foregroundSecondary" | "foregroundTertiary" | "backgroundSecondary" | "backgroundTertiary" | "surface" | "surfaceSecondary" | "surfaceTertiary" | "separator" | "separatorSecondary" | "separatorTertiary" | "separatorHover" | "separatorFocus" | "separatorFocusSecondary" | "highlight" | "highlightSecondary" | "linkForeground" | "linkBackground" | "primary" | "primary-light" | "primary-lighter" | "primary-lightest" | "primary-dark" | "primary-darker" | "primary-darkest" | "warning" | "warning-light" | "warning-lighter" | "warning-lightest" | "warning-dark" | "warning-darker" | "warning-darkest" | "error" | "error-light" | "error-lighter" | "error-lightest" | "error-dark" | "error-darker" | "error-darkest" | "success" | "success-light" | "success-lighter" | "success-lightest" | "success-dark" | "success-darker" | "success-darkest" | "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "check-ins" | "giving" | "groups" | "music-stand" | "pco" | "people" | "planning-center" | "projector" | "registrations" | "calendar" | "services" | "red-0" | "red-1" | "red-2" | "red-3" | "red-4" | "red-5" | "red-6" | "red-7" | "red-8" | "red-9" | "blue-0" | "blue-1" | "blue-2" | "blue-3" | "blue-4" | "blue-5" | "blue-6" | "blue-7" | "blue-8" | "blue-9" | "green-0" | "green-1" | "green-2" | "green-3" | "green-4" | "green-5" | "green-6" | "green-7" | "green-8" | "green-9" | "yellow-0" | "yellow-1" | "yellow-2" | "yellow-3" | "yellow-4" | "yellow-5" | "yellow-6" | "yellow-7" | "yellow-8" | "yellow-9" | "light-0" | "light-1" | "light-2" | "light-3" | "light-4" | "light-5" | "light-6" | "light-7" | "light-8" | "light-9" | "dark-0" | "dark-1" | "dark-2" | "dark-3" | "dark-4" | "dark-5" | "dark-6" | "dark-7" | "dark-8" | "dark-9" | "grey-0" | "grey-1" | "grey-2" | "grey-3" | "grey-4" | "grey-5" | "grey-6" | "grey-7" | "grey-8" | "grey-9" | "transparent", string>>> & {
109
+ } & Pick<React.CSSProperties, "alignContent" | "alignItems" | "alignSelf" | "alignmentBaseline" | "animation" | "animationDelay" | "animationDirection" | "animationDuration" | "animationFillMode" | "animationIterationCount" | "animationName" | "animationPlayState" | "animationTimingFunction" | "backfaceVisibility" | "background" | "backgroundAttachment" | "backgroundBlendMode" | "backgroundClip" | "backgroundImage" | "backgroundOrigin" | "backgroundPosition" | "backgroundPositionX" | "backgroundPositionY" | "backgroundRepeat" | "backgroundSize" | "baselineShift" | "border" | "borderBottom" | "borderBottomLeftRadius" | "borderBottomRightRadius" | "borderBottomStyle" | "borderBottomWidth" | "borderCollapse" | "borderImage" | "borderImageOutset" | "borderImageRepeat" | "borderImageSlice" | "borderImageSource" | "borderImageWidth" | "borderLeft" | "borderLeftStyle" | "borderLeftWidth" | "borderRadius" | "borderRight" | "borderRightStyle" | "borderRightWidth" | "borderSpacing" | "borderStyle" | "borderTop" | "borderTopLeftRadius" | "borderTopRightRadius" | "borderTopStyle" | "borderTopWidth" | "borderWidth" | "bottom" | "boxShadow" | "boxSizing" | "breakAfter" | "breakBefore" | "breakInside" | "clear" | "clip" | "clipPath" | "clipRule" | "columnCount" | "columnFill" | "columnGap" | "columnRule" | "columnRuleColor" | "columnRuleStyle" | "columnRuleWidth" | "columnSpan" | "columnWidth" | "columns" | "contain" | "content" | "counterIncrement" | "counterReset" | "cursor" | "direction" | "display" | "fillOpacity" | "fillRule" | "filter" | "flex" | "flexBasis" | "flexDirection" | "flexFlow" | "flexGrow" | "flexShrink" | "flexWrap" | "font" | "fontFamily" | "fontFeatureSettings" | "fontKerning" | "fontSize" | "fontStretch" | "fontStyle" | "fontVariant" | "fontVariantCaps" | "fontVariantLigatures" | "fontVariantNumeric" | "fontWeight" | "gap" | "gridArea" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridColumn" | "gridColumnEnd" | "gridColumnGap" | "gridColumnStart" | "gridGap" | "gridRow" | "gridRowEnd" | "gridRowGap" | "gridRowStart" | "gridTemplate" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "imageRendering" | "isolation" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lightingColor" | "lineHeight" | "listStyle" | "listStyleImage" | "listStylePosition" | "listStyleType" | "margin" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "mask" | "maskType" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "mixBlendMode" | "motion" | "objectFit" | "objectPosition" | "opacity" | "order" | "outline" | "outlineColor" | "outlineOffset" | "outlineStyle" | "outlineWidth" | "overflow" | "overflowWrap" | "overflowX" | "overflowY" | "padding" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "pageBreakAfter" | "pageBreakBefore" | "pageBreakInside" | "perspective" | "perspectiveOrigin" | "placeItems" | "placeSelf" | "pointerEvents" | "position" | "resize" | "right" | "strokeDasharray" | "strokeDashoffset" | "strokeLinecap" | "strokeLinejoin" | "strokeMiterlimit" | "strokeOpacity" | "strokeWidth" | "tabSize" | "tableLayout" | "textAlign" | "textDecoration" | "textIndent" | "textOrientation" | "textOverflow" | "textRendering" | "textShadow" | "textTransform" | "top" | "touchAction" | "transform" | "transformOrigin" | "transformStyle" | "transition" | "transitionDelay" | "transitionDuration" | "transitionProperty" | "transitionTimingFunction" | "verticalAlign" | "visibility" | "userSelect" | "WebkitOverflowScrolling" | "writingMode" | "whiteSpace" | "width" | "willChange" | "wordBreak" | "wordSpacing" | "wordWrap" | "zIndex"> & Partial<Record<"outlineColor" | "backgroundColor" | "borderColor" | "borderBottomColor" | "borderLeftColor" | "borderRightColor" | "borderTopColor" | "color" | "fill" | "stroke", import("type-fest").LiteralUnion<"background" | "foreground" | "foregroundSecondary" | "foregroundTertiary" | "backgroundSecondary" | "backgroundTertiary" | "surface" | "surfaceSecondary" | "surfaceTertiary" | "separator" | "separatorSecondary" | "separatorTertiary" | "separatorHover" | "separatorFocus" | "separatorFocusSecondary" | "highlight" | "highlightSecondary" | "linkForeground" | "linkBackground" | "primary" | "primary-light" | "primary-lighter" | "primary-lightest" | "primary-dark" | "primary-darker" | "primary-darkest" | "warning" | "warning-light" | "warning-lighter" | "warning-lightest" | "warning-dark" | "warning-darker" | "warning-darkest" | "error" | "error-light" | "error-lighter" | "error-lightest" | "error-dark" | "error-darker" | "error-darkest" | "success" | "success-light" | "success-lighter" | "success-lightest" | "success-dark" | "success-darker" | "success-darkest" | "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "check-ins" | "giving" | "groups" | "music-stand" | "pco" | "people" | "planning-center" | "projector" | "registrations" | "calendar" | "services" | "red-0" | "red-1" | "red-2" | "red-3" | "red-4" | "red-5" | "red-6" | "red-7" | "red-8" | "red-9" | "blue-0" | "blue-1" | "blue-2" | "blue-3" | "blue-4" | "blue-5" | "blue-6" | "blue-7" | "blue-8" | "blue-9" | "green-0" | "green-1" | "green-2" | "green-3" | "green-4" | "green-5" | "green-6" | "green-7" | "green-8" | "green-9" | "yellow-0" | "yellow-1" | "yellow-2" | "yellow-3" | "yellow-4" | "yellow-5" | "yellow-6" | "yellow-7" | "yellow-8" | "yellow-9" | "light-0" | "light-1" | "light-2" | "light-3" | "light-4" | "light-5" | "light-6" | "light-7" | "light-8" | "light-9" | "dark-0" | "dark-1" | "dark-2" | "dark-3" | "dark-4" | "dark-5" | "dark-6" | "dark-7" | "dark-8" | "dark-9" | "grey-0" | "grey-1" | "grey-2" | "grey-3" | "grey-4" | "grey-5" | "grey-6" | "grey-7" | "grey-8" | "grey-9" | "transparent", string>>> & {
106
110
  css?: any;
107
111
  paddingHorizontal?: string | number;
108
112
  paddingVertical?: string | number;
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { StackViewProps } from '../StackView';
3
+ import { MediaQueries } from '..';
4
+ export declare type ToggleSwitchProps = {
5
+ /** The color of the toggle background when it is active. */
6
+ backgroundColor?: string;
7
+ /** Whether the toggle is disabled. */
8
+ disabled?: boolean;
9
+ /** Whether the toggle is active. */
10
+ isActive: boolean;
11
+ /** The label for the toggle. */
12
+ label: string;
13
+ /** The function to call when the toggle is clicked. */
14
+ onClick: () => void;
15
+ /** The size of the toggle. */
16
+ size?: 'xs' | 'sm' | 'md';
17
+ /** The tooltip to display when the toggle is hovered. */
18
+ tooltip?: string;
19
+ } & StackViewProps;
20
+ declare type Props = React.RefAttributes<any> & React.HTMLAttributes<any> & ToggleSwitchProps & MediaQueries<ToggleSwitchProps>;
21
+ export declare function ToggleSwitch(props: Props): JSX.Element;
22
+ export default ToggleSwitch;
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom/extend-expect';
@@ -0,0 +1,2 @@
1
+ export * from './ToggleSwitch';
2
+ export { ToggleSwitch as default } from './ToggleSwitch';
@@ -208,6 +208,9 @@ export interface Theme {
208
208
  thickness?: Partial<SpinnerThickness>
209
209
  trackColor?: ColorProp
210
210
  }
211
+ toggleSwitch?: {
212
+ backgroundColor?: ColorProp
213
+ }
211
214
  }
212
215
 
213
216
  export interface MediaQueries<T> {
@@ -323,6 +326,7 @@ export const Table: React.FC<CommonProps>
323
326
  export const Tabs: React.FC<CommonProps>
324
327
  export const TextArea: React.FC<CommonProps>
325
328
  export const TimeField: React.FC<CommonProps>
329
+ export const ToggleSwitch: React.FC<CommonProps>
326
330
  export const Toolbar: React.FC<CommonProps>
327
331
  export const TokenInput: React.FC<CommonProps>
328
332
  export const Tooltip: React.FC<CommonProps>
@@ -406,5 +410,6 @@ export * from './StackView'
406
410
  export * from './Tab'
407
411
  export * from './Text'
408
412
  export * from './TileView'
413
+ export * from './ToggleSwitch'
409
414
  export * from './ThemeProvider'
410
415
  export * from './WrapView'
@@ -1,8 +1,8 @@
1
1
  export declare const nativeStyleNames: readonly ["alignContent", "alignItems", "alignSelf", "alignmentBaseline", "animation", "animationDelay", "animationDirection", "animationDuration", "animationFillMode", "animationIterationCount", "animationName", "animationPlayState", "animationTimingFunction", "backfaceVisibility", "background", "backgroundAttachment", "backgroundBlendMode", "backgroundClip", "backgroundImage", "backgroundOrigin", "backgroundPosition", "backgroundPositionX", "backgroundPositionY", "backgroundRepeat", "backgroundSize", "baselineShift", "border", "borderBottom", "borderBottomLeftRadius", "borderBottomRightRadius", "borderBottomStyle", "borderBottomWidth", "borderCollapse", "borderImage", "borderImageOutset", "borderImageRepeat", "borderImageSlice", "borderImageSource", "borderImageWidth", "borderLeft", "borderLeftStyle", "borderLeftWidth", "borderRadius", "borderRight", "borderRightStyle", "borderRightWidth", "borderSpacing", "borderStyle", "borderTop", "borderTopLeftRadius", "borderTopRightRadius", "borderTopStyle", "borderTopWidth", "borderWidth", "bottom", "boxShadow", "boxSizing", "breakAfter", "breakBefore", "breakInside", "clear", "clip", "clipPath", "clipRule", "columnCount", "columnFill", "columnGap", "columnRule", "columnRuleColor", "columnRuleStyle", "columnRuleWidth", "columnSpan", "columnWidth", "columns", "contain", "content", "counterIncrement", "counterReset", "cursor", "direction", "display", "fillOpacity", "fillRule", "filter", "flex", "flexBasis", "flexDirection", "flexFlow", "flexGrow", "flexShrink", "flexWrap", "font", "fontFamily", "fontFeatureSettings", "fontKerning", "fontSize", "fontStretch", "fontStyle", "fontVariant", "fontVariantCaps", "fontVariantLigatures", "fontVariantNumeric", "fontWeight", "gap", "gridArea", "gridAutoColumns", "gridAutoFlow", "gridAutoRows", "gridColumn", "gridColumnEnd", "gridColumnGap", "gridColumnStart", "gridGap", "gridRow", "gridRowEnd", "gridRowGap", "gridRowStart", "gridTemplate", "gridTemplateAreas", "gridTemplateColumns", "gridTemplateRows", "height", "imageRendering", "isolation", "justifyContent", "justifyItems", "justifySelf", "left", "letterSpacing", "lightingColor", "lineHeight", "listStyle", "listStyleImage", "listStylePosition", "listStyleType", "margin", "marginBottom", "marginLeft", "marginRight", "marginTop", "mask", "maskType", "maxHeight", "maxWidth", "minHeight", "minWidth", "mixBlendMode", "motion", "objectFit", "objectPosition", "opacity", "order", "outline", "outlineColor", "outlineOffset", "outlineStyle", "outlineWidth", "overflow", "overflowWrap", "overflowX", "overflowY", "padding", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "pageBreakAfter", "pageBreakBefore", "pageBreakInside", "perspective", "perspectiveOrigin", "placeItems", "placeSelf", "pointerEvents", "position", "resize", "right", "strokeDasharray", "strokeDashoffset", "strokeLinecap", "strokeLinejoin", "strokeMiterlimit", "strokeOpacity", "strokeWidth", "tabSize", "tableLayout", "textAlign", "textDecoration", "textIndent", "textOrientation", "textOverflow", "textRendering", "textShadow", "textTransform", "top", "touchAction", "transform", "transformOrigin", "transformStyle", "transition", "transitionDelay", "transitionDuration", "transitionProperty", "transitionTimingFunction", "verticalAlign", "visibility", "clipPath", "filter", "userSelect", "WebkitOverflowScrolling", "writingMode", "whiteSpace", "width", "willChange", "wordBreak", "wordSpacing", "wordWrap", "zIndex"];
2
2
  export declare type NativeStyleNames = typeof nativeStyleNames[number];
3
- export declare const colorStyleNames: readonly ["backgroundColor", "borderColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "fill", "stroke"];
3
+ export declare const colorStyleNames: readonly ["backgroundColor", "borderColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "fill", "outlineColor", "stroke"];
4
4
  export declare type ColorStyleNames = typeof colorStyleNames[number];
5
5
  export declare const customStyleNames: readonly ["css", "column", "columnStart", "columnEnd", "row", "rowStart", "rowEnd", "basis", "elevation", "grow", "marginHorizontal", "marginVertical", "paddingHorizontal", "paddingVertical", "radius", "radiusTop", "radiusRight", "radiusBottom", "radiusLeft", "x", "y", "rotate", "scale", "uppercase", "shrink", "wrap", "strokeAlign", "strokeWeight"];
6
6
  export declare type CustomStyleNames = typeof customStyleNames[number];
7
- export declare const stylePropNames: readonly ["alignContent", "alignItems", "alignSelf", "alignmentBaseline", "animation", "animationDelay", "animationDirection", "animationDuration", "animationFillMode", "animationIterationCount", "animationName", "animationPlayState", "animationTimingFunction", "backfaceVisibility", "background", "backgroundAttachment", "backgroundBlendMode", "backgroundClip", "backgroundImage", "backgroundOrigin", "backgroundPosition", "backgroundPositionX", "backgroundPositionY", "backgroundRepeat", "backgroundSize", "baselineShift", "border", "borderBottom", "borderBottomLeftRadius", "borderBottomRightRadius", "borderBottomStyle", "borderBottomWidth", "borderCollapse", "borderImage", "borderImageOutset", "borderImageRepeat", "borderImageSlice", "borderImageSource", "borderImageWidth", "borderLeft", "borderLeftStyle", "borderLeftWidth", "borderRadius", "borderRight", "borderRightStyle", "borderRightWidth", "borderSpacing", "borderStyle", "borderTop", "borderTopLeftRadius", "borderTopRightRadius", "borderTopStyle", "borderTopWidth", "borderWidth", "bottom", "boxShadow", "boxSizing", "breakAfter", "breakBefore", "breakInside", "clear", "clip", "clipPath", "clipRule", "columnCount", "columnFill", "columnGap", "columnRule", "columnRuleColor", "columnRuleStyle", "columnRuleWidth", "columnSpan", "columnWidth", "columns", "contain", "content", "counterIncrement", "counterReset", "cursor", "direction", "display", "fillOpacity", "fillRule", "filter", "flex", "flexBasis", "flexDirection", "flexFlow", "flexGrow", "flexShrink", "flexWrap", "font", "fontFamily", "fontFeatureSettings", "fontKerning", "fontSize", "fontStretch", "fontStyle", "fontVariant", "fontVariantCaps", "fontVariantLigatures", "fontVariantNumeric", "fontWeight", "gap", "gridArea", "gridAutoColumns", "gridAutoFlow", "gridAutoRows", "gridColumn", "gridColumnEnd", "gridColumnGap", "gridColumnStart", "gridGap", "gridRow", "gridRowEnd", "gridRowGap", "gridRowStart", "gridTemplate", "gridTemplateAreas", "gridTemplateColumns", "gridTemplateRows", "height", "imageRendering", "isolation", "justifyContent", "justifyItems", "justifySelf", "left", "letterSpacing", "lightingColor", "lineHeight", "listStyle", "listStyleImage", "listStylePosition", "listStyleType", "margin", "marginBottom", "marginLeft", "marginRight", "marginTop", "mask", "maskType", "maxHeight", "maxWidth", "minHeight", "minWidth", "mixBlendMode", "motion", "objectFit", "objectPosition", "opacity", "order", "outline", "outlineColor", "outlineOffset", "outlineStyle", "outlineWidth", "overflow", "overflowWrap", "overflowX", "overflowY", "padding", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "pageBreakAfter", "pageBreakBefore", "pageBreakInside", "perspective", "perspectiveOrigin", "placeItems", "placeSelf", "pointerEvents", "position", "resize", "right", "strokeDasharray", "strokeDashoffset", "strokeLinecap", "strokeLinejoin", "strokeMiterlimit", "strokeOpacity", "strokeWidth", "tabSize", "tableLayout", "textAlign", "textDecoration", "textIndent", "textOrientation", "textOverflow", "textRendering", "textShadow", "textTransform", "top", "touchAction", "transform", "transformOrigin", "transformStyle", "transition", "transitionDelay", "transitionDuration", "transitionProperty", "transitionTimingFunction", "verticalAlign", "visibility", "clipPath", "filter", "userSelect", "WebkitOverflowScrolling", "writingMode", "whiteSpace", "width", "willChange", "wordBreak", "wordSpacing", "wordWrap", "zIndex", "backgroundColor", "borderColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "fill", "stroke", "css", "column", "columnStart", "columnEnd", "row", "rowStart", "rowEnd", "basis", "elevation", "grow", "marginHorizontal", "marginVertical", "paddingHorizontal", "paddingVertical", "radius", "radiusTop", "radiusRight", "radiusBottom", "radiusLeft", "x", "y", "rotate", "scale", "uppercase", "shrink", "wrap", "strokeAlign", "strokeWeight"];
7
+ export declare const stylePropNames: readonly ["alignContent", "alignItems", "alignSelf", "alignmentBaseline", "animation", "animationDelay", "animationDirection", "animationDuration", "animationFillMode", "animationIterationCount", "animationName", "animationPlayState", "animationTimingFunction", "backfaceVisibility", "background", "backgroundAttachment", "backgroundBlendMode", "backgroundClip", "backgroundImage", "backgroundOrigin", "backgroundPosition", "backgroundPositionX", "backgroundPositionY", "backgroundRepeat", "backgroundSize", "baselineShift", "border", "borderBottom", "borderBottomLeftRadius", "borderBottomRightRadius", "borderBottomStyle", "borderBottomWidth", "borderCollapse", "borderImage", "borderImageOutset", "borderImageRepeat", "borderImageSlice", "borderImageSource", "borderImageWidth", "borderLeft", "borderLeftStyle", "borderLeftWidth", "borderRadius", "borderRight", "borderRightStyle", "borderRightWidth", "borderSpacing", "borderStyle", "borderTop", "borderTopLeftRadius", "borderTopRightRadius", "borderTopStyle", "borderTopWidth", "borderWidth", "bottom", "boxShadow", "boxSizing", "breakAfter", "breakBefore", "breakInside", "clear", "clip", "clipPath", "clipRule", "columnCount", "columnFill", "columnGap", "columnRule", "columnRuleColor", "columnRuleStyle", "columnRuleWidth", "columnSpan", "columnWidth", "columns", "contain", "content", "counterIncrement", "counterReset", "cursor", "direction", "display", "fillOpacity", "fillRule", "filter", "flex", "flexBasis", "flexDirection", "flexFlow", "flexGrow", "flexShrink", "flexWrap", "font", "fontFamily", "fontFeatureSettings", "fontKerning", "fontSize", "fontStretch", "fontStyle", "fontVariant", "fontVariantCaps", "fontVariantLigatures", "fontVariantNumeric", "fontWeight", "gap", "gridArea", "gridAutoColumns", "gridAutoFlow", "gridAutoRows", "gridColumn", "gridColumnEnd", "gridColumnGap", "gridColumnStart", "gridGap", "gridRow", "gridRowEnd", "gridRowGap", "gridRowStart", "gridTemplate", "gridTemplateAreas", "gridTemplateColumns", "gridTemplateRows", "height", "imageRendering", "isolation", "justifyContent", "justifyItems", "justifySelf", "left", "letterSpacing", "lightingColor", "lineHeight", "listStyle", "listStyleImage", "listStylePosition", "listStyleType", "margin", "marginBottom", "marginLeft", "marginRight", "marginTop", "mask", "maskType", "maxHeight", "maxWidth", "minHeight", "minWidth", "mixBlendMode", "motion", "objectFit", "objectPosition", "opacity", "order", "outline", "outlineColor", "outlineOffset", "outlineStyle", "outlineWidth", "overflow", "overflowWrap", "overflowX", "overflowY", "padding", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "pageBreakAfter", "pageBreakBefore", "pageBreakInside", "perspective", "perspectiveOrigin", "placeItems", "placeSelf", "pointerEvents", "position", "resize", "right", "strokeDasharray", "strokeDashoffset", "strokeLinecap", "strokeLinejoin", "strokeMiterlimit", "strokeOpacity", "strokeWidth", "tabSize", "tableLayout", "textAlign", "textDecoration", "textIndent", "textOrientation", "textOverflow", "textRendering", "textShadow", "textTransform", "top", "touchAction", "transform", "transformOrigin", "transformStyle", "transition", "transitionDelay", "transitionDuration", "transitionProperty", "transitionTimingFunction", "verticalAlign", "visibility", "clipPath", "filter", "userSelect", "WebkitOverflowScrolling", "writingMode", "whiteSpace", "width", "willChange", "wordBreak", "wordSpacing", "wordWrap", "zIndex", "backgroundColor", "borderColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "fill", "outlineColor", "stroke", "css", "column", "columnStart", "columnEnd", "row", "rowStart", "rowEnd", "basis", "elevation", "grow", "marginHorizontal", "marginVertical", "paddingHorizontal", "paddingVertical", "radius", "radiusTop", "radiusRight", "radiusBottom", "radiusLeft", "x", "y", "rotate", "scale", "uppercase", "shrink", "wrap", "strokeAlign", "strokeWeight"];
8
8
  export declare const pseudoPropNames: readonly ["active", "focus", "hover"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/tapestry-react",
3
- "version": "2.9.0-rc.4",
3
+ "version": "2.9.0-rc.7",
4
4
  "description": "A collection of flexible React components to help you build resilient, accessible user interfaces quickly and effectively.",
5
5
  "author": "Front End Systems Engineering <frontend@pco.bz>",
6
6
  "main": "dist/cjs/index.js",
@@ -35,6 +35,11 @@ type ButtonProps = {
35
35
  */
36
36
  focus?: object
37
37
 
38
+ /**
39
+ * Pass styles for when the button is keyboard-focused.
40
+ */
41
+ focusVisible?: object
42
+
38
43
  /**
39
44
  * Pass styles for when the button is hovered.
40
45
  */
@@ -255,7 +260,17 @@ export function Button({
255
260
  }
256
261
 
257
262
  if (disabled) {
258
- buttonProps.opacity = 0.65
263
+ const disabledStyles = buttonThemes[theme][variant || 'fill'].disabled
264
+
265
+ if (disabledStyles !== undefined) {
266
+ buttonProps = {
267
+ ...buttonProps,
268
+ ...disabledStyles,
269
+ }
270
+ } else {
271
+ buttonProps.opacity = 0.65
272
+ }
273
+
259
274
  buttonProps['aria-disabled'] = true
260
275
  buttonProps.cursor = 'not-allowed'
261
276
  buttonProps.onClick = (event) => event.preventDefault()
@@ -271,7 +286,7 @@ export function Button({
271
286
  buttonProps.hover = undefined
272
287
  buttonProps.active = undefined
273
288
  } else {
274
- buttonProps.focus = { ...buttonProps.focus, zIndex: 5 }
289
+ buttonProps.focus = { zIndex: 5, ...buttonProps.focus }
275
290
  buttonProps.cursor = 'pointer'
276
291
  buttonProps.touchAction = 'manipulation'
277
292
  buttonProps.onClick = onClick
@@ -374,7 +389,15 @@ export function Button({
374
389
 
375
390
  return (
376
391
  <Tooltip {...tooltip}>
377
- <StackView {...buttonProps} {...restProps}>
392
+ <StackView
393
+ {...buttonProps}
394
+ {...restProps}
395
+ css={{
396
+ '&:focus-visible': {
397
+ ...buttonProps.focusVisible,
398
+ },
399
+ }}
400
+ >
378
401
  {iconLeft && (
379
402
  <Icon
380
403
  size={size}
@@ -59,9 +59,11 @@ export function FilterLayout(props: Props) {
59
59
  radius={0}
60
60
  title="Filter"
61
61
  aria-label={sidebarOpen ? 'close filter' : 'open filter'}
62
- iconRight={{
63
- name: sidebarOpen ? 'general.leftChevron' : 'general.threeReducingHorizontalBars',
64
- size: sidebarOpen ? 'xs' : 'md'
62
+ iconRight={{
63
+ name: sidebarOpen
64
+ ? 'general.leftChevron'
65
+ : 'general.threeReducingHorizontalBars',
66
+ size: sidebarOpen ? 'xs' : 'md',
65
67
  }}
66
68
  onClick={toggleSidebar}
67
69
  />
@@ -70,7 +72,7 @@ export function FilterLayout(props: Props) {
70
72
  </Box>
71
73
  </StackView>
72
74
  <Divider />
73
- <StackView axis="horizontal" grow={1}>
75
+ <StackView axis="horizontal" grow={1} overflow="hidden">
74
76
  <StackView
75
77
  visible={sidebarOpen}
76
78
  basis={fill ? '100%' : sidebarWidth + 'px'}
@@ -81,9 +83,10 @@ export function FilterLayout(props: Props) {
81
83
  {sidebar}
82
84
  </StackView>
83
85
  <StackView
84
- visible={!(sidebarOpen && fill)}
86
+ visibility={sidebarOpen && fill ? 'hidden' : 'visible'}
87
+ maxHeight={sidebarOpen && fill ? 0 : 'initial'}
85
88
  grow={1}
86
- shrink={1}
89
+ shrink={sidebarOpen && fill ? 0 : 1}
87
90
  basis="100%"
88
91
  >
89
92
  {toolbar}
@@ -6,7 +6,7 @@ propsSummary: Accepts [Input](/input) props.
6
6
 
7
7
  ```jsx live
8
8
  render(() => {
9
- const [time, setTime] = React.useState([13, 30])
9
+ const [time, setTime] = React.useState([9, 30])
10
10
  return <TimeField value={time} onChange={(time) => setTime(time)} />
11
11
  })
12
12
  ```
@@ -12,19 +12,17 @@ export function addHoursToTime(time, hoursToAdd) {
12
12
  }
13
13
 
14
14
  export function addMinutesToTime(time, minutesToAdd) {
15
- const [hours, minutes] = time
16
- const totalTimeInMinutes = hours * 60 + minutes
17
- const totalMinutesInDay = 24 * 60
18
- const newTime = parseInt(totalTimeInMinutes) + parseInt(minutesToAdd)
19
-
20
- const newHours =
21
- newTime > totalMinutesInDay
22
- ? Math.floor(newTime / 60) - 24
23
- : Math.floor(newTime / 60)
24
-
25
- const newMinutes = newTime % 60
26
-
27
- return [newHours, newMinutes]
15
+ let [hours, minutes] = time
16
+ const nextMinutes = minutes + minutesToAdd
17
+ const remainderMinutes = modulo(nextMinutes, MINUTES_IN_HOUR)
18
+ if (remainderMinutes >= 0) {
19
+ const nextHours = hours + Math.floor(nextMinutes / MINUTES_IN_HOUR)
20
+ hours = modulo(nextHours, HOURS_IN_DAY)
21
+ minutes = remainderMinutes
22
+ } else {
23
+ minutes = nextMinutes
24
+ }
25
+ return [hours, minutes]
28
26
  }
29
27
 
30
28
  export function addTimeToDate(date, time) {
@@ -0,0 +1,56 @@
1
+ ---
2
+ title: ToggleSwitch
3
+ category: General
4
+ summary: ToggleSwitches are used to switch between two states, most commonly on and off, and visually show the current state.
5
+ propsSummary: Accepts [StackView](/stackview) props.
6
+ themeKey: toggleSwitch
7
+ ---
8
+
9
+ ```jsx live
10
+ render(
11
+ <StackView spacing={6}>
12
+ <StackView axis="horizontal" spacing={2}>
13
+ {['xs', 'sm', 'md'].map((size) => (
14
+ <ToggleSwitch
15
+ key={size}
16
+ label={`${size} toggle`}
17
+ size={size}
18
+ tooltip={`${size} toggle`}
19
+ />
20
+ ))}
21
+ </StackView>
22
+ <StackView axis="horizontal" spacing={2}>
23
+ <ToggleSwitch isActive label="On" tooltip="On" />
24
+ <ToggleSwitch disabled label="Disabled, off" tooltip="Disabled, off" />
25
+ <ToggleSwitch
26
+ disabled
27
+ isActive
28
+ label="Disabled, On"
29
+ tooltip="Disabled, On"
30
+ />
31
+ </StackView>
32
+ <StackView axis="horizontal" spacing={2}>
33
+ <ToggleSwitch color="red-5" isActive label="Custom color" />
34
+ <ThemeProvider theme={{ toggleSwitch: { backgroundColor: 'create35' } }}>
35
+ <ToggleSwitch isActive label="Theme-provided color" />
36
+ </ThemeProvider>
37
+ </StackView>
38
+ </StackView>
39
+ )
40
+ ```
41
+
42
+ ```jsx live
43
+ function App() {
44
+ const [isActive, setIsActive] = React.useState(false)
45
+ return (
46
+ <StackView>
47
+ <ToggleSwitch
48
+ isActive={isActive}
49
+ label="Controlled toggle"
50
+ onClick={() => setIsActive(!isActive)}
51
+ />
52
+ </StackView>
53
+ )
54
+ }
55
+ render(App)
56
+ ```
@@ -0,0 +1,51 @@
1
+ import React from 'react'
2
+ import { render, fireEvent } from '@testing-library/react'
3
+ import '@testing-library/jest-dom/extend-expect'
4
+ import ToggleSwitch from './ToggleSwitch'
5
+
6
+ describe('ToggleSwitch component', () => {
7
+ it('should render with default properties', () => {
8
+ const { getByRole } = render(
9
+ <ToggleSwitch isActive={false} label="Toggle me" onClick={() => {}} />
10
+ )
11
+
12
+ const toggleButton = getByRole('button')
13
+ expect(toggleButton).toBeInTheDocument()
14
+ })
15
+
16
+ it('should call onClick when clicked', () => {
17
+ const mockOnClick = jest.fn()
18
+ const { getByRole } = render(
19
+ <ToggleSwitch isActive={false} label="Toggle me" onClick={mockOnClick} />
20
+ )
21
+
22
+ const toggleButton = getByRole('button')
23
+ fireEvent.click(toggleButton)
24
+
25
+ expect(mockOnClick).toHaveBeenCalled()
26
+ })
27
+
28
+ it('should display the label', () => {
29
+ const label = 'Toggle me'
30
+ const { getByText } = render(
31
+ <ToggleSwitch isActive={false} label={label} onClick={() => {}} />
32
+ )
33
+
34
+ expect(getByText(label)).toBeInTheDocument()
35
+ })
36
+
37
+ it('should apply active color when isActive is true', () => {
38
+ const activeColor = 'green'
39
+ const { getByRole } = render(
40
+ <ToggleSwitch
41
+ backgroundColor={activeColor}
42
+ isActive={true}
43
+ label="Toggle me"
44
+ onClick={() => {}}
45
+ />
46
+ )
47
+
48
+ const toggleButton = getByRole('button')
49
+ expect(toggleButton).toHaveStyle(`background-color: ${activeColor}`)
50
+ })
51
+ })