Index: scribus/CMakeLists_Sources.txt
===================================================================
--- scribus/CMakeLists_Sources.txt	(revision 27207)
+++ scribus/CMakeLists_Sources.txt	(working copy)
@@ -567,6 +567,7 @@
 	ui/docks/dock_panelbase.cpp
 	ui/factories/scribusproxystyle.cpp
 	ui/widgets/color_button.cpp
+	ui/widgets/color_slider.cpp
 	ui/widgets/combo_blendmode.cpp
 	ui/widgets/combo_linestyle.cpp
 	ui/widgets/dropdown_button.cpp
Index: scribus/ui/colorpicker/colorpicker_color.cpp
===================================================================
--- scribus/ui/colorpicker/colorpicker_color.cpp	(revision 27207)
+++ scribus/ui/colorpicker/colorpicker_color.cpp	(working copy)
@@ -26,6 +26,9 @@
 
 	languageChange();
 
+	sliderAlpha->setMode(ColorSlider::Opacity);
+	sliderShade->setMode(ColorSlider::Shade);
+
 	connectSlots();
 	connect(sectionSwatches,    &SectionContainer::sizeChanged,				this, &ColorPickerColor::updateSize);
 }
@@ -34,7 +37,9 @@
 {
 	connect(swatches,			&ColorPickerColorSwatches::colorChanged,	this, &ColorPickerColor::updateColorFromSwatches);	
 	connect(numberShade,		&ScrSpinBox::valueChanged,					this, &ColorPickerColor::updateColorShade);
+	connect(sliderShade,		&ColorSlider::valueChanged,					this, &ColorPickerColor::updateColorShade);
 	connect(numberAlpha,		&ScrSpinBox::valueChanged,					this, &ColorPickerColor::updateColorAlpha);
+	connect(sliderAlpha,		&ColorSlider::valueChanged,					this, &ColorPickerColor::updateColorAlpha);
 }
 
 void ColorPickerColor::disconnectSlots()
