@galaxy-io/dls 1.5.18 → 1.6.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.
@@ -23,12 +23,18 @@ export interface AccordionProps {
23
23
  header: string;
24
24
  /** Secondary line under the header. */
25
25
  subheader?: string;
26
- /** Trailing content in the header — a count, a badge, a status. */
27
- metric?: React.ReactNode;
26
+ /** Trailing content in the header — a count, a badge, a status, an action. */
27
+ trailing?: React.ReactNode;
28
28
  /** A number is px. */
29
29
  borderRadius?: number | string;
30
30
  /** Inset for the body. @default "12px" */
31
31
  padding?: string | number;
32
+ /**
33
+ * Whether the panel can be toggled. When `false` the accordion is always
34
+ * open, the caret is hidden and the header is not interactive — `isOpen`,
35
+ * `isOpenInitial` and `onToggle` are ignored. @default true
36
+ */
37
+ isCollapsible?: boolean;
32
38
  /** Starting state in uncontrolled mode. Ignored once `isOpen` is passed. */
33
39
  isOpenInitial?: boolean;
34
40
  /** Controlled open state. Pass it together with `onToggle`. */
@@ -37,10 +43,12 @@ export interface AccordionProps {
37
43
  onToggle?: () => void;
38
44
  }
39
45
  /**
40
- * A collapsible section with a persistent header.
46
+ * A section with a persistent header and a collapsible body.
41
47
  *
42
48
  * Uncontrolled by default — it tracks its own state from `isOpenInitial`. Pass
43
- * `isOpen` *and* `onToggle` together to drive it from outside instead.
49
+ * `isOpen` *and* `onToggle` together to drive it from outside instead. Pass
50
+ * `isCollapsible={false}` for a static, always-open section: the caret goes
51
+ * away and the header stops being a button.
44
52
  */
45
- declare const Accordion: ({ children, variant, size, icon, header, subheader, metric, borderRadius, padding, isOpenInitial, isOpen: controlledIsOpen, onToggle: controlledOnToggle, }: PropsWithChildren<AccordionProps>) => React.JSX.Element;
53
+ declare const Accordion: ({ children, variant, size, icon, header, subheader, trailing, borderRadius, padding, isCollapsible, isOpenInitial, isOpen: controlledIsOpen, onToggle: controlledOnToggle, }: PropsWithChildren<AccordionProps>) => React.JSX.Element;
46
54
  export default Accordion;
@@ -9,7 +9,7 @@ import HorizontalDivider from "../dividers/HorizontalDivider.js";
9
9
  /* empty css */
10
10
  import { styled } from "@linaria/react";
11
11
  import { match } from "ts-pattern";
12
- import { useState } from "react";
12
+ import { useRef, useState } from "react";
13
13
  import { jsx, jsxs } from "react/jsx-runtime";
14
14
  import { CaretDownIcon } from "@phosphor-icons/react";
15
15
  //#region src/accordion/Accordion.tsx
@@ -49,73 +49,109 @@ var AccordionWrapper = withTheme(/*#__PURE__*/ styled("div")({
49
49
  var _exp5 = () => ({ $size }) => {
50
50
  return match($size).with("SMALL", () => "8px").with("MEDIUM", () => "12px").with("LARGE", () => "16px").exhaustive();
51
51
  };
52
- var AccordionHeader = withTheme(/*#__PURE__*/ styled("button")({
52
+ var _exp6 = () => ({ $isCollapsible }) => $isCollapsible ? "pointer" : "default";
53
+ var AccordionHeader = withTheme(/*#__PURE__*/ styled("div")({
53
54
  name: "AccordionHeader",
54
55
  class: "a1gttren",
55
56
  propsAsIs: false,
56
- vars: { "a1gttren-0": [_exp5()] }
57
+ vars: {
58
+ "a1gttren-0": [_exp5()],
59
+ "a1gttren-1": [_exp6()]
60
+ }
61
+ }));
62
+ /**
63
+ * The accessible toggle. Wraps only the leading content so a `trailing` action
64
+ * is never a button inside a button — the row above handles pointer clicks on
65
+ * the rest of the header (caret, padding) and forwards them here.
66
+ */
67
+ var _exp7 = () => ({ $isCollapsible }) => $isCollapsible ? "pointer" : "default";
68
+ var AccordionToggle = withTheme(/*#__PURE__*/ styled("button")({
69
+ name: "AccordionToggle",
70
+ class: "ai1xw52",
71
+ propsAsIs: false,
72
+ vars: { "ai1xw52-0": [_exp7()] }
57
73
  }));
58
- var _exp6 = () => ({ $isOpen }) => $isOpen ? "1fr" : "0fr";
74
+ var AccordionTrailing = /*#__PURE__*/ styled("div")({
75
+ name: "AccordionTrailing",
76
+ class: "a1f5gwwu",
77
+ propsAsIs: false
78
+ });
79
+ var _exp8 = () => ({ $isOpen }) => $isOpen ? "1fr" : "0fr";
59
80
  var AccordionContent = withTheme(/*#__PURE__*/ styled("div")({
60
81
  name: "AccordionContent",
61
- class: "ai1xw52",
82
+ class: "a1g9gu22",
62
83
  propsAsIs: false,
63
- vars: { "ai1xw52-0": [_exp6()] }
84
+ vars: { "a1g9gu22-0": [_exp8()] }
64
85
  }));
65
86
  var AccordionContentInner = withTheme(/*#__PURE__*/ styled("div")({
66
87
  name: "AccordionContentInner",
67
- class: "a1f5gwwu",
88
+ class: "a1xsnpfl",
68
89
  propsAsIs: false
69
90
  }));
70
91
  /**
71
- * A collapsible section with a persistent header.
92
+ * A section with a persistent header and a collapsible body.
72
93
  *
73
94
  * Uncontrolled by default — it tracks its own state from `isOpenInitial`. Pass
74
- * `isOpen` *and* `onToggle` together to drive it from outside instead.
95
+ * `isOpen` *and* `onToggle` together to drive it from outside instead. Pass
96
+ * `isCollapsible={false}` for a static, always-open section: the caret goes
97
+ * away and the header stops being a button.
75
98
  */
76
- var Accordion = ({ children, variant = "PRIMARY", size = "MEDIUM", icon, header, subheader, metric, borderRadius, padding = "12px", isOpenInitial = false, isOpen: controlledIsOpen, onToggle: controlledOnToggle }) => {
99
+ var Accordion = ({ children, variant = "PRIMARY", size = "MEDIUM", icon, header, subheader, trailing, borderRadius, padding = "12px", isCollapsible = true, isOpenInitial = false, isOpen: controlledIsOpen, onToggle: controlledOnToggle }) => {
77
100
  const [internalIsOpen, setInternalIsOpen] = useState(isOpenInitial);
101
+ const trailingRef = useRef(null);
78
102
  const isControlled = controlledIsOpen !== void 0;
79
- const isOpen = isControlled ? controlledIsOpen : internalIsOpen;
103
+ const isOpen = !isCollapsible || (isControlled ? controlledIsOpen : internalIsOpen);
80
104
  const handleToggle = () => {
105
+ if (!isCollapsible) return;
81
106
  if (isControlled) controlledOnToggle?.();
82
107
  else setInternalIsOpen((prev) => !prev);
83
108
  };
109
+ const handleHeaderClick = (e) => {
110
+ if (trailingRef.current?.contains(e.target)) return;
111
+ handleToggle();
112
+ };
84
113
  return /* @__PURE__ */ jsxs(AccordionWrapper, {
85
114
  $borderRadius: borderRadius,
86
115
  $variant: variant,
87
116
  $isOpen: isOpen,
88
117
  children: [
89
118
  /* @__PURE__ */ jsxs(AccordionHeader, {
90
- $isOpen: isOpen,
91
- $variant: variant,
119
+ $isCollapsible: isCollapsible,
92
120
  $size: size,
93
- onClick: handleToggle,
94
- type: "button",
95
- children: [/* @__PURE__ */ jsxs(FlexWrapper, {
96
- alignItems: AlignItems.CENTER,
97
- gap: 8,
98
- children: [icon && /* @__PURE__ */ jsx(Icon, {
99
- component: icon,
100
- variant: isOpen ? IconVariant.PRIMARY : IconVariant.SECONDARY,
101
- size: 16
102
- }), /* @__PURE__ */ jsxs(FlexWrapper, {
103
- direction: FlexDirection.COLUMN,
104
- gap: 2,
105
- children: [/* @__PURE__ */ jsx(Text, {
106
- variant: isOpen ? TextVariant.PRIMARY : TextVariant.SECONDARY,
107
- weight: TextWeight.MEDIUM,
108
- children: header
109
- }), subheader && /* @__PURE__ */ jsx(Text, {
110
- size: TextSize.BODY_SM,
111
- variant: isOpen ? TextVariant.SECONDARY : TextVariant.TERTIARY,
112
- children: subheader
113
- })]
114
- })]
115
- }), /* @__PURE__ */ jsxs(FlexWrapper, {
116
- alignItems: AlignItems.CENTER,
117
- gap: 8,
118
- children: [metric && metric, /* @__PURE__ */ jsx(Rotate, {
121
+ onClick: isCollapsible ? handleHeaderClick : void 0,
122
+ children: [
123
+ /* @__PURE__ */ jsx(AccordionToggle, {
124
+ as: isCollapsible ? "button" : "div",
125
+ $isCollapsible: isCollapsible,
126
+ type: isCollapsible ? "button" : void 0,
127
+ "aria-expanded": isCollapsible ? isOpen : void 0,
128
+ children: /* @__PURE__ */ jsxs(FlexWrapper, {
129
+ alignItems: AlignItems.CENTER,
130
+ gap: 8,
131
+ children: [icon && /* @__PURE__ */ jsx(Icon, {
132
+ component: icon,
133
+ variant: isOpen ? IconVariant.PRIMARY : IconVariant.SECONDARY,
134
+ size: 16
135
+ }), /* @__PURE__ */ jsxs(FlexWrapper, {
136
+ direction: FlexDirection.COLUMN,
137
+ gap: 2,
138
+ children: [/* @__PURE__ */ jsx(Text, {
139
+ variant: isOpen ? TextVariant.PRIMARY : TextVariant.SECONDARY,
140
+ weight: TextWeight.MEDIUM,
141
+ children: header
142
+ }), subheader && /* @__PURE__ */ jsx(Text, {
143
+ size: TextSize.BODY_SM,
144
+ variant: isOpen ? TextVariant.SECONDARY : TextVariant.TERTIARY,
145
+ children: subheader
146
+ })]
147
+ })]
148
+ })
149
+ }),
150
+ trailing && /* @__PURE__ */ jsx(AccordionTrailing, {
151
+ ref: trailingRef,
152
+ children: trailing
153
+ }),
154
+ isCollapsible && /* @__PURE__ */ jsx(Rotate, {
119
155
  isRotated: isOpen,
120
156
  deg: -180,
121
157
  children: /* @__PURE__ */ jsx(Icon, {
@@ -123,8 +159,8 @@ var Accordion = ({ children, variant = "PRIMARY", size = "MEDIUM", icon, header,
123
159
  variant: isOpen ? IconVariant.PRIMARY : IconVariant.SECONDARY,
124
160
  size: 12
125
161
  })
126
- })]
127
- })]
162
+ })
163
+ ]
128
164
  }),
129
165
  isOpen && /* @__PURE__ */ jsx(FlexItem, {
130
166
  shrink: 0,
package/dist/styles.css CHANGED
@@ -1,7 +1,9 @@
1
1
  .a1uic4p3{width:100%;background-color:var(--a1uic4p3-0);border:0.5px solid var(--a1uic4p3-1);border-radius:var(--a1uic4p3-2);overflow:hidden;overscroll-behavior:auto;}.a1uic4p3:hover{border-color:var(--a1uic4p3-3);}
2
- .a1gttren{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:space-between;-webkit-justify-content:space-between;justify-content:space-between;width:100%;padding:var(--a1gttren-0);background-color:transparent;cursor:pointer;-webkit-transition:background-color 0.075s ease-in-out;transition:background-color 0.075s ease-in-out;}
3
- .ai1xw52{display:-ms-grid;display:grid;-ms-grid-rows:var(--ai1xw52-0);grid-template-rows:var(--ai1xw52-0);-webkit-transition:grid-template-rows 0.15s ease-in-out;transition:grid-template-rows 0.15s ease-in-out;}
4
- .a1f5gwwu{overflow:hidden;overscroll-behavior:auto;}
2
+ .a1gttren{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:space-between;-webkit-justify-content:space-between;justify-content:space-between;gap:8px;width:100%;padding:var(--a1gttren-0);background-color:transparent;cursor:var(--a1gttren-1);-webkit-transition:background-color 0.075s ease-in-out;transition:background-color 0.075s ease-in-out;}
3
+ .ai1xw52{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;min-width:0;padding:0;border:none;background-color:transparent;color:inherit;font:inherit;text-align:left;cursor:var(--ai1xw52-0);}
4
+ .a1f5gwwu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;cursor:default;}
5
+ .a1g9gu22{display:-ms-grid;display:grid;-ms-grid-rows:var(--a1g9gu22-0);grid-template-rows:var(--a1g9gu22-0);-webkit-transition:grid-template-rows 0.15s ease-in-out;transition:grid-template-rows 0.15s ease-in-out;}
6
+ .a1xsnpfl{overflow:hidden;overscroll-behavior:auto;}
5
7
  .s1he36jx{position:var(--s1he36jx-0);display:var(--s1he36jx-1);-webkit-align-items:var(--s1he36jx-2);-webkit-box-align:var(--s1he36jx-2);-ms-flex-align:var(--s1he36jx-2);align-items:var(--s1he36jx-2);-webkit-box-pack:var(--s1he36jx-3);-ms-flex-pack:var(--s1he36jx-3);-webkit-justify-content:var(--s1he36jx-3);justify-content:var(--s1he36jx-3);-webkit-box-flex:var(--s1he36jx-4);-webkit-flex-grow:var(--s1he36jx-4);-ms-flex-positive:var(--s1he36jx-4);flex-grow:var(--s1he36jx-4);-webkit-flex-shrink:var(--s1he36jx-5);-ms-flex-negative:var(--s1he36jx-5);flex-shrink:var(--s1he36jx-5);-webkit-flex-basis:var(--s1he36jx-6);-ms-flex-preferred-size:var(--s1he36jx-6);flex-basis:var(--s1he36jx-6);width:var(--s1he36jx-7);height:var(--s1he36jx-8);min-width:var(--s1he36jx-9);max-width:var(--s1he36jx-10);min-height:var(--s1he36jx-11);max-height:var(--s1he36jx-12);overflow:var(--s1he36jx-13);white-space:var(--s1he36jx-14);text-overflow:var(--s1he36jx-15);padding:var(--s1he36jx-16);overscroll-behavior:auto;cursor:var(--s1he36jx-17);}
6
8
  .s12krdms{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;-webkit-flex-direction:var(--s12krdms-0);-ms-flex-direction:var(--s12krdms-0);flex-direction:var(--s12krdms-0);-webkit-align-items:var(--s12krdms-1);-webkit-box-align:var(--s12krdms-1);-ms-flex-align:var(--s12krdms-1);align-items:var(--s12krdms-1);-webkit-box-pack:var(--s12krdms-2);-ms-flex-pack:var(--s12krdms-2);-webkit-justify-content:var(--s12krdms-2);justify-content:var(--s12krdms-2);gap:var(--s12krdms-3);-webkit-box-flex-wrap:var(--s12krdms-4);-webkit-flex-wrap:var(--s12krdms-4);-ms-flex-wrap:var(--s12krdms-4);flex-wrap:var(--s12krdms-4);-webkit-box-flex:var(--s12krdms-5);-webkit-flex-grow:var(--s12krdms-5);-ms-flex-positive:var(--s12krdms-5);flex-grow:var(--s12krdms-5);-webkit-flex-shrink:var(--s12krdms-6);-ms-flex-negative:var(--s12krdms-6);flex-shrink:var(--s12krdms-6);-webkit-flex-basis:var(--s12krdms-7);-ms-flex-preferred-size:var(--s12krdms-7);flex-basis:var(--s12krdms-7);width:var(--s12krdms-8);height:var(--s12krdms-9);min-width:var(--s12krdms-10);max-width:var(--s12krdms-11);min-height:var(--s12krdms-12);max-height:var(--s12krdms-13);overflow:var(--s12krdms-14);padding:var(--s12krdms-15);margin:var(--s12krdms-16);overscroll-behavior:auto;cursor:var(--s12krdms-17);}
7
9
  .h1sww5hz{width:var(--h1sww5hz-0);height:0.5px;min-height:0.5px;-webkit-flex:var(--h1sww5hz-1);-ms-flex:var(--h1sww5hz-1);flex:var(--h1sww5hz-1);background-color:var(--h1sww5hz-2);}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galaxy-io/dls",
3
- "version": "1.5.18",
3
+ "version": "1.6.0",
4
4
  "description": "Galaxy Design Language System",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",