mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-04-07 09:16:15 +02:00
feat: alert and button styles redesign
This commit is contained in:
parent
12a6f2230d
commit
f4a69ea401
|
|
@ -125,13 +125,15 @@ export class MapService {
|
||||||
throw new Error('Base styles file not found in storage/maps')
|
throw new Error('Base styles file not found in storage/maps')
|
||||||
}
|
}
|
||||||
|
|
||||||
const localUrl = env.get('URL')
|
|
||||||
const rawStyles = JSON.parse(baseStyle.toString()) as BaseStylesFile
|
const rawStyles = JSON.parse(baseStyle.toString()) as BaseStylesFile
|
||||||
|
|
||||||
const regions = (await this.listRegions()).files
|
const regions = (await this.listRegions()).files
|
||||||
const sources = this.generateSourcesArray(regions)
|
const sources = this.generateSourcesArray(regions)
|
||||||
|
|
||||||
const baseUrl = urlJoin(localUrl, this.mapStoragePath, this.basemapsAssetsDir)
|
const localUrl = env.get('URL')
|
||||||
|
const withProtocol = localUrl.startsWith('http') ? localUrl : `http://${localUrl}`
|
||||||
|
const baseUrlPath = urlJoin(this.mapStoragePath, this.basemapsAssetsDir)
|
||||||
|
const baseUrl = new URL(baseUrlPath, withProtocol).toString()
|
||||||
|
|
||||||
const styles = await this.generateStylesFile(
|
const styles = await this.generateStylesFile(
|
||||||
rawStyles,
|
rawStyles,
|
||||||
|
|
@ -173,10 +175,15 @@ export class MapService {
|
||||||
if (region.type === 'file' && region.name.endsWith('.pmtiles')) {
|
if (region.type === 'file' && region.name.endsWith('.pmtiles')) {
|
||||||
const regionName = region.name.replace('.pmtiles', '')
|
const regionName = region.name.replace('.pmtiles', '')
|
||||||
const source: BaseStylesFile['sources'] = {}
|
const source: BaseStylesFile['sources'] = {}
|
||||||
|
const sourceUrl = new URL(
|
||||||
|
urlJoin(this.mapStoragePath, 'pmtiles', region.name),
|
||||||
|
localUrl.startsWith('http') ? localUrl : `http://${localUrl}`
|
||||||
|
).toString()
|
||||||
|
|
||||||
source[regionName] = {
|
source[regionName] = {
|
||||||
type: 'vector',
|
type: 'vector',
|
||||||
attribution: PMTILES_ATTRIBUTION,
|
attribution: PMTILES_ATTRIBUTION,
|
||||||
url: `pmtiles://http://${urlJoin(localUrl, this.mapStoragePath, 'pmtiles', region.name)}`,
|
url: `pmtiles://${sourceUrl}`,
|
||||||
}
|
}
|
||||||
sources.push(source)
|
sources.push(source)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,200 @@
|
||||||
import { ExclamationTriangleIcon, XCircleIcon } from '@heroicons/react/24/solid'
|
import * as Icons from '@heroicons/react/24/solid'
|
||||||
import { IconCircleCheck } from '@tabler/icons-react'
|
|
||||||
import classNames from '~/lib/classNames'
|
import classNames from '~/lib/classNames'
|
||||||
|
|
||||||
export type AlertProps = React.HTMLAttributes<HTMLDivElement> & {
|
export type AlertProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||||
title: string
|
title: string
|
||||||
message?: string
|
message?: string
|
||||||
type: 'warning' | 'error' | 'success'
|
type: 'warning' | 'error' | 'success' | 'info'
|
||||||
children?: React.ReactNode
|
children?: React.ReactNode
|
||||||
|
dismissible?: boolean
|
||||||
|
onDismiss?: () => void
|
||||||
|
icon?: keyof typeof Icons
|
||||||
|
variant?: 'standard' | 'bordered' | 'solid'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Alert({ title, message, type, children, ...props }: AlertProps) {
|
export default function Alert({
|
||||||
const getIcon = () => {
|
title,
|
||||||
const Icon =
|
message,
|
||||||
type === 'warning'
|
type,
|
||||||
? ExclamationTriangleIcon
|
children,
|
||||||
: type === 'error'
|
dismissible = false,
|
||||||
? XCircleIcon
|
onDismiss,
|
||||||
: IconCircleCheck
|
icon,
|
||||||
const color =
|
variant = 'standard',
|
||||||
type === 'warning' ? 'text-yellow-400' : type === 'error' ? 'text-red-400' : 'text-green-400'
|
...props
|
||||||
|
}: AlertProps) {
|
||||||
return <Icon aria-hidden="true" className={`size-5 ${color}`} />
|
const getDefaultIcon = (): keyof typeof Icons => {
|
||||||
|
switch (type) {
|
||||||
|
case 'warning':
|
||||||
|
return 'ExclamationTriangleIcon'
|
||||||
|
case 'error':
|
||||||
|
return 'XCircleIcon'
|
||||||
|
case 'success':
|
||||||
|
return 'CheckCircleIcon'
|
||||||
|
case 'info':
|
||||||
|
return 'InformationCircleIcon'
|
||||||
|
default:
|
||||||
|
return 'InformationCircleIcon'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getBackground = () => {
|
const IconComponent = () => {
|
||||||
return type === 'warning' ? 'bg-yellow-100' : type === 'error' ? 'bg-red-50' : 'bg-green-50'
|
const iconName = icon || getDefaultIcon()
|
||||||
|
const Icon = Icons[iconName]
|
||||||
|
if (!Icon) return null
|
||||||
|
|
||||||
|
return <Icon aria-hidden="true" className={classNames('size-5 shrink-0', getIconColor())} />
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTextColor = () => {
|
const getIconColor = () => {
|
||||||
return type === 'warning'
|
if (variant === 'solid') return 'text-desert-white'
|
||||||
? 'text-yellow-800'
|
switch (type) {
|
||||||
: type === 'error'
|
case 'warning':
|
||||||
? 'text-red-800'
|
return 'text-desert-orange'
|
||||||
: 'text-green-800'
|
case 'error':
|
||||||
|
return 'text-desert-red'
|
||||||
|
case 'success':
|
||||||
|
return 'text-desert-olive'
|
||||||
|
case 'info':
|
||||||
|
return 'text-desert-stone'
|
||||||
|
default:
|
||||||
|
return 'text-desert-stone'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getVariantStyles = () => {
|
||||||
|
const baseStyles = 'rounded-md transition-all duration-200'
|
||||||
|
const variantStyles: string[] = []
|
||||||
|
|
||||||
|
switch (variant) {
|
||||||
|
case 'bordered':
|
||||||
|
variantStyles.push(
|
||||||
|
type === 'warning'
|
||||||
|
? 'border-desert-orange'
|
||||||
|
: type === 'error'
|
||||||
|
? 'border-desert-red'
|
||||||
|
: type === 'success'
|
||||||
|
? 'border-desert-olive'
|
||||||
|
: type === 'info'
|
||||||
|
? 'border-desert-stone'
|
||||||
|
: ''
|
||||||
|
)
|
||||||
|
return classNames(baseStyles, 'border-2 bg-desert-white', ...variantStyles)
|
||||||
|
case 'solid':
|
||||||
|
variantStyles.push(
|
||||||
|
type === 'warning'
|
||||||
|
? 'bg-desert-orange text-desert-white border-desert-orange-dark'
|
||||||
|
: type === 'error'
|
||||||
|
? 'bg-desert-red text-desert-white border-desert-red-dark'
|
||||||
|
: type === 'success'
|
||||||
|
? 'bg-desert-olive text-desert-white border-desert-olive-dark'
|
||||||
|
: type === 'info'
|
||||||
|
? 'bg-desert-stone text-desert-white border-desert-stone-dark'
|
||||||
|
: ''
|
||||||
|
)
|
||||||
|
return classNames(baseStyles, 'shadow-sm', ...variantStyles)
|
||||||
|
default:
|
||||||
|
variantStyles.push(
|
||||||
|
type === 'warning'
|
||||||
|
? 'bg-desert-orange-lighter bg-opacity-20 border-desert-orange-light'
|
||||||
|
: type === 'error'
|
||||||
|
? 'bg-desert-red-lighter bg-opacity-20 border-desert-red-light'
|
||||||
|
: type === 'success'
|
||||||
|
? 'bg-desert-olive-lighter bg-opacity-20 border-desert-olive-light'
|
||||||
|
: type === 'info'
|
||||||
|
? 'bg-desert-stone-lighter bg-opacity-20 border-desert-stone-light'
|
||||||
|
: ''
|
||||||
|
)
|
||||||
|
return classNames(baseStyles, 'border shadow-sm', ...variantStyles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTitleColor = () => {
|
||||||
|
if (variant === 'solid') return 'text-desert-white'
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'warning':
|
||||||
|
return 'text-desert-orange-dark'
|
||||||
|
case 'error':
|
||||||
|
return 'text-desert-red-dark'
|
||||||
|
case 'success':
|
||||||
|
return 'text-desert-olive-dark'
|
||||||
|
case 'info':
|
||||||
|
return 'text-desert-stone-dark'
|
||||||
|
default:
|
||||||
|
return 'text-desert-stone-dark'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMessageColor = () => {
|
||||||
|
if (variant === 'solid') return 'text-desert-white text-opacity-90'
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'warning':
|
||||||
|
return 'text-desert-orange-dark text-opacity-80'
|
||||||
|
case 'error':
|
||||||
|
return 'text-desert-red-dark text-opacity-80'
|
||||||
|
case 'success':
|
||||||
|
return 'text-desert-olive-dark text-opacity-80'
|
||||||
|
case 'info':
|
||||||
|
return 'text-desert-stone-dark text-opacity-80'
|
||||||
|
default:
|
||||||
|
return 'text-desert-stone-dark text-opacity-80'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCloseButtonStyles = () => {
|
||||||
|
if (variant === 'solid') {
|
||||||
|
return 'text-desert-white hover:text-desert-white hover:bg-black hover:bg-opacity-20'
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'warning':
|
||||||
|
return 'text-desert-orange hover:text-desert-orange-dark hover:bg-desert-orange-lighter hover:bg-opacity-30'
|
||||||
|
case 'error':
|
||||||
|
return 'text-desert-red hover:text-desert-red-dark hover:bg-desert-red-lighter hover:bg-opacity-30'
|
||||||
|
case 'success':
|
||||||
|
return 'text-desert-olive hover:text-desert-olive-dark hover:bg-desert-olive-lighter hover:bg-opacity-30'
|
||||||
|
case 'info':
|
||||||
|
return 'text-desert-stone hover:text-desert-stone-dark hover:bg-desert-stone-lighter hover:bg-opacity-30'
|
||||||
|
default:
|
||||||
|
return 'text-desert-stone hover:text-desert-stone-dark hover:bg-desert-stone-lighter hover:bg-opacity-30'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div {...props} className={classNames(getVariantStyles(), 'p-4', props.className)} role="alert">
|
||||||
{...props}
|
<div className="flex gap-3">
|
||||||
className={classNames(
|
<IconComponent />
|
||||||
getBackground(),
|
|
||||||
props.className,
|
<div className="flex-1 min-w-0">
|
||||||
'border border-gray-200 rounded-md p-3 shadow-xs'
|
<h3 className={classNames('text-sm font-semibold', getTitleColor())}>{title}</h3>
|
||||||
)}
|
{message && (
|
||||||
>
|
<div className={classNames('mt-1 text-sm', getMessageColor())}>
|
||||||
<div className="flex flex-row justify-between items-center">
|
<p>{message}</p>
|
||||||
<div className="flex flex-row">
|
</div>
|
||||||
<div className="shrink-0">{getIcon()}</div>
|
)}
|
||||||
<div className="ml-3">
|
{children && <div className="mt-3">{children}</div>}
|
||||||
<h3 className={`text-sm font-medium ${getTextColor()}`}>{title}</h3>
|
|
||||||
{message && (
|
|
||||||
<div className={`mt-2 text-sm ${getTextColor()}`}>
|
|
||||||
<p>{message}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{children}
|
|
||||||
|
{dismissible && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onDismiss}
|
||||||
|
className={classNames(
|
||||||
|
'shrink-0 rounded-md p-1.5 transition-colors duration-150',
|
||||||
|
getCloseButtonStyles(),
|
||||||
|
'focus:outline-none focus:ring-2 focus:ring-offset-2',
|
||||||
|
type === 'warning' ? 'focus:ring-desert-orange' : '',
|
||||||
|
type === 'error' ? 'focus:ring-desert-red' : '',
|
||||||
|
type === 'success' ? 'focus:ring-desert-olive' : '',
|
||||||
|
type === 'info' ? 'focus:ring-desert-stone' : ''
|
||||||
|
)}
|
||||||
|
aria-label="Dismiss alert"
|
||||||
|
>
|
||||||
|
<Icons.XMarkIcon className="size-5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,19 @@ export interface StyledButtonProps extends React.HTMLAttributes<HTMLButtonElemen
|
||||||
// icon should be one of the HeroIcon names, e.g. ArrowTopRightOnSquareIcon
|
// icon should be one of the HeroIcon names, e.g. ArrowTopRightOnSquareIcon
|
||||||
icon?: keyof typeof Icons
|
icon?: keyof typeof Icons
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
variant?: 'primary' | 'secondary' | 'danger' | 'action'
|
variant?: 'primary' | 'secondary' | 'danger' | 'action' | 'success' | 'ghost' | 'outline'
|
||||||
|
size?: 'sm' | 'md' | 'lg'
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
|
fullWidth?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledButton: React.FC<StyledButtonProps> = ({
|
const StyledButton: React.FC<StyledButtonProps> = ({
|
||||||
children,
|
children,
|
||||||
icon,
|
icon,
|
||||||
variant = 'primary',
|
variant = 'primary',
|
||||||
|
size = 'md',
|
||||||
loading = false,
|
loading = false,
|
||||||
|
fullWidth = false,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const isDisabled = useMemo(() => {
|
const isDisabled = useMemo(() => {
|
||||||
|
|
@ -24,30 +28,113 @@ const StyledButton: React.FC<StyledButtonProps> = ({
|
||||||
const IconComponent = () => {
|
const IconComponent = () => {
|
||||||
if (!icon) return null
|
if (!icon) return null
|
||||||
const Icon = Icons[icon]
|
const Icon = Icons[icon]
|
||||||
return Icon ? <Icon className="h-4 w-4 mr-2" /> : null
|
return Icon ? <Icon className={getIconSize()} /> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
const getBgColors = () => {
|
const getIconSize = () => {
|
||||||
// if primary, use desert-green
|
switch (size) {
|
||||||
if (variant === 'primary') {
|
case 'sm':
|
||||||
return 'bg-desert-green hover:bg-desert-green-light text-white hover:shadow-lg transition-all duration-200'
|
return 'h-3.5 w-3.5 mr-1.5'
|
||||||
}
|
case 'lg':
|
||||||
// if secondary, use outlined styles
|
return 'h-5 w-5 mr-2.5'
|
||||||
if (variant === 'secondary') {
|
default:
|
||||||
return 'bg-transparent border border-desert-green text-desert-green hover:bg-desert-green-light'
|
return 'h-4 w-4 mr-2'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if danger, use red styles
|
const getSizeClasses = () => {
|
||||||
if (variant === 'danger') {
|
switch (size) {
|
||||||
return 'bg-red-600 hover:bg-red-700 text-white'
|
case 'sm':
|
||||||
|
return 'px-2.5 py-1.5 text-xs'
|
||||||
|
case 'lg':
|
||||||
|
return 'px-4 py-3 text-base'
|
||||||
|
default:
|
||||||
|
return 'px-3 py-2 text-sm'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if action, use orange styles
|
const getVariantClasses = () => {
|
||||||
if (variant === 'action') {
|
const baseTransition = 'transition-all duration-200 ease-in-out'
|
||||||
return 'bg-desert-orange hover:bg-desert-orange-light text-white'
|
const baseHover = 'hover:shadow-md active:scale-[0.98]'
|
||||||
|
|
||||||
|
switch (variant) {
|
||||||
|
case 'primary':
|
||||||
|
return `
|
||||||
|
bg-desert-green text-desert-white
|
||||||
|
hover:bg-desert-green-dark hover:shadow-lg
|
||||||
|
active:bg-desert-green-darker
|
||||||
|
disabled:bg-desert-green-light disabled:text-desert-stone-light
|
||||||
|
${baseTransition} ${baseHover}
|
||||||
|
`
|
||||||
|
|
||||||
|
case 'secondary':
|
||||||
|
return `
|
||||||
|
bg-desert-tan text-desert-white
|
||||||
|
hover:bg-desert-tan-dark hover:shadow-lg
|
||||||
|
active:bg-desert-tan-dark
|
||||||
|
disabled:bg-desert-tan-lighter disabled:text-desert-stone-light
|
||||||
|
${baseTransition} ${baseHover}
|
||||||
|
`
|
||||||
|
|
||||||
|
case 'danger':
|
||||||
|
return `
|
||||||
|
bg-desert-red text-desert-white
|
||||||
|
hover:bg-desert-red-dark hover:shadow-lg
|
||||||
|
active:bg-desert-red-dark
|
||||||
|
disabled:bg-desert-red-lighter disabled:text-desert-stone-light
|
||||||
|
${baseTransition} ${baseHover}
|
||||||
|
`
|
||||||
|
|
||||||
|
case 'action':
|
||||||
|
return `
|
||||||
|
bg-desert-orange text-desert-white
|
||||||
|
hover:bg-desert-orange-light hover:shadow-lg
|
||||||
|
active:bg-desert-orange-dark
|
||||||
|
disabled:bg-desert-orange-lighter disabled:text-desert-stone-light
|
||||||
|
${baseTransition} ${baseHover}
|
||||||
|
`
|
||||||
|
|
||||||
|
case 'success':
|
||||||
|
return `
|
||||||
|
bg-desert-olive text-desert-white
|
||||||
|
hover:bg-desert-olive-dark hover:shadow-lg
|
||||||
|
active:bg-desert-olive-dark
|
||||||
|
disabled:bg-desert-olive-lighter disabled:text-desert-stone-light
|
||||||
|
${baseTransition} ${baseHover}
|
||||||
|
`
|
||||||
|
|
||||||
|
case 'ghost':
|
||||||
|
return `
|
||||||
|
bg-transparent text-desert-green
|
||||||
|
hover:bg-desert-sand hover:text-desert-green-dark
|
||||||
|
active:bg-desert-green-lighter
|
||||||
|
disabled:text-desert-stone-light
|
||||||
|
${baseTransition}
|
||||||
|
`
|
||||||
|
|
||||||
|
case 'outline':
|
||||||
|
return `
|
||||||
|
bg-transparent border-2 border-desert-green text-desert-green
|
||||||
|
hover:bg-desert-green hover:text-desert-white hover:border-desert-green-dark
|
||||||
|
active:bg-desert-green-dark active:border-desert-green-darker
|
||||||
|
disabled:border-desert-green-lighter disabled:text-desert-stone-light
|
||||||
|
${baseTransition} ${baseHover}
|
||||||
|
`
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getLoadingSpinner = () => {
|
||||||
|
const spinnerSize = size === 'sm' ? 'h-3.5 w-3.5' : size === 'lg' ? 'h-5 w-5' : 'h-4 w-4'
|
||||||
|
return (
|
||||||
|
<Icons.ArrowPathIcon
|
||||||
|
className={`${spinnerSize} animate-spin ${fullWidth ? 'mx-auto' : ''}`}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const onClickHandler = (e: React.MouseEvent<HTMLButtonElement>) => {
|
const onClickHandler = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
if (isDisabled) {
|
if (isDisabled) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
@ -59,23 +146,30 @@ const StyledButton: React.FC<StyledButtonProps> = ({
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`block rounded-md ${getBgColors()} px-3 py-2 text-center text-sm font-semibold shadow-sm cursor-pointer disabled:opacity-50 disabled:pointer-events-none`}
|
className={`
|
||||||
|
${fullWidth ? 'w-full' : 'inline-flex'}
|
||||||
|
items-center justify-center
|
||||||
|
rounded-md font-semibold
|
||||||
|
${getSizeClasses()}
|
||||||
|
${getVariantClasses()}
|
||||||
|
focus:outline-none focus:ring-2 focus:ring-desert-green-light focus:ring-offset-2 focus:ring-offset-desert-sand
|
||||||
|
disabled:cursor-not-allowed disabled:shadow-none
|
||||||
|
${isDisabled ? 'pointer-events-none opacity-60' : 'cursor-pointer'}
|
||||||
|
`}
|
||||||
{...props}
|
{...props}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
onClick={onClickHandler}
|
onClick={onClickHandler}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Icons.EllipsisHorizontalCircleIcon className="h-5 w-5 animate-spin text-white" />
|
getLoadingSpinner()
|
||||||
) : icon ? (
|
|
||||||
<div className="flex flex-row items-center justify-center">
|
|
||||||
<IconComponent />
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
children
|
<>
|
||||||
|
{icon && <IconComponent />}
|
||||||
|
<span className={fullWidth ? 'block text-center' : ''}>{children}</span>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default StyledButton
|
export default StyledButton
|
||||||
|
|
@ -2,13 +2,40 @@
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--color-desert-white: #f6f6f4;
|
--color-desert-white: #f6f6f4;
|
||||||
--color-desert-green-light: #babaaa;
|
|
||||||
--color-desert-green: #424420;
|
|
||||||
--color-desert-orange: #a84a12;
|
|
||||||
--color-desert-sand: #f7eedc;
|
--color-desert-sand: #f7eedc;
|
||||||
/* --color-desert-sand: #E2DAC2; */
|
|
||||||
|
--color-desert-green-darker: #2a2a15;
|
||||||
|
--color-desert-green-dark: #353518;
|
||||||
|
--color-desert-green: #424420;
|
||||||
|
--color-desert-green-light: #babaaa;
|
||||||
|
--color-desert-green-lighter: #d4d4c8;
|
||||||
|
|
||||||
|
--color-desert-orange-dark: #8a3d0f;
|
||||||
|
--color-desert-orange: #a84a12;
|
||||||
|
--color-desert-orange-light: #c85815;
|
||||||
|
--color-desert-orange-lighter: #e69556;
|
||||||
|
|
||||||
|
--color-desert-tan-dark: #6b5d4f;
|
||||||
|
--color-desert-tan: #8b7355;
|
||||||
|
--color-desert-tan-light: #a8927a;
|
||||||
|
--color-desert-tan-lighter: #c9b99f;
|
||||||
|
|
||||||
|
--color-desert-red-dark: #7a2e2e;
|
||||||
|
--color-desert-red: #994444;
|
||||||
|
--color-desert-red-light: #b05555;
|
||||||
|
--color-desert-red-lighter: #d88989;
|
||||||
|
|
||||||
|
--color-desert-olive-dark: #5a5c3a;
|
||||||
|
--color-desert-olive: #6d7042;
|
||||||
|
--color-desert-olive-light: #858a55;
|
||||||
|
--color-desert-olive-lighter: #a5ab7d;
|
||||||
|
|
||||||
|
--color-desert-stone-dark: #5c5c54;
|
||||||
|
--color-desert-stone: #75756a;
|
||||||
|
--color-desert-stone-light: #8f8f82;
|
||||||
|
--color-desert-stone-lighter: #afafa5;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: var(--color-desert-sand);
|
background-color: var(--color-desert-sand);
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +70,7 @@ export default function ZimPage() {
|
||||||
<Alert
|
<Alert
|
||||||
title="The Kiwix application is not installed. Please install it to view downloaded ZIM files"
|
title="The Kiwix application is not installed. Please install it to view downloaded ZIM files"
|
||||||
type="warning"
|
type="warning"
|
||||||
|
variant='solid'
|
||||||
className="!mt-6"
|
className="!mt-6"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,7 @@ export default function ZimRemoteExplorer() {
|
||||||
title="No internet connection. You may not be able to download files."
|
title="No internet connection. You may not be able to download files."
|
||||||
message=""
|
message=""
|
||||||
type="warning"
|
type="warning"
|
||||||
|
variant="solid"
|
||||||
className="!mt-6"
|
className="!mt-6"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
@ -161,6 +162,7 @@ export default function ZimRemoteExplorer() {
|
||||||
<Alert
|
<Alert
|
||||||
title="The Kiwix application is not installed. Please install it to view downloaded ZIM files"
|
title="The Kiwix application is not installed. Please install it to view downloaded ZIM files"
|
||||||
type="warning"
|
type="warning"
|
||||||
|
variant="solid"
|
||||||
className="!mt-6"
|
className="!mt-6"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user