@@ -41,7 +46,9 @@
 {
 	disconnect(swatches,		&ColorPickerColorSwatches::colorChanged,	this, &ColorPickerColor::updateColorFromSwatches);
 	disconnect(numberShade,		&ScrSpinBox::valueChanged,					this, &ColorPickerColor::updateColorShade);
+	disconnect(sliderShade,		&ColorSlider::valueChanged,					this, &ColorPickerColor::updateColorShade);
 	disconnect(numberAlpha,		&ScrSpinBox::valueChanged,					this, &ColorPickerColor::updateColorAlpha);
+	disconnect(sliderAlpha,		&ColorSlider::valueChanged,					this, &ColorPickerColor::updateColorAlpha);
 }
 
 /* ********************************************************************************* *
@@ -73,8 +80,10 @@
 		sectionSwatches->setVisible(true);
 		numberShade->setVisible(false);
 		labelShade->setVisible(false);
+		sliderShade->setVisible(false);
 		numberAlpha->setVisible(false);
 		labelAlpha->setVisible(false);
+		sliderAlpha->setVisible(false);
 		break;
 	case Context::Text:
 	case Context::TextBackground:
@@ -82,22 +91,28 @@
 		sectionSwatches->setVisible(true);
 		numberShade->setVisible(true);
 		labelShade->setVisible(true);
+		sliderShade->setVisible(true);
 		numberAlpha->setVisible(false);
 		labelAlpha->setVisible(false);
+		sliderAlpha->setVisible(false);
 		break;
 	case Context::Fill:
 		sectionSwatches->setVisible(true);
 		numberShade->setVisible(true);
 		labelShade->setVisible(true);
+		sliderShade->setVisible(true);
 		numberAlpha->setVisible(false);
 		labelAlpha->setVisible(false);
+		sliderAlpha->setVisible(false);
 		break;
 	case Context::Line:
 		sectionSwatches->setVisible(true);
 		numberShade->setVisible(true);
 		labelShade->setVisible(true);
+		sliderShade->setVisible(true);
 		numberAlpha->setVisible(false);
 		labelAlpha->setVisible(false);
+		sliderAlpha->setVisible(false);
 		break;
 	case Context::FillMask:
 	case Context::LineMask:
@@ -104,8 +119,10 @@
 		sectionSwatches->setVisible(false);
 		numberShade->setVisible(false);
 		labelShade->setVisible(false);
+		sliderShade->setVisible(false);
 		numberAlpha->setVisible(true);
 		labelAlpha->setVisible(true);
+		sliderAlpha->setVisible(true);
 		isMask = true;
 		break;
 	case Context::DropShadow:
@@ -112,8 +129,10 @@
 		sectionSwatches->setVisible(true);
 		numberShade->setVisible(true);
 		labelShade->setVisible(true);
+		sliderShade->setVisible(true);
 		numberAlpha->setVisible(false);
 		labelAlpha->setVisible(false);
+		sliderAlpha->setVisible(false);
 		break;
 	}
 
@@ -183,12 +202,19 @@
 void ColorPickerColor::setDoc(ScribusDoc *doc)
 {
 	m_doc = doc;
+	sliderAlpha->setDoc(m_doc);
+	sliderShade->setDoc(m_doc);
 }
 
 void ColorPickerColor::setColorData(const CPColorData& color)
 {
+	if (!m_doc)
+		return;
+
 	m_color = color;
 
+	bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+
 	// update UI + controls
 	QSignalBlocker sigSwatches(swatches);
 	swatches->setCurrentColor(m_color.Name);
@@ -195,12 +221,20 @@
 
 	QSignalBlocker sigShade(numberShade);
 	numberShade->setValue(m_color.Shade);
-	numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+	numberShade->setEnabled(hasColor);
 
 	QSignalBlocker sigAlpha(numberAlpha);
 	numberAlpha->setValue(qRound(100 - (m_color.Opacity * 100)));
-	numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+	numberAlpha->setEnabled(hasColor);
 
+	QSignalBlocker sigAlphaSlider(sliderAlpha);
+	sliderAlpha->setEnabled(hasColor);
+	sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
+	QSignalBlocker sigShadeSlider(sliderShade);
+	sliderShade->setEnabled(hasColor);
+	sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
 }
 
 void ColorPickerColor::languageChange()
@@ -211,14 +245,32 @@
 void ColorPickerColor::updateColorFromSwatches()
 {
 	m_color.Name = swatches->currentColor();
-	numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
-	numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+	bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
 
+	numberShade->setEnabled(hasColor);
+	sliderShade->setEnabled(hasColor);
+	sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+	numberAlpha->setEnabled(hasColor);
+	sliderAlpha->setEnabled(hasColor);
+	sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
 	updateColor();
 }
 
 void ColorPickerColor::updateColorShade()
 {
+	QObject* obj = sender();
+	if( obj == sliderShade )
+	{
+		QSignalBlocker sigBlocker(numberShade);
+		numberShade->setValue(sliderShade->value());
+	}
+	else if( obj == numberShade )
+	{
+		QSignalBlocker sigBlocker(sliderShade);
+		sliderShade->setValue(numberShade->value());
+	}
+
 	m_color.Shade = numberShade->value();
 	updateColor();
 }
@@ -225,6 +277,18 @@
 
 void ColorPickerColor::updateColorAlpha()
 {
+	QObject* obj = sender();
+	if( obj == sliderAlpha )
+	{
+		QSignalBlocker sigBlocker(numberAlpha);
+		numberAlpha->setValue(sliderAlpha->value());
+	}
+	else if( obj == numberAlpha )
+	{
+		QSignalBlocker sigBlocker(sliderAlpha);
+		sliderAlpha->setValue(numberAlpha->value());
+	}
+
 	m_color.Opacity = (100 - numberAlpha->value()) / 100.0;
 	updateColor();
 }
Index: scribus/ui/colorpicker/colorpicker_color.ui
===================================================================
--- scribus/ui/colorpicker/colorpicker_color.ui	(revision 27207)
+++ scribus/ui/colorpicker/colorpicker_color.ui	(working copy)
@@ -59,51 +59,58 @@
        </property>
       </widget>
      </item>
-     <item row="1" column="1">
-      <widget class="QLabel" name="labelAlpha">
-       <property name="text">
-        <string>Opacity:</string>
+     <item row="0" column="2">
+      <widget class="ScrSpinBox" name="numberShade">
+       <property name="suffix">
+        <string> %</string>
        </property>
-       <property name="alignment">
-        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       <property name="maximum">
+        <double>100.000000000000000</double>
        </property>
+       <property name="singleStep">
+        <double>10.000000000000000</double>
+       </property>
       </widget>
      </item>
-     <item row="0" column="1">
+     <item row="0" column="0">
       <widget class="QLabel" name="labelShade">
        <property name="text">
         <string>Shade:</string>
        </property>
        <property name="alignment">
-        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
        </property>
       </widget>
      </item>
-     <item row="0" column="2">
-      <widget class="ScrSpinBox" name="numberShade">
-       <property name="suffix">
-        <string> %</string>
+     <item row="0" column="1">
+      <widget class="ColorSlider" name="sliderShade">
+       <property name="orientation">
+        <enum>Qt::Orientation::Horizontal</enum>
        </property>
-       <property name="maximum">
-        <double>100.000000000000000</double>
+       <property name="tickPosition">
+        <enum>QSlider::TickPosition::TicksAbove</enum>
        </property>
-       <property name="singleStep">
-        <double>10.000000000000000</double>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="labelAlpha">
+       <property name="text">
+        <string>Opacity:</string>
        </property>
+       <property name="alignment">
+        <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
+       </property>
       </widget>
      </item>
-     <item row="1" column="0">
-      <spacer name="horizontalSpacer">
+     <item row="1" column="1">
+      <widget class="ColorSlider" name="sliderAlpha">
        <property name="orientation">
-        <enum>Qt::Horizontal</enum>
+        <enum>Qt::Orientation::Horizontal</enum>
        </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>0</width>
-         <height>0</height>
-        </size>
+       <property name="tickPosition">
+        <enum>QSlider::TickPosition::TicksAbove</enum>
        </property>
-      </spacer>
+      </widget>
      </item>
     </layout>
    </item>
@@ -136,6 +143,11 @@
    <header>ui/colorpicker/colorpicker_color_swatches.h</header>
    <container>1</container>
   </customwidget>
+  <customwidget>
+   <class>ColorSlider</class>
+   <extends>QSlider</extends>
+   <header>ui/widgets/color_slider.h</header>
+  </customwidget>
  </customwidgets>
  <tabstops>
   <tabstop>numberShade</tabstop>
Index: scribus/ui/dasheditor.cpp
===================================================================
--- scribus/ui/dasheditor.cpp	(revision 27207)
+++ scribus/ui/dasheditor.cpp	(working copy)
@@ -55,7 +55,6 @@
  *
  * ********************************************************************************* */
 
