Style updates

This commit is contained in:
Sean Edmunds
2025-07-11 15:26:00 -05:00
parent 5a0b354793
commit 20fc0cbca7
15 changed files with 400 additions and 288 deletions

View File

@@ -1,11 +1,12 @@
import { Grid, Group, Stack, Text, ThemeIcon } from '@mantine/core';
import { Box, Card, Group, Stack, Text } from '@mantine/core';
import { useCommonHooks } from 'hooks';
import { useSunStateAPI } from 'hooks/useAPI';
import { useEffect, useState } from 'react';
import { FaLongArrowAltDown, FaLongArrowAltUp, FaWind } from 'react-icons/fa';
import { WiBarometer, WiHumidity, WiSunrise, WiSunset } from 'react-icons/wi';
import { themeIconClasses } from 'styles';
import { textClasses } from 'styles';
import type { CurrentWeather as CW, SunState } from 'types';
import WeatherFeaturePill from './WeatherFeaturePill';
import WeatherIcon from './WeatherIcon';
export default function CurrentWeather({ current }: { current: CW }) {
@@ -33,223 +34,251 @@ export default function CurrentWeather({ current }: { current: CW }) {
return (
<>
{current && (
<Stack
gap={0}
justify='space-between'
<Card
style={{
width: '100%',
color: 'var(--mantine-color-primary-0)',
backgroundColor: 'var(--mantine-color-search-0)',
padding: '1rem',
borderRadius: '8px',
paddingBottom: '.5rem',
marginTop: '1rem',
overflow: 'visible',
}}
>
<Group
gap={0}
justify='space-between'
style={{ width: '100%', paddingLeft: '1rem' }}
>
<Text
style={{
fontSize: '1.375rem',
textAlign: 'right',
}}
>
Current Weather
</Text>
</Group>
<Group gap={8} justify='space-between'>
<Stack gap={0} w={isMobile ? '40%' : '45%'}>
<Group gap={0} justify='flex-end'>
<WeatherIcon
textDescription={`${
current.textDescription.includes('and')
? current.textDescription.substring(
0,
current.textDescription.indexOf('and'),
)
: current.textDescription.includes('then')
? current.textDescription.substring(
0,
current.textDescription.indexOf('then'),
)
: current.textDescription
}`}
/>
<Text fz={isMobile ? '5rem' : '7rem'} fw={200}>
{current.temperature}°<sup style={{ fontSize: '3rem' }}>F</sup>
</Text>
</Group>
<Text
<Text className={textClasses.weatherTitle} classNames={textClasses}>
Current Weather
</Text>
<Group gap={32} w={'100%'} align='center' justify='center' pt={'.5rem'}>
<Stack gap={4} align='center'>
<Stack
gap={0}
style={{
fontSize: '1.375rem',
textAlign: 'right',
marginTop: '-2rem',
marginLeft: '1rem',
overflow: 'hidden',
backgroundColor: 'var(--mantine-color-background-0)',
border: 'thin solid var(--mantine-color-primary-0)',
zIndex: 1,
padding: '1rem',
borderRadius: '8px',
}}
>
{current.temperature === 69 ? 'Nice' : current.textDescription}
</Text>
<Group pos={'relative'}>
<Box
style={{
position: 'absolute',
right: '-1.25rem',
bottom: '-1.25rem',
zIndex: -1,
opacity: 0.5,
}}
>
<WeatherIcon
size={'lg'}
textDescription={`${
current.textDescription.includes('and')
? current.textDescription.substring(
0,
current.textDescription.indexOf('and'),
)
: current.textDescription.includes('then')
? current.textDescription.substring(
0,
current.textDescription.indexOf('then'),
)
: current.textDescription
}`}
/>
</Box>
<Text fz={isMobile ? '5rem' : '7rem'} fw={400}>
{current.temperature}°<sup style={{ fontSize: '3rem' }}>F</sup>
</Text>
<Box
style={{
position: 'absolute',
backgroundColor:
'color-mix(in srgb, var(--mantine-color-accent-0), transparent 80%)',
height: '200%',
width: '100%',
bottom: -40,
right: -72,
transform: 'skewX(-25deg)',
zIndex: -1,
borderRadius: '2px',
backdropFilter: 'brightness(0.5)',
}}
/>
</Group>
<Group
justify={current.textDescription.length > 25 ? 'flex-start' : 'center'}
style={{
width: '100%',
maxWidth: '180px',
whiteSpace: 'nowrap',
overflow: 'hidden',
boxSizing: 'border-box',
position: 'relative',
}}
>
<Text
className={
current.textDescription.length > 25
? textClasses.autoScrollText
: undefined
}
classNames={textClasses}
>
{current.temperature === 69 ? 'Nice' : current.textDescription}
</Text>
</Group>
</Stack>
<WeatherFeaturePill
leftSide={<Text>Feels like </Text>}
rightSide={
<Text>
{current.heatIndex ?? current.windChill ?? current.temperature}°
<sup>F</sup>
</Text>
}
highlight='right'
/>
</Stack>
<Stack gap={4} w={isMobile ? '50%' : '45%'}>
<Text>
Feels like {current.heatIndex ?? current.windChill ?? current.temperature}
°<sup>F</sup>
</Text>
<Grid align='center'>
<Grid.Col span={1}>
<ThemeIcon
className={themeIconClasses.weatherIcon}
classNames={themeIconClasses}
>
<FaLongArrowAltUp size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col
span={3}
<Stack gap={10}>
<Stack gap={0} align='center'>
<Text
className={textClasses.sectionTitle}
classNames={textClasses}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
textAlign: 'center',
}}
w={'100%'}
>
<Text>
{current.highTemp}°<sup>F</sup>
</Text>
</Grid.Col>
<Grid.Col span={1}>
<ThemeIcon
className={themeIconClasses.weatherIcon}
classNames={themeIconClasses}
>
<FaLongArrowAltDown size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col
span={1}
Temperatures
</Text>
<Group justify='center'>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<FaLongArrowAltUp size={16} />
High
</Group>
}
rightSide={
<Text>
{current.highTemp}°<sup>F</sup>
</Text>
}
highlight='right'
/>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<FaLongArrowAltDown size={16} />
Low
</Group>
}
rightSide={
<Text>
{current.lowTemp}°<sup>F</sup>
</Text>
}
highlight='right'
/>
</Group>
</Stack>
<Stack gap={0} align='center'>
<Text
className={textClasses.sectionTitle}
classNames={textClasses}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
textAlign: 'center',
}}
w={'100%'}
>
<Text>
{current.lowTemp}°<sup>F</sup>
</Text>
</Grid.Col>
</Grid>
<Grid align='center'>
<Grid.Col span={1}>
<ThemeIcon
className={themeIconClasses.weatherIcon}
classNames={themeIconClasses}
>
<WiSunrise size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col
span={3}
Conditions
</Text>
<Group justify='center'>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<WiHumidity size={16} />
Humidity
</Group>
}
rightSide={<Text>{current.humidity}%</Text>}
highlight='right'
/>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<FaWind size={16} />
Wind
</Group>
}
rightSide={<Text>{current.windSpeed}mph</Text>}
highlight='right'
/>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<WiBarometer size={16} />
Pressure
</Group>
}
rightSide={<Text>{current.pressure} in</Text>}
highlight='right'
/>
</Group>
</Stack>
<Stack gap={0} align='center'>
<Text
className={textClasses.sectionTitle}
classNames={textClasses}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
textAlign: 'center',
}}
w={'100%'}
>
<Text>{sunStates[0]?.sunrise}</Text>
</Grid.Col>
<Grid.Col span={1}>
<ThemeIcon
className={themeIconClasses.weatherIcon}
classNames={themeIconClasses}
>
<WiSunset size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col
span={3}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
}}
>
<Text>{sunStates[0]?.sunset}</Text>
</Grid.Col>
</Grid>
<Grid align='center'>
<Grid.Col span={1}>
<ThemeIcon
className={themeIconClasses.weatherIcon}
classNames={themeIconClasses}
>
<WiHumidity size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col
span={isMobile ? 4 : 3}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
}}
>
<Text>Humidity</Text>
</Grid.Col>
<Grid.Col
span={2}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
}}
>
<Text>{current.humidity}%</Text>
</Grid.Col>
</Grid>
<Grid align='center'>
<Grid.Col span={1}>
<ThemeIcon
className={themeIconClasses.weatherIcon}
classNames={themeIconClasses}
>
<FaWind size={28} />
</ThemeIcon>
</Grid.Col>
<Grid.Col
span={3}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
}}
>
<Text>Wind</Text>
</Grid.Col>
<Grid.Col
span={isMobile ? 4 : 3}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
}}
>
<Text>{current.windSpeed}mph</Text>
</Grid.Col>
</Grid>
<Grid align='center'>
<Grid.Col span={1}>
<ThemeIcon
className={themeIconClasses.weatherIcon}
classNames={themeIconClasses}
>
<WiBarometer size={32} />
</ThemeIcon>
</Grid.Col>
<Grid.Col
span={3}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
}}
>
<Text>Pressure</Text>
</Grid.Col>
<Grid.Col
span={isMobile ? 4 : 3}
style={{
marginInlineStart: isMobile ? '1rem' : undefined,
}}
>
<Text>{current.pressure} in</Text>
</Grid.Col>
</Grid>
Sun Cycle
</Text>
<Group justify='center'>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<WiSunrise
size={18}
style={{
marginTop: '2px',
marginBottom: '2px',
marginLeft: -6,
marginRight: -6,
}}
/>
</Group>
}
rightSide={<Text>{sunStates[0]?.sunrise}</Text>}
highlight='left'
/>
<WeatherFeaturePill
leftSide={
<Group gap={0}>
<WiSunset
size={18}
style={{
marginTop: '2px',
marginBottom: '2px',
marginLeft: -6,
marginRight: -6,
}}
/>
</Group>
}
rightSide={<Text>{sunStates[0]?.sunset}</Text>}
highlight='left'
/>
</Group>
</Stack>
</Stack>
</Group>
</Stack>
</Card>
)}
</>
);

