Replace style props with tailwind classes (#800)
* add utility class for `word-break: break-word` * refactor visuallyHidden style out of Page * refactor out ref sizing hack in sidebar * replace style props with tailwind classes
This commit is contained in:
parent
3255806891
commit
8903b1ef95
|
@ -1,38 +0,0 @@
|
||||||
import clsx from 'clsx'
|
|
||||||
import { useState, ReactNode } from 'react'
|
|
||||||
|
|
||||||
export function AdvancedPanel(props: { children: ReactNode }) {
|
|
||||||
const { children } = props
|
|
||||||
const [collapsed, setCollapsed] = useState(true)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
tabIndex={0}
|
|
||||||
className={clsx(
|
|
||||||
'collapse collapse-arrow relative',
|
|
||||||
collapsed ? 'collapse-close' : 'collapse-open'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
onClick={() => setCollapsed((collapsed) => !collapsed)}
|
|
||||||
className="cursor-pointer"
|
|
||||||
>
|
|
||||||
<div className="mt-4 mr-6 text-right text-sm text-gray-500">
|
|
||||||
Advanced
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="collapse-title absolute h-0 min-h-0 w-0 p-0"
|
|
||||||
style={{
|
|
||||||
top: -2,
|
|
||||||
right: -15,
|
|
||||||
color: '#6a7280' /* gray-500 */,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="collapse-content m-0 !bg-transparent !p-0">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Point, ResponsiveLine } from '@nivo/line'
|
import { Point, ResponsiveLine } from '@nivo/line'
|
||||||
|
import clsx from 'clsx'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { zip } from 'lodash'
|
import { zip } from 'lodash'
|
||||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
import { useWindowSize } from 'web/hooks/use-window-size'
|
||||||
|
@ -26,8 +27,10 @@ export function DailyCountChart(props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="w-full overflow-hidden"
|
className={clsx(
|
||||||
style={{ height: !small && (!width || width >= 800) ? 400 : 250 }}
|
'h-[250px] w-full overflow-hidden',
|
||||||
|
!small && 'md:h-[400px]'
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<ResponsiveLine
|
<ResponsiveLine
|
||||||
data={data}
|
data={data}
|
||||||
|
@ -78,8 +81,10 @@ export function DailyPercentChart(props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="w-full overflow-hidden"
|
className={clsx(
|
||||||
style={{ height: !small && (!width || width >= 800) ? 400 : 250 }}
|
'h-[250px] w-full overflow-hidden',
|
||||||
|
!small && 'md:h-[400px]'
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<ResponsiveLine
|
<ResponsiveLine
|
||||||
data={data}
|
data={data}
|
||||||
|
|
|
@ -108,10 +108,9 @@ export function ContractCard(props: {
|
||||||
/>
|
/>
|
||||||
<p
|
<p
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'break-words font-semibold text-indigo-700 group-hover:underline group-hover:decoration-indigo-400 group-hover:decoration-2',
|
'break-anywhere font-semibold text-indigo-700 group-hover:underline group-hover:decoration-indigo-400 group-hover:decoration-2',
|
||||||
questionClass
|
questionClass
|
||||||
)}
|
)}
|
||||||
style={{ /* For iOS safari */ wordBreak: 'break-word' }}
|
|
||||||
>
|
>
|
||||||
{question}
|
{question}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -40,7 +40,7 @@ export function Leaderboard(props: {
|
||||||
{users.map((user, index) => (
|
{users.map((user, index) => (
|
||||||
<tr key={user.id}>
|
<tr key={user.id}>
|
||||||
<td>{index + 1}</td>
|
<td>{index + 1}</td>
|
||||||
<td style={{ maxWidth: 190 }}>
|
<td className="max-w-[190px]">
|
||||||
<SiteLink className="relative" href={`/${user.username}`}>
|
<SiteLink className="relative" href={`/${user.username}`}>
|
||||||
<Row className="items-center gap-4">
|
<Row className="items-center gap-4">
|
||||||
<Avatar avatarUrl={user.avatarUrl} size={8} />
|
<Avatar avatarUrl={user.avatarUrl} size={8} />
|
||||||
|
|
|
@ -38,10 +38,7 @@ export function Linkify(props: { text: string; gray?: boolean }) {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
return (
|
return (
|
||||||
<span
|
<span className="break-anywhere">
|
||||||
className="break-words"
|
|
||||||
style={{ /* For iOS safari */ wordBreak: 'break-word' }}
|
|
||||||
>
|
|
||||||
{text.split(regex).map((part, i) => (
|
{text.split(regex).map((part, i) => (
|
||||||
<Fragment key={i}>
|
<Fragment key={i}>
|
||||||
{part}
|
{part}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { ManifoldLogo } from './manifold-logo'
|
||||||
import { MenuButton } from './menu'
|
import { MenuButton } from './menu'
|
||||||
import { ProfileSummary } from './profile-menu'
|
import { ProfileSummary } from './profile-menu'
|
||||||
import NotificationsIcon from 'web/components/notifications-icon'
|
import NotificationsIcon from 'web/components/notifications-icon'
|
||||||
import React, { useState } from 'react'
|
import React from 'react'
|
||||||
import { IS_PRIVATE_MANIFOLD } from 'common/envs/constants'
|
import { IS_PRIVATE_MANIFOLD } from 'common/envs/constants'
|
||||||
import { CreateQuestionButton } from 'web/components/create-question-button'
|
import { CreateQuestionButton } from 'web/components/create-question-button'
|
||||||
import { useMemberGroups } from 'web/hooks/use-group'
|
import { useMemberGroups } from 'web/hooks/use-group'
|
||||||
|
@ -25,7 +25,6 @@ import { groupPath } from 'web/lib/firebase/groups'
|
||||||
import { trackCallback, withTracking } from 'web/lib/service/analytics'
|
import { trackCallback, withTracking } from 'web/lib/service/analytics'
|
||||||
import { Group } from 'common/group'
|
import { Group } from 'common/group'
|
||||||
import { Spacer } from '../layout/spacer'
|
import { Spacer } from '../layout/spacer'
|
||||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
|
||||||
import { CHALLENGES_ENABLED } from 'common/challenge'
|
import { CHALLENGES_ENABLED } from 'common/challenge'
|
||||||
import { buildArray } from 'common/util/array'
|
import { buildArray } from 'common/util/array'
|
||||||
import TrophyIcon from 'web/lib/icons/trophy-icon'
|
import TrophyIcon from 'web/lib/icons/trophy-icon'
|
||||||
|
@ -235,19 +234,22 @@ export default function Sidebar(props: { className?: string }) {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav aria-label="Sidebar" className={className}>
|
<nav
|
||||||
|
aria-label="Sidebar"
|
||||||
|
className={clsx('flex max-h-[100vh] flex-col', className)}
|
||||||
|
>
|
||||||
<ManifoldLogo className="py-6" twoLine />
|
<ManifoldLogo className="py-6" twoLine />
|
||||||
|
|
||||||
<CreateQuestionButton user={user} />
|
<CreateQuestionButton user={user} />
|
||||||
<Spacer h={4} />
|
<Spacer h={4} />
|
||||||
{user && (
|
{user && (
|
||||||
<div className="w-full" style={{ minHeight: 80 }}>
|
<div className="min-h-[80px] w-full">
|
||||||
<ProfileSummary user={user} />
|
<ProfileSummary user={user} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Mobile navigation */}
|
{/* Mobile navigation */}
|
||||||
<div className="space-y-1 lg:hidden">
|
<div className="flex min-h-0 shrink flex-col gap-1 lg:hidden">
|
||||||
{mobileNavigationOptions.map((item) => (
|
{mobileNavigationOptions.map((item) => (
|
||||||
<SidebarItem key={item.href} item={item} currentPage={currentPage} />
|
<SidebarItem key={item.href} item={item} currentPage={currentPage} />
|
||||||
))}
|
))}
|
||||||
|
@ -266,7 +268,7 @@ export default function Sidebar(props: { className?: string }) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Desktop navigation */}
|
{/* Desktop navigation */}
|
||||||
<div className="hidden space-y-1 lg:block">
|
<div className="hidden min-h-0 shrink flex-col gap-1 lg:flex">
|
||||||
{navigationOptions.map((item) => (
|
{navigationOptions.map((item) => (
|
||||||
<SidebarItem key={item.href} item={item} currentPage={currentPage} />
|
<SidebarItem key={item.href} item={item} currentPage={currentPage} />
|
||||||
))}
|
))}
|
||||||
|
@ -286,10 +288,6 @@ export default function Sidebar(props: { className?: string }) {
|
||||||
function GroupsList(props: { currentPage: string; memberItems: Item[] }) {
|
function GroupsList(props: { currentPage: string; memberItems: Item[] }) {
|
||||||
const { currentPage, memberItems } = props
|
const { currentPage, memberItems } = props
|
||||||
|
|
||||||
const { height } = useWindowSize()
|
|
||||||
const [containerRef, setContainerRef] = useState<HTMLDivElement | null>(null)
|
|
||||||
const remainingHeight = (height ?? 0) - (containerRef?.offsetTop ?? 0)
|
|
||||||
|
|
||||||
// const preferredNotifications = useUnseenPreferredNotifications(
|
// const preferredNotifications = useUnseenPreferredNotifications(
|
||||||
// privateUser,
|
// privateUser,
|
||||||
// {
|
// {
|
||||||
|
@ -315,11 +313,7 @@ function GroupsList(props: { currentPage: string; memberItems: Item[] }) {
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div className="min-h-0 shrink space-y-0.5 overflow-auto">
|
||||||
className="flex-1 space-y-0.5 overflow-auto"
|
|
||||||
style={{ height: remainingHeight }}
|
|
||||||
ref={setContainerRef}
|
|
||||||
>
|
|
||||||
{memberItems.map((item) => (
|
{memberItems.map((item) => (
|
||||||
<a
|
<a
|
||||||
href={item.href}
|
href={item.href}
|
||||||
|
|
|
@ -164,10 +164,7 @@ export function AnswerLabel(props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip text={truncated === text ? false : text}>
|
<Tooltip text={truncated === text ? false : text}>
|
||||||
<span
|
<span className={clsx('break-anywhere whitespace-pre-line', className)}>
|
||||||
style={{ wordBreak: 'break-word' }}
|
|
||||||
className={clsx('whitespace-pre-line break-words', className)}
|
|
||||||
>
|
|
||||||
{truncated}
|
{truncated}
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
|
@ -6,13 +6,11 @@ import { Toaster } from 'react-hot-toast'
|
||||||
|
|
||||||
export function Page(props: {
|
export function Page(props: {
|
||||||
rightSidebar?: ReactNode
|
rightSidebar?: ReactNode
|
||||||
suspend?: boolean
|
|
||||||
className?: string
|
className?: string
|
||||||
rightSidebarClassName?: string
|
rightSidebarClassName?: string
|
||||||
children?: ReactNode
|
children?: ReactNode
|
||||||
}) {
|
}) {
|
||||||
const { children, rightSidebar, suspend, className, rightSidebarClassName } =
|
const { children, rightSidebar, className, rightSidebarClassName } = props
|
||||||
props
|
|
||||||
|
|
||||||
const bottomBarPadding = 'pb-[58px] lg:pb-0 '
|
const bottomBarPadding = 'pb-[58px] lg:pb-0 '
|
||||||
return (
|
return (
|
||||||
|
@ -23,10 +21,9 @@ export function Page(props: {
|
||||||
bottomBarPadding,
|
bottomBarPadding,
|
||||||
'mx-auto w-full lg:grid lg:grid-cols-12 lg:gap-x-2 xl:max-w-7xl xl:gap-x-8'
|
'mx-auto w-full lg:grid lg:grid-cols-12 lg:gap-x-2 xl:max-w-7xl xl:gap-x-8'
|
||||||
)}
|
)}
|
||||||
style={suspend ? visuallyHiddenStyle : undefined}
|
|
||||||
>
|
>
|
||||||
<Toaster />
|
<Toaster />
|
||||||
<Sidebar className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:block" />
|
<Sidebar className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" />
|
||||||
<main
|
<main
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'lg:col-span-8 lg:pt-6',
|
'lg:col-span-8 lg:pt-6',
|
||||||
|
@ -46,22 +43,7 @@ export function Page(props: {
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BottomNavBar />
|
<BottomNavBar />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const visuallyHiddenStyle = {
|
|
||||||
clip: 'rect(0 0 0 0)',
|
|
||||||
clipPath: 'inset(50%)',
|
|
||||||
height: 1,
|
|
||||||
margin: -1,
|
|
||||||
overflow: 'hidden',
|
|
||||||
padding: 0,
|
|
||||||
position: 'absolute',
|
|
||||||
width: 1,
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
userSelect: 'none',
|
|
||||||
visibility: 'hidden',
|
|
||||||
} as const
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ReactNode } from 'react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
export const linkClass =
|
export const linkClass =
|
||||||
'z-10 break-words hover:underline hover:decoration-indigo-400 hover:decoration-2'
|
'z-10 break-anywhere hover:underline hover:decoration-indigo-400 hover:decoration-2'
|
||||||
|
|
||||||
export const SiteLink = (props: {
|
export const SiteLink = (props: {
|
||||||
href: string
|
href: string
|
||||||
|
@ -19,7 +19,6 @@ export const SiteLink = (props: {
|
||||||
className={clsx(linkClass, className)}
|
className={clsx(linkClass, className)}
|
||||||
href={href}
|
href={href}
|
||||||
target={href.startsWith('http') ? '_blank' : undefined}
|
target={href.startsWith('http') ? '_blank' : undefined}
|
||||||
style={{ /* For iOS safari */ wordBreak: 'break-word' }}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
if (onClick) onClick()
|
if (onClick) onClick()
|
||||||
|
|
|
@ -148,10 +148,7 @@ export function UserPage(props: { user: User }) {
|
||||||
<Col className="mx-4 -mt-6">
|
<Col className="mx-4 -mt-6">
|
||||||
<Row className={'flex-wrap justify-between gap-y-2'}>
|
<Row className={'flex-wrap justify-between gap-y-2'}>
|
||||||
<Col>
|
<Col>
|
||||||
<span
|
<span className="break-anywhere text-2xl font-bold">
|
||||||
className="text-2xl font-bold"
|
|
||||||
style={{ wordBreak: 'break-word' }}
|
|
||||||
>
|
|
||||||
{user.name}
|
{user.name}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-gray-500">@{user.username}</span>
|
<span className="text-gray-500">@{user.username}</span>
|
||||||
|
|
|
@ -33,7 +33,7 @@ const Home = (props: { auth: { user: User } | null }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Page suspend={!!contract}>
|
<Page className={contract ? 'sr-only' : ''}>
|
||||||
<Col className="mx-auto w-full p-2">
|
<Col className="mx-auto w-full p-2">
|
||||||
<ContractSearch
|
<ContractSearch
|
||||||
user={user}
|
user={user}
|
||||||
|
|
|
@ -203,8 +203,7 @@ function NewBidTable(props: {
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
className="input input-bordered"
|
className="input input-bordered max-w-[100px]"
|
||||||
style={{ maxWidth: 100 }}
|
|
||||||
value={newBid.toString()}
|
value={newBid.toString()}
|
||||||
onChange={(e) => setNewBid(parseInt(e.target.value) || 0)}
|
onChange={(e) => setNewBid(parseInt(e.target.value) || 0)}
|
||||||
onKeyUp={(e) => {
|
onKeyUp={(e) => {
|
||||||
|
@ -292,7 +291,7 @@ export default function Simulator() {
|
||||||
YES
|
YES
|
||||||
</div>
|
</div>
|
||||||
</h1>
|
</h1>
|
||||||
<div className="mb-10 w-full" style={{ height: 500 }}>
|
<div className="mb-10 h-[500px] w-full">
|
||||||
<ResponsiveLine
|
<ResponsiveLine
|
||||||
data={data}
|
data={data}
|
||||||
yScale={{ min: 0, max: 100, type: 'linear' }}
|
yScale={{ min: 0, max: 100, type: 'linear' }}
|
||||||
|
|
|
@ -375,11 +375,10 @@ export function FirebaseAnalytics() {
|
||||||
</p>
|
</p>
|
||||||
<Spacer h={4} />
|
<Spacer h={4} />
|
||||||
<iframe
|
<iframe
|
||||||
className="w-full"
|
className="w-full border-0"
|
||||||
height={2200}
|
height={2200}
|
||||||
src="https://datastudio.google.com/embed/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3"
|
src="https://datastudio.google.com/embed/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
style={{ border: 0 }}
|
|
||||||
allowFullScreen
|
allowFullScreen
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -400,11 +399,10 @@ export function WasabiCharts() {
|
||||||
</p>
|
</p>
|
||||||
<Spacer h={4} />
|
<Spacer h={4} />
|
||||||
<iframe
|
<iframe
|
||||||
className="w-full"
|
className="w-full border-0"
|
||||||
height={21000}
|
height={21000}
|
||||||
src="https://wasabipesto.com/jupyter/manifold/"
|
src="https://wasabipesto.com/jupyter/manifold/"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
style={{ border: 0 }}
|
|
||||||
allowFullScreen
|
allowFullScreen
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -56,6 +56,10 @@ module.exports = {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'.break-anywhere': {
|
||||||
|
'overflow-wrap': 'anywhere',
|
||||||
|
'word-break': 'break-word', // for Safari
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue
Block a user