Intersections
useVueFlow exposes helpers to check whether nodes intersect with other nodes or with an area. Drag a node here to see it highlight when it overlaps another.
/* xyflow theme files. Delete these to start from our base */
/*
* `@xyflow/vue`'s `colorMode` sets `color-scheme` (light/dark/system) rather than toggling a `.dark`
* class, so these tokens use CSS `light-dark(<light>, <dark>)` to follow the resolved scheme instead of a
* `.vue-flow.dark` selector. Single values are scheme-independent.
*/
.vue-flow {
--xy-background-color: light-dark(#f7f9fb, #101012);
/* Custom Variables */
--xy-theme-selected: #16a34a;
--xy-theme-hover: light-dark(#c5c5c5, #7a7d86);
--xy-theme-edge-hover: light-dark(black, #f3f4f6);
--xy-theme-color-focus: light-dark(#e8e8e8, #4b4e57);
/* Built-in Variables see https://vueflow.dev/learn/customization/theming */
/* light-dark() is a <color> function — it must wrap only the color, not the whole border shorthand */
--xy-node-border-default: 1px solid light-dark(#ededed, #303238);
/* light-dark() can't split a comma-separated shadow list (wrapping each in a var() doesn't help — the
commas re-expand before light-dark parses its args), so the dark shadow is applied via the
prefers-color-scheme media query below, which matches `color-scheme: system` (the common case) */
--xy-node-boxshadow-default:
0px 3.54px 4.55px 0px #00000005, 0px 3.54px 4.55px 0px #0000000d,
0px 0.51px 1.01px 0px #0000001a;
--xy-node-border-radius-default: 8px;
--xy-handle-background-color-default: light-dark(#ffffff, #141519);
--xy-handle-border-color-default: light-dark(#aaaaaa, #5a5d66);
--xy-edge-label-color-default: light-dark(#505050, #e6e7ea);
--xy-node-background-color-default: light-dark(#ffffff, #1a1b1e);
--xy-theme-panel-bg: light-dark(#ffffff, #141519);
--xy-theme-panel-text: light-dark(#111827, #f3f4f6);
--xy-theme-resize-handle-bg: light-dark(#ffffff, #141519);
--xy-theme-focus-border: light-dark(#d9d9d9, #5f6470);
--xy-theme-muted-bg: light-dark(#f3f4f6, #24262c);
--xy-theme-subtle-border: light-dark(#d1d5db, #3f434c);
/* example UI tokens (consumed by the .xy-theme__* helpers below) */
--color-primary: #16a34a;
--color-background: light-dark(#fefefe, #1a1b1e);
--color-hover-bg: light-dark(#f6f6f6, #24262c);
--color-disabled: light-dark(#76797e, #8b9099);
}
.vue-flow {
background-color: var(--xy-background-color);
}
/* dark node shadow — the one token light-dark() can't express (see above) */
@media (prefers-color-scheme: dark) {
.vue-flow {
--xy-node-boxshadow-default:
0px 6px 18px 0px rgba(0, 0, 0, 0.35), 0px 2px 6px 0px rgba(0, 0, 0, 0.3),
0px 1px 2px 0px rgba(0, 0, 0, 0.35);
}
}
/* Customizing Default Theming */
.vue-flow__node {
box-shadow: var(--xy-node-boxshadow-default);
border-radius: var(--xy-node-border-radius-default);
background-color: var(--xy-node-background-color-default);
display: flex;
justify-content: center;
align-items: center;
text-align: center;
padding: 10px;
font-size: 12px;
flex-direction: column;
border: var(--xy-node-border-default);
color: var(--xy-node-color, var(--xy-node-color-default));
}
.vue-flow__node.selectable:focus {
box-shadow: 0px 0px 0px 4px var(--xy-theme-color-focus);
border-color: var(--xy-theme-focus-border);
}
.vue-flow__node.selectable:focus:active {
box-shadow: var(--xy-node-boxshadow-default);
}
.vue-flow__node.selectable:hover,
.vue-flow__node.draggable:hover {
border-color: var(--xy-theme-hover);
}
.vue-flow__node.selectable.selected {
border-color: var(--xy-theme-selected);
box-shadow: var(--xy-node-boxshadow-default);
}
.vue-flow__node-group {
background-color: light-dark(rgba(207, 182, 255, 0.4), rgba(123, 107, 148, 0.22));
border-color: light-dark(#9e86ed, #7b6b94);
}
.vue-flow__edge.selectable:hover .vue-flow__edge-path,
.vue-flow__edge.selectable.selected .vue-flow__edge-path {
stroke: var(--xy-theme-edge-hover);
}
.vue-flow__handle {
background-color: var(--xy-handle-background-color-default);
}
.vue-flow__handle.connectionindicator:hover {
pointer-events: all;
border-color: var(--xy-theme-edge-hover);
background-color: var(--xy-handle-background-color-default);
}
.vue-flow__handle.connectionindicator:focus,
.vue-flow__handle.connectingfrom,
.vue-flow__handle.connectingto {
border-color: var(--xy-theme-edge-hover);
}
.vue-flow__node-resizer {
border-radius: 0;
border: none;
}
.vue-flow__resize-control.handle {
background-color: var(--xy-theme-resize-handle-bg);
border-color: #9e86ed;
border-radius: 0;
width: 5px;
height: 5px;
}
/*
Custom Example CSS - This CSS is to improve the example experience.
You can remove it if you want to use the default styles.
New Theme Classes:
.xy-theme__button - Styles for buttons.
.xy-theme__input - Styles for text inputs.
.xy-theme__checkbox - Styles for checkboxes.
.xy-theme__select - Styles for dropdown selects.
.xy-theme__label - Styles for labels.
Use these classes to apply consistent theming across your components.
*/
.xy-theme__button-group {
display: flex;
align-items: center;
.xy-theme__button:first-child {
border-radius: 100px 0 0 100px;
}
.xy-theme__button:last-child {
border-radius: 0 100px 100px 0;
margin: 0;
}
}
/* Custom Button Styling */
.xy-theme__button {
display: inline-flex;
align-items: center;
justify-content: center;
height: 2.5rem;
padding: 0 1rem;
border-radius: 100px;
border: 1px solid var(--color-primary);
background-color: var(--color-background);
color: var(--color-primary);
transition:
background-color 0.2s ease,
border-color 0.2s ease;
box-shadow: var(--xy-node-boxshadow-default);
cursor: pointer;
}
.xy-theme__button.active {
background-color: var(--color-primary);
color: white;
border-color: var(--color-primary);
}
.xy-theme__button.active:hover,
.xy-theme__button.active:active {
background-color: var(--color-primary);
opacity: 0.9;
}
.xy-theme__button:hover {
background-color: var(--xy-controls-button-background-color-hover-default);
}
.xy-theme__button:active {
background-color: var(--color-hover-bg);
}
.xy-theme__button:disabled {
color: var(--color-disabled);
opacity: 0.8;
cursor: not-allowed;
border: 1px solid var(--color-disabled);
}
.xy-theme__button > span {
margin-right: 0.2rem;
}
/* Add gap between adjacent buttons */
.xy-theme__button + .xy-theme__button {
margin-left: 0.3rem;
}
/* Example Input Styling */
.xy-theme__input {
padding: 0.5rem 0.75rem;
border: 1px solid var(--color-primary);
border-radius: 7px;
background-color: var(--color-background);
transition:
background-color 0.2s ease,
border-color 0.2s ease;
font-size: 1rem;
color: var(--xy-theme-panel-text);
}
.xy-theme__input:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 2px rgba(22, 163, 74, 0.3);
}
/* Specific Checkbox Styling */
.xy-theme__checkbox {
appearance: none;
-webkit-appearance: none;
width: 1.25rem;
height: 1.25rem;
border-radius: 7px;
border: 2px solid var(--color-primary);
background-color: var(--color-background);
transition:
background-color 0.2s ease,
border-color 0.2s ease;
cursor: pointer;
display: inline-block;
vertical-align: middle;
margin-right: 0.5rem;
}
.xy-theme__checkbox:checked {
background-color: var(--color-primary);
border-color: var(--color-primary);
}
.xy-theme__checkbox:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(22, 163, 74, 0.3);
}
/* Dropdown Styling */
.xy-theme__select {
padding: 0.5rem 0.75rem;
border: 1px solid var(--color-primary);
border-radius: 50px;
background-color: var(--color-background);
transition:
background-color 0.2s ease,
border-color 0.2s ease;
font-size: 1rem;
color: var(--xy-theme-panel-text);
margin-right: 0.5rem;
box-shadow: var(--xy-node-boxshadow-default);
}
.xy-theme__select:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 2px rgba(22, 163, 74, 0.3);
}
.xy-theme__label {
margin-top: 10px;
margin-bottom: 3px;
display: inline-block;
color: var(--xy-theme-panel-text);
}Last updated on