diff --git a/src/islands/dev/CssGenerator.tsx b/src/islands/dev/CssGenerator.tsx new file mode 100644 index 0000000..69e5d1c --- /dev/null +++ b/src/islands/dev/CssGenerator.tsx @@ -0,0 +1,132 @@ +import { useState } from 'react'; +import { CopyButton } from '@/components/ui/CopyButton'; +import { linearGradientCss, radialGradientCss, boxShadowCss, borderRadiusCss } from '@/tools/dev/css-generators.lib'; +import type { Lang } from '@/i18n/config'; + +type Tab = 'gradient' | 'shadow' | 'radius'; + +const TR: Record> = { + en: { + intro: 'Generate CSS for gradients, box-shadows and border-radius with a live preview — copy the code straight into your stylesheet. Runs in your browser.', + gradient: 'Gradient', shadow: 'Box shadow', radius: 'Border radius', + type: 'Type', linear: 'Linear', radial: 'Radial', angle: 'Angle', color1: 'Color 1', color2: 'Color 2', + x: 'Offset X', y: 'Offset Y', blur: 'Blur', spread: 'Spread', color: 'Color', inset: 'Inset', + tl: 'Top-left', tr: 'Top-right', br: 'Bottom-right', bl: 'Bottom-left', copy: 'Copy CSS', + }, + id: { + intro: 'Buat CSS untuk gradien, box-shadow, dan border-radius dengan pratinjau langsung — salin kodenya langsung ke stylesheet Anda. Berjalan di browser Anda.', + gradient: 'Gradien', shadow: 'Box shadow', radius: 'Border radius', + type: 'Tipe', linear: 'Linear', radial: 'Radial', angle: 'Sudut', color1: 'Warna 1', color2: 'Warna 2', + x: 'Offset X', y: 'Offset Y', blur: 'Blur', spread: 'Spread', color: 'Warna', inset: 'Inset', + tl: 'Kiri-atas', tr: 'Kanan-atas', br: 'Kanan-bawah', bl: 'Kiri-bawah', copy: 'Salin CSS', + }, +}; + +function Slider({ label, value, set, min, max }: { label: string; value: number; set: (n: number) => void; min: number; max: number }) { + return ( + + ); +} + +export default function CssGenerator({ lang = 'en' }: { lang?: Lang }) { + const t = TR[lang] ?? TR.en; + const [tab, setTab] = useState('gradient'); + + const [gType, setGType] = useState<'linear' | 'radial'>('linear'); + const [angle, setAngle] = useState(90); + const [c1, setC1] = useState('#7c3aed'); + const [c2, setC2] = useState('#22d3ee'); + + const [sx, setSx] = useState(4); const [sy, setSy] = useState(6); const [sblur, setSblur] = useState(16); + const [sspread, setSspread] = useState(0); const [scolor, setScolor] = useState('#00000040'); const [sinset, setSinset] = useState(false); + + const [tl, setTl] = useState(16); const [tr, setTr] = useState(16); const [br, setBr] = useState(16); const [bl, setBl] = useState(16); + + const gradient = gType === 'linear' + ? linearGradientCss(angle, [{ color: c1, pos: 0 }, { color: c2, pos: 100 }]) + : radialGradientCss('circle', [{ color: c1, pos: 0 }, { color: c2, pos: 100 }]); + const shadow = boxShadowCss({ x: sx, y: sy, blur: sblur, spread: sspread, color: scolor, inset: sinset }); + const radius = borderRadiusCss(tl, tr, br, bl); + + const css = tab === 'gradient' ? `background: ${gradient};` + : tab === 'shadow' ? `box-shadow: ${shadow};` + : `border-radius: ${radius};`; + + const previewStyle: React.CSSProperties = tab === 'gradient' ? { background: gradient } + : tab === 'shadow' ? { boxShadow: shadow, background: 'var(--tw-prose-body, #fff)' } + : { borderRadius: radius, background: gradient }; + + const input = 'w-full border-2 border-border bg-muted p-1.5 text-sm'; + + return ( +
+

{t.intro}

+ +
+ {(['gradient', 'shadow', 'radius'] as const).map(x => ( + + ))} +
+ +
+
+ {tab === 'gradient' && ( + <> +
+ {(['linear', 'radial'] as const).map(g => ( + + ))} +
+ {gType === 'linear' && } +
+ + +
+ + )} + {tab === 'shadow' && ( + <> +
+ + + + +
+
+ + +
+ + )} + {tab === 'radius' && ( +
+ + + + +
+ )} +
+ +
+
+
+
+ +
+
+ CSS + +
+