@planningcenter/tapestry 4.0.1-rc.2 → 4.1.0-rc.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/dist/components/DataTable/TableActions.d.ts.map +1 -1
- package/dist/components/DataTable/TableActions.js +6 -4
- package/dist/components/DataTable/TableActions.js.map +1 -1
- package/dist/components/internal/tooltip/Tooltip.js +62 -8
- package/dist/components/internal/tooltip/Tooltip.js.map +1 -1
- package/dist/index.css +24 -7
- package/dist/index.css.map +1 -1
- package/dist/reactRender.css +1393 -1376
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRenderLegacy.css +1393 -1376
- package/dist/reactRenderLegacy.css.map +1 -1
- package/dist/unstable.css +24 -7
- package/dist/unstable.css.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableActions.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/TableActions.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TableActions.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/TableActions.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEhD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,KAAK,IAAI,CAAA;IACtD,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yDAAyD;IACzD,IAAI,EAAE,SAAS,CAAA;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;CACrD,CAAA;AAED,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,mFAAmF;IACnF,YAAY,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CAClC;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY;6CAItB,iBAAiB;;CAsBnB,CAAA"}
|
|
@@ -5,6 +5,7 @@ import { IconButton } from '../button/IconButton.js';
|
|
|
5
5
|
import '../button/LoadingButton.js';
|
|
6
6
|
import '../button/PageHeaderActionsDropdownButton.js';
|
|
7
7
|
import { ButtonGroup } from '../button-group/ButtonGroup.js';
|
|
8
|
+
import { Tooltip } from '../internal/tooltip/Tooltip.js';
|
|
8
9
|
import React__default from 'react';
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -16,10 +17,11 @@ const TableActions = ({ actions, resultNoun, selectedKeys, }) => {
|
|
|
16
17
|
// The count/noun suffix is the same for every table action, so compute it once
|
|
17
18
|
// here rather than per-button inside the map below.
|
|
18
19
|
const countSuffix = getTableActionCountSuffix(selectedKeys.length, resultNoun);
|
|
19
|
-
return (React__default.createElement(ButtonGroup, { "aria-label": "Table actions" }, actions.map(({ callback, disabled, icon, label, onClick }) => (React__default.createElement(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
return (React__default.createElement(ButtonGroup, { "aria-label": "Table actions" }, actions.map(({ callback, disabled, icon, label, onClick }) => (React__default.createElement(Tooltip, { key: label, content: label, placement: "bottom" },
|
|
21
|
+
React__default.createElement(IconButton, { "aria-label": `${label}${countSuffix}`, disabled: disabled, icon: icon, onClick: (event) => {
|
|
22
|
+
onClick?.(event);
|
|
23
|
+
callback?.(selectedKeys);
|
|
24
|
+
} }))))));
|
|
23
25
|
};
|
|
24
26
|
TableActions.displayName = "TableActions";
|
|
25
27
|
const numberFormatter = new Intl.NumberFormat();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableActions.js","sources":["../../../src/components/DataTable/TableActions.tsx"],"sourcesContent":["import { IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport React, { type ReactNode } from \"react\"\n\nimport type { ResultNoun } from \"./ResultsCount\"\n\n/**\n * A table action rendered as an `IconButton` in the button group above the\n * table. Replaces the original RFC's `{ buttonProps; callback }` shape with a\n * narrower, more controllable API so the design can evolve without exposing the\n * full button surface.\n */\nexport type TableAction = {\n /** Called with the keys of the currently selected rows when the action is triggered. */\n callback?: (selectedKeys: (number | string)[]) => void\n /** Whether the action's button is disabled. */\n disabled?: boolean\n /** The icon rendered inside the action's icon button. */\n icon: ReactNode\n /** Accessible label for the icon-only action button. */\n label: string\n /** Standard click handler, invoked with the click event before `callback`. */\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n}\n\nexport interface TableActionsProps {\n /** The table actions to render as an `IconButton` group. */\n actions: TableAction[]\n /**\n * The noun used to describe the selection in each action's `aria-label`.\n * See {@link ResultNoun}.\n */\n resultNoun?: ResultNoun\n /** The keys of the currently selected rows, passed to each action's `callback`. */\n selectedKeys: (number | string)[]\n}\n\n/**\n * Renders the table actions as an `IconButton` group displayed directly after\n * the results count, above the table. Each entry becomes an icon button whose\n * `callback` receives the keys of the currently selected rows.\n */\nexport const TableActions = ({\n actions,\n resultNoun,\n selectedKeys,\n}: TableActionsProps) => {\n // The count/noun suffix is the same for every table action, so compute it once\n // here rather than per-button inside the map below.\n const countSuffix = getTableActionCountSuffix(selectedKeys.length, resultNoun)\n\n return (\n <ButtonGroup aria-label=\"Table actions\">\n {actions.map(({ callback, disabled, icon, label, onClick }) => (\n <
|
|
1
|
+
{"version":3,"file":"TableActions.js","sources":["../../../src/components/DataTable/TableActions.tsx"],"sourcesContent":["import { IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport { Tooltip } from \"@components/internal/tooltip\"\nimport React, { type ReactNode } from \"react\"\n\nimport type { ResultNoun } from \"./ResultsCount\"\n\n/**\n * A table action rendered as an `IconButton` in the button group above the\n * table. Replaces the original RFC's `{ buttonProps; callback }` shape with a\n * narrower, more controllable API so the design can evolve without exposing the\n * full button surface.\n */\nexport type TableAction = {\n /** Called with the keys of the currently selected rows when the action is triggered. */\n callback?: (selectedKeys: (number | string)[]) => void\n /** Whether the action's button is disabled. */\n disabled?: boolean\n /** The icon rendered inside the action's icon button. */\n icon: ReactNode\n /** Accessible label for the icon-only action button. */\n label: string\n /** Standard click handler, invoked with the click event before `callback`. */\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n}\n\nexport interface TableActionsProps {\n /** The table actions to render as an `IconButton` group. */\n actions: TableAction[]\n /**\n * The noun used to describe the selection in each action's `aria-label`.\n * See {@link ResultNoun}.\n */\n resultNoun?: ResultNoun\n /** The keys of the currently selected rows, passed to each action's `callback`. */\n selectedKeys: (number | string)[]\n}\n\n/**\n * Renders the table actions as an `IconButton` group displayed directly after\n * the results count, above the table. Each entry becomes an icon button whose\n * `callback` receives the keys of the currently selected rows.\n */\nexport const TableActions = ({\n actions,\n resultNoun,\n selectedKeys,\n}: TableActionsProps) => {\n // The count/noun suffix is the same for every table action, so compute it once\n // here rather than per-button inside the map below.\n const countSuffix = getTableActionCountSuffix(selectedKeys.length, resultNoun)\n\n return (\n <ButtonGroup aria-label=\"Table actions\">\n {actions.map(({ callback, disabled, icon, label, onClick }) => (\n <Tooltip key={label} content={label} placement=\"bottom\">\n <IconButton\n aria-label={`${label}${countSuffix}`}\n disabled={disabled}\n icon={icon}\n onClick={(event) => {\n onClick?.(event)\n callback?.(selectedKeys)\n }}\n />\n </Tooltip>\n ))}\n </ButtonGroup>\n )\n}\n\nTableActions.displayName = \"TableActions\"\n\nconst numberFormatter = new Intl.NumberFormat()\n\n/**\n * The count/noun suffix appended to each table action's `aria-label` when rows\n * are selected, e.g. `\" (2 selected people)\"` — so `\"Email\"` reads as\n * `\"Email (2 selected people)\"`. Empty when nothing is selected. Falls back to\n * the default `\"result\"` noun when `resultNoun` isn't provided. Shared across\n * every action, so it's computed once rather than per-button.\n */\nfunction getTableActionCountSuffix(\n count: number,\n resultNoun: ResultNoun | undefined\n): string {\n if (!count) return \"\"\n const [singular, plural] = Array.isArray(resultNoun)\n ? resultNoun\n : typeof resultNoun === \"string\"\n ? [resultNoun, `${resultNoun}s`]\n : [\"result\", \"results\"]\n const noun = count === 1 ? singular : plural\n const formattedCount = numberFormatter.format(count)\n return ` (${formattedCount} selected ${noun})`\n}\n"],"names":["React"],"mappings":";;;;;;;;;;AAsCA;;;;AAIG;AACI,MAAM,YAAY,GAAG,CAAC,EAC3B,OAAO,EACP,UAAU,EACV,YAAY,GACM,KAAI;;;IAGtB,MAAM,WAAW,GAAG,yBAAyB,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC;AAE9E,IAAA,QACEA,cAAA,CAAA,aAAA,CAAC,WAAW,EAAA,EAAA,YAAA,EAAY,eAAe,IACpC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MACxDA,cAAA,CAAA,aAAA,CAAC,OAAO,EAAA,EAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAC,QAAQ,EAAA;QACrDA,cAAA,CAAA,aAAA,CAAC,UAAU,kBACG,CAAA,EAAG,KAAK,GAAG,WAAW,CAAA,CAAE,EACpC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,CAAC,KAAK,KAAI;AACjB,gBAAA,OAAO,GAAG,KAAK,CAAC;AAChB,gBAAA,QAAQ,GAAG,YAAY,CAAC;AAC1B,YAAA,CAAC,GACD,CACM,CACX,CAAC,CACU;AAElB;AAEA,YAAY,CAAC,WAAW,GAAG,cAAc;AAEzC,MAAM,eAAe,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE;AAE/C;;;;;;AAMG;AACH,SAAS,yBAAyB,CAChC,KAAa,EACb,UAAkC,EAAA;AAElC,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,EAAE;IACrB,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU;AACjD,UAAE;AACF,UAAE,OAAO,UAAU,KAAK;AACtB,cAAE,CAAC,UAAU,EAAE,CAAA,EAAG,UAAU,GAAG;AAC/B,cAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;AAC3B,IAAA,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,QAAQ,GAAG,MAAM;IAC5C,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC;AACpD,IAAA,OAAO,CAAA,EAAA,EAAK,cAAc,CAAA,UAAA,EAAa,IAAI,GAAG;AAChD;;;;"}
|
|
@@ -1,12 +1,66 @@
|
|
|
1
1
|
import { tokens } from '@planningcenter/tapestry-tokens/tokens';
|
|
2
|
-
import 'classnames';
|
|
3
|
-
import 'react';
|
|
4
|
-
import 'react-aria/Overlay';
|
|
5
|
-
import 'react-aria/useOverlayPosition';
|
|
6
|
-
import 'react-aria/useTooltipTrigger';
|
|
7
|
-
import 'react-stately/useTooltipTriggerState';
|
|
8
|
-
import './TooltipTriggerContext.js';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import React__default, { useRef, useId } from 'react';
|
|
4
|
+
import { Overlay } from 'react-aria/Overlay';
|
|
5
|
+
import { useOverlayPosition } from 'react-aria/useOverlayPosition';
|
|
6
|
+
import { useTooltipTrigger, useTooltip } from 'react-aria/useTooltipTrigger';
|
|
7
|
+
import { useTooltipTriggerState } from 'react-stately/useTooltipTriggerState';
|
|
8
|
+
import { TooltipTriggerContext } from './TooltipTriggerContext.js';
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
// Single source of truth for the arrow's dimensions -- index.css reads these
|
|
11
|
+
// via --tds-tooltip-arrow-size/--tds-tooltip-arrow-depth instead of its own literals.
|
|
12
|
+
const ARROW_SIZE = 10;
|
|
13
|
+
const ARROW_DEPTH = 5;
|
|
14
|
+
const FOCUS_RING_REACH = parseFloat(tokens["--t-focus-ring-offset"]) +
|
|
11
15
|
parseFloat(tokens["--t-focus-ring-width"]);
|
|
16
|
+
/**
|
|
17
|
+
* Shows a short hover/focus hint next to a trigger. Built from React Aria's
|
|
18
|
+
* tooltip hooks rather than `react-aria-components`'s `<Tooltip>`, because
|
|
19
|
+
* that component unmounts its content entirely while closed, so a screen
|
|
20
|
+
* reader's virtual cursor never gets access to the description unless real
|
|
21
|
+
* DOM focus lands on the trigger. This keeps the tooltip content always
|
|
22
|
+
* mounted and wires `aria-describedby` unconditionally, toggling only CSS
|
|
23
|
+
* visibility.
|
|
24
|
+
*/
|
|
25
|
+
function Tooltip({ children, content, placement = "bottom start", }) {
|
|
26
|
+
const triggerRef = useRef(null);
|
|
27
|
+
const overlayRef = useRef(null);
|
|
28
|
+
const tooltipId = `tds-tooltip-${useId()}`;
|
|
29
|
+
const state = useTooltipTriggerState();
|
|
30
|
+
const { triggerProps } = useTooltipTrigger({}, state, triggerRef);
|
|
31
|
+
const { tooltipProps: ariaTooltipProps } = useTooltip({ id: tooltipId }, state);
|
|
32
|
+
const { arrowProps, overlayProps, placement: resolvedPlacement, } = useOverlayPosition({
|
|
33
|
+
arrowSize: ARROW_SIZE,
|
|
34
|
+
isOpen: state.isOpen,
|
|
35
|
+
offset: ARROW_DEPTH + FOCUS_RING_REACH,
|
|
36
|
+
onClose: () => state.close(true),
|
|
37
|
+
overlayRef,
|
|
38
|
+
placement,
|
|
39
|
+
targetRef: triggerRef,
|
|
40
|
+
});
|
|
41
|
+
const contextValue = {
|
|
42
|
+
ref: triggerRef,
|
|
43
|
+
triggerProps: {
|
|
44
|
+
...triggerProps,
|
|
45
|
+
"aria-describedby": tooltipId,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
49
|
+
React__default.createElement(TooltipTriggerContext.Provider, { value: contextValue }, children),
|
|
50
|
+
React__default.createElement(Overlay, { disableFocusManagement: true },
|
|
51
|
+
React__default.createElement("div", { ...ariaTooltipProps, ...overlayProps, ref: overlayRef, className: classNames("tds-tooltip", {
|
|
52
|
+
"tds-tooltip--open": state.isOpen,
|
|
53
|
+
}), "data-placement": resolvedPlacement, style: {
|
|
54
|
+
...overlayProps.style,
|
|
55
|
+
"--tds-tooltip-arrow-depth-raw": `${ARROW_DEPTH}px`,
|
|
56
|
+
"--tds-tooltip-arrow-size-raw": `${ARROW_SIZE}px`,
|
|
57
|
+
} },
|
|
58
|
+
content,
|
|
59
|
+
React__default.createElement("div", { className: "tds-tooltip-arrow", ...arrowProps },
|
|
60
|
+
React__default.createElement("svg", { "aria-hidden": true, className: "tds-tooltip-arrow-icon", role: "img", viewBox: `0 0 ${ARROW_SIZE} ${ARROW_DEPTH}` },
|
|
61
|
+
React__default.createElement("polygon", { points: `${ARROW_SIZE / 2},0 0,${ARROW_DEPTH} ${ARROW_SIZE},${ARROW_DEPTH}` })))))));
|
|
62
|
+
}
|
|
63
|
+
Tooltip.displayName = "Tooltip";
|
|
64
|
+
|
|
65
|
+
export { Tooltip };
|
|
12
66
|
//# sourceMappingURL=Tooltip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.js","sources":["../../../../src/components/internal/tooltip/Tooltip.tsx"],"sourcesContent":["import { tokens } from \"@planningcenter/tapestry-tokens/tokens\"\nimport classNames from \"classnames\"\nimport React, { type ReactElement, useId, useRef } from \"react\"\nimport { Overlay } from \"react-aria/Overlay\"\nimport {\n type Placement,\n useOverlayPosition,\n} from \"react-aria/useOverlayPosition\"\nimport { useTooltip, useTooltipTrigger } from \"react-aria/useTooltipTrigger\"\nimport { useTooltipTriggerState } from \"react-stately/useTooltipTriggerState\"\n\nimport { TooltipTriggerContext } from \"./TooltipTriggerContext\"\n\n// Single source of truth for the arrow's dimensions -- index.css reads these\n// via --tds-tooltip-arrow-size/--tds-tooltip-arrow-depth instead of its own literals.\nconst ARROW_SIZE = 10\nconst ARROW_DEPTH = 5\nconst FOCUS_RING_REACH =\n parseFloat(tokens[\"--t-focus-ring-offset\"]) +\n parseFloat(tokens[\"--t-focus-ring-width\"])\n\nexport interface TooltipProps {\n /**\n * A single `BaseButton`-derived element (e.g. `IconButton`, `Button`) to\n * act as the trigger. Must be exactly one trigger — nothing enforces this\n * at runtime, so a fragment with more than one child would silently hand\n * every child the same ref and trigger props.\n */\n children: ReactElement\n /**\n * The hint text. Best used with information beyond the trigger's accessible name\n * (e.g. its `aria-label` or visible label).\n */\n content: string\n /** Where the tooltip renders relative to the trigger. Default `'bottom start'`. */\n placement?: Placement\n}\n\n/**\n * Shows a short hover/focus hint next to a trigger. Built from React Aria's\n * tooltip hooks rather than `react-aria-components`'s `<Tooltip>`, because\n * that component unmounts its content entirely while closed, so a screen\n * reader's virtual cursor never gets access to the description unless real\n * DOM focus lands on the trigger. This keeps the tooltip content always\n * mounted and wires `aria-describedby` unconditionally, toggling only CSS\n * visibility.\n */\nexport function Tooltip({\n children,\n content,\n placement = \"bottom start\",\n}: TooltipProps) {\n const triggerRef = useRef<HTMLButtonElement>(null)\n const overlayRef = useRef<HTMLDivElement>(null)\n const tooltipId = `tds-tooltip-${useId()}`\n\n const state = useTooltipTriggerState()\n const { triggerProps } = useTooltipTrigger({}, state, triggerRef)\n const { tooltipProps: ariaTooltipProps } = useTooltip(\n { id: tooltipId },\n state\n )\n\n const {\n arrowProps,\n overlayProps,\n placement: resolvedPlacement,\n } = useOverlayPosition({\n arrowSize: ARROW_SIZE,\n isOpen: state.isOpen,\n offset: ARROW_DEPTH + FOCUS_RING_REACH,\n onClose: () => state.close(true),\n overlayRef,\n placement,\n targetRef: triggerRef,\n })\n\n const contextValue = {\n ref: triggerRef,\n triggerProps: {\n ...triggerProps,\n \"aria-describedby\": tooltipId,\n },\n }\n\n return (\n <>\n <TooltipTriggerContext.Provider value={contextValue}>\n {children}\n </TooltipTriggerContext.Provider>\n <Overlay disableFocusManagement>\n <div\n {...ariaTooltipProps}\n {...overlayProps}\n ref={overlayRef}\n className={classNames(\"tds-tooltip\", {\n \"tds-tooltip--open\": state.isOpen,\n })}\n data-placement={resolvedPlacement}\n style={\n {\n ...overlayProps.style,\n \"--tds-tooltip-arrow-depth-raw\": `${ARROW_DEPTH}px`,\n \"--tds-tooltip-arrow-size-raw\": `${ARROW_SIZE}px`,\n } as React.CSSProperties\n }\n >\n {content}\n <div className=\"tds-tooltip-arrow\" {...arrowProps}>\n <svg\n aria-hidden\n className=\"tds-tooltip-arrow-icon\"\n role=\"img\"\n viewBox={`0 0 ${ARROW_SIZE} ${ARROW_DEPTH}`}\n >\n <polygon\n points={`${ARROW_SIZE / 2},0 0,${ARROW_DEPTH} ${ARROW_SIZE},${ARROW_DEPTH}`}\n />\n </svg>\n </div>\n </div>\n </Overlay>\n </>\n )\n}\n\nTooltip.displayName = \"Tooltip\"\n"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"Tooltip.js","sources":["../../../../src/components/internal/tooltip/Tooltip.tsx"],"sourcesContent":["import { tokens } from \"@planningcenter/tapestry-tokens/tokens\"\nimport classNames from \"classnames\"\nimport React, { type ReactElement, useId, useRef } from \"react\"\nimport { Overlay } from \"react-aria/Overlay\"\nimport {\n type Placement,\n useOverlayPosition,\n} from \"react-aria/useOverlayPosition\"\nimport { useTooltip, useTooltipTrigger } from \"react-aria/useTooltipTrigger\"\nimport { useTooltipTriggerState } from \"react-stately/useTooltipTriggerState\"\n\nimport { TooltipTriggerContext } from \"./TooltipTriggerContext\"\n\n// Single source of truth for the arrow's dimensions -- index.css reads these\n// via --tds-tooltip-arrow-size/--tds-tooltip-arrow-depth instead of its own literals.\nconst ARROW_SIZE = 10\nconst ARROW_DEPTH = 5\nconst FOCUS_RING_REACH =\n parseFloat(tokens[\"--t-focus-ring-offset\"]) +\n parseFloat(tokens[\"--t-focus-ring-width\"])\n\nexport interface TooltipProps {\n /**\n * A single `BaseButton`-derived element (e.g. `IconButton`, `Button`) to\n * act as the trigger. Must be exactly one trigger — nothing enforces this\n * at runtime, so a fragment with more than one child would silently hand\n * every child the same ref and trigger props.\n */\n children: ReactElement\n /**\n * The hint text. Best used with information beyond the trigger's accessible name\n * (e.g. its `aria-label` or visible label).\n */\n content: string\n /** Where the tooltip renders relative to the trigger. Default `'bottom start'`. */\n placement?: Placement\n}\n\n/**\n * Shows a short hover/focus hint next to a trigger. Built from React Aria's\n * tooltip hooks rather than `react-aria-components`'s `<Tooltip>`, because\n * that component unmounts its content entirely while closed, so a screen\n * reader's virtual cursor never gets access to the description unless real\n * DOM focus lands on the trigger. This keeps the tooltip content always\n * mounted and wires `aria-describedby` unconditionally, toggling only CSS\n * visibility.\n */\nexport function Tooltip({\n children,\n content,\n placement = \"bottom start\",\n}: TooltipProps) {\n const triggerRef = useRef<HTMLButtonElement>(null)\n const overlayRef = useRef<HTMLDivElement>(null)\n const tooltipId = `tds-tooltip-${useId()}`\n\n const state = useTooltipTriggerState()\n const { triggerProps } = useTooltipTrigger({}, state, triggerRef)\n const { tooltipProps: ariaTooltipProps } = useTooltip(\n { id: tooltipId },\n state\n )\n\n const {\n arrowProps,\n overlayProps,\n placement: resolvedPlacement,\n } = useOverlayPosition({\n arrowSize: ARROW_SIZE,\n isOpen: state.isOpen,\n offset: ARROW_DEPTH + FOCUS_RING_REACH,\n onClose: () => state.close(true),\n overlayRef,\n placement,\n targetRef: triggerRef,\n })\n\n const contextValue = {\n ref: triggerRef,\n triggerProps: {\n ...triggerProps,\n \"aria-describedby\": tooltipId,\n },\n }\n\n return (\n <>\n <TooltipTriggerContext.Provider value={contextValue}>\n {children}\n </TooltipTriggerContext.Provider>\n <Overlay disableFocusManagement>\n <div\n {...ariaTooltipProps}\n {...overlayProps}\n ref={overlayRef}\n className={classNames(\"tds-tooltip\", {\n \"tds-tooltip--open\": state.isOpen,\n })}\n data-placement={resolvedPlacement}\n style={\n {\n ...overlayProps.style,\n \"--tds-tooltip-arrow-depth-raw\": `${ARROW_DEPTH}px`,\n \"--tds-tooltip-arrow-size-raw\": `${ARROW_SIZE}px`,\n } as React.CSSProperties\n }\n >\n {content}\n <div className=\"tds-tooltip-arrow\" {...arrowProps}>\n <svg\n aria-hidden\n className=\"tds-tooltip-arrow-icon\"\n role=\"img\"\n viewBox={`0 0 ${ARROW_SIZE} ${ARROW_DEPTH}`}\n >\n <polygon\n points={`${ARROW_SIZE / 2},0 0,${ARROW_DEPTH} ${ARROW_SIZE},${ARROW_DEPTH}`}\n />\n </svg>\n </div>\n </div>\n </Overlay>\n </>\n )\n}\n\nTooltip.displayName = \"Tooltip\"\n"],"names":["React"],"mappings":"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"}
|
package/dist/index.css
CHANGED
|
@@ -4834,12 +4834,15 @@ a.tds-dropdown-item:is(:hover, :active){
|
|
|
4834
4834
|
}
|
|
4835
4835
|
|
|
4836
4836
|
.tds-modal-overlay{
|
|
4837
|
+
--tds-modal-min-margin-block:var(--t-spacing-3);
|
|
4838
|
+
|
|
4837
4839
|
position:fixed;
|
|
4838
4840
|
inset:0;
|
|
4839
4841
|
z-index:1000;
|
|
4840
|
-
display:
|
|
4841
|
-
|
|
4842
|
-
justify-
|
|
4842
|
+
display:grid;
|
|
4843
|
+
grid-template-rows:minmax(var(--tds-modal-min-margin-block), 1fr) auto minmax(var(--tds-modal-min-margin-block), 1fr);
|
|
4844
|
+
justify-items:center;
|
|
4845
|
+
overflow-y:auto;
|
|
4843
4846
|
background:hsl(0 0% 0% / 40%);
|
|
4844
4847
|
}
|
|
4845
4848
|
|
|
@@ -4859,10 +4862,12 @@ a.tds-dropdown-item:is(:hover, :active){
|
|
|
4859
4862
|
|
|
4860
4863
|
.tds-modal-frame{
|
|
4861
4864
|
--tds-modal-width:600px;
|
|
4862
|
-
|
|
4865
|
+
--tds-modal-edge-margin-inline:var(--t-spacing-3);
|
|
4863
4866
|
display:flex;
|
|
4867
|
+
|
|
4868
|
+
grid-row:2;
|
|
4864
4869
|
justify-content:center;
|
|
4865
|
-
width:min(var(--tds-modal-width), calc(100% -
|
|
4870
|
+
width:min(var(--tds-modal-width), calc(100% - var(--tds-modal-edge-margin-inline) * 2));
|
|
4866
4871
|
}
|
|
4867
4872
|
|
|
4868
4873
|
.tds-modal-frame[data-entering]{
|
|
@@ -4905,7 +4910,7 @@ a.tds-dropdown-item:is(:hover, :active){
|
|
|
4905
4910
|
display:flex;
|
|
4906
4911
|
flex-direction:column;
|
|
4907
4912
|
width:100%;
|
|
4908
|
-
padding-block:var(--t-spacing-3);
|
|
4913
|
+
padding-block-start:var(--t-spacing-3);
|
|
4909
4914
|
padding-inline:0;
|
|
4910
4915
|
background:var(--t-surface-color-card);
|
|
4911
4916
|
|
|
@@ -4968,7 +4973,7 @@ a.tds-dropdown-item:is(:hover, :active){
|
|
|
4968
4973
|
gap:var(--t-spacing-2);
|
|
4969
4974
|
align-items:center;
|
|
4970
4975
|
justify-content:flex-end;
|
|
4971
|
-
padding-block
|
|
4976
|
+
padding-block:var(--t-spacing-3);
|
|
4972
4977
|
padding-inline:var(--t-spacing-4);
|
|
4973
4978
|
border-top:1px solid var(--t-border-color);
|
|
4974
4979
|
}
|
|
@@ -4977,6 +4982,18 @@ a.tds-dropdown-item:is(:hover, :active){
|
|
|
4977
4982
|
margin-inline-end:auto;
|
|
4978
4983
|
}
|
|
4979
4984
|
|
|
4985
|
+
@media (min-width: 720px){
|
|
4986
|
+
.tds-modal-overlay{
|
|
4987
|
+
--tds-modal-min-margin-block:0;
|
|
4988
|
+
}
|
|
4989
|
+
|
|
4990
|
+
.tds-modal-footer{
|
|
4991
|
+
position:sticky;
|
|
4992
|
+
bottom:0;
|
|
4993
|
+
background:var(--t-surface-color-card);
|
|
4994
|
+
}
|
|
4995
|
+
}
|
|
4996
|
+
|
|
4980
4997
|
.tds-number-stepper{
|
|
4981
4998
|
--tds-number-stepper-button-offset:4px;
|
|
4982
4999
|
--tds-number-stepper-button-gap:2px;
|