Theme Raed uses a structured SCSS architecture with Tailwind’s @apply directive for component styling.
Architecture
The stylesheet architecture follows ITCSS (Inverted Triangle CSS) principles:
01-settings/ → Global variables and configuration
02-generic/ → Reset, common styles, animations
03-elements/ → Base element styling
04-components/ → Component-specific styles
05-utilities/ → Helper classes and fixes
Import structure
// Settings
@import './01-settings/tailwind' ;
@import './01-settings/fonts' ;
@import './01-settings/global' ;
@import './01-settings/breakpoints' ;
// Generic
@import './02-generic/reset' ;
@import './02-generic/common' ;
@import './02-generic/animations' ;
@import './02-generic/rtl' ;
@import './02-generic/ltr' ;
// Elements
@import './03-elements/form' ;
@import './03-elements/buttons' ;
@import './03-elements/radio' ;
// Components
@import './04-components/header' ;
@import './04-components/footer' ;
@import './04-components/product' ;
@import './04-components/slider' ;
// ... more components
// Utilities
@import './05-utilities/chat-bots' ;
@import './05-utilities/swal' ;
@import './05-utilities/safari-fixes' ;
All styles use Tailwind classes via @apply directive to maintain consistency with the design system.
.btn {
@ apply transition duration-300 flex-1 inline-flex justify-center items-center ;
@ apply px-6 pb-2 .5 pt-2 text-sm font-bold rounded-md ;
@ apply hover :opacity - 80 whitespace - nowrap;
}
Primary
Outline
Danger
Icon
.btn--primary {
@ apply text-primary-reverse border border-primary bg-primary ;
}
Usage: < button class = "btn btn--primary" > Submit </ button >
.btn--outline-primary {
@ apply border border-primary text-primary ;
@ apply hover :bg - primary hover:text - primary - reverse;
}
Usage: < button class = "btn btn--outline-primary" > Learn more </ button >
.btn--danger {
@ apply bg-red-400 text-white hover :opacity - 80;
}
Usage: < button class = "btn btn--danger" > Delete </ button >
.btn--icon {
@ apply flex items-center justify-center transition ;
@ apply bg-white text-gray-500 border-gray- 200;
@ apply hover :border - gray - 200 hover:text - gray - 600;
@ apply mx-1 border rounded-full w-10 h- 10;
}
Usage: < button class = "btn--icon" >
< i class = "sicon-heart" ></ i >
</ button >
Loading state
Disabled state
.btn--is-loading {
pointer-events : none ;
.loader {
width : 16 px ;
margin : 0 5 px ;
opacity : 1 ;
transform : scale ( 1 );
}
}
.form-input {
@ apply w-full h-10 transition-colors duration- 300;
@ apply focus :ring - transparent focus:border - primary;
@ apply text-sm border-gray-200 rounded-md ;
appearance : none ;
-webkit-appearance : none ;
}
.form-label {
@ apply block text-sm font-bold text-gray-700 mb-2 .5 ;
@ apply md :mb - 0 sm:mt - px;
}
Validation states
.has-error {
@ apply border-red-400 focus :border - red - 500;
}
Usage: < input class = "form-input has-error" type = "email" >
.has-success {
@ apply border-green-500 focus :border - green - 600;
}
Usage: < input class = "form-input has-success" type = "email" >
Product card patterns
Base product entry
.product-entry {
@ apply h-full transition-shadow duration- 300;
@ apply bg-white hover :shadow - default rounded - lg;
@ apply justify-between flex relative ;
}
Wishlist variant
.product-entry--wishlist {
@ apply justify-between p-4 flex-col sm :flex - row;
.product-entry__image {
@ apply overflow-hidden w-16 h-12 md :w - 20 md:h - 16 rounded - md;
}
}
Product card image zoom
.magnify-wrapper {
.img-magnifier-glass {
@ apply hidden sm : block ;
position : absolute ;
z-index : 3 ;
border-radius : 50 % ;
cursor : none ;
width : 300 px ;
height : 300 px ;
opacity : 0 ;
pointer-events : none ;
transform : scale ( 0 );
transition : transform .5 s ease ;
box-shadow : inset 0 px 0 px 30 px #949494 ;
}
& :hover {
.img-magnifier-glass {
opacity : 1 ;
pointer-events : initial ;
transform : scale ( 1 );
transition-delay : 0.3 s ;
}
}
}
Sticky product bar
Mobile-only sticky add-to-cart bar:
@media ( max-width : 640 px ) {
.is-sticky-product-bar {
& .product-single {
@ apply pb- 28;
}
.sticky-product-bar {
@ apply flex flex-wrap flex-col gap-2 .5 ;
@ apply fixed z- [ 2 ] bottom-0 left-0 p-3 w-full ;
@ apply justify-between items-center ;
@ apply shadow- [ - 1 px _ - 2 px _9 px _0_ rgba (0,0,0,0 .05 )];
@ apply transition duration-700 delay- 500;
@ apply translate-y-100 opacity-0 ease-elastic ;
& __quantity ,
salla-add-product-button {
@ apply translate-y-5 opacity- 0;
@ apply transition duration-700 ease-elastic w-full ;
}
.hydrated & {
& ,
& __quantity ,
salla-add-product-button {
@ apply translate-y-0 opacity- 100;
}
}
}
}
}
.share-btns-list {
@ apply absolute z-10 overflow-hidden opacity-0 top- 12;
@ apply bg-white flex items-center flex-col ;
@ apply shadow-huge rounded- 3 xl ;
a {
@ apply block p-3 hover :text - primary;
}
}
No content placeholder
.no-content-placeholder {
@ apply flex flex-col items-center justify-center ;
@ apply py-12 text-center ;
.icon {
@ apply text-6xl text-gray-300 mb- 4;
}
p {
@ apply text-gray-500 mb- 6;
}
}
Usage:
< div class = "no-content-placeholder" >
< i class = "sicon-shopping-bag icon" ></ i >
< p > {{ trans('pages.cart.empty_cart') }} </ p >
< a href = "/" class = "btn btn--outline-primary btn--rounded-full" >
{{ trans('common.elements.back_home') }}
</ a >
</ div >
RTL/LTR utilities
Direction-specific helpers:
< div class = "rtl:ml-4 ltr:mr-4" >
<!-- Margin-left in RTL, margin-right in LTR -->
</ div >
< div class = "rtl:pl-5 ltr:pr-5" >
<!-- Padding-left in RTL, padding-right in LTR -->
</ div >
Always use rtl: and ltr: prefixes for directional spacing to ensure proper layout in both Arabic and English.
Rounded icon
Circular icon container:
.rounded-icon {
@ apply w-16 h-16 flex justify-center items-center ;
@ apply rounded-full text- 2 xl ;
}
Usage:
< i class = "bg-primary text-white rounded-icon sicon-shipping-fast" ></ i >
Link patterns
.link--primary {
@ apply text-primary hover :text - primary - d transition ;
}
Cart item patterns
.cart-item {
salla-conditional-fields > section {
@ apply px-0 pt-0 last :mb - 0 last:pb - 0;
}
}
Mobile-first approach
All responsive styles use mobile-first breakpoints:
// Base styles (mobile)
.header-search {
@ apply hidden ;
}
// Tablet and up
@media ( min-width : 768 px ) {
.header-search {
@ apply flex- 1;
}
}
CSS custom properties
Use CSS variables for dynamic theming:
:root {
--font-main : 'DINNextLTArabic' ;
--color-primary : {{ theme .color.primary }};
--color-primary-dark : {{ theme .color . darker (0 .15 ) }};
--color-primary-light : {{ theme .color . lighter (0 .15 ) }};
--color-primary-reverse : {{ theme .color.reverse_text }};
}
These are set dynamically in the master layout based on theme settings.