Files
iD/modules/ui/fields/directional_combo.js
Tobias ce51b33cf2 Improve combobox dropdown styling to give labels more room and readability (#10127)
* Fields: Break long lines in combo dropdown instead of ellipsis

Longer translations keys are not readable with ellipsis and the tooltip only shows the description (or fallback), not the title.

This change makes long use line breaks with small line height to make the whole text visible.

* Fields: Use table styles for rows to maximize available space

The flex box solution gave a lot of space to the label. This solution minimizes that space to give more space to the values dropdown.
2024-02-26 14:02:22 +01:00

130 lines
3.8 KiB
JavaScript

import { dispatch as d3_dispatch } from 'd3-dispatch';
import { select as d3_select } from 'd3-selection';
import { utilRebind } from '../../util';
import { uiFieldCombo } from './combo';
export function uiFieldDirectionalCombo(field, context) {
var dispatch = d3_dispatch('change');
var items = d3_select(null);
var wrap = d3_select(null);
var _tags;
var _combos = {};
// fallback for schema-builder v5's cycleway field type: can be removed eventually
if (field.type === 'cycleway') {
field = {
...field,
key: field.keys[0],
keys: field.keys.slice(1)
};
}
function directionalCombo(selection) {
function stripcolon(s) {
return s.replace(':', '');
}
wrap = selection.selectAll('.form-field-input-wrap')
.data([0]);
wrap = wrap.enter()
.append('div')
.attr('class', 'form-field-input-wrap form-field-input-' + field.type)
.merge(wrap);
var div = wrap.selectAll('ul')
.data([0]);
div = div.enter()
.append('ul')
.attr('class', 'rows rows-table')
.merge(div);
items = div.selectAll('li')
.data(field.keys);
var enter = items.enter()
.append('li')
.attr('class', function(d) { return 'labeled-input preset-directionalcombo-' + stripcolon(d); });
enter
.append('div')
.attr('class', 'label preset-label-directionalcombo')
.attr('for', function(d) { return 'preset-input-directionalcombo-' + stripcolon(d); })
.html(function(d) { return field.t.html('types.' + d); });
enter
.append('div')
.attr('class', 'preset-input-directionalcombo-wrap form-field-input-wrap')
.each(function(key) {
const subField = {
...field,
type: 'combo',
key
};
const combo = uiFieldCombo(subField, context);
combo.on('change', t => change(key, t[key]));
_combos[key] = combo;
d3_select(this).call(combo);
});
items = items.merge(enter);
// Update
wrap.selectAll('.preset-input-directionalcombo')
.on('change', change)
.on('blur', change);
}
function change(key, newValue) {
const commonKey = field.key;
const otherKey = key === field.keys[0] ? field.keys[1] : field.keys[0];
dispatch.call('change', this, tags => {
const otherValue = tags[otherKey] || tags[commonKey];
if (newValue === otherValue) {
// both tags match, use the common tag to tag both sides the same way
tags[commonKey] = newValue;
delete tags[key];
delete tags[otherKey];
} else {
// Always set both left and right as changing one can affect the other
tags[key] = newValue;
delete tags[commonKey];
tags[otherKey] = otherValue;
}
return tags;
});
}
directionalCombo.tags = function(tags) {
_tags = tags;
const commonKey = field.key;
for (let key in _combos) {
const uniqueValues = [... new Set([]
.concat(_tags[commonKey])
.concat(_tags[key])
.filter(Boolean))];
_combos[key].tags({ [key]: uniqueValues.length > 1 ? uniqueValues : uniqueValues[0] });
}
};
directionalCombo.focus = function() {
var node = wrap.selectAll('input').node();
if (node) node.focus();
};
return utilRebind(directionalCombo, dispatch, 'on');
}