@lo-ink/ui 0.4.1 → 0.4.3

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/Button.js CHANGED
@@ -2,5 +2,5 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  import { forwardRef } from "react";
3
3
  import { classes } from "./utils.js";
4
4
  export const Button = forwardRef(function Button({ variant = "primary", size = "medium", loading = false, loadingLabel = "Loading", fullWidth = false, leading, trailing, className, disabled, children, type = "button", ...props }, ref) {
5
- return (_jsx("button", { ...props, ref: ref, type: type, disabled: disabled || loading, "aria-busy": loading || undefined, className: classes("lo-ui-button", `lo-ui-button--${variant}`, `lo-ui-button--${size}`, fullWidth && "lo-ui-button--full", className), children: loading ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "lo-ui-spinner", "aria-hidden": "true" }), _jsx("span", { children: loadingLabel })] })) : (_jsxs(_Fragment, { children: [leading && _jsx("span", { className: "lo-ui-button__icon", children: leading }), _jsx("span", { children: children }), trailing && _jsx("span", { className: "lo-ui-button__icon", children: trailing })] })) }));
5
+ return (_jsx("button", { ...props, ref: ref, type: type, disabled: disabled || loading, "aria-busy": loading || undefined, className: classes("lo-ui-button", `lo-ui-button--${variant}`, `lo-ui-button--${size}`, fullWidth && "lo-ui-button--full", className), children: loading ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "lo-ui-spinner", "aria-hidden": "true" }), _jsx("span", { className: "lo-ui-button__label", children: loadingLabel })] })) : (_jsxs(_Fragment, { children: [leading && _jsx("span", { className: "lo-ui-button__icon", children: leading }), _jsx("span", { className: "lo-ui-button__label", children: children }), trailing && _jsx("span", { className: "lo-ui-button__icon", children: trailing })] })) }));
6
6
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../src/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,SAAU,SAAQ,IAAI,CACrC,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,kFAAkF;AAClF,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,KAAK,EACL,aAAa,EACb,EAAE,EAAE,UAAU,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,SAAS,+BA8EX"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../src/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,SAAU,SAAQ,IAAI,CACrC,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,kFAAkF;AAClF,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,KAAK,EACL,aAAa,EACb,EAAE,EAAE,UAAU,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,SAAS,+BAkFX"}
package/dist/Tabs.js CHANGED
@@ -9,6 +9,8 @@ export function Tabs({ options, value, onValueChange, id: providedId, className,
9
9
  const focusValue = options.some((option) => option.value === value && !option.disabled)
10
10
  ? value
11
11
  : options.find((option) => !option.disabled)?.value;
12
+ // Recreated arrays and labels must not override a user's manual scrolling.
13
+ const optionStructure = JSON.stringify(options.map((option) => [option.value, Boolean(option.disabled)]));
12
14
  useEffect(() => {
13
15
  const selected = row.current?.querySelector('[aria-selected="true"]');
14
16
  if (!selected || !row.current)
@@ -20,7 +22,7 @@ export function Tabs({ options, value, onValueChange, id: providedId, className,
20
22
  viewport.scrollLeft += bounds.left - visible.left;
21
23
  else if (bounds.right > visible.right)
22
24
  viewport.scrollLeft += bounds.right - visible.right;
23
- }, [value, options]);
25
+ }, [value, optionStructure]);
24
26
  return (_jsx("div", { ...props, id: id, ref: row, role: "tablist", "aria-orientation": "horizontal", className: classes("lo-ui-tabs", className), children: options.map((option, index) => (_jsx("button", { id: `${id}-tab-${index}`, type: "button", role: "tab", "aria-selected": option.value === value, "aria-controls": option.panelId, tabIndex: option.value === focusValue ? 0 : -1, disabled: option.disabled, className: "lo-ui-tab", onClick: () => onValueChange(option.value), onKeyDown: (event) => {
25
27
  if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key))
26
28
  return;
package/dist/styles.css CHANGED
@@ -112,7 +112,13 @@
112
112
  background: transparent;
113
113
  }
114
114
 
115
+ .lo-ui-button__label {
116
+ min-width: 0;
117
+ overflow-wrap: anywhere;
118
+ }
119
+
115
120
  .lo-ui-button__icon {
121
+ flex: 0 0 auto;
116
122
  width: 20px;
117
123
  height: 20px;
118
124
  display: inline-grid;
@@ -327,6 +333,10 @@
327
333
  transform: translateX(20px);
328
334
  }
329
335
 
336
+ .lo-ui-switch:dir(rtl):checked::after {
337
+ transform: translateX(-20px);
338
+ }
339
+
330
340
  .lo-ui-switch:disabled {
331
341
  cursor: default;
332
342
  opacity: 0.55;
@@ -356,7 +366,8 @@
356
366
  transition: transform var(--lo-motion-fast) var(--lo-ease-out);
357
367
  }
358
368
 
359
- .lo-ui-checkbox:checked {
369
+ .lo-ui-checkbox:checked,
370
+ .lo-ui-checkbox:indeterminate {
360
371
  background: var(--lo-color-accent-fill);
361
372
  border-color: var(--lo-color-accent-fill);
362
373
  }
@@ -370,6 +381,12 @@
370
381
  transform: translateY(-1px) rotate(-45deg) scale(1);
371
382
  }
372
383
 
384
+ .lo-ui-checkbox:indeterminate::after {
385
+ height: 0;
386
+ border-width: 0 0 2px;
387
+ transform: none;
388
+ }
389
+
373
390
  .lo-ui-list-section {
374
391
  display: flex;
375
392
  flex-direction: column;
@@ -710,6 +727,57 @@
710
727
  border-radius: var(--lo-radius-full);
711
728
  }
712
729
 
730
+ @media (forced-colors: active) {
731
+ .lo-ui-switch,
732
+ .lo-ui-checkbox {
733
+ forced-color-adjust: none;
734
+ background: Canvas;
735
+ border: 1px solid ButtonText;
736
+ --lo-color-focus: ButtonText;
737
+ }
738
+
739
+ .lo-ui-switch {
740
+ padding: 1px;
741
+ }
742
+
743
+ .lo-ui-switch::after {
744
+ background: ButtonText;
745
+ box-shadow: none;
746
+ }
747
+
748
+ .lo-ui-switch:checked,
749
+ .lo-ui-checkbox:checked,
750
+ .lo-ui-checkbox:indeterminate {
751
+ background: Highlight;
752
+ border-color: Highlight;
753
+ }
754
+
755
+ .lo-ui-switch:checked::after {
756
+ background: HighlightText;
757
+ }
758
+
759
+ .lo-ui-checkbox::after {
760
+ border-color: HighlightText;
761
+ }
762
+
763
+ .lo-ui-tab[aria-selected="true"] {
764
+ forced-color-adjust: none;
765
+ color: HighlightText;
766
+ --lo-color-focus: ButtonText;
767
+ }
768
+
769
+ .lo-ui-tab[aria-selected="true"]::before {
770
+ background: Highlight;
771
+ }
772
+
773
+ .lo-ui-progress {
774
+ forced-color-adjust: none;
775
+ border: 1px solid CanvasText;
776
+ --lo-color-border: Canvas;
777
+ --lo-color-accent: Highlight;
778
+ }
779
+ }
780
+
713
781
  :where(.lo-ui-root code, .lo-ui-root pre) {
714
782
  font-family: var(--lo-font-family-mono);
715
783
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lo-ink/ui",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "Accessible React components for LO miniapps",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/Button.tsx CHANGED
@@ -47,12 +47,12 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
47
47
  {loading ? (
48
48
  <>
49
49
  <span className="lo-ui-spinner" aria-hidden="true" />
50
- <span>{loadingLabel}</span>
50
+ <span className="lo-ui-button__label">{loadingLabel}</span>
51
51
  </>
52
52
  ) : (
53
53
  <>
54
54
  {leading && <span className="lo-ui-button__icon">{leading}</span>}
55
- <span>{children}</span>
55
+ <span className="lo-ui-button__label">{children}</span>
56
56
  {trailing && <span className="lo-ui-button__icon">{trailing}</span>}
57
57
  </>
58
58
  )}
package/src/Tabs.tsx CHANGED
@@ -39,6 +39,10 @@ export function Tabs({
39
39
  )
40
40
  ? value
41
41
  : options.find((option) => !option.disabled)?.value;
42
+ // Recreated arrays and labels must not override a user's manual scrolling.
43
+ const optionStructure = JSON.stringify(
44
+ options.map((option) => [option.value, Boolean(option.disabled)]),
45
+ );
42
46
  useEffect(() => {
43
47
  const selected = row.current?.querySelector<HTMLElement>(
44
48
  '[aria-selected="true"]',
@@ -51,7 +55,7 @@ export function Tabs({
51
55
  viewport.scrollLeft += bounds.left - visible.left;
52
56
  else if (bounds.right > visible.right)
53
57
  viewport.scrollLeft += bounds.right - visible.right;
54
- }, [value, options]);
58
+ }, [value, optionStructure]);
55
59
  return (
56
60
  <div
57
61
  {...props}
package/src/styles.css CHANGED
@@ -112,7 +112,13 @@
112
112
  background: transparent;
113
113
  }
114
114
 
115
+ .lo-ui-button__label {
116
+ min-width: 0;
117
+ overflow-wrap: anywhere;
118
+ }
119
+
115
120
  .lo-ui-button__icon {
121
+ flex: 0 0 auto;
116
122
  width: 20px;
117
123
  height: 20px;
118
124
  display: inline-grid;
@@ -327,6 +333,10 @@
327
333
  transform: translateX(20px);
328
334
  }
329
335
 
336
+ .lo-ui-switch:dir(rtl):checked::after {
337
+ transform: translateX(-20px);
338
+ }
339
+
330
340
  .lo-ui-switch:disabled {
331
341
  cursor: default;
332
342
  opacity: 0.55;
@@ -356,7 +366,8 @@
356
366
  transition: transform var(--lo-motion-fast) var(--lo-ease-out);
357
367
  }
358
368
 
359
- .lo-ui-checkbox:checked {
369
+ .lo-ui-checkbox:checked,
370
+ .lo-ui-checkbox:indeterminate {
360
371
  background: var(--lo-color-accent-fill);
361
372
  border-color: var(--lo-color-accent-fill);
362
373
  }
@@ -370,6 +381,12 @@
370
381
  transform: translateY(-1px) rotate(-45deg) scale(1);
371
382
  }
372
383
 
384
+ .lo-ui-checkbox:indeterminate::after {
385
+ height: 0;
386
+ border-width: 0 0 2px;
387
+ transform: none;
388
+ }
389
+
373
390
  .lo-ui-list-section {
374
391
  display: flex;
375
392
  flex-direction: column;
@@ -710,6 +727,57 @@
710
727
  border-radius: var(--lo-radius-full);
711
728
  }
712
729
 
730
+ @media (forced-colors: active) {
731
+ .lo-ui-switch,
732
+ .lo-ui-checkbox {
733
+ forced-color-adjust: none;
734
+ background: Canvas;
735
+ border: 1px solid ButtonText;
736
+ --lo-color-focus: ButtonText;
737
+ }
738
+
739
+ .lo-ui-switch {
740
+ padding: 1px;
741
+ }
742
+
743
+ .lo-ui-switch::after {
744
+ background: ButtonText;
745
+ box-shadow: none;
746
+ }
747
+
748
+ .lo-ui-switch:checked,
749
+ .lo-ui-checkbox:checked,
750
+ .lo-ui-checkbox:indeterminate {
751
+ background: Highlight;
752
+ border-color: Highlight;
753
+ }
754
+
755
+ .lo-ui-switch:checked::after {
756
+ background: HighlightText;
757
+ }
758
+
759
+ .lo-ui-checkbox::after {
760
+ border-color: HighlightText;
761
+ }
762
+
763
+ .lo-ui-tab[aria-selected="true"] {
764
+ forced-color-adjust: none;
765
+ color: HighlightText;
766
+ --lo-color-focus: ButtonText;
767
+ }
768
+
769
+ .lo-ui-tab[aria-selected="true"]::before {
770
+ background: Highlight;
771
+ }
772
+
773
+ .lo-ui-progress {
774
+ forced-color-adjust: none;
775
+ border: 1px solid CanvasText;
776
+ --lo-color-border: Canvas;
777
+ --lo-color-accent: Highlight;
778
+ }
779
+ }
780
+
713
781
  :where(.lo-ui-root code, .lo-ui-root pre) {
714
782
  font-family: var(--lo-font-family-mono);
715
783
  }