Located in register_controls() under TAB_CONTENT
Item 1: Widget Header (Text + Alignment)
Item 2: Default Rate Selection (Market vs. Fixed)
Item 3: Default Coins (Input for “From” and “To”)
Item 4: Branding/Referral URL (Link control)
Item 5: API Key (Existing)
Located in register_controls() under TAB_STYLE
Item 6: Container Controls (Background Color, Max-Width, Border Radius)
Item 7: Typography (Title Font, Size, Color)
Item 8: Button Accents (Active Gradient colors, Inactive Backgrounds)
Located in render()
Item 9: Update HTML to display Sidebar Text/Links.
Item 10: Inject CSS classes based on Sidebar choices.
Located in your JS file/section
Item 11: Set JS variables based on Elementor Sidebar settings.
To begin, we are going to add the first control to your sidebar so you can rename or align that “KoinTool Swap” title.
Look for the function named: protected function register_controls() {
Place this right at the beginning of that function. This creates the “Widget Header” section in your Elementor sidebar.
// --- SECTION 1: WIDGET HEADER ---
$this->start_controls_section(
'section_header_settings',
[
'label' => esc_html__( 'Widget Header', 'kointool' ),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'title_text',
[
'label' => esc_html__( 'Title', 'kointool' ),
'type' => \Elementor\Controls_Manager::TEXT,
'default' => esc_html__( 'KoinTool Swap', 'kointool' ),
'placeholder' => esc_html__( 'Enter your title here', 'kointool' ),
]
);
$this->add_control(
'title_alignment',
[
'label' => esc_html__( 'Alignment', 'kointool' ),
'type' => \Elementor\Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'kointool' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'kointool' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'kointool' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'selectors' => [
'{{WRAPPER}} .kts-title' => 'text-align: {{VALUE}};',
],
]
);
$this->end_controls_section();
This step adds the controls to choose which rate type the widget starts on and which coins are pre-selected when the page loads.
Directly after the end_controls_section() from Step 1.
This creates the “Swap Settings” section in your Elementor sidebar.
// --- SECTION 2: SWAP SETTINGS ---
$this->start_controls_section(
'section_swap_settings',
[
'label' => esc_html__( 'Swap Settings', 'kointool' ),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'default_rate_type',
[
'label' => esc_html__( 'Default Rate Type', 'kointool' ),
'type' => \Elementor\Controls_Manager::SELECT,
'default' => 'standard',
'options' => [
'standard' => esc_html__( 'Exchange now (Market)', 'kointool' ),
'fixed' => esc_html__( 'Fixed Rate', 'kointool' ),
],
]
);
$this->add_control(
'default_from_coin',
[
'label' => esc_html__( 'Default From Coin', 'kointool' ),
'type' => \Elementor\Controls_Manager::TEXT,
'default' => 'btc',
'placeholder' => esc_html__( 'e.g. btc', 'kointool' ),
]
);
$this->add_control(
'default_to_coin',
[
'label' => esc_html__( 'Default To Coin', 'kointool' ),
'type' => \Elementor\Controls_Manager::TEXT,
'default' => 'eth',
'placeholder' => esc_html__( 'e.g. eth', 'kointool' ),
]
);
$this->end_controls_section();
This allows you to change the destination of the “Expected Rate” links so they point back to your site with your referral parameters.
Directly after the end_controls_section() from Step 2.
// --- SECTION 3: BRANDING & LINKS ---
$this->start_controls_section(
'section_branding',
[
'label' => esc_html__( 'Branding & Links', 'kointool' ),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'referral_url',
[
'label' => esc_html__( 'Referral/Info URL', 'kointool' ),
'type' => \Elementor\Controls_Manager::URL,
'placeholder' => esc_html__( 'https://kointool.com', 'kointool' ),
'default' => [
'url' => 'https://kointool.com',
'is_external' => true,
'nofollow' => true,
],
]
);
$this->end_controls_section();
You likely already have this, but to keep the Blueprint complete, ensure your API key control is wrapped in its own section or added to the “Swap Settings.”
// --- SECTION 4: API CONFIGURATION ---
$this->start_controls_section(
'section_api_config',
[
'label' => esc_html__( 'API Settings', 'kointool' ),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'api_key',
[
'label' => esc_html__( 'API Key', 'kointool' ),
'type' => \Elementor\Controls_Manager::TEXT,
'default' => '', // Your default key here
]
);
$this->end_controls_section();
Located in register_controls() under TAB_STYLE
This phase moves the visual heavy lifting into the Elementor Sidebar. Instead of editing your CSS file, you’ll use color pickers and sliders to update your three “Temp Kits.”
This controls the physical box (#kts-vault). It allows you to toggle between your “SwapKit” yellow look and the “KoinTool” blue look by changing the background and width.
Add this right after the last end_controls_section() from Phase 1:
// --- SECTION 5: CONTAINER STYLE ---
$this->start_controls_section(
'section_container_style',
[
'label' => esc_html__( 'Container', 'kointool' ),
'tab' => \Elementor\Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'vault_bg_color',
[
'label' => esc_html__( 'Background Color', 'kointool' ),
'type' => \Elementor\Controls_Manager::COLOR,
'default' => '#121214',
'selectors' => [
'{{WRAPPER}} #kts-vault' => 'background-color: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'vault_max_width',
[
'label' => esc_html__( 'Max Width (px)', 'kointool' ),
'type' => \Elementor\Controls_Manager::SLIDER,
'size_units' => [ 'px' ],
'range' => [
'px' => [ 'min' => 300, 'max' => 800 ],
],
'default' => [ 'unit' => 'px', 'size' => 500 ],
'selectors' => [
'{{WRAPPER}} #kts-vault' => 'max-width: {{SIZE}}{{UNIT}};',
],
]
);
$this->add_control(
'vault_border_radius',
[
'label' => esc_html__( 'Border Radius', 'kointool' ),
'type' => \Elementor\Controls_Manager::SLIDER,
'size_units' => [ 'px' ],
'default' => [ 'unit' => 'px', 'size' => 24 ],
'selectors' => [
'{{WRAPPER}} #kts-vault' => 'border-radius: {{SIZE}}{{UNIT}};',
],
]
);
$this->end_controls_section();
This links your theme’s fonts to the widget and fixes the “Title Alignment” and “Font Size” issues.
Add this after Step 5:
// --- SECTION 6: TYPOGRAPHY ---
$this->start_controls_section(
'section_typography_style',
[
'label' => esc_html__( 'Typography', 'kointool' ),
'tab' => \Elementor\Controls_Manager::TAB_STYLE,
]
);
$this->add_group_control(
\Elementor\Group_Control_Typography::get_type(),
[
'name' => 'title_typography',
'label' => esc_html__( 'Title Font', 'kointool' ),
'selector' => '{{WRAPPER}} .kts-title',
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Title Color', 'kointool' ),
'type' => \Elementor\Controls_Manager::COLOR,
'default' => '#fff',
'selectors' => [
'{{WRAPPER}} .kts-title' => 'color: {{VALUE}};',
],
]
);
$this->end_controls_section();
This is the “Magic” section. It replaces our hardcoded purple gradient with a dynamic one, allowing you to create the “Yellow/Black” kit or the “Blue/Dark” kit instantly.
Add this after Step 6:
// --- SECTION 7: BUTTONS & TOGGLES ---
$this->start_controls_section(
'section_button_style',
[
'label' => esc_html__( 'Buttons & Accents', 'kointool' ),
'tab' => \Elementor\Controls_Manager::TAB_STYLE,
]
);
$this->add_group_control(
\Elementor\Group_Control_Background::get_type(),
[
'name' => 'active_button_bg',
'label' => esc_html__( 'Active Button Gradient', 'kointool' ),
'types' => [ 'classic', 'gradient' ],
'selector' => '{{WRAPPER}} .kts-rate-btn.active, {{WRAPPER}} .kts-main-btn',
]
);
$this->add_control(
'inactive_button_color',
[
'label' => esc_html__( 'Inactive Button BG', 'kointool' ),
'type' => \Elementor\Controls_Manager::COLOR,
'default' => '#1b1b1f',
'selectors' => [
'{{WRAPPER}} .kts-rate-btn' => 'background-color: {{VALUE}};',
],
]
);
$this->end_controls_section();
Located in the render() function at the bottom of your widget file.
This phase is where the “Brain” (Sidebar) actually talks to the “Body” (HTML). We replace your hardcoded strings with PHP variables.
Find your render() function and replace the top section with this:
protected function render() {
$settings = $this->get_settings_for_display();
// 1. Handle the Header Logic
$title = ! empty( $settings['title_text'] ) ? $settings['title_text'] : '';
// 2. Handle the Rate Toggle Logic
$default_rate = $settings['default_rate_type'];
$market_active = ( 'standard' === $default_rate ) ? 'active' : '';
$fixed_active = ( 'fixed' === $default_rate ) ? 'active' : '';
// 3. Handle the Branding Link
$referral_url = ! empty( $settings['referral_url']['url'] ) ? $settings['referral_url']['url'] : 'https://kointool.com';
?>
Find your opening <div id="kts-vault"> in the render() function and replace it with this “Data Attribute” version:
// Step 8.5: Injecting Sidebar Data into HTML Attributes
$default_from = ! empty( $settings['default_from_coin'] ) ? $settings['default_from_coin'] : 'btc';
$default_to = ! empty( $settings['default_to_coin'] ) ? $settings['default_to_coin'] : 'eth';
$api_key = ! empty( $settings['api_key'] ) ? $settings['api_key'] : '';
?>
This goes in your JS file or the script section of your plugin.
The JS needs to know what you picked in Elementor so it can start the API calls correctly (e.g., starting with BTC/ETH or Fixed/Market).
Add these lines to the very top of your Widget Initialization script:
// Step 9: The v2.6 Handshake
const ktsVault = document.getElementById('kts-vault');
const activeBtn = ktsVault.querySelector('.kts-rate-btn.active');
// 1. Set the initial state based on the Elementor Sidebar
let isFixed = activeBtn.getAttribute('data-rate-type') === 'fixed';
// 2. Grab the default coins (We will pass these from PHP in the next step)
let currentFrom = ktsVault.getAttribute('data-default-from') || 'btc';
let currentTo = ktsVault.getAttribute('data-default-to') || 'eth';
Find where you define your from and to variables in your JS and replace them with this:
// Step 9.5: Syncing JS variables with the Sidebar Data Attributes
const vaultContainer = document.getElementById('kts-vault');
// Grab the coins you set in the Elementor Sidebar
let currentFrom = vaultContainer.getAttribute('data-default-from').toLowerCase();
let currentTo = vaultContainer.getAttribute('data-default-to').toLowerCase();
// Grab the API Key you set in the Elementor Sidebar
const apiKey = vaultContainer.getAttribute('data-api-key');