Skip to content

Commit b58ed97

Browse files
authored
Add data-separator "focus" state (#706)
1 parent f4e5e08 commit b58ed97

12 files changed

Lines changed: 43 additions & 10 deletions

File tree

integrations/tests/src/components/Separator.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function Separator({
1919
"min-h-2 min-w-2 shrink-0 rounded rounded-xs overflow-hidden",
2020
"bg-slate-600 [&[data-separator='hover']]:bg-slate-500 [&[data-separator='active']]:bg-slate-300",
2121
"text-slate-900 [&[data-separator='hover']]:text-slate-950 [&[data-separator='active']]:text-slate-950",
22-
"focus:outline-none",
22+
"[&[data-separator='hover']]:outline-none",
2323
className
2424
)}
2525
{...rest}

integrations/tests/tests/keyboard-interactions.spec.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,12 @@ test.describe("keyboard interactions: window splitter api", () => {
8484

8585
const separator = page.getByRole("separator");
8686

87+
await expect(separator).toHaveAttribute("data-separator", "inactive");
88+
8789
await separator.focus();
90+
91+
await expect(separator).toHaveAttribute("data-separator", "focus");
92+
8893
await page.keyboard.press("ArrowDown");
8994

9095
await assertLayoutChangeCounts(mainPage, 2);

integrations/tests/tests/pointer-interactions.spec.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,10 @@ test.describe("pointer interactions", () => {
592592
await expect(separator).toHaveAttribute("data-separator", "active");
593593

594594
await page.mouse.up();
595+
await expect(separator).toHaveAttribute("data-separator", "focus");
596+
597+
await page.mouse.move(0, 0);
598+
await page.mouse.down();
595599
await expect(separator).toHaveAttribute("data-separator", "inactive");
596600
});
597601

integrations/tests/tests/stacking-order.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,9 @@ test.describe("stacking order", () => {
120120

121121
// Releasing the cursor under the overlaid element should do two things:
122122
// It should deactivate the separator
123-
// It should transition to an "inactive" state because it's now blocked
123+
// It should update the data state
124124
await page.mouse.up();
125-
await expect(separator).toHaveAttribute("data-separator", "inactive");
125+
await expect(separator).not.toHaveAttribute("data-separator", "active");
126126
await assertLayoutChangeCounts(mainPage, 3, 2);
127127

128128
// No-op

lib/components/separator/Separator.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export function Separator({
5454

5555
const [dragState, setDragState] =
5656
useState<InteractionState["state"]>("inactive");
57+
const [isFocused, setIsFocused] = useState(false);
5758

5859
const elementRef = useRef<HTMLDivElement | null>(null);
5960

@@ -137,6 +138,25 @@ export function Separator({
137138
cursor = "not-allowed";
138139
}
139140

141+
let dataSeparator = undefined;
142+
if (disabled) {
143+
dataSeparator = "disabled";
144+
} else {
145+
switch (dragState) {
146+
case "active": {
147+
dataSeparator = "active";
148+
break;
149+
}
150+
default: {
151+
if (isFocused) {
152+
dataSeparator = "focus";
153+
} else {
154+
dataSeparator = dragState;
155+
}
156+
}
157+
}
158+
}
159+
140160
return (
141161
<div
142162
{...rest}
@@ -148,9 +168,11 @@ export function Separator({
148168
aria-valuenow={aria.valueNow}
149169
children={children}
150170
className={className}
151-
data-separator={disabled ? "disabled" : dragState}
171+
data-separator={dataSeparator}
152172
data-testid={id}
153173
id={id}
174+
onBlur={() => setIsFocused(false)}
175+
onFocus={() => setIsFocused(true)}
154176
ref={mergedRef}
155177
role="separator"
156178
style={{
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"html": "<div><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">Separator</span><span class=\"\"></span></div>\n<div><span class=\"\"> </span><span class=\"tok-propertyName\">className</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"</span></div>\n<div><span class=\"tok-string\"> bg-slate-600</span></div>\n<div><span class=\"tok-string\"> [&#38;[data-separator='hover']]:bg-slate-500</span></div>\n<div><span class=\"tok-string\"> [&#38;[data-separator='active']]:bg-slate-400</span></div>\n<div><span class=\"tok-string\"> \"</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">/&#62;</span></div>"
2+
"html": "<div><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">Separator</span><span class=\"\"></span></div>\n<div><span class=\"\"> </span><span class=\"tok-propertyName\">className</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"</span></div>\n<div><span class=\"tok-string\"> bg-slate-600</span></div>\n<div><span class=\"tok-string\"> [&#38;[data-separator='hover']]:bg-slate-500</span></div>\n<div><span class=\"tok-string\"> [&#38;[data-separator='active']]:bg-slate-400</span></div>\n<div><span class=\"tok-string\"> [&#38;[data-separator='focus']]:bg-sky-400</span></div>\n<div><span class=\"tok-string\"> \"</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">/&#62;</span></div>"
33
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"html": "<div><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"disabled\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"inactive\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"hover\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"active\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span></div>"
2+
"html": "<div><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"disabled\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"inactive\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"hover\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"active\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span><span class=\"\"></span></div>\n<div><span class=\"\"></span><span class=\"tok-punctuation\">&#60;</span><span class=\"tok-typeName\">div</span><span class=\"\"> </span><span class=\"tok-propertyName\">data-separator</span><span class=\"tok-operator\">=</span><span class=\"tok-string\">\"focus\"</span><span class=\"\"> </span><span class=\"tok-punctuation\">/&#62;</span></div>"
33
}

public/generated/search-index.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,8 @@
288288
"n": 1
289289
},
290290
"2": {
291-
"v": " Examples Custom CSS styles className and style props can be used to customize styles, but there are a few limitations to remember: Certain style properties cannot be overridden; (refer to component documentation for a list of specific styles) Panel styles are applied to a nested HTMLDivElement to prevent interfering with the Flex layout When styling a Separator, use the data-separator attribute rather than :hover or :active pseudo-classes. This attribute is updated when the pointer is near enough to a separator element to be interactive, even if it is not directly on top of the element. < div data-separator = \"disabled\" /> \n < div data-separator = \"inactive\" /> \n < div data-separator = \"hover\" /> \n < div data-separator = \"active\" /> An example using Tailwind CSS might look something like this. < Separator \n className = \" \n bg-slate-600 \n [&[data-separator='hover']]:bg-slate-500 \n [&[data-separator='active']]:bg-slate-400 \n \" \n /> ",
292-
"n": 0.082
291+
"v": " Examples Custom CSS styles className and style props can be used to customize styles, but there are a few limitations to remember: Certain style properties cannot be overridden; (refer to component documentation for a list of specific styles) Panel styles are applied to a nested HTMLDivElement to prevent interfering with the Flex layout When styling a Separator, use the data-separator attribute rather than :hover or :active pseudo-classes. This attribute is updated when the pointer is near enough to a separator element to be interactive, even if it is not directly on top of the element. < div data-separator = \"disabled\" /> \n < div data-separator = \"inactive\" /> \n < div data-separator = \"hover\" /> \n < div data-separator = \"active\" /> \n < div data-separator = \"focus\" /> An example using Tailwind CSS might look something like this. < Separator \n className = \" \n bg-slate-600 \n [&[data-separator='hover']]:bg-slate-500 \n [&[data-separator='active']]:bg-slate-400 \n [&[data-separator='focus']]:bg-sky-400 \n \" \n /> ",
292+
"n": 0.08
293293
}
294294
}
295295
},

public/generated/search-records.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
{
9191
"path": "/examples/custom-css-styles",
9292
"section": "Examples",
93-
"text": " Examples Custom CSS styles className and style props can be used to customize styles, but there are a few limitations to remember: Certain style properties cannot be overridden; (refer to component documentation for a list of specific styles) Panel styles are applied to a nested HTMLDivElement to prevent interfering with the Flex layout When styling a Separator, use the data-separator attribute rather than :hover or :active pseudo-classes. This attribute is updated when the pointer is near enough to a separator element to be interactive, even if it is not directly on top of the element. < div data-separator = \"disabled\" /> \n < div data-separator = \"inactive\" /> \n < div data-separator = \"hover\" /> \n < div data-separator = \"active\" /> An example using Tailwind CSS might look something like this. < Separator \n className = \" \n bg-slate-600 \n [&[data-separator='hover']]:bg-slate-500 \n [&[data-separator='active']]:bg-slate-400 \n \" \n /> ",
93+
"text": " Examples Custom CSS styles className and style props can be used to customize styles, but there are a few limitations to remember: Certain style properties cannot be overridden; (refer to component documentation for a list of specific styles) Panel styles are applied to a nested HTMLDivElement to prevent interfering with the Flex layout When styling a Separator, use the data-separator attribute rather than :hover or :active pseudo-classes. This attribute is updated when the pointer is near enough to a separator element to be interactive, even if it is not directly on top of the element. < div data-separator = \"disabled\" /> \n < div data-separator = \"inactive\" /> \n < div data-separator = \"hover\" /> \n < div data-separator = \"active\" /> \n < div data-separator = \"focus\" /> An example using Tailwind CSS might look something like this. < Separator \n className = \" \n bg-slate-600 \n [&[data-separator='hover']]:bg-slate-500 \n [&[data-separator='active']]:bg-slate-400 \n [&[data-separator='focus']]:bg-sky-400 \n \" \n /> ",
9494
"title": "Custom CSS styles"
9595
},
9696
{

src/components/styled-panels/Separator.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function Separator({
2222
"rounded rounded-xs flex items-center justify-center",
2323
"bg-slate-600 [&[data-separator='disabled']]:opacity-50 [&[data-separator='hover']]:bg-slate-500 [&[data-separator='active']]:bg-slate-400",
2424
"text-slate-900 [&[data-separator='hover']]:text-slate-950 [&[data-separator='active']]:text-slate-950",
25-
"focus:bg-slate-400",
25+
"[&[data-separator='focus']]:bg-sky-400",
2626
orientation === "horizontal" ? "w-4 sm:w-2" : "h-4 sm:h-2",
2727
className
2828
)}

0 commit comments

Comments
 (0)