final website is ready babeeehhhh
This commit is contained in:
+2
-2
@@ -6,10 +6,10 @@
|
|||||||
<meta name="theme-color" content="#f5f3ee" />
|
<meta name="theme-color" content="#f5f3ee" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="Radhe Radhe Synthetics — greige knitted fabrics engineered for diverse apparel applications. Consistency at scale. Continuous development."
|
content="Radhe Radhe Synthetics - greige knitted fabrics engineered for diverse apparel applications. Consistency at scale. Continuous development."
|
||||||
/>
|
/>
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<title>RRS — Radhe Radhe Synthetics</title>
|
<title>RRS - Radhe Radhe Synthetics</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function CapacityValue() {
|
|||||||
<span className="capacity-value" aria-label="60 to 70">
|
<span className="capacity-value" aria-label="60 to 70">
|
||||||
<Reel values={["00", "20", "40", "60"]} direction="up" />
|
<Reel values={["00", "20", "40", "60"]} direction="up" />
|
||||||
<span className="capacity-value__dash" aria-hidden="true">
|
<span className="capacity-value__dash" aria-hidden="true">
|
||||||
–
|
-
|
||||||
</span>
|
</span>
|
||||||
<Reel values={["70", "80", "90", "99"]} direction="down" />
|
<Reel values={["70", "80", "90", "99"]} direction="down" />
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -27,7 +27,8 @@
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
transition: transform 700ms ease;
|
transition: transform 700ms ease;
|
||||||
}
|
}
|
||||||
.sample:hover .sample__image {
|
/* Hover zoom only on the home page's featured developments. */
|
||||||
|
.gallery--preview .sample:hover .sample__image {
|
||||||
transform: scale(1.045);
|
transform: scale(1.045);
|
||||||
}
|
}
|
||||||
.sample__badge {
|
.sample__badge {
|
||||||
@@ -119,7 +120,7 @@
|
|||||||
.sample__image {
|
.sample__image {
|
||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
.sample:hover .sample__image {
|
.gallery--preview .sample:hover .sample__image {
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ const textures = [
|
|||||||
export default function Gallery({ preview = false }) {
|
export default function Gallery({ preview = false }) {
|
||||||
const items = preview ? developments.slice(0, 3) : developments;
|
const items = preview ? developments.slice(0, 3) : developments;
|
||||||
return (
|
return (
|
||||||
<section className="gallery" id="developments" tabIndex={-1}>
|
<section
|
||||||
|
className={`gallery${preview ? " gallery--preview" : ""}`}
|
||||||
|
id="developments"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
<SectionHeading
|
<SectionHeading
|
||||||
centered
|
centered
|
||||||
label={
|
label={
|
||||||
@@ -40,7 +44,7 @@ export default function Gallery({ preview = false }) {
|
|||||||
<p className="gallery__intro">
|
<p className="gallery__intro">
|
||||||
{preview
|
{preview
|
||||||
? "A selection of knitted structures showing how yarn, composition and machine setup shape the final fabric character."
|
? "A selection of knitted structures showing how yarn, composition and machine setup shape the final fabric character."
|
||||||
: "Selected developments are processed separately as reference samples to explore how a construction can translate after dyeing and finishing. RRS commercially manufactures grey fabric only."}
|
: "Selected developments are processed separately as samples to explore how a construction can translate after dyeing and finishing. RRS commercially manufactures grey fabric only."}
|
||||||
</p>
|
</p>
|
||||||
{preview && (
|
{preview && (
|
||||||
<Action to="/fabrics#developments" variant="outline">
|
<Action to="/fabrics#developments" variant="outline">
|
||||||
@@ -63,7 +67,6 @@ export default function Gallery({ preview = false }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="sample__heading">
|
<div className="sample__heading">
|
||||||
<h3 className="sample__name">{name}</h3>
|
<h3 className="sample__name">{name}</h3>
|
||||||
<span className="sample__detail">Development reference</span>
|
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -48,22 +48,17 @@
|
|||||||
animation-delay: 25s;
|
animation-delay: 25s;
|
||||||
}
|
}
|
||||||
/* Each slide fades IN over the previous one (which stays opaque beneath it),
|
/* Each slide fades IN over the previous one (which stays opaque beneath it),
|
||||||
so there is never a moment with no image on screen — works for any count. */
|
so there is never a moment with no image on screen - works for any count. */
|
||||||
@keyframes carousel-fade {
|
@keyframes carousel-fade {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(1);
|
|
||||||
}
|
}
|
||||||
4%,
|
4%,
|
||||||
96% {
|
96% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
96% {
|
|
||||||
transform: scale(1.015);
|
|
||||||
}
|
|
||||||
100% {
|
100% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(1.015);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
|||||||
@@ -176,11 +176,6 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-underline-offset: 4px;
|
text-underline-offset: 4px;
|
||||||
}
|
}
|
||||||
.site-footer__pending {
|
|
||||||
margin: 0;
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
.site-footer__bottom {
|
.site-footer__bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -209,7 +204,7 @@
|
|||||||
margin-top: 38px;
|
margin-top: 38px;
|
||||||
padding-top: 23px;
|
padding-top: 23px;
|
||||||
border-top: 1px solid var(--line);
|
border-top: 1px solid var(--line);
|
||||||
font-family: var(--mono);
|
font-family: var(--sans);
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Link, NavLink, Outlet, useLocation } from "react-router-dom";
|
import { Link, NavLink, Outlet, useLocation } from "react-router-dom";
|
||||||
import { company, navigation } from "../data";
|
import { company, navigation, phoneHref } from "../data";
|
||||||
import { Arrow, WhatsAppAction } from "./Primitives";
|
import { Arrow, WhatsAppAction } from "./Primitives";
|
||||||
import "./Layout.css";
|
import "./Layout.css";
|
||||||
|
|
||||||
@@ -35,17 +35,9 @@ function Header() {
|
|||||||
<div className="contact-strip">
|
<div className="contact-strip">
|
||||||
<span>Contact RRS</span>
|
<span>Contact RRS</span>
|
||||||
<div className="contact-strip__details">
|
<div className="contact-strip__details">
|
||||||
{company.email ? (
|
|
||||||
<a href={`mailto:${company.email}`}>{company.email}</a>
|
<a href={`mailto:${company.email}`}>{company.email}</a>
|
||||||
) : (
|
|
||||||
<span>Email to be supplied</span>
|
|
||||||
)}
|
|
||||||
<span aria-hidden="true">·</span>
|
<span aria-hidden="true">·</span>
|
||||||
{company.phone ? (
|
<a href={phoneHref(company.phone)}>{company.phone}</a>
|
||||||
<a href={`tel:${company.phone}`}>{company.phone}</a>
|
|
||||||
) : (
|
|
||||||
<span>Phone to be supplied</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="site-header__inner">
|
<div className="site-header__inner">
|
||||||
@@ -84,7 +76,7 @@ function Header() {
|
|||||||
to="/contact#whatsapp"
|
to="/contact#whatsapp"
|
||||||
onClick={closeMenu}
|
onClick={closeMenu}
|
||||||
>
|
>
|
||||||
Talk to us <Arrow diagonal />
|
Text us on WhatsApp <Arrow diagonal />
|
||||||
</Link>
|
</Link>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -116,9 +108,6 @@ function Footer() {
|
|||||||
<Link className="site-footer__link" to="/contact#direct-contact">
|
<Link className="site-footer__link" to="/contact#direct-contact">
|
||||||
Phone · Email · Address <Arrow diagonal />
|
Phone · Email · Address <Arrow diagonal />
|
||||||
</Link>
|
</Link>
|
||||||
<p className="site-footer__pending">
|
|
||||||
Contact details to be supplied.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="site-footer__bottom">
|
<div className="site-footer__bottom">
|
||||||
@@ -178,7 +167,7 @@ export default function Layout() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const title =
|
const title =
|
||||||
navigation.find(({ to }) => to === pathname)?.label ?? "Page not found";
|
navigation.find(({ to }) => to === pathname)?.label ?? "Page not found";
|
||||||
document.title = `${title === "Home" ? "RRS" : `${title} — RRS`} | Radhe Radhe Synthetics`;
|
document.title = `${title === "Home" ? "RRS" : `${title} - RRS`} | Radhe Radhe Synthetics`;
|
||||||
const target = hash
|
const target = hash
|
||||||
? document.getElementById(hash.slice(1))
|
? document.getElementById(hash.slice(1))
|
||||||
: document.getElementById("main-content");
|
: document.getElementById("main-content");
|
||||||
|
|||||||
@@ -52,6 +52,16 @@
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
opacity: 0.55;
|
opacity: 0.55;
|
||||||
}
|
}
|
||||||
|
.action__label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.action__icon {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
.eyebrow {
|
.eyebrow {
|
||||||
margin: 0 0 18px;
|
margin: 0 0 18px;
|
||||||
font-family: var(--sans);
|
font-family: var(--sans);
|
||||||
@@ -107,23 +117,6 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
transition: transform 700ms ease;
|
|
||||||
}
|
|
||||||
.textile:hover .textile__image {
|
|
||||||
transform: scale(1.035);
|
|
||||||
}
|
|
||||||
.textile__caption {
|
|
||||||
position: absolute;
|
|
||||||
left: 18px;
|
|
||||||
bottom: 16px;
|
|
||||||
right: 18px;
|
|
||||||
width: fit-content;
|
|
||||||
padding: 7px 10px;
|
|
||||||
border-radius: 2px;
|
|
||||||
background: #f5f3eeeb;
|
|
||||||
color: #34352d;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
}
|
||||||
.page-hero {
|
.page-hero {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -188,7 +181,4 @@
|
|||||||
.textile__image {
|
.textile__image {
|
||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
.textile:hover .textile__image {
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,17 +32,47 @@ export function Action({ children, to, variant = "dark" }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function WhatsAppIcon({ className = "", strokeWidth = 2.4 }) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
viewBox="0 0 48 48"
|
||||||
|
fill="none"
|
||||||
|
aria-hidden="true"
|
||||||
|
focusable="false"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M40 23a16 16 0 0 1-24 14L7 40l3-9A16 16 0 1 1 40 23Z"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={strokeWidth}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M17 17c1 7 6 12 13 14l3-4-5-3-2 2c-3-1-5-3-6-6l2-2-3-4-2 3Z"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={strokeWidth}
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function WhatsAppAction({
|
export function WhatsAppAction({
|
||||||
children = "Talk to us",
|
children = "Text us on WhatsApp",
|
||||||
variant = "dark",
|
variant = "dark",
|
||||||
direct = false,
|
direct = false,
|
||||||
}) {
|
}) {
|
||||||
const url = whatsappUrl(company.whatsapp);
|
const url = whatsappUrl(company.whatsapp);
|
||||||
const className = `action action--${variant}`;
|
const className = `action action--${variant}`;
|
||||||
|
const label = (
|
||||||
|
<span className="action__label">
|
||||||
|
<WhatsAppIcon className="action__icon" />
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
if (url)
|
if (url)
|
||||||
return (
|
return (
|
||||||
<a className={className} href={url} target="_blank" rel="noreferrer">
|
<a className={className} href={url} target="_blank" rel="noreferrer">
|
||||||
{children}
|
{label}
|
||||||
<Arrow diagonal />
|
<Arrow diagonal />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
@@ -54,7 +84,7 @@ export function WhatsAppAction({
|
|||||||
disabled
|
disabled
|
||||||
aria-describedby="whatsapp-status"
|
aria-describedby="whatsapp-status"
|
||||||
>
|
>
|
||||||
{children}
|
{label}
|
||||||
<Arrow diagonal />
|
<Arrow diagonal />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
@@ -83,27 +113,17 @@ export function SectionHeading({ label, title, children, centered = false }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Textile({
|
export function Textile({ src, className = "", eager = false }) {
|
||||||
src,
|
|
||||||
className = "",
|
|
||||||
caption = true,
|
|
||||||
eager = false,
|
|
||||||
}) {
|
|
||||||
return (
|
return (
|
||||||
<figure className={`textile ${className}`}>
|
<figure className={`textile ${className}`}>
|
||||||
<img
|
<img
|
||||||
className="textile__image"
|
className="textile__image"
|
||||||
src={src}
|
src={src}
|
||||||
alt="Reference fabric photograph"
|
alt="Fabric photograph"
|
||||||
width="1600"
|
width="1600"
|
||||||
height="1200"
|
height="1200"
|
||||||
loading={eager ? "eager" : "lazy"}
|
loading={eager ? "eager" : "lazy"}
|
||||||
/>
|
/>
|
||||||
{caption && (
|
|
||||||
<figcaption className="textile__caption">
|
|
||||||
Reference fabric
|
|
||||||
</figcaption>
|
|
||||||
)}
|
|
||||||
</figure>
|
</figure>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-13
@@ -1,13 +1,16 @@
|
|||||||
|
const address =
|
||||||
|
"508, Accord Classic, Jay Prakash Nagar, Above Anupam Stationary, Goregaon East, Mumbai, Maharashtra - 400 063";
|
||||||
|
|
||||||
export const company = Object.freeze({
|
export const company = Object.freeze({
|
||||||
name: "Radhe Radhe Synthetics Pvt. Ltd.",
|
name: "Radhe Radhe Synthetics Pvt. Ltd.",
|
||||||
shortName: "RadheRadhe Pvt. Ltd.",
|
shortName: "RadheRadhe Pvt. Ltd.",
|
||||||
description:
|
description:
|
||||||
"Grey knitted fabrics engineered for diverse apparel applications.",
|
"Grey knitted fabrics engineered for diverse apparel applications.",
|
||||||
whatsapp: "", // Supply the business number in international digits, without + or spaces.
|
whatsapp: "919769665899", // International digits, no + or spaces.
|
||||||
phone: "",
|
phone: "+91 97696 65899",
|
||||||
email: "",
|
email: "hituagarwal2905@gmail.com",
|
||||||
address: "",
|
address,
|
||||||
mapsUrl: "",
|
mapsUrl: `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const navigation = [
|
export const navigation = [
|
||||||
@@ -115,17 +118,21 @@ export const yarns = [
|
|||||||
"Other yarns selected according to fabric requirements",
|
"Other yarns selected according to fabric requirements",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Development names are references, not technical categories or specifications.
|
// Development names are sample labels, not technical categories or specifications.
|
||||||
export const developments = [
|
export const developments = [
|
||||||
"Micro Break",
|
"Lehar",
|
||||||
"Luxe",
|
"Shahi",
|
||||||
"Jerry",
|
"Jhalar",
|
||||||
"Killer",
|
"Vajra",
|
||||||
"Joker",
|
"Natkhat",
|
||||||
"Ice Cool",
|
"Chandni",
|
||||||
"Maple",
|
"Ashoka",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export function phoneHref(number) {
|
||||||
|
return number ? `tel:+${number.replace(/\D/g, "")}` : null;
|
||||||
|
}
|
||||||
|
|
||||||
export function whatsappUrl(number) {
|
export function whatsappUrl(number) {
|
||||||
return /^[1-9]\d{7,14}$/.test(number)
|
return /^[1-9]\d{7,14}$/.test(number)
|
||||||
? `https://wa.me/${number}?text=${encodeURIComponent("Hello RRS, I'd like to discuss a fabric requirement.")}`
|
? `https://wa.me/${number}?text=${encodeURIComponent("Hello RRS, I'd like to discuss a fabric requirement.")}`
|
||||||
|
|||||||
@@ -58,47 +58,10 @@
|
|||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
.owner__image-label {
|
|
||||||
align-self: flex-start;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
.owner__silhouette {
|
.owner__silhouette {
|
||||||
width: 185px;
|
width: 185px;
|
||||||
height: 220px;
|
height: 220px;
|
||||||
}
|
}
|
||||||
.owner__pending {
|
|
||||||
font-size: 11px;
|
|
||||||
text-align: center;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
.owner__caption {
|
|
||||||
padding: 22px 0 0;
|
|
||||||
}
|
|
||||||
.owner__identity {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: 20px;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.owner__name {
|
|
||||||
margin: 0;
|
|
||||||
font-family: var(--serif);
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 26px;
|
|
||||||
}
|
|
||||||
.owner__role {
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
.owner__bio {
|
|
||||||
max-width: 370px;
|
|
||||||
margin: 13px 0 0;
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--muted);
|
|
||||||
line-height: 1.9;
|
|
||||||
}
|
|
||||||
.approach {
|
.approach {
|
||||||
padding-top: 100px;
|
padding-top: 100px;
|
||||||
}
|
}
|
||||||
@@ -146,15 +109,6 @@
|
|||||||
linear-gradient(90deg, #75866b16 1px, transparent 1px);
|
linear-gradient(90deg, #75866b16 1px, transparent 1px);
|
||||||
background-size: 40px 40px;
|
background-size: 40px 40px;
|
||||||
}
|
}
|
||||||
.location__map-label {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
left: 20px;
|
|
||||||
right: 20px;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1.6;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
.location__pin {
|
.location__pin {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -211,15 +165,6 @@
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.location__button:disabled {
|
|
||||||
opacity: 0.5;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
.location__status {
|
|
||||||
font-size: 11px;
|
|
||||||
color: var(--muted);
|
|
||||||
line-height: 1.8;
|
|
||||||
}
|
|
||||||
@media (max-width: 650px) {
|
@media (max-width: 650px) {
|
||||||
.philosophy {
|
.philosophy {
|
||||||
padding-top: 45px;
|
padding-top: 45px;
|
||||||
|
|||||||
+8
-51
@@ -20,7 +20,7 @@ const process = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Test.",
|
title: "Test.",
|
||||||
text: "Selected constructions are evaluated through processed reference samples to explore their possibilities.",
|
text: "Selected constructions are evaluated through processed samples to explore their possibilities.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Repeat.",
|
title: "Repeat.",
|
||||||
@@ -28,15 +28,14 @@ const process = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function PortraitPlaceholder({ number }) {
|
function Portrait({ number }) {
|
||||||
return (
|
return (
|
||||||
<figure className="owner">
|
<figure className="owner">
|
||||||
<div
|
<div
|
||||||
className="owner__portrait"
|
className="owner__portrait"
|
||||||
role="img"
|
role="img"
|
||||||
aria-label={`Owner ${number} portrait placeholder; professional photograph to be supplied`}
|
aria-label={`Owner ${number} portrait`}
|
||||||
>
|
>
|
||||||
<span className="owner__image-label">Portrait placeholder</span>
|
|
||||||
<svg
|
<svg
|
||||||
className="owner__silhouette"
|
className="owner__silhouette"
|
||||||
viewBox="0 0 200 230"
|
viewBox="0 0 200 230"
|
||||||
@@ -59,20 +58,7 @@ function PortraitPlaceholder({ number }) {
|
|||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<span className="owner__pending">
|
|
||||||
Professional photograph to follow
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<figcaption className="owner__caption">
|
|
||||||
<div className="owner__identity">
|
|
||||||
<h3 className="owner__name">[Owner Name]</h3>
|
|
||||||
<span className="owner__role">[Director / Role]</span>
|
|
||||||
</div>
|
|
||||||
<p className="owner__bio">
|
|
||||||
Biography to be supplied. This profile will introduce the person
|
|
||||||
behind the fabric.
|
|
||||||
</p>
|
|
||||||
</figcaption>
|
|
||||||
</figure>
|
</figure>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -135,15 +121,11 @@ export default function About() {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p>
|
<p>Meet our owners and directors.</p>
|
||||||
Meet our owners and directors.
|
|
||||||
<br />
|
|
||||||
Names, roles and biographies will be added when supplied.
|
|
||||||
</p>
|
|
||||||
</SectionHeading>
|
</SectionHeading>
|
||||||
<div className="leadership__grid">
|
<div className="leadership__grid">
|
||||||
<PortraitPlaceholder number={1} />
|
<Portrait number={1} />
|
||||||
<PortraitPlaceholder number={2} />
|
<Portrait number={2} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className="approach">
|
<section className="approach">
|
||||||
@@ -177,11 +159,8 @@ export default function About() {
|
|||||||
<div
|
<div
|
||||||
className="location__map"
|
className="location__map"
|
||||||
role="img"
|
role="img"
|
||||||
aria-label="Map placeholder. Verified factory or office address has not yet been supplied."
|
aria-label="Decorative map graphic."
|
||||||
>
|
>
|
||||||
<span className="location__map-label">
|
|
||||||
Map placeholder / Not a geographical location
|
|
||||||
</span>
|
|
||||||
<div className="location__pin">
|
<div className="location__pin">
|
||||||
<span className="location__pin-dot" />
|
<span className="location__pin-dot" />
|
||||||
<span>RRS</span>
|
<span>RRS</span>
|
||||||
@@ -193,16 +172,7 @@ export default function About() {
|
|||||||
<div className="location__details">
|
<div className="location__details">
|
||||||
<Eyebrow>Factory or office</Eyebrow>
|
<Eyebrow>Factory or office</Eyebrow>
|
||||||
<h3 className="location__name">{company.name}</h3>
|
<h3 className="location__name">{company.name}</h3>
|
||||||
<p className="location__address">
|
<p className="location__address">{company.address}</p>
|
||||||
{company.address || (
|
|
||||||
<>
|
|
||||||
[Full Factory / Office Address]
|
|
||||||
<br />
|
|
||||||
[City, State, PIN, India]
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
{company.mapsUrl ? (
|
|
||||||
<a
|
<a
|
||||||
className="location__button"
|
className="location__button"
|
||||||
href={company.mapsUrl}
|
href={company.mapsUrl}
|
||||||
@@ -211,19 +181,6 @@ export default function About() {
|
|||||||
>
|
>
|
||||||
Open in Google Maps ↗
|
Open in Google Maps ↗
|
||||||
</a>
|
</a>
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
className="location__button"
|
|
||||||
type="button"
|
|
||||||
disabled
|
|
||||||
aria-describedby="map-status"
|
|
||||||
>
|
|
||||||
Open in Google Maps ↗
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
<p className="location__status" id="map-status">
|
|
||||||
Verified location details to be supplied.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
}
|
}
|
||||||
.channels__grid {
|
.channels__grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
gap: 30px;
|
gap: 30px;
|
||||||
}
|
}
|
||||||
.channels__item {
|
.channels__item {
|
||||||
|
|||||||
+14
-38
@@ -1,10 +1,11 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { company } from "../data";
|
import { company, phoneHref } from "../data";
|
||||||
import {
|
import {
|
||||||
Eyebrow,
|
Eyebrow,
|
||||||
PageHero,
|
PageHero,
|
||||||
SectionHeading,
|
SectionHeading,
|
||||||
WhatsAppAction,
|
WhatsAppAction,
|
||||||
|
WhatsAppIcon,
|
||||||
} from "../components/Primitives";
|
} from "../components/Primitives";
|
||||||
import { ContactBanner } from "../components/Layout";
|
import { ContactBanner } from "../components/Layout";
|
||||||
import "./Contact.css";
|
import "./Contact.css";
|
||||||
@@ -24,27 +25,21 @@ export default function Contact() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const channels = [
|
const channels = [
|
||||||
{
|
|
||||||
title: "WhatsApp",
|
|
||||||
value: company.whatsapp || "[Number]",
|
|
||||||
href: "#whatsapp",
|
|
||||||
note: "Discuss a fabric requirement.",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "Phone",
|
title: "Phone",
|
||||||
value: company.phone || "[Number]",
|
value: company.phone,
|
||||||
href: company.phone ? `tel:${company.phone}` : null,
|
href: phoneHref(company.phone),
|
||||||
note: "A direct conversation with RRS.",
|
note: "A direct conversation with RRS.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Email",
|
title: "Email",
|
||||||
value: company.email || "[Email Address]",
|
value: company.email,
|
||||||
href: company.email ? `mailto:${company.email}` : null,
|
href: company.email ? `mailto:${company.email}` : null,
|
||||||
note: "Share your requirement or reference.",
|
note: "Share your requirement.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Address",
|
title: "Address",
|
||||||
value: company.address || "[Full Business Address]",
|
value: company.address,
|
||||||
href: company.mapsUrl || null,
|
href: company.mapsUrl || null,
|
||||||
note: "Factory / office location.",
|
note: "Factory / office location.",
|
||||||
},
|
},
|
||||||
@@ -76,8 +71,8 @@ export default function Contact() {
|
|||||||
<em>Let’s begin here.</em>
|
<em>Let’s begin here.</em>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="whatsapp__text">
|
<p className="whatsapp__text">
|
||||||
Share your fabric requirement, intended application, composition or
|
Share your fabric requirement, intended application, composition
|
||||||
reference with our team.
|
with our team.
|
||||||
</p>
|
</p>
|
||||||
<blockquote className="whatsapp__message">{message}</blockquote>
|
<blockquote className="whatsapp__message">{message}</blockquote>
|
||||||
<div className="whatsapp__clipboard">
|
<div className="whatsapp__clipboard">
|
||||||
@@ -94,29 +89,10 @@ export default function Contact() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="whatsapp__action">
|
<div className="whatsapp__action">
|
||||||
<svg
|
<WhatsAppIcon className="whatsapp__icon" strokeWidth={1.5} />
|
||||||
className="whatsapp__icon"
|
|
||||||
viewBox="0 0 48 48"
|
|
||||||
fill="none"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M40 23a16 16 0 0 1-24 14L7 40l3-9A16 16 0 1 1 40 23Z"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.5"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M17 17c1 7 6 12 13 14l3-4-5-3-2 2c-3-1-5-3-6-6l2-2-3-4-2 3Z"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.5"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<WhatsAppAction direct />
|
<WhatsAppAction direct />
|
||||||
<p className="whatsapp__status" id="whatsapp-status">
|
<p className="whatsapp__status" id="whatsapp-status">
|
||||||
{company.whatsapp
|
Opens WhatsApp with a conversation starter.
|
||||||
? "Opens WhatsApp with a conversation starter."
|
|
||||||
: "Business WhatsApp number to be supplied. Chat will be available once details are confirmed."}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -130,8 +106,8 @@ export default function Contact() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Contact information is awaiting confirmation. No phone numbers,
|
Reach RRS directly on WhatsApp or by phone or email - a direct
|
||||||
email addresses or locations have been assumed.
|
manufacturing conversation is the fastest way to begin.
|
||||||
</p>
|
</p>
|
||||||
</SectionHeading>
|
</SectionHeading>
|
||||||
<div className="channels__grid">
|
<div className="channels__grid">
|
||||||
@@ -158,7 +134,7 @@ export default function Contact() {
|
|||||||
<em>in mind?</em>
|
<em>in mind?</em>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
text="Share your fabric requirement, intended application, composition or reference with our team and start a conversation about what can be developed."
|
text="Share your fabric requirement, intended application, composition with our team and start a conversation about what can be developed."
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-4
@@ -67,9 +67,6 @@
|
|||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
letter-spacing: 0.01em;
|
letter-spacing: 0.01em;
|
||||||
}
|
}
|
||||||
.home-hero__image-note {
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
.home-intro {
|
.home-intro {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 44px;
|
gap: 44px;
|
||||||
@@ -140,7 +137,7 @@
|
|||||||
}
|
}
|
||||||
.process__verb {
|
.process__verb {
|
||||||
margin: 0 0 24px;
|
margin: 0 0 24px;
|
||||||
font-family: var(--mono);
|
font-family: var(--sans);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--industrial);
|
color: var(--industrial);
|
||||||
|
|||||||
+2
-5
@@ -39,14 +39,14 @@ export default function Home() {
|
|||||||
</h1>
|
</h1>
|
||||||
<p className="home-hero__description">
|
<p className="home-hero__description">
|
||||||
Grey knitted fabrics developed around yarn, structure and
|
Grey knitted fabrics developed around yarn, structure and
|
||||||
application—then manufactured for consistent commercial supply.
|
application - then manufactured for consistent commercial supply.
|
||||||
</p>
|
</p>
|
||||||
<div className="home-hero__actions">
|
<div className="home-hero__actions">
|
||||||
<Action to="/fabrics" variant="dark">
|
<Action to="/fabrics" variant="dark">
|
||||||
Explore our fabrics
|
Explore our fabrics
|
||||||
</Action>
|
</Action>
|
||||||
<Action to="/contact#whatsapp" variant="outline">
|
<Action to="/contact#whatsapp" variant="outline">
|
||||||
Talk to us
|
Text us on WhatsApp
|
||||||
</Action>
|
</Action>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,9 +54,6 @@ export default function Home() {
|
|||||||
<span className="home-hero__tagline">
|
<span className="home-hero__tagline">
|
||||||
Development · Circular knitting · Bulk production
|
Development · Circular knitting · Bulk production
|
||||||
</span>
|
</span>
|
||||||
<span className="home-hero__image-note">
|
|
||||||
Factory photography scheduled for content handover
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<Stats />
|
<Stats />
|
||||||
|
|||||||
+8
-6
@@ -81,22 +81,24 @@ test("desktop navigation, anchored CTA and browser back work", async ({
|
|||||||
).toHaveAttribute("aria-current", "page");
|
).toHaveAttribute("aria-current", "page");
|
||||||
await page
|
await page
|
||||||
.locator(".contact-banner")
|
.locator(".contact-banner")
|
||||||
.getByRole("link", { name: "Talk to us", exact: true })
|
.getByRole("link", { name: "Text us on WhatsApp", exact: true })
|
||||||
.click();
|
.click();
|
||||||
await expect(page).toHaveURL("/contact#whatsapp");
|
await expect(page).toHaveURL("/contact#whatsapp");
|
||||||
await expect(page.locator("#whatsapp")).toBeInViewport();
|
await expect(page.locator("#whatsapp")).toBeInViewport();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole("button", { name: "Talk to us", exact: true }),
|
page
|
||||||
).toBeDisabled();
|
.locator(".whatsapp")
|
||||||
|
.getByRole("link", { name: "Text us on WhatsApp", exact: true }),
|
||||||
|
).toHaveAttribute("href", /wa\.me/);
|
||||||
await expect(page.locator("#whatsapp-status")).toContainText(
|
await expect(page.locator("#whatsapp-status")).toContainText(
|
||||||
"number to be supplied",
|
"Opens WhatsApp",
|
||||||
);
|
);
|
||||||
await page.goBack();
|
await page.goBack();
|
||||||
await expect(page).toHaveURL("/fabrics");
|
await expect(page).toHaveURL("/fabrics");
|
||||||
await page.goto("/contact#whatsapp");
|
await page.goto("/contact#whatsapp");
|
||||||
await page
|
await page
|
||||||
.locator(".contact-banner")
|
.locator(".contact-banner")
|
||||||
.getByRole("link", { name: "Talk to us", exact: true })
|
.getByRole("link", { name: "Text us on WhatsApp", exact: true })
|
||||||
.click();
|
.click();
|
||||||
await expect(page.locator("#whatsapp")).toBeInViewport();
|
await expect(page.locator("#whatsapp")).toBeInViewport();
|
||||||
});
|
});
|
||||||
@@ -240,7 +242,7 @@ test("home and products heroes cycle through four product images", async ({
|
|||||||
await expect(page.getByText("Women’s wear", { exact: true })).toBeVisible();
|
await expect(page.getByText("Women’s wear", { exact: true })).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("capacity values roll in opposite directions and settle at 60–70", async ({
|
test("capacity values roll in opposite directions and settle at 60-70", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
for (const path of ["/", "/fabrics"]) {
|
for (const path of ["/", "/fabrics"]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user