-const int RADIUS = 6;
 const double HAIRLINE = 0.001;
 
 DashPreview::DashPreview(QWidget *pa) : QFrame(pa)
Index: scribus/ui/factories/scribusproxystyle.cpp
===================================================================
--- scribus/ui/factories/scribusproxystyle.cpp	(revision 27207)
+++ scribus/ui/factories/scribusproxystyle.cpp	(working copy)
@@ -18,6 +18,8 @@
 
 #include "prefsmanager.h"
 #include "scribus.h"
+#include "ui/widgets/color_slider.h"
+#include "util_gui.h"
 
 // https://doc.qt.io/qt-6/qstyle.html#standardPalette
 QPalette createLightPalette()
@@ -64,6 +66,167 @@
 	return static_cast<ScribusProxyStyle*>(qApp->style());
 }
 
+QRect ScribusProxyStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const
+{
+	QRect rect = QProxyStyle::subControlRect(cc, option, sc, widget);
+
+	switch (cc)
+	{
+	case QStyle::ComplexControl::CC_Slider:
+	{
+		const QStyleOptionSlider *soSlider = qstyleoption_cast<const QStyleOptionSlider *>(option);
+
+		if (soSlider && widget->inherits("ColorSlider") )
+		{
+			QRect ret;
+			bool horizontal = soSlider->orientation == Qt::Horizontal;
+			int thickness = RADIUS * 2;
+			int center = (horizontal) ? (soSlider->rect.height() - thickness) / 2 : (soSlider->rect.width() - thickness) / 2;
+			int sliderOffset = (soSlider->tickPosition != QSlider::NoTicks) ? thickness : center;
+
+			switch (sc)
+			{
+			case SC_SliderHandle:
+			{
+				int len = thickness + 2; //proxy()->pixelMetric(PM_SliderLength, styleOption, widget);
+				int sliderPos = sliderPositionFromValue(soSlider->minimum, soSlider->maximum, soSlider->sliderPosition, (horizontal ? soSlider->rect.width() : soSlider->rect.height()) - len, soSlider->upsideDown);
+
+				if (horizontal)
+					ret.setRect(soSlider->rect.x() + sliderPos, soSlider->rect.y() + sliderOffset, len, thickness);
+				else
+					ret.setRect(soSlider->rect.x() + 1, soSlider->rect.y() + sliderPos, thickness, len);
+
+				break;
+			}
+			case SC_SliderGroove:
+				if (horizontal)
+					ret.setRect(soSlider->rect.x(), soSlider->rect.y() + sliderOffset + 1, soSlider->rect.width(), thickness - 3);
+				else
+					ret.setRect(soSlider->rect.x() + 2, soSlider->rect.y(), thickness - 3, soSlider->rect.height());
+
+				break;
+			case SC_SliderTickmarks:
+			{
+				int tickOffset = (soSlider->tickPosition != QSlider::NoTicks) ? thickness : 0;
+
+				if (soSlider->tickPosition != QSlider::NoTicks)
+				{
+					if (horizontal)
+						ret.setRect(soSlider->rect.x() + 1, soSlider->rect.y(), soSlider->rect.width() - 3, thickness);
+					else
+						ret.setRect(soSlider->rect.x() + tickOffset, soSlider->rect.y() + 1, thickness, soSlider->rect.height() - 3);
+				}
+				break;
+			}
+			default:
+				break;
+			}
+
+			return visualRect(soSlider->direction, soSlider->rect, ret);
+		}
+	}
+	break;
+	default:
+		break;
+	}
+
+	return rect;
+}
+
+void ScribusProxyStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const
+{
+	switch (cc)
+	{
+	case QStyle::ComplexControl::CC_Slider:
+	{
+		const ColorSlider *wdg = qobject_cast<const ColorSlider *>(widget);
+		const QStyleOptionSlider *soSlider = qstyleoption_cast<const QStyleOptionSlider *>(opt);
+
+		if (soSlider && wdg)
+		{
+			painter->save();
+			painter->setRenderHint(QPainter::Antialiasing, true);
+
+			QRect groove = subControlRect(CC_Slider, soSlider, SC_SliderGroove, widget);
+			QRect handle = subControlRect(CC_Slider, soSlider, SC_SliderHandle, widget);
+			QRect tickmarks = subControlRect(CC_Slider, soSlider, SC_SliderTickmarks, widget);
+
+			// Draw Slider
+			if ((soSlider->subControls & SC_SliderGroove) && groove.isValid())
+			{
+				double radius = (soSlider->orientation == Qt::Horizontal) ? groove.height() / 2 + 0.5 : groove.width() / 2 + 0.5;
+
+				QPainterPath border;
+				border.addRoundedRect(groove.toRectF().adjusted(0.5, 0.5, -0.5, -0.5), radius, radius);
+
+				// Draw Slider Gradients
+				painter->setClipPath(border);
+				if (wdg->backgroundImage().isNull() || !widget->isEnabled())
+					painter->fillRect(groove, widget->palette().color(QPalette::Window));
+				else
+				{
+					renderCheckerPattern(painter, groove);
+					painter->drawImage(groove, wdg->backgroundImage());
+				}
+				painter->setClipping(false);
+
+				// Draw Slider Border
+				painter->setPen(widget->palette().color(QPalette::Mid));
+				painter->setBrush(Qt::NoBrush);
+				painter->drawPath(border);
+				painter->setPen(Qt::NoPen);
+			}
+
+			// Draw Handle
+			if ((soSlider->subControls & SC_SliderHandle) && handle.isValid())
+				drawCircularHandle(painter, handle.center() + QPointF(0.5, 0.5), RADIUS * 2, Qt::NoBrush, widget->isEnabled());
+
+			// Draw Tickmarks
+			if ((soSlider->subControls & SC_SliderTickmarks) && tickmarks.isValid() && soSlider->tickInterval > 0)
+			{
+				QFont font = widget->font();
+				font.setPixelSize(8);
+				painter->setFont(font);
+
+				if (soSlider->orientation == Qt::Horizontal)
+				{
+					double ratio = double(tickmarks.width() - (2 * RADIUS)) / double(soSlider->tickInterval);
+
+					for (int x = 0; x <= soSlider->tickInterval; x++)
+					{
+						QRect tick(double(x) * ratio + RADIUS + 1, tickmarks.bottom() - 3, 1, 2);
+						QString label = QString::number((x * soSlider->maximum / soSlider->tickInterval) - abs(soSlider->minimum));
+						int offset = QFontMetrics(painter->font()).size(Qt::TextSingleLine, label).width() / 2;
+
+						painter->setPen(widget->palette().color(QPalette::WindowText));
+						painter->drawText(qBound(0, tick.left() - offset, tickmarks.width()), tickmarks.bottom() - 4, label);
+						painter->fillRect(tick, widget->palette().color(QPalette::WindowText));
+					}
+				}
+				else
+				{
+					double ratio = double(tickmarks.height() - (2 * RADIUS)) / double(soSlider->tickInterval);
+
+					for (int y = 0; y <= soSlider->tickInterval; y++)
+					{
+						QRect tick(tickmarks.left() + 2, double(y) * ratio + RADIUS + 1, 2, 1);
+						painter->fillRect(tick, widget->palette().color(QPalette::WindowText));
+					}
+				}
+			}
+
+			painter->restore();
+			return;
+		}
+	}
+		break;
+	default:
+		break;
+	}
+
+	QProxyStyle::drawComplexControl(cc, opt, painter, widget);
+}
+
 bool ScribusProxyStyle::eventFilter(QObject *object, QEvent *event)
 {
 	if (object == qApp && event->type() == QEvent::ThemeChange)
Index: scribus/ui/factories/scribusproxystyle.h
===================================================================
--- scribus/ui/factories/scribusproxystyle.h	(revision 27207)
+++ scribus/ui/factories/scribusproxystyle.h	(working copy)
@@ -20,6 +20,9 @@
 
 	static ScribusProxyStyle* instance();
 
+	QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget = nullptr) const override;
+	void drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const override;
+
 protected:
 	bool eventFilter(QObject *object, QEvent *event) override;
 
