Skip to content

Commit bb4e89c

Browse files
talissoncostaclaude
andcommitted
fix(a11y): size and centre the field label info icon
The design puts the info icon at 20x20 beside the label; ours asked for 12, and since info-outlined draws its circle across 20 of a 24 viewBox that rendered a 10px target. It is 16 now. It also sat 2px above the text. .control-label is display: block, so the tooltip's inline-flex wrapper took part in inline layout, and an inline-flex box whose only child is a replaced element baselines on its bottom margin edge rather than its content. The svg { vertical-align: bottom } rule alongside it cannot correct that: vertical-align is ignored on flex items. Laying the label out as a centred flex row puts the icon dead on the text centre. vertical-align: middle was the other candidate and overshoots by 1.3px, aligning to half the x-height rather than the cap centre. That goes on FieldLabel's own element, not on .control-label. Nine hand-written labels across six other files carry that class, none of them with an icon to align, so they keep display: block and this touches only what FieldLabel renders. The stylesheet is unchanged. Checked against block: the label keeps its full width, and a long label still wraps to the same height. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent a7d2438 commit bb4e89c

5 files changed

Lines changed: 6 additions & 25 deletions

File tree

frontend/.storybook/preview.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ window.Row = Row
6161
window.FormGroup = FormGroup
6262
// isMobile is set at app boot; stub it so components that read it render in Storybook.
6363
window.isMobile = false
64-
// toast() is registered at app boot by project-components.js. Stub it so
65-
// components that fire one on interaction (ValueEditor's copy) don't throw.
6664
window.toast = (message) => console.log('[toast]', message)
6765

6866
/** @type { import('storybook').Preview } */

frontend/documentation/components/ValueEditor.stories.tsx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ export default meta
1313

1414
type Story = StoryObj
1515

16-
// The real call sites always pass a tooltip, so the stories do too: without
17-
// one the label renders without the info icon the design shows.
1816
const DEFAULT_TOOLTIP = Constants.strings.REMOTE_CONFIG_DESCRIPTION
1917

2018
const Interactive = ({
@@ -32,9 +30,6 @@ const Interactive = ({
3230
)
3331
}
3432

35-
// Empty state. The "Enter a value..." text is not a real ::placeholder — it is
36-
// rendered into the contenteditable and styled by `code.txt.empty`, which reads
37-
// --color-text-tertiary, the same token every ::placeholder uses.
3833
export const Default: Story = {
3934
render: () => <Interactive label='Value' />,
4035
}
@@ -43,8 +38,6 @@ export const WithValue: Story = {
4338
render: () => <Interactive label='Value' initialValue='DEFAULT_VALUE' />,
4439
}
4540

46-
// Copy is pinned to the first line rather than centred, so it stays put as the
47-
// editor grows, and the value keeps clear of it.
4841
export const Multiline: Story = {
4942
render: () => (
5043
<Interactive
@@ -66,14 +59,12 @@ export const Json: Story = {
6659
),
6760
}
6861

69-
// Invalid JSON surfaces a warning against the active language label.
7062
export const InvalidJson: Story = {
7163
render: () => (
7264
<Interactive label='Value' language='json' initialValue='{ "colour": ' />
7365
),
7466
}
7567

76-
// The size used for multivariate variation values, matching adjacent inputs.
7768
export const CodeMedium: Story = {
7869
render: () => (
7970
<Interactive
@@ -85,15 +76,12 @@ export const CodeMedium: Story = {
8576
),
8677
}
8778

88-
// Read-only display (MV control/override values). The language row and copy are
89-
// both hidden, which is existing behaviour rather than a decision.
9079
export const Disabled: Story = {
9180
render: () => (
9281
<Interactive label='Control value' disabled initialValue='DEFAULT_VALUE' />
9382
),
9483
}
9584

96-
// The SAML metadata field pins the language and hides the whole row.
9785
export const OnlyOneLang: Story = {
9886
render: () => (
9987
<Interactive

frontend/web/components/ValueEditor.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ class Validation extends Component {
9191
render() {
9292
const displayLanguage =
9393
this.props.language === 'ini' ? 'toml' : this.props.language
94-
// Icon forwards className for only a handful of its cases, so the colour
95-
// class goes on a wrapper and the icon inherits through currentColor.
96-
// saveFeatureWithValidation reads the error id off the DOM to decide
97-
// whether to warn before saving, so both ids stay.
9894
return this.state.error ? (
9995
<Tooltip
10096
title={
@@ -154,8 +150,6 @@ class ValueEditor extends Component {
154150

155151
render() {
156152
const { ...rest } = this.props
157-
// Copy used to be the last item of the language row, so hiding that row
158-
// hid copy too. It now lives inside the editor, so repeat the conditions.
159153
const showCopy = !this.props.onlyOneLang && !this.props.disabled
160154
return (
161155
<div

frontend/web/components/base/forms/FieldLabel.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ const FieldLabel: FC<FieldLabelProps> = ({
2727
tooltip,
2828
tooltipPlace = 'top',
2929
}) => (
30-
<label id={id} htmlFor={htmlFor} className={cn('control-label', className)}>
30+
<label
31+
id={id}
32+
htmlFor={htmlFor}
33+
className={cn('control-label d-flex align-items-center', className)}
34+
>
3135
{children}
3236
{required && (
3337
<span className='text-danger ml-1' aria-hidden>
@@ -36,7 +40,7 @@ const FieldLabel: FC<FieldLabelProps> = ({
3640
)}
3741
{tooltip && (
3842
<Tooltip
39-
title={<Icon name='info-outlined' width={12} height={12} />}
43+
title={<Icon name='info-outlined' width={16} height={16} />}
4044
place={tooltipPlace}
4145
titleClassName='cursor-pointer ml-1 d-inline-flex align-items-center'
4246
>

frontend/web/styles/3rdParty/_hljs.scss

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@
4848
}
4949
}
5050

51-
// Copy sits inside the editor, pinned to the first line rather than centred:
52-
// the editor grows with multi-line values.
5351
.value-editor__copy {
5452
position: absolute;
5553
top: 18px;
@@ -63,7 +61,6 @@
6361
}
6462
}
6563

66-
// Keep long values clear of the copy button.
6764
&:has(.value-editor__copy) .hljs {
6865
padding-right: 44px;
6966
}

0 commit comments

Comments
 (0)