mirror of https://github.com/mkrhere/pw2
Muthu Kumar
5 months ago
8 changed files with 2387 additions and 1816 deletions
File diff suppressed because it is too large
After Width: | Height: | Size: 252 B |
@ -0,0 +1,88 @@ |
|||||
|
import React from "react"; |
||||
|
import { css, cx } from "@emotion/css"; |
||||
|
import { HookSet } from "../../util/useSet"; |
||||
|
import { ReactComponent as Cross } from "../../assets/cross.svg"; |
||||
|
|
||||
|
type Tags = HookSet<string>; |
||||
|
|
||||
|
const tag = css` |
||||
|
border: none; |
||||
|
cursor: pointer; |
||||
|
border-radius: 0.5rem; |
||||
|
padding: 0.5rem 0.8rem; |
||||
|
font-size: 0.85rem; |
||||
|
background: var(--card-bg); |
||||
|
color: var(--text-colour); |
||||
|
|
||||
|
display: flex; |
||||
|
align-items: flex-end; |
||||
|
|
||||
|
transition: all 100ms ease-in-out; |
||||
|
|
||||
|
&:hover { |
||||
|
background: var(--card-tags-hover); |
||||
|
} |
||||
|
|
||||
|
&.active { |
||||
|
background: var(--card-tags); |
||||
|
} |
||||
|
`;
|
||||
|
|
||||
|
export const Tag = (props: { tag: string; selected: Tags }) => { |
||||
|
const { selected } = props; |
||||
|
|
||||
|
const active = selected.has(props.tag); |
||||
|
const select = () => |
||||
|
selected.has(props.tag) |
||||
|
? selected.remove(props.tag) |
||||
|
: selected.add(props.tag); |
||||
|
|
||||
|
return ( |
||||
|
<button className={cx(tag, { active })} onClick={select}> |
||||
|
{props.tag} |
||||
|
<span |
||||
|
className={cx( |
||||
|
css` |
||||
|
width: 0; |
||||
|
opacity: 0; |
||||
|
margin-inline-start: 0; |
||||
|
transition: all 100ms ease-in-out; |
||||
|
overflow: hidden; |
||||
|
|
||||
|
&.active { |
||||
|
opacity: 1; |
||||
|
width: 0.85rem; |
||||
|
margin-inline-start: 0.5rem; |
||||
|
} |
||||
|
`,
|
||||
|
{ active }, |
||||
|
)}> |
||||
|
<Cross |
||||
|
className={css` |
||||
|
display: ${active ? "block" : "none"}; |
||||
|
height: 0.85rem; |
||||
|
width: 0.85rem; |
||||
|
fill: var(--text-colour); |
||||
|
`}
|
||||
|
/> |
||||
|
</span> |
||||
|
</button> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export const Tags = (props: { tags: string[]; selected: Tags }) => { |
||||
|
const { tags, selected } = props; |
||||
|
|
||||
|
return ( |
||||
|
<div |
||||
|
className={css` |
||||
|
display: flex; |
||||
|
gap: 0.5rem; |
||||
|
flex-wrap: wrap; |
||||
|
`}>
|
||||
|
{tags.map(tag => ( |
||||
|
<Tag tag={tag} selected={selected} /> |
||||
|
))} |
||||
|
</div> |
||||
|
); |
||||
|
}; |
@ -0,0 +1 @@ |
|||||
|
export const offscreenWidth = "85rem"; |
@ -0,0 +1,41 @@ |
|||||
|
import { useState } from "react"; |
||||
|
|
||||
|
export type HookSet<T> = { |
||||
|
size: number; |
||||
|
set: Set<T>; |
||||
|
add: (value: T) => void; |
||||
|
remove: (value: T) => void; |
||||
|
clear: () => void; |
||||
|
has: (value: T) => boolean; |
||||
|
}; |
||||
|
|
||||
|
function useSet<T>(initialValues: T[] = []): HookSet<T> { |
||||
|
const [set, setSet] = useState(new Set(initialValues)); |
||||
|
|
||||
|
const add = (value: T) => { |
||||
|
setSet(prevSet => new Set([...prevSet, value])); |
||||
|
}; |
||||
|
|
||||
|
const remove = (value: T) => { |
||||
|
setSet(prevSet => { |
||||
|
const newSet = new Set(prevSet); |
||||
|
newSet.delete(value); |
||||
|
return newSet; |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const clear = () => { |
||||
|
setSet(new Set()); |
||||
|
}; |
||||
|
|
||||
|
return { |
||||
|
size: set.size, |
||||
|
set, |
||||
|
add, |
||||
|
remove, |
||||
|
clear, |
||||
|
has: (value: T) => set.has(value), |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default useSet; |
Loading…
Reference in new issue