Index: scribus/ui/gradientpreview.cpp
===================================================================
--- scribus/ui/gradientpreview.cpp	(revision 27207)
+++ scribus/ui/gradientpreview.cpp	(working copy)
@@ -29,7 +29,6 @@
 #include "gradientpreview.h"
 #include "util_gui.h"
 
-const int RADIUS = 6;
 const int GRADIENT_HEIGHT = 20;
 
 /* ********************************************************************************* *
Index: scribus/ui/widgets/color_slider.cpp
===================================================================
--- scribus/ui/widgets/color_slider.cpp	(revision 27207)
+++ scribus/ui/widgets/color_slider.cpp	(working copy)
@@ -18,8 +18,6 @@
  *
  * ********************************************************************************* */
 
-const int RADIUS = 6;
-
 ColorSlider::ColorSlider(QWidget *parent): ColorSlider(Mode::RGBRed, parent) {}
 
 ColorSlider::ColorSlider(Mode mode, QWidget *parent): QSlider(parent)
@@ -553,7 +551,7 @@
 	QSignalBlocker blocker(this);
 
 	double v1, v2, v3, v4;
-	int multplier = 1;
+	// int multplier = 1;
 
 	switch (m_mode)
 	{
Index: scribus/ui/widgets/color_slider.h
===================================================================
--- scribus/ui/widgets/color_slider.h	(revision 27207)
+++ scribus/ui/widgets/color_slider.h	(working copy)
@@ -55,11 +55,12 @@
 	ColorSlider(QWidget* parent = nullptr);
 	ColorSlider(Mode mode, QWidget* parent = nullptr);
 
-	const ScColor& color() const{ return m_color; }
+	const ScColor& color() const { return m_color; }
 	double opacity() const { return m_opacity; } // 0.0 - 100.0
 	double shade() const { return m_shade; } // 0.0 - 100.0
 	Mode mode() const { return m_mode; }
 	bool isDynamic() const { return m_dynamicColor; }
+	const QImage& backgroundImage() const { return m_background; }
 
 public slots:
 	void setDoc(ScribusDoc *doc);
Index: scribus/util_gui.h
===================================================================
--- scribus/util_gui.h	(revision 27207)
+++ scribus/util_gui.h	(working copy)
@@ -9,6 +9,8 @@
 class VColorStop;
 class ScPattern;
 
+const int RADIUS = 6;
+
 void SCRIBUS_API drawCircularHandle(QPainter * painter, QPointF center, qreal width, QBrush background, bool isEnabled = true);
 void SCRIBUS_API drawPointerHandle(QPainter * painter, QPointF pointer, qreal width, QColor background, bool isEnabled = true, bool isEmpty = false);
 void SCRIBUS_API renderCheckerPattern(QPainter *painter, QRectF rect);
