Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- night-light-provider.tsx
- 'use client'
- import { createContext, useContext, useEffect, useState } from 'react'
- type NightLightContextType = {
- enabled: boolean
- strength: number // 0-100 scale
- toggle: () => void
- setStrength: (value: number) => void
- }
- const NightLightContext = createContext<NightLightContextType | undefined>(
- undefined
- )
- export function NightLightProvider({
- children
- }: {
- children: React.ReactNode
- }) {
- const [enabled, setEnabled] = useState(false)
- const [strength, setStrength] = useState(50)
- const toggle = () => setEnabled(prev => !prev)
- useEffect(() => {
- const styleId = 'night-light-style'
- let styleElement = document.getElementById(
- styleId
- ) as HTMLStyleElement | null
- if (!styleElement) {
- styleElement = document.createElement('style')
- styleElement.id = styleId
- document.head.appendChild(styleElement)
- }
- if (enabled) {
- // Усиливаем эффект: 85% -> 55% Windows (коэффициент ~1.55)
- const enhancedOpacity = (strength / 100) * 0.93 // было 0.6, стало 0.93
- const color = `rgba(255, 159, 46, ${enhancedOpacity})`
- styleElement.textContent = `
- html::after {
- content: '';
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: ${color};
- mix-blend-mode: multiply;
- pointer-events: none;
- z-index: 2147483647;
- }
- `
- } else {
- styleElement.textContent = ''
- }
- return () => {
- if (styleElement) {
- styleElement.textContent = ''
- }
- }
- }, [enabled, strength])
- return (
- <NightLightContext.Provider
- value={{ enabled, strength, toggle, setStrength }}
- >
- {children}
- </NightLightContext.Provider>
- )
- }
- export function useNightLight() {
- const context = useContext(NightLightContext)
- if (context === undefined) {
- throw new Error(
- 'useNightLight must be used within a NightLightProvider'
- )
- }
- return context
- }
- night-light-toggle.tsx
- ////////////////////////////////////////////////////
- ////////////////////////////////////////////////////
- 'use client'
- import { Moon, Sun } from 'lucide-react'
- import { Button } from '@/components/ui/common/Button'
- import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger
- } from '@/components/ui/common/DropdownMenu'
- import { Slider } from '@/components/ui/common/Slider'
- import { useNightLight } from './night-light-provider'
- export function NightLightToggle() {
- const { enabled, strength, toggle, setStrength } = useNightLight()
- return (
- <div className='relative'>
- <DropdownMenu>
- <DropdownMenuTrigger asChild>
- <Button
- variant='outline'
- size='icon'
- className={`relative ${enabled ? 'bg-amber-100/50 hover:bg-amber-100/70' : ''}`}
- >
- <Sun
- className={`h-[1.2rem] w-[1.2rem] transition-all ${enabled ? 'scale-0 opacity-0' : 'scale-100 opacity-100'}`}
- />
- <Moon
- className={`absolute h-[1.2rem] w-[1.2rem] transition-all ${enabled ? 'scale-100 text-amber-600 opacity-100' : 'scale-0 opacity-0'}`}
- />
- <span className='sr-only'>Toggle night light</span>
- </Button>
- </DropdownMenuTrigger>
- <DropdownMenuContent align='end' className='w-56'>
- <div className='p-2'>
- <h4 className='mb-1 flex justify-between text-sm font-medium'>
- <span>Night light</span>
- <span className='text-amber-600'>
- {enabled ? `${strength}%` : 'Off'}
- </span>
- </h4>
- <Slider
- value={[strength]}
- min={0}
- max={100}
- step={1}
- onValueChange={values => setStrength(values[0])}
- className='my-2 w-full'
- disabled={!enabled}
- />
- <div className='flex justify-between text-xs text-muted-foreground'>
- <span>Less warm</span>
- <span>More warm</span>
- </div>
- </div>
- <DropdownMenuItem
- onClick={toggle}
- className='cursor-pointer focus:bg-amber-50'
- >
- {enabled ? 'Turn off' : 'Turn on'}
- </DropdownMenuItem>
- </DropdownMenuContent>
- </DropdownMenu>
- {enabled && (
- <div className='absolute -right-1 -top-1 h-2.5 w-2.5 rounded-full border border-white bg-amber-500' />
- )}
- </div>
- )
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement