blob: deb74d0d39c1f5d6b45bf899e6e65f567251d4e5 [file]
import 'package:jaspr/dom.dart';
import 'package:jaspr/jaspr.dart';
import 'package:web/web.dart' as web;
import '../../../utils/provider.dart';
import '../../../utils/styles.dart';
import '../../agent/models/agent_run_state.dart';
import '../../agent/view_models/agent_chat_view_model.dart';
import 'icons.dart';
/// A reusable "Fix with AI" button used in the problems panel and
/// injected into CodeMirror lint tooltips.
///
/// Uses the CSS class `fix-with-ai-btn` which is also applied by
/// `LintTooltipEnhancer` for raw DOM buttons in editor tooltips.
class FixWithAIButton extends StatelessComponent {
const FixWithAIButton({required this.onPressed, this.disabled, super.key});
/// Called when the button is clicked.
final void Function() onPressed;
/// Optional override to manually disable the button.
final bool? disabled;
/// Shared styles for the `fix-with-ai-btn` CSS class.
///
/// These styles are intentionally global (not scoped to a parent selector)
/// so that they also apply to the raw DOM buttons injected by
/// `LintTooltipEnhancer` inside CodeMirror tooltips.
@css
static List<StyleRule> get styles => [
css('.fix-with-ai-btn').styles(
display: .inlineFlex,
padding: .symmetric(vertical: 3.px, horizontal: 8.px),
border: .none,
radius: .circular(4.px),
cursor: .pointer,
transition: .combine([
Transition('background-color', duration: 150.ms, curve: .ease),
Transition('color', duration: 150.ms, curve: .ease),
Transition('opacity', duration: 150.ms, curve: .ease),
]),
alignItems: .center,
gap: Gap.all(4.px),
color: colorPrimary,
fontSize: 11.px,
fontWeight: .w500,
backgroundColor: Colors.transparent,
),
css('.fix-with-ai-btn:not(:disabled):hover').styles(
color: colorOnPrimary,
backgroundColor: colorPrimary,
),
css('.fix-with-ai-btn:disabled').styles(
opacity: .5,
cursor: .notAllowed,
color: colorOnSurfaceVariant,
backgroundColor: Colors.transparent,
),
];
@override
Component build(BuildContext context) {
final viewModel = context.watch<AgentChatViewModel>();
final isRunning = viewModel.runState == AgentRunState.running;
final isDisabled = disabled ?? isRunning;
return button(
classes: 'fix-with-ai-btn',
attributes: {
'title': 'Fix with Agent',
if (isDisabled) 'disabled': '',
},
events: {
'click': (web.Event e) {
e.stopPropagation();
if (!isDisabled) {
onPressed();
}
},
},
[
autoFixHighIcon(),
const .text('Fix with Agent'),
],
);
}
}