View File

@@ -1,4 +1,4 @@
import { Group, SimpleGrid, Stack, Text } from '@mantine/core';
import { Card, Group, SimpleGrid, Stack, Text } from '@mantine/core';
import { useCommonHooks } from 'hooks';
import { textClasses } from 'styles';
import type { ExtendedForecast } from 'types';
@@ -13,31 +13,22 @@ export default function ExtendedForecastCard({
const day = forecast.slice(2, 14).filter((item: ExtendedForecast) => item.isDaytime);
const night = forecast.slice(2, 14).filter((item: ExtendedForecast) => !item.isDaytime);
return (
<Stack
gap={0}
<Card
w={'100%'}
justify='space-between'
style={{
color: 'var(--mantine-color-primary-0)',
backgroundColor: 'var(--mantine-color-search-0)',
padding: '1rem',
borderRadius: '8px',
paddingBottom: '.5rem',
marginTop: '.5rem',
overflow: 'visible',
}}
>
<Group
gap={0}
style={{ width: '100%', marginBottom: '.5rem', paddingLeft: '1rem' }}
>
<Text
style={{
fontSize: '1.375rem',
textAlign: 'left',
}}
>
Extended Forecast
</Text>
</Group>
<SimpleGrid w={'100%'} cols={isMobile ? 3 : 6}>
<Text className={textClasses.weatherTitle} classNames={textClasses}>
Extended Forecast
</Text>
<SimpleGrid w={'100%'} pt={'.5rem'} cols={isMobile ? 3 : 6}>
{day.map((item: ExtendedForecast, index: number) => {
const short = item.shortForecast.includes('And')
? item.shortForecast.substring(0, item.shortForecast.indexOf('And'))
@@ -56,7 +47,7 @@ export default function ExtendedForecastCard({
}}
>
<Text>{item.name}</Text>
<WeatherIcon textDescription={short} />
<WeatherIcon size='md' textDescription={short} />
<Group
justify={short.length > 15 ? 'flex-start' : 'center'}
style={{
@@ -82,6 +73,6 @@ export default function ExtendedForecastCard({
);
})}
</SimpleGrid>
</Stack>
</Card>
);
}

View File

@@ -0,0 +1,61 @@
import { Box, Group } from '@mantine/core';
function WeatherFeaturePill({
leftSide,
rightSide,
highlight,
}: {
leftSide: React.ReactNode;
rightSide: React.ReactNode;
highlight?: string;
}) {
return (
<Group
gap={2}
w={'fit-content'}
style={{
color: 'var(--mantine-color-background-0)',
backgroundColor: 'var(--mantine-color-primary-0)',
borderRadius: '16px',
padding: '2px',
}}
>
<Box
style={{
color:
highlight === 'left'
? 'var(--mantine-color-primary-0)'
: 'var(--mantine-color-background-0)',
backgroundColor:
highlight === 'left'
? 'var(--mantine-color-background-0)'
: 'var(--mantine-color-primary-0)',
borderRadius: '16px',
paddingLeft: '8px',
paddingRight: '8px',
}}
>
{leftSide}
</Box>
<Box
style={{
color:
highlight === 'right'
? 'var(--mantine-color-primary-0)'
: 'var(--mantine-color-background-0)',
backgroundColor:
highlight === 'right'
? 'var(--mantine-color-background-0)'
: 'var(--mantine-color-primary-0)',
borderRadius: '16px',
paddingLeft: '8px',
paddingRight: '8px',
}}
>
{rightSide}
</Box>
</Group>
);
}
export default WeatherFeaturePill;

View File

@@ -10,7 +10,13 @@ import SunnyIcon from '../../assets/weather/sunny.svg';
import ThunderstormIcon from '../../assets/weather/thunderstorm.svg';
import WindyIcon from '../../assets/weather/windy.svg';
export default function WeatherIcon({ textDescription }: { textDescription: string }) {
export default function WeatherIcon({
size,
textDescription,
}: {
size: string;
textDescription: string;
}) {
const icon = textDescription.includes('then')
? textDescription.substring(0, textDescription.trim().indexOf('then'))
: textDescription;
@@ -173,7 +179,11 @@ export default function WeatherIcon({ textDescription }: { textDescription: stri
return (
<Image
style={{ width: '75px', height: '75px' }}
style={
size === 'lg'
? { width: '150px', height: '150px' }
: { width: '75px', height: '75px' }
}
src={lookupSource(icon).src}
alt={lookupSource(icon).alt}
/>