@hjmds/react 1.29.0 → 1.31.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/auth-screen.d.ts +18 -3
- package/dist/auth-screen.d.ts.map +1 -1
- package/dist/auth-screen.js +22 -6
- package/dist/auth-screen.js.map +1 -1
- package/dist/bottom-navigation.d.ts +7 -0
- package/dist/bottom-navigation.d.ts.map +1 -1
- package/dist/bottom-navigation.js +64 -8
- package/dist/bottom-navigation.js.map +1 -1
- package/dist/carousel.d.ts +29 -1
- package/dist/carousel.d.ts.map +1 -1
- package/dist/carousel.js +27 -3
- package/dist/carousel.js.map +1 -1
- package/dist/display.d.ts +8 -2
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +12 -7
- package/dist/display.js.map +1 -1
- package/dist/evidence.d.ts +3 -1862
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +112 -300
- package/dist/evidence.js.map +1 -1
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +2 -1
- package/dist/forms.js.map +1 -1
- package/dist/image-choice.d.ts +5 -0
- package/dist/image-choice.d.ts.map +1 -1
- package/dist/image-choice.js +4 -3
- package/dist/image-choice.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/internal/field-error.d.ts +19 -0
- package/dist/internal/field-error.d.ts.map +1 -0
- package/dist/internal/field-error.js +19 -0
- package/dist/internal/field-error.js.map +1 -0
- package/dist/internal/initial-focus.d.ts.map +1 -1
- package/dist/internal/initial-focus.js +49 -7
- package/dist/internal/initial-focus.js.map +1 -1
- package/dist/internal/media-album.d.ts +49 -0
- package/dist/internal/media-album.d.ts.map +1 -0
- package/dist/internal/media-album.js +31 -0
- package/dist/internal/media-album.js.map +1 -0
- package/dist/internal/message-reactions.d.ts +28 -2
- package/dist/internal/message-reactions.d.ts.map +1 -1
- package/dist/internal/message-reactions.js +21 -5
- package/dist/internal/message-reactions.js.map +1 -1
- package/dist/layout.d.ts +19 -3
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +10 -3
- package/dist/layout.js.map +1 -1
- package/dist/navigation.d.ts +3 -1
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +4 -2
- package/dist/navigation.js.map +1 -1
- package/dist/number-field.d.ts.map +1 -1
- package/dist/number-field.js +2 -1
- package/dist/number-field.js.map +1 -1
- package/dist/overlays.d.ts +65 -0
- package/dist/overlays.d.ts.map +1 -1
- package/dist/overlays.js +36 -3
- package/dist/overlays.js.map +1 -1
- package/dist/public-exports.generated.d.ts +221 -0
- package/dist/public-exports.generated.d.ts.map +1 -0
- package/dist/public-exports.generated.js +670 -0
- package/dist/public-exports.generated.js.map +1 -0
- package/dist/screen-flows.d.ts +104 -12
- package/dist/screen-flows.d.ts.map +1 -1
- package/dist/screen-flows.js +87 -18
- package/dist/screen-flows.js.map +1 -1
- package/dist/screens.d.ts +59 -8
- package/dist/screens.d.ts.map +1 -1
- package/dist/screens.js +57 -15
- package/dist/screens.js.map +1 -1
- package/dist/select.d.ts.map +1 -1
- package/dist/select.js +2 -1
- package/dist/select.js.map +1 -1
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +3 -2
- package/dist/selection.js.map +1 -1
- package/dist/steps.d.ts +11 -1
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +11 -6
- package/dist/steps.js.map +1 -1
- package/dist/styles.css +139 -20
- package/dist/styles.layered.css +139 -20
- package/dist/supplemental-display.d.ts.map +1 -1
- package/dist/supplemental-display.js +2 -48
- package/dist/supplemental-display.js.map +1 -1
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +1 -0
- package/dist/theme.js.map +1 -1
- package/package.json +3 -3
package/dist/steps.d.ts
CHANGED
|
@@ -6,10 +6,15 @@ export type StepsProps<Id extends string = string> = Omit<HTMLAttributes<HTMLOLi
|
|
|
6
6
|
statusLabels: StepsStatusLabels;
|
|
7
7
|
composeAccessibleName: ComposeStepsAccessibleName;
|
|
8
8
|
renderMark?: (status: StepStatus, position: number) => ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Return to a step before the cursor (2026-10-18, spint compose). Only those steps become buttons; the cursor and
|
|
11
|
+
* later steps stay static so the flow never skips forward past validation. Omit it while the flow is locked.
|
|
12
|
+
*/
|
|
13
|
+
onStepPress?: (id: Id) => void;
|
|
9
14
|
/** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */
|
|
10
15
|
layoutStyle?: HjmCompositionStyleProp;
|
|
11
16
|
}>;
|
|
12
|
-
/** Linear
|
|
17
|
+
/** Linear progress steps with one canonical cursor; steps before it can be pressed to go back. */
|
|
13
18
|
export declare const Steps: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLOListElement>, "children"> & Readonly<{
|
|
14
19
|
descriptor: Readonly<{
|
|
15
20
|
steps: readonly Readonly<{
|
|
@@ -28,6 +33,11 @@ export declare const Steps: import("react").ForwardRefExoticComponent<Omit<HTMLA
|
|
|
28
33
|
}>;
|
|
29
34
|
composeAccessibleName: ComposeStepsAccessibleName;
|
|
30
35
|
renderMark?: (status: StepStatus, position: number) => ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Return to a step before the cursor (2026-10-18, spint compose). Only those steps become buttons; the cursor and
|
|
38
|
+
* later steps stay static so the flow never skips forward past validation. Omit it while the flow is locked.
|
|
39
|
+
*/
|
|
40
|
+
onStepPress?: (id: string) => void;
|
|
31
41
|
/** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */
|
|
32
42
|
layoutStyle?: HjmCompositionStyleProp;
|
|
33
43
|
}> & import("react").RefAttributes<HTMLOListElement>>;
|
package/dist/steps.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../src/steps.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../src/steps.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACvB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,MAAM,MAAM,UAAU,CAAC,EAAE,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CACvD,cAAc,CAAC,gBAAgB,CAAC,EAChC,UAAU,CACX,GAAG,QAAQ,CAAC;IACX,UAAU,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC;IAChC,YAAY,EAAE,iBAAiB,CAAC;IAChC,qBAAqB,EAAE,0BAA0B,CAAC;IAClD,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,SAAS,CAAC;IACjE;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,IAAI,CAAC;IAC/B,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEH,kGAAkG;AAClG,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;2BAZO,0BAA0B;iBACpC,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,SAAS;IAChE;;;OAGG;kCACuB,IAAI;IAC9B,gGAAgG;kBAClF,uBAAuB;qDAgDrC,CAAC"}
|
package/dist/steps.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { resolveStepsDescriptor, } from "@hjmds/design-contracts/components/steps";
|
|
3
|
-
import { forwardRef } from "react";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { resolveStepsDescriptor, stepsRecipe, } from "@hjmds/design-contracts/components/steps";
|
|
3
|
+
import { forwardRef, useId } from "react";
|
|
4
4
|
import { classNames } from "./internal.js";
|
|
5
|
-
/** Linear
|
|
6
|
-
export const Steps = forwardRef(function Steps({ descriptor, statusLabels, composeAccessibleName, renderMark, className, layoutStyle, ...props }, ref) {
|
|
5
|
+
/** Linear progress steps with one canonical cursor; steps before it can be pressed to go back. */
|
|
6
|
+
export const Steps = forwardRef(function Steps({ descriptor, statusLabels, composeAccessibleName, renderMark, onStepPress, className, layoutStyle, ...props }, ref) {
|
|
7
7
|
const steps = resolveStepsDescriptor(descriptor, { statusLabels, composeAccessibleName });
|
|
8
|
-
|
|
8
|
+
const statusId = useId();
|
|
9
|
+
return (_jsx("ol", { ...props, style: { ["--hjm-steps-press-target"]: `${stepsRecipe.press.minTouchTarget}px`, ...props.style, ...layoutStyle }, ref: ref, className: classNames("hjm-steps", className), children: steps.map((step, index) => {
|
|
10
|
+
const content = _jsxs(_Fragment, { children: [_jsxs("div", { className: "hjm-steps__rail", "aria-hidden": "true", children: [_jsx("span", { className: "hjm-steps__indicator", children: renderMark?.(step.status, step.position) ?? (step.status === "complete" ? "✓" : step.status === "error" ? "!" : step.position) }), index === steps.length - 1 ? null : _jsx("span", { className: "hjm-steps__connector" })] }), _jsxs("div", { className: "hjm-steps__copy", children: [_jsx("span", { className: "hjm-steps__label", children: step.label }), step.description === undefined ? null : (_jsx("span", { className: "hjm-steps__description", children: step.description })), _jsx("span", { className: "hjm-visually-hidden", id: `${statusId}-${index}`, children: step.statusLabel })] })] });
|
|
11
|
+
// A pressable step is one named button; its status stays a description so the name keeps order + label.
|
|
12
|
+
return step.revisitable && onStepPress ? (_jsx("li", { className: "hjm-steps__step", "data-status": step.status, children: _jsx("button", { type: "button", className: "hjm-steps__press", "aria-label": step.accessibleName, "aria-describedby": `${statusId}-${index}`, onClick: () => onStepPress(step.id), children: content }) }, step.id)) : (_jsx("li", { "aria-label": step.accessibleName, "aria-current": step.status === "current" || step.status === "error" ? "step" : undefined, className: "hjm-steps__step", "data-status": step.status, children: content }, step.id));
|
|
13
|
+
}) }));
|
|
9
14
|
});
|
|
10
15
|
//# sourceMappingURL=steps.js.map
|
package/dist/steps.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"steps.js","sourceRoot":"","sources":["../src/steps.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,sBAAsB,
|
|
1
|
+
{"version":3,"file":"steps.js","sourceRoot":"","sources":["../src/steps.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveStepsDescriptor,\n stepsRecipe,\n type ComposeStepsAccessibleName,\n type StepStatus,\n type StepsDescriptor,\n type StepsStatusLabels,\n} from \"@hjmds/design-contracts/components/steps\";\nimport { forwardRef, useId, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type StepsProps<Id extends string = string> = Omit<\n HTMLAttributes<HTMLOListElement>,\n \"children\"\n> & Readonly<{\n descriptor: StepsDescriptor<Id>;\n statusLabels: StepsStatusLabels;\n composeAccessibleName: ComposeStepsAccessibleName;\n renderMark?: (status: StepStatus, position: number) => ReactNode;\n /**\n * Return to a step before the cursor (2026-10-18, spint compose). Only those steps become buttons; the cursor and\n * later steps stay static so the flow never skips forward past validation. Omit it while the flow is locked.\n */\n onStepPress?: (id: Id) => void;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\n/** Linear progress steps with one canonical cursor; steps before it can be pressed to go back. */\nexport const Steps = forwardRef<HTMLOListElement, StepsProps>(function Steps(\n { descriptor, statusLabels, composeAccessibleName, renderMark, onStepPress, className, layoutStyle, ...props },\n ref,\n) {\n const steps = resolveStepsDescriptor(descriptor, { statusLabels, composeAccessibleName });\n const statusId = useId();\n return (\n <ol {...props} style={{ [\"--hjm-steps-press-target\" as string]: `${stepsRecipe.press.minTouchTarget}px`, ...props.style, ...layoutStyle }} ref={ref} className={classNames(\"hjm-steps\", className)}>\n {steps.map((step, index) => {\n const content = <>\n <div className=\"hjm-steps__rail\" aria-hidden=\"true\">\n <span className=\"hjm-steps__indicator\">\n {renderMark?.(step.status, step.position) ?? (\n step.status === \"complete\" ? \"✓\" : step.status === \"error\" ? \"!\" : step.position\n )}\n </span>\n {index === steps.length - 1 ? null : <span className=\"hjm-steps__connector\" />}\n </div>\n <div className=\"hjm-steps__copy\">\n <span className=\"hjm-steps__label\">{step.label}</span>\n {step.description === undefined ? null : (\n <span className=\"hjm-steps__description\">{step.description}</span>\n )}\n <span className=\"hjm-visually-hidden\" id={`${statusId}-${index}`}>{step.statusLabel}</span>\n </div>\n </>;\n // A pressable step is one named button; its status stays a description so the name keeps order + label.\n return step.revisitable && onStepPress ? (\n <li className=\"hjm-steps__step\" data-status={step.status} key={step.id}>\n <button type=\"button\" className=\"hjm-steps__press\" aria-label={step.accessibleName} aria-describedby={`${statusId}-${index}`}\n onClick={() => onStepPress(step.id)}>{content}</button>\n </li>\n ) : (\n <li\n aria-label={step.accessibleName}\n aria-current={step.status === \"current\" || step.status === \"error\" ? \"step\" : undefined}\n className=\"hjm-steps__step\"\n data-status={step.status}\n key={step.id}\n >{content}</li>\n );\n })}\n </ol>\n );\n});\n"]}
|
package/dist/styles.css
CHANGED
|
@@ -372,7 +372,7 @@
|
|
|
372
372
|
the support text fades, so a custom Field control dims without needing a class. A component
|
|
373
373
|
recipe value (Select, NumberField, OtpField, SearchField, PasswordField) arrives as an
|
|
374
374
|
inline --hjm-field-disabled-opacity on the root. */
|
|
375
|
-
.hjm-field[data-state="disabled"] > :not(.hjm-field__description):not(.hjm-field__error) { opacity: var(--hjm-field-disabled-opacity); }
|
|
375
|
+
.hjm-field[data-state="disabled"] > :not(.hjm-field__description):not(.hjm-field__error):not([data-hjm-field-error]) { opacity: var(--hjm-field-disabled-opacity); }
|
|
376
376
|
.hjm-field__input {
|
|
377
377
|
inline-size: 100%;
|
|
378
378
|
min-inline-size: 0;
|
|
@@ -600,6 +600,18 @@
|
|
|
600
600
|
inset-block-start: 50%;
|
|
601
601
|
translate: -50% -50%;
|
|
602
602
|
}
|
|
603
|
+
/* Prominent center destination: bottomNavigationRecipe.prominentDestination, lifted so its label stays on the
|
|
604
|
+
other labels' line. The circle keeps brand fill in both states; the label carries selection. */
|
|
605
|
+
.hjm-bottom-navigation li[data-prominent="true"] .hjm-bottom-navigation__indicator {
|
|
606
|
+
inline-size: var(--hjm-bottom-navigation-prominent-diameter);
|
|
607
|
+
block-size: var(--hjm-bottom-navigation-prominent-diameter);
|
|
608
|
+
margin-block-start: calc(-1 * var(--hjm-bottom-navigation-prominent-lift));
|
|
609
|
+
border-radius: var(--hjm-radius-full);
|
|
610
|
+
color: var(--hjm-color-on-primary);
|
|
611
|
+
background: var(--hjm-color-primary);
|
|
612
|
+
box-shadow: var(--hjm-shadow-floating);
|
|
613
|
+
}
|
|
614
|
+
.hjm-bottom-navigation li[data-prominent="true"] .hjm-bottom-navigation__indicator > :first-child { transform: none; }
|
|
603
615
|
|
|
604
616
|
.hjm-number-field__control {
|
|
605
617
|
padding-inline: 0;
|
|
@@ -1719,6 +1731,22 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
1719
1731
|
AuthScreenLayout safeAreaBottom (2026-10-17 1.28 adoption: products wrapped the layout in their own inset). */
|
|
1720
1732
|
padding-block-end: max(var(--hjm-auth-screen-padding-block), env(safe-area-inset-bottom, 0px));
|
|
1721
1733
|
}
|
|
1734
|
+
/* With title/exit the layout owns the ScreenLayout centered header band: full-bleed over the inline padding, at the
|
|
1735
|
+
shared screen gutter, with the former top padding moved below it (2026-10-18: products kept a TopBar above). */
|
|
1736
|
+
.hjm-auth-screen[data-header] { padding-block-start: 0; }
|
|
1737
|
+
.hjm-auth-screen__header {
|
|
1738
|
+
display: grid;
|
|
1739
|
+
grid-template-columns: 1fr minmax(0, auto) 1fr;
|
|
1740
|
+
align-items: center;
|
|
1741
|
+
box-sizing: border-box;
|
|
1742
|
+
min-block-size: var(--hjm-auth-screen-header-min-height);
|
|
1743
|
+
margin-inline: calc(var(--hjm-auth-screen-padding-inline) * -1);
|
|
1744
|
+
margin-block-end: var(--hjm-auth-screen-padding-block);
|
|
1745
|
+
padding-inline: var(--hjm-auth-screen-header-padding-inline);
|
|
1746
|
+
padding-block: var(--hjm-auth-screen-header-padding-block);
|
|
1747
|
+
}
|
|
1748
|
+
.hjm-auth-screen__header-title { min-inline-size: 0; text-align: center; overflow-wrap: anywhere; }
|
|
1749
|
+
.hjm-auth-screen__header-title > * { margin: 0; }
|
|
1722
1750
|
.hjm-auth-screen__block {
|
|
1723
1751
|
display: flex;
|
|
1724
1752
|
flex: 1;
|
|
@@ -1770,17 +1798,18 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
1770
1798
|
flex-wrap: wrap;
|
|
1771
1799
|
justify-content: center;
|
|
1772
1800
|
align-items: center;
|
|
1773
|
-
column-gap: var(--hjm-auth-screen-link-gap);
|
|
1774
1801
|
}
|
|
1775
|
-
/* 2026-10-17 "간격 줄여": 보이는 간격은
|
|
1776
|
-
|
|
1802
|
+
/* 2026-10-17 "간격 줄여": 보이는 간격은 linkGap + 구분점뿐이다. 44 터치 높이는 배경 없는 min-block-size다.
|
|
1803
|
+
2026-10-18 링크 사이 간격을 flex column-gap에서 링크의 inline 여백으로 옮겼다. 보이는 간격은 같고(column-gap 0),
|
|
1804
|
+
가로 터치 폭이 그 여백만큼 링크 상자 안에 든다. 예전 가상 요소는 상자 밖으로 linkGap만큼 뻗어, 긴 링크가 푸터 폭을
|
|
1805
|
+
다 쓰면 푸터의 스크롤 폭을 넓혔다(웹 scenario-matrix auth-screen long-copy 288 > 282). 여백을 gap과 함께 두면
|
|
1806
|
+
글자 사이가 두 배로 벌어지므로 gap은 두지 않는다. */
|
|
1777
1807
|
.hjm-auth-screen__link {
|
|
1778
|
-
position: relative;
|
|
1779
1808
|
display: inline-flex;
|
|
1780
1809
|
align-items: center;
|
|
1781
1810
|
min-block-size: var(--hjm-auth-screen-link-target);
|
|
1782
1811
|
margin: 0;
|
|
1783
|
-
padding: 0;
|
|
1812
|
+
padding: 0 var(--hjm-auth-screen-link-gap);
|
|
1784
1813
|
border: 0;
|
|
1785
1814
|
background: none;
|
|
1786
1815
|
font-family: var(--hjm-font-family-ui, inherit);
|
|
@@ -1788,12 +1817,6 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
1788
1817
|
text-underline-offset: 0.18em;
|
|
1789
1818
|
cursor: pointer;
|
|
1790
1819
|
}
|
|
1791
|
-
.hjm-auth-screen__link::after {
|
|
1792
|
-
content: "";
|
|
1793
|
-
position: absolute;
|
|
1794
|
-
inset-block: 0;
|
|
1795
|
-
inset-inline: calc(var(--hjm-auth-screen-link-gap) * -1);
|
|
1796
|
-
}
|
|
1797
1820
|
.hjm-auth-screen__link:focus-visible {
|
|
1798
1821
|
outline: var(--hjm-focus-width) solid var(--hjm-color-focus);
|
|
1799
1822
|
outline-offset: var(--hjm-focus-offset);
|
|
@@ -2191,6 +2214,46 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
2191
2214
|
background: var(--hjm-backdrop-modal);
|
|
2192
2215
|
overscroll-behavior: contain;
|
|
2193
2216
|
}
|
|
2217
|
+
/* Dialog overlayLayer: viewport-sized, decorative, above the card (later sibling) and never a pointer target. */
|
|
2218
|
+
.hjm-dialog__overlay-layer {
|
|
2219
|
+
position: absolute;
|
|
2220
|
+
inset: 0;
|
|
2221
|
+
pointer-events: none;
|
|
2222
|
+
}
|
|
2223
|
+
/* ImmersiveOverlay: an edge-to-edge stage and control bar with no scrim, card or gutter. */
|
|
2224
|
+
.hjm-overlay.hjm-immersive-positioner {
|
|
2225
|
+
align-items: stretch;
|
|
2226
|
+
padding: 0;
|
|
2227
|
+
background: var(--hjm-immersive-background);
|
|
2228
|
+
}
|
|
2229
|
+
.hjm-immersive {
|
|
2230
|
+
display: flex;
|
|
2231
|
+
flex-direction: column;
|
|
2232
|
+
inline-size: 100%;
|
|
2233
|
+
block-size: 100%;
|
|
2234
|
+
color: var(--hjm-color-text);
|
|
2235
|
+
background: var(--hjm-immersive-background);
|
|
2236
|
+
outline: none;
|
|
2237
|
+
}
|
|
2238
|
+
.hjm-immersive__stage {
|
|
2239
|
+
position: relative;
|
|
2240
|
+
flex: 1 1 auto;
|
|
2241
|
+
min-block-size: 0;
|
|
2242
|
+
overflow: hidden;
|
|
2243
|
+
}
|
|
2244
|
+
.hjm-immersive__controls {
|
|
2245
|
+
display: flex;
|
|
2246
|
+
flex-direction: column;
|
|
2247
|
+
gap: var(--hjm-immersive-gap);
|
|
2248
|
+
padding: var(--hjm-immersive-padding);
|
|
2249
|
+
padding-inline: max(var(--hjm-immersive-padding), env(safe-area-inset-left)) max(var(--hjm-immersive-padding), env(safe-area-inset-right));
|
|
2250
|
+
padding-block-end: max(var(--hjm-immersive-padding), env(safe-area-inset-bottom));
|
|
2251
|
+
}
|
|
2252
|
+
.hjm-immersive__actions {
|
|
2253
|
+
display: flex;
|
|
2254
|
+
align-items: center;
|
|
2255
|
+
gap: var(--hjm-immersive-action-gap);
|
|
2256
|
+
}
|
|
2194
2257
|
.hjm-dialog,
|
|
2195
2258
|
.hjm-alert-dialog,
|
|
2196
2259
|
.hjm-sheet {
|
|
@@ -2207,6 +2270,8 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
2207
2270
|
.hjm-dialog { inline-size: min(36rem, 100%); }
|
|
2208
2271
|
.hjm-dialog[data-size="small"] { inline-size: min(28rem, 100%); }
|
|
2209
2272
|
.hjm-dialog[data-size="large"] { inline-size: min(48rem, 100%); }
|
|
2273
|
+
/* Dialog scrollEnabled={false}: the card keeps its scroll offset while a gesture in the body owns the pointer. */
|
|
2274
|
+
.hjm-dialog[data-scroll="locked"] { overflow: hidden; overscroll-behavior: contain; touch-action: none; }
|
|
2210
2275
|
.hjm-alert-dialog[data-size="small"] { inline-size: min(28rem, 100%); }
|
|
2211
2276
|
.hjm-alert-dialog[data-size="large"] { inline-size: min(48rem, 100%); }
|
|
2212
2277
|
.hjm-dialog__header,
|
|
@@ -2748,6 +2813,9 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
2748
2813
|
.hjm-steps__step[data-status="pending"] .hjm-steps__label { color: var(--hjm-color-text-muted); }
|
|
2749
2814
|
.hjm-steps__step[data-status="error"] .hjm-steps__label { color: var(--hjm-color-danger); }
|
|
2750
2815
|
.hjm-steps__description { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); overflow-wrap: anywhere; }
|
|
2816
|
+
/* A step before the cursor is one button over marker and label (Steps onStepPress); the cell keeps its static layout. */
|
|
2817
|
+
.hjm-steps__press { display: grid; align-content: start; gap: var(--hjm-space-xs); min-inline-size: 0; min-block-size: var(--hjm-steps-press-target); margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: start; cursor: pointer; }
|
|
2818
|
+
.hjm-steps__press:focus-visible { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: var(--hjm-focus-offset); }
|
|
2751
2819
|
|
|
2752
2820
|
.hjm-file-picker { display: grid; gap: var(--hjm-space-xs); }
|
|
2753
2821
|
.hjm-file-picker__label { color: var(--hjm-color-text); font-weight: var(--hjm-text-emphasis-medium); }
|
|
@@ -2934,10 +3002,12 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
2934
3002
|
.hjm-carousel__rotation { justify-self: start; }
|
|
2935
3003
|
.hjm-carousel__controls, .hjm-carousel__dots { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--hjm-space-xs); }
|
|
2936
3004
|
.hjm-carousel__controls { flex-wrap: nowrap; } .hjm-carousel__dots { flex-shrink: 1; min-inline-size: 0; }
|
|
2937
|
-
|
|
2938
|
-
.hjm-
|
|
2939
|
-
.hjm-carousel__dot
|
|
2940
|
-
.hjm-carousel__dot
|
|
3005
|
+
/* PageIndicator is the same dot row for a product-owned pager (carouselRecipe.dot). */
|
|
3006
|
+
.hjm-page-indicator { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--hjm-space-xs); min-inline-size: 0; }
|
|
3007
|
+
.hjm-carousel__dot, .hjm-page-indicator__dot { display: grid; place-items: center; min-inline-size: var(--hjm-control-min-touch-target); min-block-size: var(--hjm-control-min-touch-target); border: 0; border-radius: var(--hjm-radius-full); background: transparent; cursor: pointer; }
|
|
3008
|
+
.hjm-carousel__dot > span, .hjm-page-indicator__dot > span { inline-size: var(--hjm-space-xs); block-size: var(--hjm-space-xs); border-radius: var(--hjm-radius-full); background: var(--hjm-color-text-weak); } /* carouselRecipe.dot.color.inactive (border.strong), as Native */
|
|
3009
|
+
.hjm-carousel__dot[data-current="true"] > span, .hjm-page-indicator__dot[data-current="true"] > span { background: var(--hjm-color-content-brand); }
|
|
3010
|
+
.hjm-carousel__dot:focus-visible, .hjm-page-indicator__dot:focus-visible { outline: 2px solid var(--hjm-color-content-brand); outline-offset: 2px; }
|
|
2941
3011
|
|
|
2942
3012
|
/* The viewport action follows the content in DOM order. Its measured clearance
|
|
2943
3013
|
belongs on the scroll content, not on the fixed button (docs/floating-action-button.md). */
|
|
@@ -3113,6 +3183,16 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
3113
3183
|
.hjm-tabs:is([data-appearance="gooey"], [data-appearance="slide"]) .hjm-tabs__list { position: relative; }
|
|
3114
3184
|
.hjm-tabs:is([data-appearance="gooey"], [data-appearance="slide"]) .hjm-tabs__tab[data-state="selected"]::after { display: none; }
|
|
3115
3185
|
.hjm-tabs__indicator { position: absolute; bottom: 0; height: 2px; border-radius: var(--hjm-radius-full); background: var(--hjm-color-content-brand); pointer-events: none; }
|
|
3186
|
+
/* indicator="filled" (tabsRecipe.indicators.filled): a surface-accent pill behind the selected tab, no list divider.
|
|
3187
|
+
The moving pill spans the tab height and sits under the labels. */
|
|
3188
|
+
.hjm-tabs[data-indicator="filled"] .hjm-tabs__list { border: 0; }
|
|
3189
|
+
.hjm-tabs[data-indicator="filled"] .hjm-tabs__tab { border-radius: var(--hjm-radius-full); }
|
|
3190
|
+
.hjm-tabs[data-indicator="filled"] .hjm-tabs__tab[data-state="selected"] { color: var(--hjm-color-content-brand); }
|
|
3191
|
+
.hjm-tabs[data-indicator="filled"] .hjm-tabs__tab[data-state="selected"]::after { display: none; }
|
|
3192
|
+
.hjm-tabs[data-indicator="filled"]:not([data-indicator-motion="moving"]) .hjm-tabs__tab[data-state="selected"] { background: var(--hjm-color-surface-accent); }
|
|
3193
|
+
.hjm-tabs[data-indicator="filled"] .hjm-tabs__indicator { top: 0; bottom: 0; height: auto; border-radius: var(--hjm-radius-full); background: var(--hjm-color-surface-accent); z-index: 0; }
|
|
3194
|
+
.hjm-tabs[data-indicator="filled"] .hjm-tabs__list { position: relative; }
|
|
3195
|
+
.hjm-tabs[data-indicator="filled"] .hjm-tabs__tab { z-index: 1; }
|
|
3116
3196
|
.hjm-tabs__gooey { height: 6px; }
|
|
3117
3197
|
|
|
3118
3198
|
/* Capsule destinations retain route/link semantics. At larger text sizes we show
|
|
@@ -3167,6 +3247,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
3167
3247
|
.hjm-screen__header { display: flex; flex-wrap: wrap; align-items: center; gap: var(--hjm-screen-item-gap, var(--hjm-space-sm)); padding: var(--hjm-screen-padding); flex: 0 0 auto; }
|
|
3168
3248
|
.hjm-screen__heading { flex: 1 1 calc(var(--hjm-screen-header-min) * var(--hjm-text-scale, 1)); min-inline-size: 0; overflow-wrap: anywhere; }
|
|
3169
3249
|
.hjm-screen__heading > * { margin: 0; }
|
|
3250
|
+
.hjm-screen__title-leading { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; }
|
|
3170
3251
|
.hjm-screen__notice { padding-inline: var(--hjm-screen-padding); flex: 0 0 auto; }
|
|
3171
3252
|
/* --hjm-screen-body-inline is the body's inline padding and the distance a bleeding CollectionRail crosses (Native
|
|
3172
3253
|
ScreenBodyInsetContext); inset variants change this one value instead of the padding itself. */
|
|
@@ -3175,7 +3256,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
3175
3256
|
(review S5#9: body 16 + row 16 put DM avatars ~32 from the edge). "none" keeps its host-owns-all meaning. */
|
|
3176
3257
|
.hjm-screen[data-content-inset="body-edge"] > .hjm-screen__body { --hjm-screen-body-inline: 0px; }
|
|
3177
3258
|
/* Overlay content is not in the screen body, even when rendered inside it: a bleeding rail there stays in its box. */
|
|
3178
|
-
.hjm-sheet, .hjm-dialog, .hjm-alert-dialog, .hjm-popover { --hjm-screen-body-inline: 0px; }
|
|
3259
|
+
.hjm-sheet, .hjm-dialog, .hjm-alert-dialog, .hjm-popover { --hjm-screen-body-inline: 0px; --hjm-bottom-navigation-inset: 0px; }
|
|
3179
3260
|
/* contentInset="none" hands every inset to the host: no footer rule, as on Native (BottomCTA then draws its own bar). */
|
|
3180
3261
|
.hjm-screen[data-content-inset="none"] > .hjm-screen__footer { border-block-start: 0; }
|
|
3181
3262
|
.hjm-screen__body[data-scroll="screen"] { overflow-y: auto; }
|
|
@@ -3184,7 +3265,10 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
3184
3265
|
.hjm-screen__centered-content { margin-block: auto; flex-shrink: 0; inline-size: 100%; }
|
|
3185
3266
|
.hjm-screen__body[data-replacement="true"] { display: flex; flex-direction: column; }
|
|
3186
3267
|
.hjm-screen__state { margin-block: auto; flex-shrink: 0; display: flex; flex-direction: column; align-items: center; gap: var(--hjm-screen-state-gap, var(--hjm-space-md)); padding-block: var(--hjm-screen-gap); text-align: center; }
|
|
3187
|
-
.hjm-screen__footer { flex: 0 0 auto; padding: var(--hjm-screen-padding); padding-block-end: max(var(--hjm-screen-padding), env(safe-area-inset-bottom)); border-block-start: 1px solid var(--hjm-color-border); }
|
|
3268
|
+
.hjm-screen__footer { flex: 0 0 auto; padding: var(--hjm-screen-padding); padding-block-end: max(var(--hjm-screen-padding), env(safe-area-inset-bottom), calc(var(--hjm-screen-padding) + var(--hjm-bottom-navigation-inset, 0px))); border-block-start: 1px solid var(--hjm-color-border); }
|
|
3269
|
+
/* --hjm-bottom-navigation-inset (BottomNavigationInsetProvider) is the viewport bottom the fixed bar covers. The last
|
|
3270
|
+
region keeps its gutter above the bar; without a provider the value is 0 and the padding is unchanged. */
|
|
3271
|
+
.hjm-screen__body:last-child { padding-block-end: calc(var(--hjm-screen-padding) + var(--hjm-bottom-navigation-inset, 0px)); }
|
|
3188
3272
|
/* SearchScreen filtersOverflow=scroll; why: screen-flows.tsx. Block padding keeps focus rings unclipped.
|
|
3189
3273
|
--hjm-search-filters-bleed = screen padding + hostGutter (1.13.1), set inline by SearchScreen. */
|
|
3190
3274
|
.hjm-search-screen__filters { --f: calc(var(--hjm-focus-width) + var(--hjm-focus-offset)); --b: var(--hjm-search-filters-bleed, var(--hjm-screen-padding)); overflow-x: auto; margin: calc(-1 * var(--f)) calc(-1 * var(--b)); padding: var(--f) var(--b); scroll-padding-inline: var(--b); scrollbar-width: none; }
|
|
@@ -3232,6 +3316,17 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
3232
3316
|
[dir="rtl"] .hjm-chat-message[data-tail] .hjm-chat-message__bubble::before { transform: scaleX(-1); }
|
|
3233
3317
|
|
|
3234
3318
|
.hjm-chat-message__meta { display: flex; flex-shrink: 0; align-items: center; gap: var(--hjm-space-xs); }
|
|
3319
|
+
/* Reaction summary pill (sizes inline from chatMessageRecipe.reactionSummary); own reaction shows the brand border. */
|
|
3320
|
+
.hjm-chat-message__reaction-summary { display: inline-flex; align-items: center; box-sizing: border-box; border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-full); background: var(--hjm-color-surface); color: var(--hjm-color-text); font: inherit; line-height: 1; cursor: pointer; }
|
|
3321
|
+
.hjm-chat-message__reaction-summary[data-selected] { border-color: var(--hjm-color-content-brand); }
|
|
3322
|
+
.hjm-chat-message__reaction-summary:hover:not(:disabled) { background: var(--hjm-color-surface-alt); }
|
|
3323
|
+
.hjm-chat-message__reaction-summary:focus-visible { outline: 2px solid var(--hjm-color-focus, currentColor); outline-offset: 2px; }
|
|
3324
|
+
.hjm-chat-message__reaction-summary:disabled { opacity: 0.5; cursor: default; }
|
|
3325
|
+
/* Typing dots (typingIndicatorRecipe via custom properties): staggered pulse, static under reduced motion. */
|
|
3326
|
+
.hjm-typing-indicator__dot { inline-size: var(--hjm-typing-dot); block-size: var(--hjm-typing-dot); border-radius: 50%; background: var(--hjm-color-text-muted); animation: hjm-typing-pulse var(--hjm-typing-cycle) ease-in-out infinite both; }
|
|
3327
|
+
.hjm-typing-indicator[data-reduced-motion] .hjm-typing-indicator__dot { animation: none; }
|
|
3328
|
+
@media (prefers-reduced-motion: reduce) { .hjm-typing-indicator__dot { animation: none; } }
|
|
3329
|
+
@keyframes hjm-typing-pulse { 0%, 100% { opacity: var(--hjm-typing-rest); } 50% { opacity: 1; } }
|
|
3235
3330
|
/* A quoted reply heads the bubble and is divided from the answer. */
|
|
3236
3331
|
.hjm-chat-message__reply { border-block-end: 1px solid var(--hjm-color-border); padding-block-end: var(--hjm-space-xs); margin-block-end: var(--hjm-space-xs); display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
|
|
3237
3332
|
.hjm-chat-message__quote { inline-size: 100%; border-inline: 0; border-block-start: 0; background: none; padding-inline: 0; padding-block-start: 0; color: inherit; font: inherit; text-align: start; cursor: pointer; }
|
|
@@ -3242,6 +3337,13 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
3242
3337
|
.hjm-chat-message__media-item > img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }
|
|
3243
3338
|
button.hjm-chat-message__media-item { cursor: pointer; }
|
|
3244
3339
|
button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm-color-focus, currentColor); outline-offset: -2px; }
|
|
3340
|
+
/* Paged media album (2026-10-18, mediaAlbumRecipe): one mounted page in the host's media width, counter row below. */
|
|
3341
|
+
.hjm-media-album { display: flex; flex-direction: column; max-inline-size: 100%; }
|
|
3342
|
+
.hjm-media-album__page { display: block; inline-size: 100%; overflow: hidden; padding: 0; border: 0; background: var(--hjm-color-surface-alt); }
|
|
3343
|
+
.hjm-media-album__page > img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }
|
|
3344
|
+
button.hjm-media-album__page { cursor: pointer; }
|
|
3345
|
+
button.hjm-media-album__page:focus-visible { outline: 2px solid var(--hjm-color-focus, currentColor); outline-offset: -2px; }
|
|
3346
|
+
.hjm-media-album__controls { display: flex; align-items: center; justify-content: space-between; }
|
|
3245
3347
|
.hjm-chat-message__bubble[data-photo-only] { background: none; padding: 0; }
|
|
3246
3348
|
.hjm-chat-message__bubble[data-photo-only]::before { display: none; }
|
|
3247
3349
|
/* Only the shared default gutter narrows to the timeline gutter; "none" and "body-edge" keep their own meaning. */
|
|
@@ -3254,8 +3356,12 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
|
|
|
3254
3356
|
.hjm-image-choice { display: flex; flex-direction: column; gap: var(--hjm-space-xs); }
|
|
3255
3357
|
.hjm-image-choice__label { font-weight: var(--hjm-text-emphasis-medium); }
|
|
3256
3358
|
.hjm-image-choice__tiles { display: flex; flex-wrap: wrap; gap: var(--hjm-image-choice-gap); }
|
|
3257
|
-
|
|
3258
|
-
|
|
3359
|
+
/* The button is a column (ring frame, optional item label) so the label shares the tap target; the ring is drawn on
|
|
3360
|
+
the inner frame (2026-10-18 showItemLabels). */
|
|
3361
|
+
.hjm-image-choice__tile { display: flex; flex-direction: column; gap: var(--hjm-image-choice-item-label-gap); inline-size: calc(var(--hjm-image-choice-size) + (var(--hjm-image-choice-ring) + var(--hjm-image-choice-offset)) * 2); padding: 0; border: 0; border-radius: calc(var(--hjm-image-choice-radius) + var(--hjm-image-choice-ring) + var(--hjm-image-choice-offset)); background: none; color: inherit; cursor: pointer; }
|
|
3362
|
+
.hjm-image-choice__ring { position: relative; display: block; inline-size: 100%; aspect-ratio: 1; padding: var(--hjm-image-choice-offset); border: var(--hjm-image-choice-ring) solid transparent; border-radius: inherit; }
|
|
3363
|
+
.hjm-image-choice__tile[data-selected] .hjm-image-choice__ring { border-color: var(--hjm-color-content-brand); }
|
|
3364
|
+
.hjm-image-choice__item-label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; }
|
|
3259
3365
|
.hjm-image-choice__tile:focus-visible { outline: 2px solid var(--hjm-color-focus, currentColor); outline-offset: 2px; }
|
|
3260
3366
|
.hjm-image-choice__tile:disabled { opacity: 0.5; cursor: default; }
|
|
3261
3367
|
.hjm-image-choice__image { display: block; inline-size: 100%; block-size: 100%; overflow: hidden; border-radius: var(--hjm-image-choice-radius); background: var(--hjm-color-surface); }
|
|
@@ -3303,6 +3409,8 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
|
|
|
3303
3409
|
.hjm-comment-row__reactions:focus-visible { outline: 2px solid var(--hjm-color-focus, currentColor); outline-offset: 2px; }
|
|
3304
3410
|
.hjm-comment-row__media { align-self: flex-start; overflow: hidden; margin-block-start: 4px; }
|
|
3305
3411
|
.hjm-comment-row__media > img { display: block; inline-size: 100%; block-size: auto; }
|
|
3412
|
+
.hjm-comment-row__album { align-self: flex-start; margin-block-start: 4px; }
|
|
3413
|
+
.hjm-comment-row__panel { min-inline-size: 0; }
|
|
3306
3414
|
/* commentThreadRecipe.actionAnchor (2026-10-17 measured audit): the 44 targets centre on the identity's first line
|
|
3307
3415
|
(--hjm-comment-anchor-line, set per row), so like/more glyphs share the author line's centre instead of sitting
|
|
3308
3416
|
12px below it. When HJM's own like/more is the last control (data-edge), the whole column takes the IconButton edge
|
|
@@ -3416,6 +3524,17 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
|
|
|
3416
3524
|
.hjm-card[data-interactive="true"] { font: inherit; color: inherit; text-align: inherit; cursor: pointer; min-inline-size: var(--hjm-control-min-touch-target); min-block-size: var(--hjm-control-min-touch-target); }
|
|
3417
3525
|
.hjm-card[data-interactive="true"]:active:not(:disabled) { opacity: var(--hjm-card-pressed-opacity); }
|
|
3418
3526
|
.hjm-card[data-interactive="true"]:disabled { opacity: var(--hjm-card-disabled-opacity); cursor: default; }
|
|
3527
|
+
/* Whole-card activation beside actions: the article keeps its semantics, a transparent button covers it, and only the
|
|
3528
|
+
action controls rise above that button, so the gaps around them still open the card. */
|
|
3529
|
+
.hjm-card[data-activation="overlay"] { position: relative; }
|
|
3530
|
+
.hjm-card__activator { position: absolute; inset: 0; z-index: 0; margin: 0; padding: 0; border: 0; border-radius: inherit; background: transparent; cursor: pointer; }
|
|
3531
|
+
.hjm-card__activator:disabled { cursor: default; }
|
|
3532
|
+
.hjm-card[data-activation="overlay"] > .hjm-card__actions { position: relative; z-index: 1; pointer-events: none; }
|
|
3533
|
+
.hjm-card[data-activation="overlay"] > .hjm-card__actions > * { pointer-events: auto; }
|
|
3534
|
+
/* Press/disabled feedback belongs to the card target (media and body); action controls keep their own states. */
|
|
3535
|
+
.hjm-card[data-activation="overlay"]:has(> .hjm-card__activator:active:not(:disabled)) > :is(.hjm-card__media, .hjm-card__body) { opacity: var(--hjm-card-pressed-opacity); }
|
|
3536
|
+
.hjm-card[data-activation="overlay"]:has(> .hjm-card__activator:disabled) > :is(.hjm-card__media, .hjm-card__body) { opacity: var(--hjm-card-disabled-opacity); }
|
|
3537
|
+
.hjm-card[data-activation="overlay"]:has(> .hjm-card__activator:focus-visible) { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: var(--hjm-focus-offset); }
|
|
3419
3538
|
|
|
3420
3539
|
/* Full destination cards keep all names and widths stable; colors remain product semantic roles. */
|
|
3421
3540
|
.hjm-bottom-navigation[data-selection="tile"] .hjm-bottom-navigation__surface { background: var(--hjm-color-surface-accent); }
|