diff --git a/src/templates/components/Background/Background.sass b/src/templates/components/Background/Background.sass new file mode 100644 index 0000000..1e0b5bc --- /dev/null +++ b/src/templates/components/Background/Background.sass @@ -0,0 +1 @@ +@use '/src/styles/classes.sass' diff --git a/src/templates/components/Background/Background.tsx b/src/templates/components/Background/Background.tsx new file mode 100644 index 0000000..e33e37d --- /dev/null +++ b/src/templates/components/Background/Background.tsx @@ -0,0 +1,50 @@ +import './Background.sass' +import { Show, createSignal } from 'solid-js' +import fs from 'fs' +import webpPath from '../../../templates/images/background.webp' +import avifPath from '../../../templates/images/background.avif' +import noBackground from '../../../templates/images/no-background.webp' + +interface Props { + image?: boolean + color?: string +} + +let [imageLoaded, setImageLoaded] = createSignal(false) + +const checkBackground = () => { + if (!fs.existsSync(avifPath.src) && !fs.existsSync(webpPath.src)) { + setImageLoaded(true) + } else { + setImageLoaded(false) + } +} + +export default (props: Props) => { + checkBackground() + + return ( + <> + + + + + + + An image background + + + + + + An alternative background if found no image background + + + + + +
+ + + ) +} diff --git a/src/templates/components/Button/Button.sass b/src/templates/components/Button/Button.sass new file mode 100644 index 0000000..329ba1d --- /dev/null +++ b/src/templates/components/Button/Button.sass @@ -0,0 +1,223 @@ +@use '/src/styles/variables.sass' as vars +@use '/src/styles/fonts.sass' as fonts +@use 'sass:color' + +$bulmaPrimary: rgb(0, 235, 199) +$bulmaPrimaryText: rgb(0, 31, 26) +$bulmaLink: rgb(92, 111, 255) +$bulmaLinkText: rgb(245, 246, 255) +$bulmaInfo: rgb(128, 217, 255) +$bulmaInfoText: rgb(0, 36, 51) +$bulmaSuccess: rgb(91, 205, 154) +$bulmaSuccessText: rgb(10, 31, 21) +$bulmaWarning: rgb(255, 191, 41) +$bulmaWarningText: rgb(41, 29, 0) +$bulmaDanger: rgb(255, 128, 153) +$bulmaDangerText: rgb(26, 0, 5) +$bulmaLight: rgb(255, 255, 255) +$bulmaLightText: rgb(46, 51, 61) +$bulmaDark: rgb(57, 63, 76) +$bulmaDarkText: rgb(243, 244, 246) +$bulmaText: rgb(31, 34, 41) +$bulmaTextText: rgb(235, 236, 240) +$bulmaGhost: rgba(0,0,0,0) +$bulmaGhostText: rgb(66, 88, 255) + +$bootstrapTextLight: rgb(255, 255, 253) +$bootstrapTextDark: rgb(0, 0, 2) +$bootstrapTextLink: rgb(139, 185, 254) +$bootstrapPrimary: rgb(13, 110, 253) +$bootstrapSecondary: rgb(92, 99, 106) +$bootstrapSuccess: rgb(21, 115, 71) +$bootstrapDanger: rgb(187, 45, 59) +$bootstrapWarning: rgb(255, 202, 44) +$bootstrapInfo: rgb(49, 210, 242) +$bootstrapLight: rgb(211, 212, 213) +$bootstrapDark: rgb(33, 37, 41) + +.button + background-color: vars.$primaryColor + border: none + color: white + padding: 0.5rem 1.25rem + text-align: center + text-decoration: none + display: inline-block + font-size: 1rem + font-weight: 500 + cursor: pointer + transition: all 0.2s ease-out + + &:hover + background-color: color.adjust(vars.$primaryColor, $blackness: 20%) + + &:active + transform: scale(0.95) + +.bu-primary + @extend .button + font-family: fonts.$Inter + background-color: $bulmaPrimary + color: $bulmaPrimaryText + border: none + font-size: 1rem + border-radius: 0.375rem + font-weight: 500 + padding: 0.5rem 1.25rem + height: 2.5rem + + &:hover + background-color: color.adjust($bulmaPrimary, $lightness: 10%) + +.bu-link + @extend .bu-primary + background-color: $bulmaLink + color: $bulmaLinkText + + &:hover + background-color: color.adjust($bulmaLink, $lightness: 5%) + +.bu-info + @extend .bu-primary + background-color: $bulmaInfo + color: $bulmaInfoText + + &:hover + background-color: color.adjust($bulmaInfo, $lightness: 5%) + +.bu-success + @extend .bu-primary + background-color: $bulmaSuccess + color: $bulmaSuccessText + + &:hover + background-color: color.adjust($bulmaSuccess, $lightness: 5%) + +.bu-warning + @extend .bu-primary + background-color: $bulmaWarning + color: $bulmaWarningText + + &:hover + background-color: color.adjust($bulmaWarning, $lightness: 5%) + +.bu-danger + @extend .bu-primary + background-color: $bulmaDanger + color: $bulmaDangerText + + &:hover + background-color: color.adjust($bulmaDanger, $lightness: 5%) + +.bu-light + @extend .bu-primary + background-color: $bulmaLight + color: $bulmaLightText + + &:hover + background-color: color.adjust($bulmaLight, $lightness: 5%) + +.bu-dark + @extend .bu-primary + background-color: $bulmaDark + color: $bulmaDarkText + + &:hover + background-color: color.adjust($bulmaDark, $lightness: 5%) + +.bu-text + @extend .bu-primary + background-color: rgba(0,0,0,0) + color: $bulmaTextText + text-decoration: underline + + &:hover + background-color: hsl(221,14%,14%) + +.bu-ghost + @extend .bu-primary + background-color: $bulmaGhost + color: $bulmaGhostText + + &:hover + background-color: transparent + text-decoration: underline + +.bo-primary + @extend .button + font-family: 'Segoe UI', fonts.$Roboto + background-color: $bootstrapPrimary + color: $bootstrapTextLight + border: none + font-size: 1rem + border-radius: 0.375rem + font-weight: 400 + padding: 0.5rem 1.25rem + height: 2.5rem + margin: 0.25rem 0.125rem + + &:hover + background-color: color.adjust($bootstrapPrimary, $blackness: 10%) + +.bo-secondary + @extend .bo-primary + background-color: $bootstrapSecondary + + &:hover + background-color: color.adjust($bootstrapSecondary, $blackness: 10%) + +.bo-success + @extend .bo-primary + background-color: $bootstrapSuccess + + &:hover + background-color: color.adjust($bootstrapSuccess, $blackness: 10%) + +.bo-danger + @extend .bo-primary + background-color: $bootstrapDanger + + &:hover + background-color: color.adjust($bootstrapDanger, $blackness: 10%) + +.bo-warning + @extend .bo-primary + background-color: $bootstrapWarning + color: $bootstrapTextDark + + &:hover + background-color: color.adjust($bootstrapWarning, $lightness: 5%) + +.bo-info + @extend .bo-primary + background-color: $bootstrapInfo + color: $bootstrapTextDark + + &:hover + background-color: color.adjust($bootstrapInfo, $lightness: 5%) + +.bo-light + @extend .bo-primary + background-color: $bootstrapLight + color: $bootstrapTextDark + + &:hover + background-color: color.adjust($bootstrapLight, $blackness: 10%) + +.bo-dark + @extend .bo-primary + background-color: $bootstrapDark + // color: $bootstrapTextDark + + &:hover + background-color: color.adjust($bootstrapDark, $lightness: 10%) + +.bo-link + @extend .bo-primary + background-color: transparent + color: $bootstrapTextLink + text-decoration: underline + + &:hover + color: color.adjust($bootstrapTextLink, $lightness: 5%) + background-color: transparent diff --git a/src/templates/components/Button/Button.tsx b/src/templates/components/Button/Button.tsx new file mode 100644 index 0000000..61b7e7a --- /dev/null +++ b/src/templates/components/Button/Button.tsx @@ -0,0 +1,65 @@ +import './Button.sass' +import { Show, Switch, Match } from 'solid-js' + +interface Props { + label?: string + to?: string + onClick?: () => void + edges?: 'curved' | 'rounded' | 'flat' + design?: 'bu-primary' | 'bu-link' | 'bu-info' | 'bu-success' | 'bu-warning' | 'bu-danger' | 'bu-dark' | 'bu-light' | 'bu-text' | 'bu-ghost' | 'bo-primary' | 'bo-secondary' | 'bo-success' | 'bo-danger' | 'bo-warning' | 'bo-info' | 'bo-light' | 'bo-dark' | 'bo-link' +} + +const getBorderRadius = (edge: Props['edges']) => { + switch (edge) { + case 'curved': + return 'border-radius: 6px' + case 'rounded': + return 'border-radius: 32px' + case 'flat': + return 'border-radius: 0' + default: + return 'border-radius: 0' + } +} + +export default (props: Props) => { + const borderRadius = getBorderRadius(props.edges) + + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/src/templates/components/Image/Image.tsx b/src/templates/components/Image/Image.tsx new file mode 100644 index 0000000..bfb3b19 --- /dev/null +++ b/src/templates/components/Image/Image.tsx @@ -0,0 +1,36 @@ +import sharp from 'sharp' +import fs from 'fs' + +interface Props { + src: string + size?: number + alt?: string +} + +const convertImage = async (props: Props) => { + const avifOutputPath = `src/assets/optimized/${props.src.split('.').slice(0, -1).join('.')}.avif` + const webpOutputPath = `src/assets/optimized/${props.src.split('.').slice(0, -1).join('.')}.webp` + + if (!fs.existsSync(webpOutputPath) || !fs.existsSync(avifOutputPath)) { + const avifBuffer = await sharp(`src/assets/images/${props.src}`).avif({ quality: 60 }).resize(props.size).toBuffer() + await sharp(avifBuffer).toFile(avifOutputPath) + + const webpBuffer = await sharp(`src/assets/images/${props.src}`).webp({ quality: 75 }).resize(props.size).toBuffer() + await sharp(webpBuffer).toFile(webpOutputPath) + } +} + +export default (props: Props) => { + const imageSrc = `src/assets/optimized/${props.src.split('.').slice(0, -1).join('.')}.webp` + convertImage(props) + + return ( + <> + + + + {props.alt} + + + ) +} diff --git a/src/templates/components/Link/Link.tsx b/src/templates/components/Link/Link.tsx new file mode 100644 index 0000000..4ccf49f --- /dev/null +++ b/src/templates/components/Link/Link.tsx @@ -0,0 +1,14 @@ +interface Props { + to: string + children?: any +} + +export default (props: Props) => { + return ( + <> + + {props.children} + + + ) +} diff --git a/src/templates/components/Logo/Logo.tsx b/src/templates/components/Logo/Logo.tsx new file mode 100644 index 0000000..d293b1a --- /dev/null +++ b/src/templates/components/Logo/Logo.tsx @@ -0,0 +1,19 @@ +import webpPath from '../../../templates/images/logo.webp' +import avifPath from '../../../templates/images/logo.avif' + +interface Props { + size?: number + alt?: string +} + +export default (props: Props) => { + return ( + <> + + + + logo + + + ) +} diff --git a/src/templates/components/Optimizer/OptimizeBackground.tsx b/src/templates/components/Optimizer/OptimizeBackground.tsx new file mode 100644 index 0000000..2c004f5 --- /dev/null +++ b/src/templates/components/Optimizer/OptimizeBackground.tsx @@ -0,0 +1,17 @@ +import sharp from 'sharp' + +const convertBackground = async () => { + const inputSrc = 'src/assets/images/background.png' + const webpOutput = 'src/templates/images/background.webp' + const avifOutput = 'src/templates/images/background.avif' + + const avifBuffer = await sharp(inputSrc).avif({ quality: 60 }).resize(1920).toBuffer() + await sharp(avifBuffer).toFile(avifOutput) + + const webpBuffer = await sharp(inputSrc).webp({ quality: 75 }).resize(1920).toBuffer() + await sharp(webpBuffer).toFile(webpOutput) +} + +export default () => { + convertBackground() +} diff --git a/src/templates/components/Optimizer/OptimizeLogo.tsx b/src/templates/components/Optimizer/OptimizeLogo.tsx new file mode 100644 index 0000000..fb39b0d --- /dev/null +++ b/src/templates/components/Optimizer/OptimizeLogo.tsx @@ -0,0 +1,22 @@ +import sharp from 'sharp' + +interface Props { + size?: number + alt?: string +} + +const convertLogo = async (props: Props) => { + const inputSrc = 'src/assets/images/logo.png' + const webpImage = 'src/templates/images/logo.webp' + const avifImage = 'src/templates/images/logo.avif' + + const avifBuffer = await sharp(inputSrc).avif({ quality: 60 }).resize(props.size).toBuffer() + await sharp(avifBuffer).toFile(avifImage) + + const webpBuffer = await sharp(inputSrc).webp({ quality: 75 }).resize(props.size).toBuffer() + await sharp(webpBuffer).toFile(webpImage) +} + +export default (props: Props) => { + convertLogo(props) +} diff --git a/src/templates/components/Page/Page.sass b/src/templates/components/Page/Page.sass new file mode 100644 index 0000000..3d97ca8 --- /dev/null +++ b/src/templates/components/Page/Page.sass @@ -0,0 +1,15 @@ +.page + margin: 2rem + height: auto + +.column + @extend .page + display: flex + flex-direction: column + text-align: center + justify-content: center + align-items: center + +.row + @extend .column + flex-direction: row diff --git a/src/templates/components/Page/Page.tsx b/src/templates/components/Page/Page.tsx new file mode 100644 index 0000000..d16977f --- /dev/null +++ b/src/templates/components/Page/Page.tsx @@ -0,0 +1,20 @@ +import './Page.sass' +import { Show, Switch, Match } from 'solid-js' + +interface Props { + children?: any + alignment?: 'row' | 'column' +} + +export default (props: Props) => { + return ( + <> + +
{props.children}
+
+ +
{props.children}
+
+ + ) +} diff --git a/src/templates/images/no-background.webp b/src/templates/images/no-background.webp new file mode 100644 index 0000000..87c7f4c Binary files /dev/null and b/src/templates/images/no-background.webp differ