style.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import re
  2. from typing import List, Optional
  3. from nicegui import ui
  4. from .examples import Example
  5. SPECIAL_CHARACTERS = re.compile('[^(a-z)(A-Z)(0-9)-]')
  6. def link_target(name: str, offset: str = '0') -> ui.link_target:
  7. """Create a link target that can be linked to with a hash."""
  8. target = ui.link_target(name).style(f'position: absolute; top: {offset}; left: 0')
  9. assert target.parent_slot is not None
  10. target.parent_slot.parent.classes('relative')
  11. return target
  12. def section_heading(subtitle_: str, title_: str) -> None:
  13. """Render a section heading with a subtitle."""
  14. ui.label(subtitle_).classes('md:text-lg font-bold')
  15. ui.markdown(title_).classes('text-3xl md:text-5xl font-medium mt-[-12px] fancy-em')
  16. def heading(title_: str) -> ui.markdown:
  17. """Render a heading."""
  18. return ui.markdown(title_).classes('text-2xl md:text-3xl xl:text-4xl font-medium text-white')
  19. def title(content: str) -> ui.markdown:
  20. """Render a title."""
  21. return ui.markdown(content).classes('text-4xl sm:text-5xl md:text-6xl font-medium fancy-em')
  22. def subtitle(content: str) -> ui.markdown:
  23. """Render a subtitle."""
  24. return ui.markdown(content).classes('text-xl sm:text-2xl md:text-3xl leading-7')
  25. def example_link(example: Example) -> None:
  26. """Render a link to an example."""
  27. with ui.link(target=example.url) \
  28. .classes('bg-[#5898d420] p-4 self-stretch rounded flex flex-col gap-2') \
  29. .style('box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1)'):
  30. ui.label(example.title).classes(replace='font-bold')
  31. ui.markdown(example.description).classes(replace='bold-links arrow-links')
  32. def features(icon: str, title_: str, items: List[str]) -> None:
  33. """Render a list of features."""
  34. with ui.column().classes('gap-1'):
  35. ui.icon(icon).classes('max-sm:hidden text-3xl md:text-5xl mb-3 text-primary opacity-80')
  36. ui.label(title_).classes('font-bold mb-3')
  37. ui.markdown('\n'.join(f'- {item}' for item in items)).classes('bold-links arrow-links -ml-4')
  38. def side_menu() -> ui.left_drawer:
  39. """Render the side menu."""
  40. return ui.left_drawer() \
  41. .classes('column no-wrap gap-1 bg-[#eee] dark:bg-[#1b1b1b] mt-[-20px] px-8 py-20') \
  42. .style('height: calc(100% + 20px) !important')
  43. def subheading(text: str, *, link: Optional[str] = None, major: bool = False, anchor_name: Optional[str] = None) -> None:
  44. """Render a subheading with an anchor that can be linked to with a hash."""
  45. name = anchor_name or create_anchor_name(text)
  46. ui.html(f'<div id="{name}"></div>').style('position: relative; top: -90px')
  47. with ui.row().classes('gap-2 items-center relative'):
  48. classes = 'text-3xl' if major else 'text-2xl'
  49. if link:
  50. ui.link(text, link).classes(classes)
  51. else:
  52. ui.label(text).classes(classes)
  53. with ui.link(target=f'#{name}').classes('absolute').style('transform: translateX(-150%)'):
  54. ui.icon('link', size='sm').classes('opacity-10 hover:opacity-80')
  55. def create_anchor_name(text: str) -> str:
  56. """Create an anchor name that can be linked to with a hash."""
  57. return SPECIAL_CHARACTERS.sub('_', text).lower()